Description
Summary
If a Construction's outermost layer (facing outdoors) or innermost
layer (facing the zone interior) is an OS:Material:AirGap, the model
translates to IDF without any warning, but EnergyPlus then fails with
a FATAL error very early in GetSurfaceData, well before any
useful diagnostics run:
** Severe ** CheckAndSetConstructionProperties: Outside Layer is Air for construction EXTERIOR WALL
** ~~~ ** Error in material F04 WALL AIR SPACE RESISTANCE
** Fatal ** GetSurfaceData: Errors discovered, program terminates.
EnergyPlus's own check (CheckAndSetConstructionProperties) already
knows this is invalid — but the OpenStudio SDK has no equivalent check
at authoring time (e.g. in Construction::setLayers, or as part of
Model.validityReport). Anyone building Construction objects
programmatically from an external material/layer list (import
pipelines, generative scripts, measures) can silently produce an
invalid model that only fails much later, after a full
translate-and-run cycle, with no indication of which construction or
why until they go digging in eplusout.err.
A warning (or a validityReport entry) raised directly when
setLayers is called with an AirGap in position 0 or position N-1
would let people catch this immediately, in their own script/measure,
instead of discovering it downstream in EnergyPlus.
Minimal reproduction (self-contained, no external files needed)
Built entirely from OpenStudio's own bundled example model — no
external geometry or project data involved. Python shown, same idea
applies in Ruby via OpenStudio::Model.exampleModel:
import openstudio
m = openstudio.model.exampleModel()
constructions = {c.name().get(): c for c in m.getConstructions()}
c = constructions["Exterior Wall"].to_Construction().get()
layers = list(c.layers())
# "F04 Wall air space resistance" is already an AirGap material in the
# example model, just correctly placed in the middle of the stack.
airgap = [l for l in layers if not l.to_AirGap().isNull()][0]
others = [l for l in layers if l.handle() != airgap.handle()]
# Move it to the front (outermost layer) -- this is what triggers the
# fatal error. No warning/error is raised at this point.
c.setLayers(openstudio.model.MaterialVector([airgap] + others))
m.save(openstudio.path("broken_airgap_outer.osm"), True)
ft = openstudio.energyplus.ForwardTranslator()
ft.translateModel(m).save(openstudio.path("broken_airgap_outer.idf"), True)
Then running that IDF through EnergyPlus (design-day only is enough,
no need for an annual run) with any weather file reproduces the fatal
error above.
Attached in eplus_airgap_repro.zip:
baseline_ok.idf / baseline_ok_eplusout.err — the unmodified
example model, completes successfully (73 Warning, 0 Severe).
broken_airgap_outer.idf / broken_airgap_outer_eplusout.err — same
model, only the "Exterior Wall" construction's layer order changed
as shown above, fails FATAL.
USA_CO_Golden-NREL.724666_TMY3.epw — the weather file used (NREL's
own standard sample EPW, bundled with the SDK/Application install).
Expected behavior
Either Construction::setLayers (C++ SDK) rejects/warns when an
AirGap-derived material ends up at index 0 or the last index, or at
minimum Model.validityReport(StrictnessLevel.Draft) (or equivalent)
flags it — so this shows up while authoring the model, not after a
full EnergyPlus run.
Actual behavior
No warning anywhere in the OpenStudio SDK (Ruby or Python) when
building/saving such a Construction, or during ForwardTranslator.
The only signal is EnergyPlus's own fatal error, several steps removed
from the actual mistake.
Versions
- OpenStudio SDK (pip
openstudio): 3.11.0
- OpenStudio Application: 1.11.0-rc2
- EnergyPlus: 25.2.0
Additional context
Ran into the EnergyPlus-side version of this while building an
external BIM → OpenStudio import pipeline: a construction whose layer
order came from imported data ended up with an air-gap layer at the
boundary, and the only symptom was this fatal error after a full
translate + run. Worth noting EnergyPlus's message itself is already
reasonably clear once you reach it (names the construction and the
offending material) — the gap is that nothing catches it earlier, at
the SDK level, for anyone assembling constructions programmatically.
by jmcaamanog
eplus_airgap_repro.zip
Current Behavior
No warning anywhere in the OpenStudio SDK (Ruby or Python) when
building/saving such a Construction, or during ForwardTranslator.
The only signal is EnergyPlus's own fatal error, several steps removed
from the actual mistake:
** Severe ** CheckAndSetConstructionProperties: Outside Layer is Air for construction EXTERIOR WALL
** ~~~ ** Error in material F04 WALL AIR SPACE RESISTANCE
** Fatal ** GetSurfaceData: Errors discovered, program terminates.
Expected Behavior
Either Construction::setLayers (C++ SDK) rejects/warns when an
AirGap-derived material ends up at index 0 or the last index, or at
minimum Model.validityReport (or equivalent) flags it -- so this shows
up while authoring the model, not after a full EnergyPlus run.
Steps to reproduce
-
Take the OSM attached (broken_airgap_outer.osm.txt) -- it's
OpenStudio's own bundled example model (openstudio.model.exampleModel()
in the Python SDK / OpenStudio::Model.exampleModel in Ruby), with a
single change: the "Exterior Wall" construction's layer order was
modified so its AirGap material ("F04 Wall air space resistance",
already present in the unmodified example model) is now the
outermost layer instead of the middle of the stack.
-
No warning or error appears when building/saving this model, nor
when running it through the ForwardTranslator to IDF.
-
Run the resulting IDF through EnergyPlus with any weather file
(design-day-only is enough, no need for a full annual run) -- it
fails FATAL during GetSurfaceData (see Current Behavior above).
-
For contrast, baseline_ok.osm.txt is the exact same model with the
layer order untouched -- it completes successfully (73 Warning, 0
Severe).
Minimal code used to produce the difference (Python; same idea with
OpenStudio::Model.exampleModel in Ruby):
import openstudio
m = openstudio.model.exampleModel()
constructions = {c.name().get(): c for c in m.getConstructions()}
c = constructions["Exterior Wall"].to_Construction().get()
layers = list(c.layers())
airgap = [l for l in layers if not l.to_AirGap().isNull()][0]
others = [l for l in layers if l.handle() != airgap.handle()]
# Moves the air gap to the front (outermost layer) -- no warning
# raised here, but this is what makes EnergyPlus fail fatally later.
c.setLayers(openstudio.model.MaterialVector([airgap] + others))
Possible Solution
No response
Operating System affected
Windows 11
Environment
OS: Windows 11 Home, build 10.0.22631 (x86_64)
OpenStudio SDK: 3.11.0 (Python bindings, pip install openstudio)
Python: 3.13.14
EnergyPlus: 25.2.0-cf7368216c
Version of OpenStudio
3.11.0
Context
No response
Description
Summary
If a
Construction's outermost layer (facing outdoors) or innermostlayer (facing the zone interior) is an
OS:Material:AirGap, the modeltranslates to IDF without any warning, but EnergyPlus then fails with
a FATAL error very early in
GetSurfaceData, well before anyuseful diagnostics run:
EnergyPlus's own check (
CheckAndSetConstructionProperties) alreadyknows this is invalid — but the OpenStudio SDK has no equivalent check
at authoring time (e.g. in
Construction::setLayers, or as part ofModel.validityReport). Anyone buildingConstructionobjectsprogrammatically from an external material/layer list (import
pipelines, generative scripts, measures) can silently produce an
invalid model that only fails much later, after a full
translate-and-run cycle, with no indication of which construction or
why until they go digging in
eplusout.err.A warning (or a
validityReportentry) raised directly whensetLayersis called with anAirGapin position 0 or position N-1would let people catch this immediately, in their own script/measure,
instead of discovering it downstream in EnergyPlus.
Minimal reproduction (self-contained, no external files needed)
Built entirely from OpenStudio's own bundled example model — no
external geometry or project data involved. Python shown, same idea
applies in Ruby via
OpenStudio::Model.exampleModel:Then running that IDF through EnergyPlus (design-day only is enough,
no need for an annual run) with any weather file reproduces the fatal
error above.
Attached in
eplus_airgap_repro.zip:baseline_ok.idf/baseline_ok_eplusout.err— the unmodifiedexample model, completes successfully (73 Warning, 0 Severe).
broken_airgap_outer.idf/broken_airgap_outer_eplusout.err— samemodel, only the "Exterior Wall" construction's layer order changed
as shown above, fails FATAL.
USA_CO_Golden-NREL.724666_TMY3.epw— the weather file used (NREL'sown standard sample EPW, bundled with the SDK/Application install).
Expected behavior
Either
Construction::setLayers(C++ SDK) rejects/warns when anAirGap-derived material ends up at index 0 or the last index, or atminimum
Model.validityReport(StrictnessLevel.Draft)(or equivalent)flags it — so this shows up while authoring the model, not after a
full EnergyPlus run.
Actual behavior
No warning anywhere in the OpenStudio SDK (Ruby or Python) when
building/saving such a
Construction, or duringForwardTranslator.The only signal is EnergyPlus's own fatal error, several steps removed
from the actual mistake.
Versions
openstudio): 3.11.0Additional context
Ran into the EnergyPlus-side version of this while building an
external BIM → OpenStudio import pipeline: a construction whose layer
order came from imported data ended up with an air-gap layer at the
boundary, and the only symptom was this fatal error after a full
translate + run. Worth noting EnergyPlus's message itself is already
reasonably clear once you reach it (names the construction and the
offending material) — the gap is that nothing catches it earlier, at
the SDK level, for anyone assembling constructions programmatically.
by jmcaamanog
eplus_airgap_repro.zip
Current Behavior
No warning anywhere in the OpenStudio SDK (Ruby or Python) when
building/saving such a Construction, or during ForwardTranslator.
The only signal is EnergyPlus's own fatal error, several steps removed
from the actual mistake:
** Severe ** CheckAndSetConstructionProperties: Outside Layer is Air for construction EXTERIOR WALL
** ~~~ ** Error in material F04 WALL AIR SPACE RESISTANCE
** Fatal ** GetSurfaceData: Errors discovered, program terminates.
Expected Behavior
Either Construction::setLayers (C++ SDK) rejects/warns when an
AirGap-derived material ends up at index 0 or the last index, or at
minimum Model.validityReport (or equivalent) flags it -- so this shows
up while authoring the model, not after a full EnergyPlus run.
Steps to reproduce
Take the OSM attached (broken_airgap_outer.osm.txt) -- it's
OpenStudio's own bundled example model (openstudio.model.exampleModel()
in the Python SDK / OpenStudio::Model.exampleModel in Ruby), with a
single change: the "Exterior Wall" construction's layer order was
modified so its AirGap material ("F04 Wall air space resistance",
already present in the unmodified example model) is now the
outermost layer instead of the middle of the stack.
No warning or error appears when building/saving this model, nor
when running it through the ForwardTranslator to IDF.
Run the resulting IDF through EnergyPlus with any weather file
(design-day-only is enough, no need for a full annual run) -- it
fails FATAL during GetSurfaceData (see Current Behavior above).
For contrast, baseline_ok.osm.txt is the exact same model with the
layer order untouched -- it completes successfully (73 Warning, 0
Severe).
Minimal code used to produce the difference (Python; same idea with
OpenStudio::Model.exampleModel in Ruby):
Possible Solution
No response
Operating System affected
Windows 11
Environment
OS: Windows 11 Home, build 10.0.22631 (x86_64)
OpenStudio SDK: 3.11.0 (Python bindings, pip install openstudio)
Python: 3.13.14
EnergyPlus: 25.2.0-cf7368216c
Version of OpenStudio
3.11.0
Context
No response