NatLabRockies / NatLabRockies/OpenStudio
ForwardTranslator writes an uninitialized/garbage value into "DX Heating Coil Sizing Ratio" for ZoneHVAC:PackagedTerminalHeatPump, at scale, in the pip openstudio 3.11.0 SDK
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 646
- Forks
- 237
- Avg merge
- 3d 11h
- Merged PRs (30d)
- 10
Description
Description
See https://github.com/openstudiocoalition/OpenStudioApplication/issues/890 filed by @jmcaamanog for details
When openstudio.energyplus.ForwardTranslator translates an .osm model containing a large
number (~49, confirmed) of ZoneHVAC:PackagedTerminalHeatPump objects, it writes an invalid,
apparently-uninitialized value (4.94065645841247e-324, i.e. std::numeric_limits<double>::denorm_min()
— a classic "read of unset/garbage memory" pattern) into the optional field "DX Heating Coil
Sizing Ratio" of the resulting IDF ZoneHVAC:PackagedTerminalHeatPump object. EnergyPlus then
rejects the value outright ("is not a valid Object Type") and the simulation terminates with a
Fatal Error before running.
This reproduces consistently and only with the pip openstudio 3.11.0 wheel
(pip install openstudio==3.11.0). It does not reproduce with the openstudio-3.10.0 CLI
(openstudio.exe, bundled EnergyPlus 25.1.0) translating the exact same model. Both environments
bundle the same EnergyPlus release (25.1.0), so the difference is in the OpenStudio
ForwardTranslator/model library itself between these two builds, not in EnergyPlus.
Current Behavior
During ForwardTranslator.translateModel(model) (pip 3.11.0), repeated for every affected PTHP
object:
[BOOST_ASSERT] <2> Assertion value failed on line 362 of double __cdecl
openstudio::model::detail::ZoneHVACPackagedTerminalHeatPump_Impl::dXHeatingCoilSizingRatio(void)
const in file D:\a\OpenStudio\OpenStudio\src\model\ZoneHVACPackagedTerminalHeatPump.cpp.
The resulting IDF ZoneHVAC:PackagedTerminalHeatPump object then contains:
, !- Capacity Control Method
, !- Minimum Supply Air Temperature in Cooling Mode {C}
, !- Maximum Supply Air Temperature in Heating Mode {C}
4.94065645841247e-324; !- DX Heating Coil Sizing Ratio
EnergyPlus then fails at the GetSurfaceData/IDD-parsing stage (or later, depending on which tool
wrote the file) with:
** Severe ** Object contains more field values than maximum number of IDD fields and is not extensible.
** Severe ** Error parsing "ZoneHVAC:PackagedTerminalHeatPump". Error in following line.
** Severe ** ~~~ 4.94065645841247e-324; !- DX Heating Coil Sizing Ratio
** Severe ** "4.94065645841247e-324" is not a valid Object Type.
repeated once per affected PTHP object (49 times in our case), followed by:
EnergyPlus Terminated--Error(s) Detected.
Confirmed NOT autosize-related: the source .osm template had this field genuinely
unset/blank (isEmpty on the underlying IDF field is True, confirmed via
ZoneHVACPackagedTerminalHeatPump.getString(<field index>)), and the bug reproduces identically
whether the heating/cooling coil capacities are left in Autosize or explicitly hard-sized (we
tried both, to rule out an autosizing-calculation code path as the trigger — same failure either
way, same garbage value).
Expected Behavior
ForwardTranslator should either (a) correctly omit the "DX Heating Coil Sizing Ratio" field when
it is unset on the model object (as it already does correctly for models with few PTHP objects),
or (b) if some internal autosizing-related computation needs a value for it, fall back to the IDD
default (1.0) instead of writing whatever uninitialized memory the getter happens to return.
Steps to reproduce
We don't have a small, shareable, from-scratch repro script yet (our case involves a real building
model we can't publish), but the pattern that triggers it reliably is:
- Build (or load) an OpenStudio model with a genuinely large number (order of 40-50+) of
ThermalZones, each with its ownZoneHVAC:PackagedTerminalHeatPump(Fan:SystemModelsupply
fan,Coil:Heating:DX:SingleSpeed,Coil:Cooling:DX:SingleSpeed,Coil:Heating:Electric
supplemental heater) — in our case, all 49 were.clone()-d from a single real template PTHP
object (with populated schedules/curves) into the target model, once per zone. - Leave the "DX Heating Coil Sizing Ratio" field unset (its default state after cloning from a
template that also never had it explicitly set). - Translate the model with
openstudio.energyplus.ForwardTranslatorunder the pipopenstudio
3.11.0 wheel. - Observe the repeated
BOOST_ASSERTondXHeatingCoilSizingRatio()and the garbage value
written into the IDF.
If someone from the OpenStudio team wants to build a minimal repro: a loop that creates N
ZoneHVACPackagedTerminalHeatPump objects (with real Fan:SystemModel + DX coils + electric
backup coil, not defaults) attached to N zones, then runs ForwardTranslator, scaling N up from a
handful to 40-50, would likely find the exact threshold.
Possible Solution
No response
Operating System affected
Windows 11
Environment
- Failing:
openstudio3.11.0 installed viapipon Windows 11, Python 3.11. - Not failing (same model, same EnergyPlus release):
C:\openstudio-3.10.0\bin\openstudio.exe
(the official 3.10.0 CLI distribution), which bundles EnergyPlus 25.1.0-1c11a3d85f — the
exact same EnergyPlus version string reported by the pip 3.11.0 install when it does run. - OS: Windows 11.
Version of OpenStudio
3.11.0
Context
- This was found while building a tool that merges real building materials/HVAC (
ZoneHVAC:PackagedTerminalHeatPump,
cloned from a real reference model of the building) onto a much finer-grained geometry (73
thermal zones) exported from a Revit BIM model — a legitimate, real-world use case for having
many PTHP-equipped zones in one model. - Happy to provide more detail, the exact IDF fragment (without the real building's proprietary
geometry), or test further scale thresholds if useful for triage.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at src/model/ZoneHVACPackagedTerminalHeatPump.cpp, especially dXHeatingCoilSizingRatio(), and trace how ForwardTranslator.translateModel() emits ZoneHVAC:PackagedTerminalHeatPump fields for cloned objects. Reproduce with the pip 3.11.0 wheel while scaling the PTHP count, then verify that the unset field is omitted or receives the IDD default and that EnergyPlus accepts the translated IDF.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100