Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#4668 - Wrap E+ 22.2 new People fields #4669

Merged
merged 7 commits into from Sep 2, 2022

Conversation

jmarrec
Copy link
Collaborator

@jmarrec jmarrec commented Sep 2, 2022

Pull request overview

Pull Request Author

  • Model API Changes / Additions
  • Any new or modified fields have been implemented in the EnergyPlus ForwardTranslator (and ReverseTranslator as appropriate)
  • Model API methods are tested (in src/model/test)
  • EnergyPlus ForwardTranslator Tests (in src/energyplus/Test)
  • If a new object or method, added a test in NREL/OpenStudio-resources: Add Link
  • If needed, added VersionTranslation rules for the objects (src/osversion/VersionTranslator.cpp)
  • Verified that C# bindings built fine on Windows, partial classes used as needed, etc.
  • All new and existing tests passes
  • If methods have been deprecated, update rest of code to use the new methods

Labels:

  • If change to an IDD file, add the label IDDChange
  • If breaking existing API, add the label APIChange
  • If deemed ready, add label Pull Request - Ready for CI so that CI builds your PR

Review Checklist

This will not be exhaustively relevant to every PR.

  • Perform a Code Review on GitHub
  • Code Style, strip trailing whitespace, etc.
  • All related changes have been implemented: model changes, model tests, FT changes, FT tests, VersionTranslation, OS App
  • Labeling is ok
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified

@jmarrec jmarrec self-assigned this Sep 2, 2022
@jmarrec jmarrec changed the base branch from develop to v22.2.0-IOFreeze September 2, 2022 12:52
Comment on lines 11425 to 11444
A14, \field Thermal Comfort Model 1 Type
\type choice
\key Fanger
\key Pierce
\key KSU
\key AdaptiveASH55
\key AdaptiveCEN15251
\key CoolingEffectASH55
\key AnkleDraftASH55
\note optional (only needed for people thermal comfort results reporting)
A15, \field Thermal Comfort Model 2 Type
\type choice
\key Fanger
\key Pierce
\key KSU
\key AdaptiveASH55
\key AdaptiveCEN15251
\key CoolingEffectASH55
\key AnkleDraftASH55
\note optional (second type of thermal comfort model and results reporting)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E+ added three new fields after these, which we originally treated (as it should have been) as \extensible-fields. We unfortunately cannot do that anymore, so put back the 7 individual fields. That's why most epJSON tests where failing.

Comment on lines +6849 to +6864
A11, \field Ankle Level Air Velocity Schedule Name
\type object-list
\object-list ScheduleNames
\note units in the schedule are m/s
\note this is the schedule of the air speed at the 0.1 m above the floor
\note optional (only required for runs of thermal comfort models AnkleDraftASH55)
N2, \field Cold Stress Temperature Threshold
\type real
\units C
\note this is the indoor safe temperature threshold for cold stress
\default 15.56
N3; \field Heat Stress Temperature Threshold
\type real
\units C
\note this is the indoor safe temperature threshold for heat stress
\default 30
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new OS fields

Comment on lines +94 to +101
/** Returns the ankle-level air velocity schedule. */
boost::optional<Schedule> ankleLevelAirVelocitySchedule() const;

double coldStressTemperatureThreshold() const;
bool isColdStressTemperatureThresholdDefaulted() const;

double heatStressTemperatureThreshold() const;
bool isHeatStressTemperatureThresholdDefaulted() const;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods

Comment on lines +154 to +161
bool setAnkleLevelAirVelocitySchedule(Schedule& schedule);
void resetAnkleLevelAirVelocitySchedule();

bool setColdStressTemperatureThreshold(double coldStressTemperatureThreshold);
void resetColdStressTemperatureThreshold();

bool setHeatStressTemperatureThreshold(double heatStressTemperatureThreshold);
void resetHeatStressTemperatureThreshold();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setters Methods

