Skip to content

EMS actuator for Coil:Heating:DX:SingleSpeed gross rated heating capacity#11527

Open
brianlball wants to merge 4 commits intodevelopfrom
heating_dx_gross_cap_actuator
Open

EMS actuator for Coil:Heating:DX:SingleSpeed gross rated heating capacity#11527
brianlball wants to merge 4 commits intodevelopfrom
heating_dx_gross_cap_actuator

Conversation

@brianlball
Copy link
Copy Markdown
Contributor

Summary

Resolves #11301. Adds an EMS actuator named Autosized Rated Total Heating Capacity on Coil:Heating:DX:SingleSpeed, mirroring the existing Autosized Rated Total Cooling Capacity actuator on Coil:Cooling:DX:SingleSpeed. Enables EMS programs to override the autosized gross heating capacity — primary use case: dual-fuel forced-air systems where the heat pump is sized to cooling capacity and the supplemental gas coil carries full heating capacity.

What changed

  • src/EnergyPlus/DXCoils.cc — adds a second loop inside the existing if (AnyEnergyManagementSystemInModel) block in GetDXCoils, iterating heating-single-speed indices and registering one SetupEMSActuator call. ~12 LOC.
  • The override plumbing was already in place: RatedTotCapEMSOverrideOn/Value(1) are members of the shared DXCoilData struct and are already consumed by HeatingCapacitySizer in SizeDXCoil (the Mode check at DXCoils.cc:7769 already includes HeatingDXSingleSpeed). Only the SetupEMSActuator registration was missing.

Call graph

