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
Conversation
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) |
There was a problem hiding this comment.
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.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new OS fields
/** Returns the ankle-level air velocity schedule. */ | ||
boost::optional<Schedule> ankleLevelAirVelocitySchedule() const; | ||
|
||
double coldStressTemperatureThreshold() const; | ||
bool isColdStressTemperatureThresholdDefaulted() const; | ||
|
||
double heatStressTemperatureThreshold() const; | ||
bool isHeatStressTemperatureThresholdDefaulted() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Methods
bool setAnkleLevelAirVelocitySchedule(Schedule& schedule); | ||
void resetAnkleLevelAirVelocitySchedule(); | ||
|
||
bool setColdStressTemperatureThreshold(double coldStressTemperatureThreshold); | ||
void resetColdStressTemperatureThreshold(); | ||
|
||
bool setHeatStressTemperatureThreshold(double heatStressTemperatureThreshold); | ||
void resetHeatStressTemperatureThreshold(); |
There was a problem hiding this comment.
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()}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ScheduleTypeRegistry entry
// 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); | ||
} |
There was a problem hiding this comment.
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
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()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FT new fields
// 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); |
There was a problem hiding this comment.
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
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); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RT new fields
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()); |
There was a problem hiding this comment.
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
…re we had made Thermal Conform Model extensible, so now we can't
d6bce42
to
76ca256
Compare
@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 |
85ad3a1
to
f7988f1
Compare
Pull request overview
People
: newAnkle Level Air Velocity Schedule Name
,Cold Stress Temperature Threshold
, andHeat Stress Temperature Threshold
fields #4668Pull Request Author
src/model/test
)src/energyplus/Test
)src/osversion/VersionTranslator.cpp
)Labels:
IDDChange
APIChange
Pull Request - Ready for CI
so that CI builds your PRReview Checklist
This will not be exhaustively relevant to every PR.