Skip to content

Conversation

@jmarrec
Copy link
Contributor

@jmarrec jmarrec commented May 20, 2025

Pull request overview

Description of the purpose of this PR

This PR reverts to the 24.2.0 functionality which catches these errors during the GetInput (GetZoneAirSetPoints).

The Defect file, when run with this PR will no longer segfault, but will Fatal out as expected, as was done in 24.2.0

   ** Warning ** processZoneEquipmentInput: ZoneHVAC:EquipmentList = LIVING_EQUIPMENT
   **   ~~~   ** ...zero assigned to Zone Equipment Heating or No-Load Sequence=1, apparent gap in sequence assignments in this equipment list.
   ** Severe  ** Control Type Schedule=ALWAYS_ON
   **   ~~~   ** ..specifies 1 (ThermostatSetpoint:SingleHeating) as the control type. Not valid for this zone.
   **   ~~~   ** ..reference ZoneControl:Thermostat=THERMOSTAT_LIVING
   **   ~~~   ** ..reference ZONE=LIVING
   ** Severe  ** GetStagedDualSetpoint: Errors with invalid names in ZoneControl:Thermostat:StagedDualSetpoint objects.
   **   ~~~   ** ...These will not be read in.  Other errors may occur.
   **  Fatal  ** Errors getting Zone Control input data.  Preceding condition(s) cause termination.

Pull Request Author

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies

Reviewer

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • 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
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

@jmarrec jmarrec self-assigned this May 20, 2025
@jmarrec jmarrec added the Defect Includes code to repair a defect in EnergyPlus label May 20, 2025
Comment on lines +1106 to +1116
"ZoneControl:Thermostat,",
" Zone1 Thermostat, !- Name",
" Zone1, !- Zone or ZoneList Name",
" Single HEATING Control Type Sched, !- Control Type Schedule Name",
" ThermostatSetpoint:SingleCooling, !- Control 1 Object Type",
" Thermostat Setpoint Single Cooling; !- Control 1 Name",

"Schedule:Constant,",
" Single HEATING Control Type Sched, !- Name",
" Control Type, !- Schedule Type Limits Name",
" 1; !- Hourly Value", // <-------- 1 = Single Heating, which is WRONG
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Test reproduces the defect

Comment on lines 1149 to 1171
GetZoneData(*state, ErrorsFound);
ASSERT_FALSE(ErrorsFound);

EXPECT_THROW(GetZoneAirSetPoints(*state), EnergyPlus::FatalError);
std::string const error_string = delimited_string({
" ** Severe ** Control Type Schedule=SINGLE HEATING CONTROL TYPE SCHED",
" ** ~~~ ** ..specifies 1 (ThermostatSetpoint:SingleHeating) as the control type. Not valid for this zone.",
" ** ~~~ ** ..reference ZoneControl:Thermostat=ZONE1 THERMOSTAT",
" ** ~~~ ** ..reference ZONE=ZONE1",
" ** Severe ** GetStagedDualSetpoint: Errors with invalid names in ZoneControl:Thermostat:StagedDualSetpoint objects.",
" ** ~~~ ** ...These will not be read in. Other errors may occur.",
" ** Fatal ** Errors getting Zone Control input data. Preceding condition(s) cause termination.",
" ...Summary of Errors that led to program termination:",
" ..... Reference severe error count=2",
" ..... Last severe error=GetStagedDualSetpoint: Errors with invalid names in ZoneControl:Thermostat:StagedDualSetpoint objects.",
});
EXPECT_TRUE(compare_err_stream(error_string, true));
// Avoid calling InitZoneAirSetPoints(*state); but still initialize needed arrays
state->dataHeatBalFanSys->TempControlType.allocate(1);
state->dataHeatBalFanSys->TempControlTypeRpt.allocate(1);
state->dataHeatBalFanSys->zoneTstatSetpts.allocate(1);

CalcZoneAirTempSetPoints(*state);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Initially

/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1152: Failure
Expected: GetZoneAirSetPoints(*state) throws an exception of type EnergyPlus::FatalError.
  Actual: it throws nothing.
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/Fixtures/EnergyPlusFixture.cc:211: Failure
Expected equality of these values:
  expected_string
    Which is: "\n"
  stream_str
    Which is: ""
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1154: Failure
Value of: compare_err_stream(error_string, true)
  Actual: false
Expected: true
Process 92525 stopped
* thread #1, name = 'energyplus_test', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x4c)
    frame #0: 0x0000555556fc818a energyplus_tests`EnergyPlus::Sched::Schedule::getCurrentVal(this=0x0000000000000000) const at ScheduleManager.hh:275:20
   272
   273 	        Real64 getCurrentVal() const
   274 	        {
-> 275 	            return EMSActuatedOn ? EMSVal : currentVal;
   276 	        }
   277
   278 	        // Looks up a given Schedule value for an hour & timestep, minding whether DST is enabled or not

Comment on lines 703 to 732
for (HVAC::SetptType setptType : HVAC::setptTypes) {
auto const &setpt = tempZone.setpts[(int)setptType];
if (!setpt.isUsed) continue;

if (!setpt.isUsed) {
// Catch early issues
if (tempZone.setptTypeSched->hasVal(state, (int)setptType)) {
ShowSevereError(state, format("Control Type Schedule={}", tempZone.setptTypeSched->Name));
ShowContinueError(
state,
format("..specifies {} ({}) as the control type. Not valid for this zone.", (int)setptType, setptTypeNames[(int)setptType]));
ShowContinueError(state, format("..reference {}={}", cZControlTypes((int)ZoneControlTypes::TStat), tempZone.Name));
ShowContinueError(state, format("..reference ZONE={}", tempZone.ZoneName));
ErrorsFound = true;
}
continue;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fix:

  • if !setpt.isUsed but setptTypeSched hasVal => throw

@jmarrec jmarrec changed the title FIx #11026 - Bad thermostat control type value results in crash due to null schedule pointer Fix #11026 - Bad thermostat control type value results in crash due to null schedule pointer May 20, 2025
@jmarrec jmarrec force-pushed the 11026_Bad_Thermostat_Control_Type branch from c900f8a to e1f17a1 Compare May 22, 2025 13:10
jmarrec added 7 commits May 23, 2025 17:33
```shell
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1152: Failure
Expected: GetZoneAirSetPoints(*state) throws an exception of type EnergyPlus::FatalError.
  Actual: it throws nothing.
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/Fixtures/EnergyPlusFixture.cc:211: Failure
Expected equality of these values:
  expected_string
    Which is: "\n"
  stream_str
    Which is: ""
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1154: Failure
Value of: compare_err_stream(error_string, true)
  Actual: false
Expected: true
Process 92525 stopped
* thread #1, name = 'energyplus_test', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x4c)
    frame #0: 0x0000555556fc818a energyplus_tests`EnergyPlus::Sched::Schedule::getCurrentVal(this=0x0000000000000000) const at ScheduleManager.hh:275:20
   272
   273 	        Real64 getCurrentVal() const
   274 	        {
-> 275 	            return EMSActuatedOn ? EMSVal : currentVal;
   276 	        }
   277
   278 	        // Looks up a given Schedule value for an hour & timestep, minding whether DST is enabled or not
```
setptTypes was sized to 5 element, but only 4 were explicitly declared in the initializer. The 5th is zero initialized, which added SetptType::Uncontrolled

cf https://godbolt.org/z/jbbzc9hnn
@jmarrec jmarrec force-pushed the 11026_Bad_Thermostat_Control_Type branch from 87f404a to c37009f Compare May 23, 2025 15:38
@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 0b04a3d

Regression Summary
  • Table Big Diffs: 3

@jmarrec jmarrec requested a review from Myoldmopar May 26, 2025 10:23
@jmarrec
Copy link
Contributor Author

jmarrec commented May 26, 2025

Not sure what the macos-14 regression are tripping on.

image

Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

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

This looks great. Catching the control type value looks fine and the unit tests look sufficient.

ShowContinueError(state, format("..reference {}={}", cZControlTypes((int)ZoneControlTypes::TStat), tempZone.Name));
ShowContinueError(state, format("..reference ZONE={}", tempZone.ZoneName));
ErrorsFound = true;
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm trying to think about what happens if someone uses an API actuator to adjust the schedule value later. I know there are probably lots of places in the code that this could cause some issues, so not necessarily saying we need to do anything here, just thinking about possible impacts.

@Myoldmopar
Copy link
Member

Looking good here, merging this. Thanks @jmarrec

@Myoldmopar Myoldmopar merged commit ab397a3 into develop May 28, 2025
9 checks passed
@Myoldmopar Myoldmopar deleted the 11026_Bad_Thermostat_Control_Type branch May 28, 2025 14:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Defect Includes code to repair a defect in EnergyPlus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bad thermostat control type value results in crash due to null schedule pointer

5 participants