GetDXCoils
  └─ if (AnyEnergyManagementSystemInModel)
       ├─ for cooling-single-speed coils: register 3 actuators  (existing)
       └─ for heating-single-speed coils: register 1 actuator   (new, #11301)
            └─ SetupEMSActuator("Coil:Heating:DX:SingleSpeed",
                                thisDXCoil.Name,
                                "Autosized Rated Total Heating Capacity",
                                "[W]",
                                thisDXCoil.RatedTotCapEMSOverrideOn(1),
                                thisDXCoil.RatedTotCapEMSOverrideValue(1))

SizeDXCoil
  └─ DataEMSOverrideON  = thisDXCoil.RatedTotCapEMSOverrideOn(Mode)       (pre-existing)
     DataEMSOverride    = thisDXCoil.RatedTotCapEMSOverrideValue(Mode)    (pre-existing)
     if (HeatingDXSingleSpeed or ...) HeatingCapacitySizer.size()         (pre-existing)

Naming rationale

  • Parallels cooling sibling Autosized Rated Total Cooling Capacity.
  • Consistent with the internal sizer label Rated Total Heating Capacity used in HeatingCapacitySizing.cc:184 and WaterHeatingCapacitySizing.cc:113.

Test plan

  • Unit test EnergyPlusFixture.CoilHeatingDXSingleSpeed_GrossCapacityActuator in tst/EnergyPlus/unit/DXCoils.unit.cc — scans EMSActuatorAvailable after GetDXCoils and asserts the heating actuator is registered with correct units and name. Test-red without the fix, test-green with it (separate commits for verification).
  • Integration test EMSHeatingDXSingleSpeedCapacityOverride.idf — derived from HeatPumpAuto.idf; EMS program overrides capacity to 7500 W at AfterComponentInputReadIn. EIO confirms User-Specified Gross Rated Heating Capacity [W], 7500.00000 (vs autosize without override). DESIGN_DAY_ONLY.
  • Regression: all 474 DX/Coil/Heat/Cool unit tests pass; all 92 EMS/sizing unit tests pass.
  • Pre-commit (clang-format v19, constexpr, license, IDD) and gcc-warning script clean on touched files.

Docs

  • doc/readthedocs/sphinx/ems-application-guide/ems-application-guide.rst — new paragraph under DX Heating Coils describing the actuator and its calling point.

…capacity

Issue #11301: scan EMSActuatorAvailable after GetDXCoils for the
heating sibling of Autosized Rated Total Cooling Capacity; fails because
the actuator is not yet registered.
Issue #11301: adds Autosized Rated Total Heating Capacity [W] actuator
at the end of GetDXCoils, parallel to the existing cooling sibling.
RatedTotCapEMSOverrideOn/Value(1) are already consumed by
HeatingCapacitySizer in SizeDXCoil, so only the registration was missing.
Issue #11301: new EMSHeatingDXSingleSpeedCapacityOverride.idf derived
from HeatPumpAuto.idf exercises the new actuator end-to-end; EIO shows
User-Specified 7500 W (vs autosize). EMS application guide gains a
paragraph under DX Heating Coils mirroring the cooling sibling.
@brianlball brianlball added the NewFeature Includes code to add a new feature to EnergyPlus label Apr 14, 2026
@github-actions
Copy link
Copy Markdown

⚠️ Regressions detected on ubuntu-24.04 for commit a93b58a

Regression Summary
  • Audit: 3
  • EDD: 2

@brianlball
Copy link
Copy Markdown
Contributor Author

Regression diff explanation (CI run 24415448969)

The `Process completed with exit code 1` annotation is from `gha_regressions.py`, which exits non-zero on any diff but is informational on fork PRs (the "Fail on Regressions from Forked Repository" step is skipped, so the job conclusion is ✓ `success`).

Three IDFs show diffs, all of which are the expected mechanical side-effect of registering one new EMS actuator per `Coil:Heating:DX:SingleSpeed`:

IDF # heating SS coils `audit.diff` `edd.diff` `tbl.*.htm`
`ASHRAE901_OfficeSmall_STD2019_Denver` 5 `numEMSActuatorsAvailable` 1667→1672 (+5) all cells `class="equal"`, value 0
`EMSCurveOverride_PackagedTerminalHeatPump` 3 558→561 (+3) +3 new actuator lines all equal, 0
`PythonPluginCurveOverride_PackagedTerminalHeatPump` 3 558→561 (+3) +3 new actuator lines all equal, 0

The delta in `numEMSActuatorsAvailable` equals the count of `Coil:Heating:DX:SingleSpeed` objects in each IDF. The added `eplusout.edd` lines are all of the form:

```
EnergyManagementSystem:Actuator Available,<HEATING_COIL_NAME>,Coil:Heating:DX:SingleSpeed,Autosized Rated Total Heating Capacity,[W]
```

No simulation-behavior changes (all `tbl` comparison cells are `equal`/0). No ESO, SQL, or tabular numerical diffs. The actuator is only consumed when an EMS program binds to it, and none of these IDFs do.

These diffs are safe to merge.

@github-actions
Copy link
Copy Markdown

⚠️ Regressions detected on macos-14 for commit a93b58a

Regression Summary
  • Audit: 3
  • EDD: 2

Issue #11301: clarify the implicit parse-order array layout in DXCoils.hh
(cooling single-speed first, heating single-speed next, etc.) and annotate
the heating actuator loop with the same note.

New unit test registers 2 cooling + 2 heating single-speed coils and
verifies each capacity actuator's UniqueIDName matches the correct coil
and no cross-wiring occurs between cooling and heating ComponentTypeName.
@brianlball brianlball force-pushed the heating_dx_gross_cap_actuator branch from 8e9a234 to 8c3162b Compare April 14, 2026 20:04
@github-actions
Copy link
Copy Markdown

⚠️ Regressions detected on macos-14 for commit 6337a1c

Regression Summary
  • Audit: 3
  • EDD: 2

@github-actions
Copy link
Copy Markdown

⚠️ Regressions detected on ubuntu-24.04 for commit f21d579

Regression Summary
  • Audit: 3
  • EDD: 2

@github-actions
Copy link
Copy Markdown

⚠️ Regressions detected on macos-14 for commit f21d579

Regression Summary
  • Audit: 3
  • EDD: 2

@brianlball brianlball requested a review from Copilot April 14, 2026 21:00
@brianlball brianlball review requested due to automatic review settings April 14, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

NewFeature Includes code to add a new feature to EnergyPlus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EMS actuator is not available for the Gross Capacity field for the Heating:DX:SingleSpeed object

2 participants