Description
See openstudiocoalition/OpenStudioApplication#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 own ZoneHVAC:PackagedTerminalHeatPump (Fan:SystemModel supply
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.ForwardTranslator under the pip openstudio
3.11.0 wheel.
- Observe the repeated
BOOST_ASSERT on dXHeatingCoilSizingRatio() 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:
openstudio 3.11.0 installed via pip on 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.
Description
See openstudiocoalition/OpenStudioApplication#890 filed by @jmcaamanog for details
When
openstudio.energyplus.ForwardTranslatortranslates an.osmmodel containing a largenumber (~49, confirmed) of
ZoneHVAC:PackagedTerminalHeatPumpobjects, 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:PackagedTerminalHeatPumpobject. EnergyPlus thenrejects 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
openstudio3.11.0 wheel(
pip install openstudio==3.11.0). It does not reproduce with theopenstudio-3.10.0CLI(
openstudio.exe, bundled EnergyPlus 25.1.0) translating the exact same model. Both environmentsbundle 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 PTHPobject:
The resulting IDF
ZoneHVAC:PackagedTerminalHeatPumpobject then contains:EnergyPlus then fails at the
GetSurfaceData/IDD-parsing stage (or later, depending on which toolwrote the file) with:
repeated once per affected PTHP object (49 times in our case), followed by:
Confirmed NOT autosize-related: the source
.osmtemplate had this field genuinelyunset/blank (
isEmptyon the underlying IDF field isTrue, confirmed viaZoneHVACPackagedTerminalHeatPump.getString(<field index>)), and the bug reproduces identicallywhether the heating/cooling coil capacities are left in
Autosizeor explicitly hard-sized (wetried both, to rule out an autosizing-calculation code path as the trigger — same failure either
way, same garbage value).
Expected Behavior
ForwardTranslatorshould either (a) correctly omit the "DX Heating Coil Sizing Ratio" field whenit 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:
ThermalZones, each with its ownZoneHVAC:PackagedTerminalHeatPump(Fan:SystemModelsupplyfan,
Coil:Heating:DX:SingleSpeed,Coil:Cooling:DX:SingleSpeed,Coil:Heating:Electricsupplemental heater) — in our case, all 49 were
.clone()-d from a single real template PTHPobject (with populated schedules/curves) into the target model, once per zone.
template that also never had it explicitly set).
openstudio.energyplus.ForwardTranslatorunder the pipopenstudio3.11.0 wheel.
BOOST_ASSERTondXHeatingCoilSizingRatio()and the garbage valuewritten into the IDF.
If someone from the OpenStudio team wants to build a minimal repro: a loop that creates N
ZoneHVACPackagedTerminalHeatPumpobjects (with realFan:SystemModel+ DX coils + electricbackup coil, not defaults) attached to N zones, then runs
ForwardTranslator, scaling N up from ahandful to 40-50, would likely find the exact threshold.
Possible Solution
No response
Operating System affected
Windows 11
Environment
openstudio3.11.0 installed viapipon Windows 11, Python 3.11.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.
Version of OpenStudio
3.11.0
Context
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.
geometry), or test further scale thresholds if useful for triage.