Skip to content

Fix #10944: unused EMS actuator warning never fires#11525

Open
brianlball wants to merge 2 commits intodevelopfrom
unused_actuator_warn
Open

Fix #10944: unused EMS actuator warning never fires#11525
brianlball wants to merge 2 commits intodevelopfrom
unused_actuator_warn

Conversation

@brianlball
Copy link
Copy Markdown
Contributor

@brianlball brianlball commented Apr 14, 2026

Summary

  • Fixes Provide a warning for unused actuators #10944 - end-of-sim warning for unused EMS actuators never fired.
  • Root cause: checkForUnusedActuatorsAtEnd checked ErlVariable.Value.initialized, but that flag has dual meaning: "safe to read as right-hand-side operand" AND "was SET by Erl program". Actuators get initialized=true early (inherited from the Null sentinel at registration) so the first meaning applies cleanly - but the guard read it as the second meaning and never tripped.
  • Fix: add a dedicated wasActuated bool on ActuatorUsedType. Set it only when the user's Erl program assigns a concrete value to the actuator (Type != Null in the post-ManageEMS actuator-update loop at EMSManager.cc:345). Check that flag in the end-of-sim guard. Leaves Value.initialized and the Null sentinel alone.

Why this approach (history)

First attempt flipped the Null sentinel's initialized flag to false. That seemed surgical but broke right-hand-side reads of actuators that hadn't been SET yet but had subsystem-provided defaults - the expression evaluator at RuntimeLanguageProcessor.cc:1800 reads the same flag to gate "is this variable safe to use in an expression." CI caught it via regressions in integration.EMSUserDefined5ZoneAirCooled and integration.PythonPluginUserDefined5ZoneAirCooled. The current fix matches Myoldmopar's original suggestion in the issue ("a simple flag on each actuator").

Call graph - issue & fix

BEFORE FIX
==========
  IDF: EMS:Actuator A1  +  EMS:Program "Set Al = 2" (typo, A1 untouched)
         |
  [EMSManager.cc:1988]  if (!ErlVariable[A1].Value.initialized)
                                                  ^^^^^^^^^^^
                        true (inherited from Null sentinel at setup)
                        so !true = false -> guard never passes
         v
  (no warning emitted)  X


AFTER FIX
=========
  ActuatorUsedType gains bool wasActuated = false  (default)

  [EMSManager.cc:345]  // post-ManageEMS actuator-update loop
    for each EMSActuatorUsed:
        if (ErlVar.Value.Type != Null) {                // user SET a concrete value
            thisActuatorUsed.wasActuated = true;        // <- NEW
            ...push value to component, set *Actuated=true...
        }

  [EMSManager.cc:1988]  if (!EMSActuatorUsed[i].wasActuated)     // <- NEW guard
         v
  ShowWarningError: "Unused EMS Actuator detected ... A1"  OK

  Null sentinel semantics: untouched.
  Value.initialized semantics (right-hand-side readability): untouched.

Files changed

  • src/EnergyPlus/DataRuntimeLanguage.hh - add wasActuated field on ActuatorUsedType
  • src/EnergyPlus/EMSManager.cc - set the flag in the actuator-update else branch; check it in the end-of-sim guard
  • tst/EnergyPlus/unit/EMSManager.unit.cc - new UnusedActuatorWarning test

Test plan

  • New EnergyPlusFixture.UnusedActuatorWarning asserts warning fires for unused actuator
  • Full unit test suite post-fix: 2213 tests passed, 0 failures
  • integration.EMSUserDefined5ZoneAirCooled: passes locally (was the CI regression in the prior attempt)
  • All 18 integration.EMS* tests: pass
  • pre-commit (clang-format v19, constexpr, license): clean
  • scripts/check_gcc_warnings.py src/EnergyPlus/EMSManager.cc: clean

IDF with actuator A1 + program `Set Al = 2` (typo).
Expect err stream contains "Unused EMS Actuator detected A1"
after checkForUnusedActuatorsAtEnd; stream is empty on develop.

Fails on current source - verifies the gap.
@brianlball brianlball added the Defect Includes code to repair a defect in EnergyPlus label Apr 14, 2026
@brianlball brianlball force-pushed the unused_actuator_warn branch from 1179f5f to 2469735 Compare April 14, 2026 15:22
@brianlball brianlball added the DoNotMerge Code that requires additional attention and investigation label Apr 14, 2026
Prior attempt flipped Null sentinel initialized=false, which
broke right-hand-side reads of actuators that hadn't been SET
yet but had subsystem-provided default values (regressed
EMSUserDefined5ZoneAirCooled, PythonPluginUserDefined5ZoneAirCooled).
Value.initialized has dual meaning - both "safe to read as
right-hand-side operand" and "was SET by Erl" - so co-opting
it for the warning check was wrong.

Per Myoldmopar's suggestion in the issue, add a dedicated
`wasActuated` bool on ActuatorUsedType. Set it in the
EMSManager.cc post-ManageEMS actuator-update loop (else branch
where Type != Null, i.e. user SET a concrete value). Check it
in checkForUnusedActuatorsAtEnd instead of Value.initialized.
Leaves Null sentinel and Value.initialized semantics untouched.
@brianlball brianlball force-pushed the unused_actuator_warn branch from 2469735 to e91fc19 Compare April 14, 2026 16:17
@NatLabRockies NatLabRockies deleted a comment from github-actions bot Apr 14, 2026
@NatLabRockies NatLabRockies deleted a comment from github-actions bot Apr 14, 2026
@NatLabRockies NatLabRockies deleted a comment from github-actions bot Apr 14, 2026
@NatLabRockies NatLabRockies deleted a comment from github-actions bot Apr 14, 2026
@github-actions
Copy link
Copy Markdown

⚠️ Regressions detected on ubuntu-24.04 for commit 87694ef

Regression Summary
  • ERR: 13

@brianlball
Copy link
Copy Markdown
Contributor Author

image

@brianlball
Copy link
Copy Markdown
Contributor Author

brianlball commented Apr 14, 2026

Regression diffs — all expected, warning working as intended

The regression tool flagged 13 files with diffs. All 13 are ERR-file-only — no ESO, no tabular, no SQL. Simulation output values are identical to develop baseline across all 13. The diffs are purely the new Unused EMS Actuator detected warning firing on actuators declared in these IDFs that no Erl program ever SETs — exactly what #10944 is asking this warning to catch.

Pattern breakdown

Cluster Unused actuator names Files (count × warns) Nature
Apartment/hotel setpoint templates S_APARTMENT_CLGSETP_ACTUATOR, S_APARTMENT_HTGSETP_ACTUATOR, S_GUESTROOM_CLGSETP_ACTUATOR, S_GUESTROOM_HTGSETP_ACTUATOR ApartmentHighRise ×4, ApartmentMidRise ×4, HotelSmall ×4 Prototype-building boilerplate: Schedule:Compact setpoint actuators declared for a family of spaces, only a subset driven
Hospital extra water heat SPs PATRMS_EXTRAWATERHEATC_SP, ER_EXTRAWATERHEATC_SP (+3 more) Hospital ×5 System Node Setpoint actuators declared but unused
OfficeLarge chiller pump flow CHILLER1PUMPFLOW OfficeLarge ×1, _Chiller205 ×1, _Chiller205_Detailed ×1, _ChillerEIR ×1 Shared root IDF; 4 chiller-variant tests inherit one orphan
Restaurant lights DINING_LIGHT_ACTUATOR, KITCHEN_LIGHT_ACTUATOR RestaurantFastFood ×2, RestaurantSitDown ×2 Lights actuators declared as scaffolding
EMS demand/manager demos HEATSYS1_BOILER_SETPOINT EMSDemandManager_LargeOffice ×1, EMSReplaceTraditionalManagers_LargeOffice ×1 Demo IDF with a declared-but-never-SET boiler setpoint actuator
Python plugin variant (not run locally) PythonPluginUserDefinedWindACAuto Almost certainly same flavor — IDF declares actuator, Python setActuatorValue takes over bypassing Erl

Sample hit (EMSDemandManager_LargeOffice)

** Warning ** checkForUnusedActuatorsAtEnd: Unused EMS Actuator detected...
**   ~~~   ** Check Erl programs related to EMS actuator variable name = HEATSYS1_BOILER_SETPOINT
**   ~~~   ** EMS Actuator type name = SYSTEM NODE SETPOINT
**   ~~~   ** EMS Actuator unique component name = HEATSYS1 SUPPLY EQUIPMENT OUTLET NODE
**   ~~~   ** EMS Actuator control type = TEMPERATURE SETPOINT

Conclusion

Keeping the warnings as-is. Each flagged actuator is a genuine declared-but-unused case. If the corpus authors meant these as placeholders, the warning now documents that; if they're dead, it flags them for cleanup. Either way, this is the fix working on real-world data.

@brianlball brianlball removed the DoNotMerge Code that requires additional attention and investigation label Apr 14, 2026
@github-actions
Copy link
Copy Markdown

⚠️ Regressions detected on macos-14 for commit 87694ef

Regression Summary
  • ERR: 13

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.

Provide a warning for unused actuators

1 participant