-
Notifications
You must be signed in to change notification settings - Fork 400
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
Schedule API #10848
Schedule API #10848
Conversation
|
auto &s_sched = state.dataSched; | ||
for (int i = 0; i < (int)s_sched->scheduleTypes.size(); ++i) if (s_sched->scheduleTypes[i]->Name == name) return i; | ||
return -1; | ||
} |
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.
[src/EnergyPlus/ScheduleManager.cc:99]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:227]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:241]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:273]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:385]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2409]:(style),[constParameterReference],Parameter 'state' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2497]:(style),[constParameterReference],Parameter 'state' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2502]:(style),[constParameterReference],Parameter 'state' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2515]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2553]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2587]:(style),[constVariableReference],Variable 's_sched' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2725]:(style),[constParameterReference],Parameter 'state' can be declared as reference to const
[src/EnergyPlus/ScheduleManager.cc:2978]:(style),[constVariableReference],Variable 's_glob' can be declared as reference to const
I noticed that Schedule Value was added to the rdd for 1ZoneUncontrolled_win_1.idf. There are no schedules in that file. There is a ScheduleTypeLimits object.
The error file shows there are 2 unused schedules:
|
Hmmmm. I think I know what this is, but I will verify after I am done looking at something more serious. In this refactor, |
|
|
|
|
|
|
…e vectors and not just arrays
|
|
|
|
src/EnergyPlus/RefrigeratedCase.cc
Outdated
@@ -2242,7 +2242,7 @@ void GetRefrigerationInput(EnergyPlusData &state) | |||
} | |||
|
|||
++AlphaNum; // A6 | |||
if (lAlphaBlanks(AlphaNum)) { | |||
if (!lAlphaBlanks(AlphaNum)) { |
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.
What's this?
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.
I was trying to bisect something I was seeing locally so I reverted this line. I didn't work.
|
|
@@ -852,7 +852,7 @@ | |||
Until: 24:00,23.89, !- Field 23 | |||
For: Sunday Holidays AllOtherDays, !- Field 25 | |||
Until: 8:00,29.44, !- Field 26 | |||
Until: 8:00,26.67, !- Field 28 | |||
Until: 8:00,26.67, !- Field 28 Is this supposed to be 9:00? |
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.
Given the occupancy schedule pattern for Type1, Type2 and Type3 where Type1 occupancy occurs at 8 AM this look correct.
Schedule:Compact,
Type1_OCC_SCH, !- Name
For: Sunday Holidays AllOtherDays, !- Field 50
Until: 08:00,0.0, !- Field 51
Until: 10:00,0.05, !- Field 53
Schedule:Compact,
Type2_OCC_SCH, !- Name
For: Sunday Holidays AllOtherDays, !- Field 52
Until: 09:00,0.0, !- Field 53
Until: 10:00,0.05, !- Field 55
Schedule:Compact,
Type3_OCC_SCH, !- Name
For: Sunday Holidays AllOtherDays, !- Field 62
Until: 10:00,0.0, !- Field 63
Until: 11:00,0.11, !- Field 65
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.
It does? Two consecutive "Until 8:00, X" statements is correct? At the very least one of them is redundant. Which one though?
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.
Two consecutive "Until 8:00, X" statements is NOT correct input syntax (but it doesn't hurt anything). The point is that the 2nd 8:00 should not be 9:00 since occupancy starts at 8:00. I think the developer noticed that occupancy started at 8:00 and simply changed the time on the 2nd line from 9 to 8. So the question is did the developer want 29.44 C or 26.67 C as the Tstat temp from midnight to 8:00? Either way the occupied Tstat setting of 23.89 C should begin at 8:00.
For: Sunday Holidays AllOtherDays, !- Field 25
Until: 8:00,29.44, !- Field 26
Until: 8:00,26.67, !- Field 28
Until: 23:00,23.89, !- Field 30
Until: 24:00,23.89; !- Field 32
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.
Or maybe the first Until 8:00
should really be Until 7:00
?
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.
Using Until 7:00
for the Type 1 Tstat schedules (Type1_CLGSETP_*) would be consistent with Type 2 and Type 3 cooling set point schedules.
Schedule:Compact,
Type1_CLGSETP_SCH_YES_OPTIMUM, !- Name
For: Sunday Holidays AllOtherDays, !- Field 25
Until: 8:00,29.44, !- Field 26
Until: 8:00,26.67, !- Field 28
Schedule:Compact,
Type2_CLGSETP_SCH_YES_OPTIMUM, !- Name
For: Sunday Holidays AllOtherDays, !- Field 23
Until: 8:00,29.44, !- Field 24
Until: 9:00,26.67, !- Field 26
Schedule:Compact,
Type3_CLGSETP_SCH_YES_OPTIMUM, !- Name
For: Sunday Holidays AllOtherDays, !- Field 23
Until: 9:00,29.44, !- Field 24
Until: 10:00,26.67, !- Field 26
|
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.
This is not a detailed walk-through, because a detailed one would take 5X comments (mostly in the Schedule and ZoneTempPredictorCorrector modules). Hopefully, it's enough. Most of the changes are just templates repeated over and over and over again. How schedule pointers are set up in IDF objects. How errors in schedule pointers or limits are printed. How schedule values are read. Rinse. Repeat.
@@ -457,6 +457,8 @@ namespace AirLoopHVACDOAS { | |||
++AirLoopDOASNum; | |||
AirLoopDOAS thisDOAS; | |||
|
|||
ErrorObjectHeader eoh{routineName, cCurrentModuleObject, thisObjectName}; |
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.
You're going to see a lot of this as all of the new schedule handling code uses this error reporting pattern.
@@ -117,7 +117,7 @@ namespace AirLoopHVACDOAS { | |||
|
|||
int m_AirLoopDOASNum = 0; | |||
int m_OASystemNum = 0; | |||
int m_AvailManagerSchedPtr = 0; | |||
Sched::Schedule *m_AvailManagerSched = nullptr; |
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.
Oh the irony. No more int SchedPtr
, int SchedIndex
, int SchedPtrIdx
, int Sch
, only Sched::Schedule *xSched = nullptr;
@@ -184,6 +184,10 @@ struct AirLoopHVACDOASData : BaseGlobalStruct | |||
std::vector<AirLoopHVACDOAS::AirLoopMixer> airloopMixer; | |||
std::vector<AirLoopHVACDOAS::AirLoopSplitter> airloopSplitter; | |||
|
|||
void init_constant_state([[maybe_unused]] EnergyPlusData &state) override |
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.
This hook initializes builtin state, which for schedules includes the AlwaysOn
and AlwaysOff
schedule objects.
if (this->availScheduleIndex == 0) { | ||
ShowSevereError(state, std::string{routineName} + state.dataCoilCooingDX->coilCoolingDXObjectName + "=\"" + this->name + "\", invalid"); | ||
ShowContinueError(state, "...Availability Schedule Name=\"" + input_data.availability_schedule_name + "\"."); | ||
this->availSched = Sched::GetScheduleAlwaysOn(state); |
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.
This is how you get the AlwaysOn
schedule object.
@@ -215,7 +214,7 @@ void CoilCoolingDXCurveFitPerformance::simulate(EnergyPlus::EnergyPlusData &stat | |||
Real64 LoadSHR) | |||
{ | |||
static constexpr std::string_view RoutineName = "CoilCoolingDXCurveFitPerformance::simulate"; | |||
Real64 reportingConstant = state.dataHVACGlobal->TimeStepSys * Constant::SecInHour; | |||
Real64 reportingConstant = state.dataHVACGlobal->TimeStepSys * Constant::rSecsInHour; |
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.
Oh, this is important too. For SecsInHour
, MinutesInDay
, etc. there are now both r
and i
variants. The i
variants are used as indices in schedules or for loops. The r
variants are in products with physical quantities. Just saves an integer-to-real conversion.
|
||
ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)}; | ||
|
||
if (s_sched->dayScheduleMap.find(Alphas(1)) != s_sched->dayScheduleMap.end()) { |
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.
Instead of using std::unordered_map
to check for duplicate names but then finding the indices of existing objects using linear search, why not use a single std::map
to do both?
ControlTypeNum, | ||
TempControlledZone.ControlTypeSchedName)); | ||
ShowContinueError(state, "..valid range values are [0,4]."); | ||
for (HVAC::SetptType setptType : HVAC::setptTypes) { |
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.
Each temperature controlled zone only has four possible thermostats (one of each type) and they are tracked in this fixed-size std::array
, not need to track them via separate lists that track not only thermostat existence but thermostat type.
EPVector<ZoneTempPredictorCorrector::ZoneComfortFangerControl> SetPointSingleHeatingFanger; | ||
EPVector<ZoneTempPredictorCorrector::ZoneComfortFangerControl> SetPointSingleCoolingFanger; | ||
EPVector<ZoneTempPredictorCorrector::ZoneComfortFangerControl> SetPointSingleHeatCoolFanger; | ||
EPVector<ZoneTempPredictorCorrector::ZoneComfortFangerControl> SetPointDualHeatCoolFanger; |
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.
All of this separate list tracking is not necessary.
@@ -4035,6 +4034,8 @@ TEST_F(EnergyPlusFixture, AirLoopHVACDOASTest) | |||
|
|||
ASSERT_TRUE(process_idf(idf_objects)); | |||
|
|||
state->init_state(*state); |
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.
call init_state()
after process_idf()
to construct objects specified in the IDF file. For now, init_state()
only constructs schedule and fluid properties objects, all other objects are still construced "on first use" by the ubiquitous if (state.dataX->GetInput) { GetXInput(state); state.dataX->GetInput = false; }
pattern. Incrementally, more object types will be constructed this way.
@@ -4132,7 +4131,8 @@ TEST_F(EnergyPlusFixture, AirLoopHVACDOASTest) | |||
|
|||
state->dataEnvrn->OutBaroPress = 101325.0; | |||
|
|||
state->dataScheduleMgr->Schedule(1).CurrentValue = 1.0; // set availability and fan schedule to 1 | |||
auto *sched = Sched::GetSchedule(*state, "ALWAYS_ON"); |
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.
Don't rely on position to manipulate schedules created by IDF snippets, use the schedule name. It's a little slower, but this is a unit test so speed doesn't matter and it's much more robust and transparent.
All unit test change are of this form.
|
|
Alright, there is now just one unit test failing...not sure what that's about yet. Otherwise it's just regressions. I can summarize what I see locally for regressions: Text Files
Table Diffs
Math Diffs
So I think all that is left here is confirming the ERR diffs are expected, or if we should do any final work there, and then fixing the one failing unit test that GitHub is showing on Mac (Apple Silicon). |
|
Look at that, all green! OK, this is dropping in. Thanks @amirroth for the huge refactor here. I'll be happy to help anyone with their branches containing conflicts after this merge. |
Alright, buckle up. This mother of all PRs (at least to this point). It just grew and grew and grew and if it doesn't get merged soon, it's probably going to grow even more.
The main change in this PR is the transition of the
Schedule
API from a procedural one to an object-oriented one. Specifically,GetScheduleCurrentValue(state, schedIndex, errorsFound)
has been replace withsched->getCurrentValue()
everywhere. And it turns out that everywhere is a lot.The switch from a procedural index-based API to an object-oriented API is predicated on the ability to create objects before their first use. This is enabled by the
dataX->init_state()
methods which call the correspondingGetXInput()
functions at the beginning of the simulation rather than starting every function with a guardedif (state.dataX->GetInputFlag) { GetXInput(state); state.dataX->GetInputFlag = false; }
call. Thestate.dataSchedule->init_state()
method has been moved to the front portion of thestate->init_state()
method and now callsGetScheduleInput()
.And additional change that relates to both of these is that the commonly used
AlwaysOn
andAlwaysOff
fake schedule indices (-1
and0
) have been eliminated.AlwaysOn
andAlwaysOff
are now actual schedule objects and can use thesched->getCurrentValue()
. These schedules are built-in and can be accessed via theGetSchedAlwaysOn(state)
andGetSchedAlwaysOff(state)
functions.Because of the frequent need for these schedules, the
init_state()
function was split into two,init_constant_state()
andinit_state()
, the former constructs built-in objects that do not appear in the input file. The latter constructs objects that appear in the input file. ForSchedule
,init_constant_state()
constructs theScheduleAlwaysOn
andScheduleAlwaysOff
objects. For FluidProperties, it constructs theWater
andSteam
objects. This split simplifies unit testing.One other significant change that was pulled into this PR is a revision of the zone SetPoint schedule framework. The existing framework was quite complicated and included at least one unnecessary level of indirection, and in some places two levels. Conceptually, the structure here is fairly straightforward. There are four types of setpoint schedules
Heat
,Cool
,SingleHeatCool
, andDualHeatCool
and a control schedule that toggles between them. That framework has been simplified.The other changes have to do with naming conventions. All schedule object pointers are now called
xSched
and specifically all availablity schedule pointers calledavailSched
. The namespace name has been shortened fromScheduleManager
toSched
although it appears far less frequently with an object-oriented API than with a procedural API.A final note about unit tests. Previously, unit test schedule values were accessed and over-written by schedule index. But this is brittle because it relies on the order in which Schedule object definitions appeared in the IDF snippet. It's also not very readable. Those were changed to
GetSched(state, "name")->currVal = 1.0
(or whatever it is). A bit slower, yes, but speed doesn't matter for unit tests and this is more readable and robust.There are diffs, and they fall into five categories:
PlantLoopHeatPump_EIR_AirSource_Hospital_wSixPipeHeatRecovery
), that we (mostly @rraustad working on this) have not been able to track down. These large diffs do not result in large table diffs. I say we go ahead and merge this anyway. This is a big baby and only a teaspoon of bathwater.