@@ -327,6 +327,7 @@ namespace model {
{"People", "Work Efficiency", "workEfficiencySchedule", true, "", 0.0, 1.0},
{"People", "Clothing Insulation", "clothingInsulationSchedule", true, "ClothingInsulation", 0.0, OptionalDouble()},
{"People", "Air Velocity", "airVelocitySchedule", true, "Velocity", 0.0, OptionalDouble()},
{"People", "Ankle Level Air Velocity", "ankleLevelAirVelocitySchedule", true, "Velocity", 0.0, OptionalDouble()},
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ScheduleTypeRegistry entry

Comment on lines +153 to +164
// As of 22.2.0, this is no longer possible to make this an extensible field
// because E+ added 3 regular fields at the end (eg: Ankle Level Velocity Schedule Name)
for (int i = 0, numComfortModelTypes = 0; i < definition.numThermalComfortModelTypes(); ++i) {
OptionalString s = definition.getThermalComfortModelType(i);
if (s) {
idfObject.pushExtensibleGroup(StringVector(1U, *s));
++numComfortModelTypes;
if (numComfortModelTypes > 7) {
LOG(Warn, "For " << definition.briefDescription() << ", only 7 Thermal Confort Model Types are supported by EnergyPlus, number "
<< numComfortModelTypes << " [=" << *s << "] will be ignored.");
} else {
idfObject.setString(PeopleFields::ThermalComfortModel1Type + i, *s);
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FT: Annoying but necessary to write to the now non-extensible fields

Comment on lines +168 to +180
if (boost::optional<Schedule> schedule_ = modelObject.ankleLevelAirVelocitySchedule()) {
if (auto idf_schedule_ = translateAndMapModelObject(schedule_.get())) {
idfObject.setString(PeopleFields::AnkleLevelAirVelocityScheduleName, idf_schedule_->nameString());
}
}

if (!modelObject.isColdStressTemperatureThresholdDefaulted()) {
idfObject.setDouble(PeopleFields::ColdStressTemperatureThreshold, modelObject.coldStressTemperatureThreshold());
}

if (!modelObject.isHeatStressTemperatureThresholdDefaulted()) {
idfObject.setDouble(PeopleFields::HeatStressTemperatureThreshold, modelObject.heatStressTemperatureThreshold());
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FT new fields

Comment on lines +134 to +139
// As of 22.2.0, this is no longer possible to make this an extensible field
// because E+ added 3 regular fields at the end (eg: Ankle Level Velocity Schedule Name)
for (unsigned i = PeopleFields::ThermalComfortModel1Type, k = 0; i <= PeopleFields::ThermalComfortModel7Type; ++i) {
s = workspaceObject.getString(i, false, true);
if (s) {
definition.setThermalComfortModelType(i, *s);
definition.setThermalComfortModelType(k++, *s);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RT: Annoying but necessary to read the now non-extensible fields

Comment on lines +238 to +262
target = workspaceObject.getTarget(openstudio::PeopleFields::AnkleLevelAirVelocityScheduleName);
if (target) {
OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
if (modelObject) {
if (OptionalSchedule intermediate = modelObject->optionalCast<Schedule>()) {
Schedule schedule(*intermediate);
bool ok = people.setAnkleLevelAirVelocitySchedule(schedule);
if (!ok) {
LOG(Error, "Unable to set " << people.briefDescription() << "'s Ankle Level Air Velocity schedule to " << schedule.briefDescription()
<< ", likely because of a ScheduleTypeLimits conflict.");
}
}
}
}

d = workspaceObject.getDouble(openstudio::PeopleFields::ColdStressTemperatureThreshold);
if (d) {
people.setColdStressTemperatureThreshold(*d);
}

d = workspaceObject.getDouble(openstudio::PeopleFields::HeatStressTemperatureThreshold);
if (d) {
people.setHeatStressTemperatureThreshold(*d);
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RT new fields

Comment on lines +64 to +253
EXPECT_EQ(15.0, peopleObject.getDouble(PeopleFields::ColdStressTemperatureThreshold).get());
EXPECT_EQ(31.0, peopleObject.getDouble(PeopleFields::HeatStressTemperatureThreshold).get());
}

TEST_F(EnergyPlusFixture, ReverseTranslator_People) {

ReverseTranslator rt;

Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus);

OptionalWorkspaceObject _i_zone = w.addObject(IdfObject(IddObjectType::Zone));
ASSERT_TRUE(_i_zone);
_i_zone->setName("Space1");

OptionalWorkspaceObject _i_people = w.addObject(IdfObject(IddObjectType::People));
ASSERT_TRUE(_i_people);

EXPECT_TRUE(_i_people->setPointer(PeopleFields::ZoneorZoneListorSpaceorSpaceListName, _i_zone->handle()));

auto assignSchedule = [&_i_people, &w](unsigned index, const std::string& scheduleName) {
OptionalWorkspaceObject _i_sch = w.addObject(IdfObject(IddObjectType::Schedule_Constant));
ASSERT_TRUE(_i_sch);

_i_sch->setName(scheduleName);
EXPECT_TRUE(_i_people->setPointer(index, _i_sch->handle()));
};

assignSchedule(PeopleFields::NumberofPeopleScheduleName, "NumberofPeopleSchedule");
EXPECT_TRUE(_i_people->setString(PeopleFields::NumberofPeopleCalculationMethod, "Area/Person"));
EXPECT_TRUE(_i_people->setDouble(PeopleFields::NumberofPeople, 0.0));
EXPECT_TRUE(_i_people->setDouble(PeopleFields::PeopleperFloorArea, 0.0));
EXPECT_TRUE(_i_people->setDouble(PeopleFields::FloorAreaperPerson, 10.0));
EXPECT_TRUE(_i_people->setDouble(PeopleFields::FractionRadiant, 0.35));
EXPECT_TRUE(_i_people->setDouble(PeopleFields::SensibleHeatFraction, 0.2));

assignSchedule(PeopleFields::ActivityLevelScheduleName, "ActivitySchedule");
EXPECT_TRUE(_i_people->setDouble(PeopleFields::CarbonDioxideGenerationRate, 3.6e-08));
EXPECT_TRUE(_i_people->setString(PeopleFields::EnableASHRAE55ComfortWarnings, "Yes"));
EXPECT_TRUE(_i_people->setString(PeopleFields::MeanRadiantTemperatureCalculationType, "SurfaceWeighted"));
EXPECT_TRUE(_i_people->setString(PeopleFields::SurfaceName_AngleFactorListName, ""));
assignSchedule(PeopleFields::WorkEfficiencyScheduleName, "WorkEfficiencySchedule");
EXPECT_TRUE(_i_people->setString(PeopleFields::ClothingInsulationCalculationMethod, ""));
EXPECT_TRUE(_i_people->setString(PeopleFields::ClothingInsulationCalculationMethodScheduleName, ""));
assignSchedule(PeopleFields::ClothingInsulationScheduleName, "ClothingInsulationSchedule");
assignSchedule(PeopleFields::AirVelocityScheduleName, "AirVelocitySchedule");
EXPECT_TRUE(_i_people->setString(PeopleFields::ThermalComfortModel1Type, "Fanger"));
EXPECT_TRUE(_i_people->setString(PeopleFields::ThermalComfortModel2Type, "Pierce"));
EXPECT_TRUE(_i_people->setString(PeopleFields::ThermalComfortModel3Type, ""));
EXPECT_TRUE(_i_people->setString(PeopleFields::ThermalComfortModel4Type, ""));
EXPECT_TRUE(_i_people->setString(PeopleFields::ThermalComfortModel5Type, ""));
EXPECT_TRUE(_i_people->setString(PeopleFields::ThermalComfortModel6Type, ""));
EXPECT_TRUE(_i_people->setString(PeopleFields::ThermalComfortModel7Type, ""));
assignSchedule(PeopleFields::AnkleLevelAirVelocityScheduleName, "AnkleLevelAirVelocitySchedule");
EXPECT_TRUE(_i_people->setDouble(PeopleFields::ColdStressTemperatureThreshold, 15.0));
EXPECT_TRUE(_i_people->setDouble(PeopleFields::HeatStressTemperatureThreshold, 31.0));

Model m = rt.translateWorkspace(w);

ASSERT_EQ(1, m.getConcreteModelObjects<People>().size());
ASSERT_EQ(1, m.getConcreteModelObjects<PeopleDefinition>().size());

auto p = m.getConcreteModelObjects<People>()[0];

EXPECT_EQ("People 1", p.nameString());
ASSERT_TRUE(p.space());
ASSERT_TRUE(p.numberofPeopleSchedule());
EXPECT_EQ("NumberofPeopleSchedule", p.numberofPeopleSchedule()->nameString());
ASSERT_TRUE(p.activityLevelSchedule());
EXPECT_EQ("ActivitySchedule", p.activityLevelSchedule()->nameString());
ASSERT_TRUE(p.workEfficiencySchedule());
EXPECT_EQ("WorkEfficiencySchedule", p.workEfficiencySchedule()->nameString());
ASSERT_TRUE(p.clothingInsulationSchedule());
EXPECT_EQ("ClothingInsulationSchedule", p.clothingInsulationSchedule()->nameString());
ASSERT_TRUE(p.airVelocitySchedule());
EXPECT_EQ("AirVelocitySchedule", p.airVelocitySchedule()->nameString());

// E+ object doesn't have one
EXPECT_EQ(1.0, p.multiplier());
ASSERT_TRUE(p.ankleLevelAirVelocitySchedule());
EXPECT_EQ("AnkleLevelAirVelocitySchedule", p.ankleLevelAirVelocitySchedule()->nameString());
EXPECT_EQ(15.0, p.coldStressTemperatureThreshold());
EXPECT_EQ(31.0, p.heatStressTemperatureThreshold());

auto pd = p.definition().cast<PeopleDefinition>();
EXPECT_EQ("Area/Person", pd.numberofPeopleCalculationMethod());
EXPECT_FALSE(pd.numberofPeople());
EXPECT_FALSE(pd.peopleperSpaceFloorArea());
ASSERT_TRUE(pd.spaceFloorAreaperPerson());
EXPECT_EQ(10.0, pd.spaceFloorAreaperPerson().get());
EXPECT_EQ(0.35, pd.fractionRadiant());
ASSERT_TRUE(pd.sensibleHeatFraction());
EXPECT_EQ(0.2, pd.sensibleHeatFraction().get());
EXPECT_EQ(3.6e-08, pd.carbonDioxideGenerationRate());
EXPECT_TRUE(pd.enableASHRAE55ComfortWarnings());
EXPECT_EQ("SurfaceWeighted", pd.meanRadiantTemperatureCalculationType());

ASSERT_EQ(2, pd.numThermalComfortModelTypes());
ASSERT_EQ(2, pd.numExtensibleGroups());
EXPECT_EQ("Fanger", pd.getThermalComfortModelType(0).get());
EXPECT_EQ("Pierce", pd.getThermalComfortModelType(1).get());
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full FT test and full RT test

@jmarrec
Copy link
Collaborator Author

jmarrec commented Sep 2, 2022

@joseph-robertson if you can take a quick look that'd be great. I'm going to merge it because we can fix whatever is needed on the 22.2.0-IOFreeze branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant