Skip to content

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 #890

Description

@jmcaamanog

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.

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.

Symptom (exact messages observed)

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).

Confirmed scale-dependent, not just "any PTHP": translating a model with 1-5
ZoneHVAC:PackagedTerminalHeatPump objects (built by cloning the exact same source object
repeatedly into a small test model) does not reproduce the bug — the field is correctly
omitted (not written at all, as expected for an unset optional trailing field). It only appears
once the model reaches the scale of our real building (73 total thermal zones, 49 of them
equipped with a ZoneHVAC:PackagedTerminalHeatPump). We were not able to narrow down the exact
zone/object count threshold between "small test model, works" and "49 zones, fails" due to time
constraints — this would be useful information for whoever picks this up.

A second, related but distinct observation (model/IDD schema mismatch)

Separately, we found that saving a model containing a ZoneHVAC:PackagedTerminalHeatPump object
that was originally clone()-d from a .osm file declaring a newer OpenStudio version (3.11.0)
into a model being saved by the 3.10.0 CLI can result in the saved .osm text containing
one extra field for that specific object type beyond what OpenStudio 3.10.0's own IDD defines
for OS:ZoneHVAC:PackagedTerminalHeatPump (25 fields) — i.e. the saved file has 26 raw fields for
that object. Reloading that file with a stricter loader (openstudio.exe run -w model.osw, as
opposed to a plain script calling VersionTranslator().loadModel() + ForwardTranslator, which
tolerates it silently) then fails with:

[utilities.idf.IdfObject] <Error> IdfObject of type 'OS:ZoneHVAC:PackagedTerminalHeatPump' cannot
have field index of 25. Cutting off IdfObject field parsing here, with the following text
remaining:

We are not certain whether this second issue shares a root cause with the first (both involve the
same object type and the same trailing "DX Heating Coil Sizing Ratio"-adjacent field region), or
is a separate clone()/cross-version-schema issue. Flagging both together since they were found
in the same investigation and both revolve around the same object type/field.

Steps to reproduce (best available — no fully minimal isolated repro yet)

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:

  1. 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.
  2. Leave the "DX Heating Coil Sizing Ratio" field unset (its default state after cloning from a
    template that also never had it explicitly set).
  3. Translate the model with openstudio.energyplus.ForwardTranslator under the pip openstudio
    3.11.0
    wheel.
  4. 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.

Workaround we are using

Translate/simulate this specific model using the OpenStudio 3.10.0 CLI
(C:\openstudio-3.10.0\bin\openstudio.exe, ForwardTranslator + EnergyPlus.exe directly) instead
of the pip 3.11.0 SDK. This avoids the bug entirely for the same model — the field is correctly
never written the CLI 3.10.0 build reproduces it, IDF is well-formed, EnergyPlus runs to
completion.

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.

Additional 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.

by jmcaamnog

Metadata

Metadata

Assignees

No one assigned

    Labels

    OpenStudio SDK IssueAn issue that is not related to OpenStudioApplication but to NREL/OpenStudio SDK

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions