Skip to content

Commit

Permalink
Merge pull request #4452 from NREL/4448_phiRotation_DaylightControl
Browse files Browse the repository at this point in the history
Fix #4448 - Issues with angles in DaylightingControl
  • Loading branch information
tijcolem authored Oct 6, 2021
2 parents 96d5b42 + 97aa01d commit 6265b7e
Show file tree
Hide file tree
Showing 7 changed files with 381 additions and 25 deletions.
47 changes: 45 additions & 2 deletions src/energyplus/ForwardTranslator/ForwardTranslateThermalZone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,51 @@ namespace energyplus {
<< " degrees about Y axis not mapped for OS:Daylighting:Control " << primaryDaylightingControl->name().get());
}

// glare
double glareAngle = primaryDaylightingControl->phiRotationAroundZAxis();
// glare:
// * openstudio uses the right-hand rule, y points North and x points east.
// So a positive rotation around the z-axis is counter-clockwise in the horizontal plane
// * E+ on the other hand is looking for something that is clockwise:
// > Field: Glare Calculation Azimuth Angle of View Direction Clockwise from Zone y-Axis
// > It is the angle, measured clockwise in the horizontal plane, between the zone y-axis and the occupant view direction

// 3D View:
// z
//
//
//
// | │ ▲
// +└►├─┘
// │ . OS convention for ϕ
// │ .
// │ .<-◝
// │. ) ϕ
// ○─────────────────► y
// ╱ * )
// ╱ *<-◞ E+ Field
// ╱ *
//
//
// x
//
// 2D View, from the top:
//
// y
// ▲ Glare Calculation Azimuth Angle of View Direction Clockwise from Zone y axis
// \ │ E+ /
// \ OS ϕ ├─────┐ /
// \ ┌────┤ ▼/
// \▼ │ /
// \ │ /
// \ │ /
// \ │ /
// \ | /
// (◯)───────────────►x
// z
//

double glareAngle = -primaryDaylightingControl->phiRotationAroundZAxis();
// Force [0,360[
glareAngle = normalizeAngle0to360(glareAngle);
daylightingControlObject.setDouble(Daylighting_ControlsFields::GlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis, glareAngle);

if (OptionalDouble d = primaryDaylightingControl->maximumAllowableDiscomfortGlareIndex()) {
Expand Down
28 changes: 21 additions & 7 deletions src/energyplus/Test/DaylightingControl_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,33 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_DaylightingControl_3216) {

DaylightingControl daylightingControl(model);
daylightingControl.setThetaRotationAroundYAxis(90.0);
daylightingControl.setPhiRotationAroundZAxis(180.0);
daylightingControl.setPhiRotationAroundZAxis(-180.0);

EXPECT_TRUE(thermalZone.setPrimaryDaylightingControl(daylightingControl));

ForwardTranslator ft;
Workspace w = ft.translateModel(model);
{
Workspace w = ft.translateModel(model);

WorkspaceObjectVector idfObjs = w.getObjectsByType(IddObjectType::Daylighting_Controls);
ASSERT_EQ(1u, idfObjs.size());
WorkspaceObject idf_d(idfObjs[0]);

WorkspaceObjectVector idfObjs = w.getObjectsByType(IddObjectType::Daylighting_Controls);
ASSERT_EQ(1u, idfObjs.size());
WorkspaceObject idf_d(idfObjs[0]);
EXPECT_EQ(-daylightingControl.phiRotationAroundZAxis(),
idf_d.getDouble(Daylighting_ControlsFields::GlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis).get());
}

EXPECT_EQ(daylightingControl.phiRotationAroundZAxis(),
idf_d.getDouble(Daylighting_ControlsFields::GlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis).get());
daylightingControl.setPhiRotationAroundZAxis(45.0);
{
Workspace w = ft.translateModel(model);

WorkspaceObjectVector idfObjs = w.getObjectsByType(IddObjectType::Daylighting_Controls);
ASSERT_EQ(1u, idfObjs.size());
WorkspaceObject idf_d(idfObjs[0]);

// -45, so +360 to end up with a positive value => 315
EXPECT_EQ(315, idf_d.getDouble(Daylighting_ControlsFields::GlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis).get());
}
}

TEST_F(EnergyPlusFixture, ForwardTranslator_DaylightingControl_AvailabilitySchedule) {
Expand Down
6 changes: 3 additions & 3 deletions src/model/DaylightingControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,9 @@ namespace model {
Transformation transformation = Transformation::rotation(rotationAxis, angle);
EulerAngles eulerAngles = transformation.eulerAngles();

this->setPsiRotationAroundXAxis(eulerAngles.psi());
this->setThetaRotationAroundYAxis(eulerAngles.theta());
this->setPhiRotationAroundZAxis(eulerAngles.phi());
this->setPsiRotationAroundXAxis(radToDeg(eulerAngles.psi()));
this->setThetaRotationAroundYAxis(radToDeg(eulerAngles.theta()));
this->setPhiRotationAroundZAxis(radToDeg(eulerAngles.phi()));

return true;
}
Expand Down
Loading

0 comments on commit 6265b7e

Please # to comment.