Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions HPXMLtoOpenStudio/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<schema_version>3.1</schema_version>
<name>hpxm_lto_openstudio</name>
<uid>b1543b30-9465-45ff-ba04-1d1f85e763bc</uid>
<version_id>889d304f-d469-460a-bf8a-52dd5017cc64</version_id>
<version_modified>2025-12-02T20:23:54Z</version_modified>
<version_id>a7d95e29-2b50-4ab1-9305-6b45a9a40c97</version_id>
<version_modified>2025-12-03T00:23:38Z</version_modified>
<xml_checksum>D8922A73</xml_checksum>
<class_name>HPXMLtoOpenStudio</class_name>
<display_name>HPXML to OpenStudio Translator</display_name>
Expand Down Expand Up @@ -348,13 +348,13 @@
<filename>defaults.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>AEE3B3DF</checksum>
<checksum>73012C00</checksum>
</file>
<file>
<filename>electric_panel.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>1A0EEA02</checksum>
<checksum>CBC36507</checksum>
</file>
<file>
<filename>energyplus.rb</filename>
Expand Down Expand Up @@ -390,7 +390,7 @@
<filename>hpxml_schema/HPXML.xsd</filename>
<filetype>xsd</filetype>
<usage_type>resource</usage_type>
<checksum>1F53ED27</checksum>
<checksum>8CE42BA2</checksum>
</file>
<file>
<filename>hpxml_schema/README.md</filename>
Expand Down Expand Up @@ -738,7 +738,7 @@
<filename>test_electric_panel.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>8B8F26FB</checksum>
<checksum>1C83DE0B</checksum>
</file>
<file>
<filename>test_enclosure.rb</filename>
Expand Down Expand Up @@ -810,7 +810,7 @@
<filename>test_validation.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>70A4508D</checksum>
<checksum>4654A43C</checksum>
</file>
<file>
<filename>test_vehicle.rb</filename>
Expand Down
2 changes: 1 addition & 1 deletion HPXMLtoOpenStudio/resources/defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3966,7 +3966,7 @@ def self.apply_electric_panels(runner, hpxml_header, hpxml_bldg, unit_num)
electric_panel.headroom_spaces_isdefaulted = true
end

ElectricPanel.calculate(runner, hpxml_header, hpxml_bldg, electric_panel)
ElectricPanel.calculate(hpxml_header, hpxml_bldg, electric_panel)
end
end

Expand Down
17 changes: 4 additions & 13 deletions HPXMLtoOpenStudio/resources/electric_panel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
module ElectricPanel
# Calculates load-based capacity and breaker spaces for an electric panel.
#
# @param runner [OpenStudio::Measure::OSRunner] Object typically used to display warnings
# @param hpxml_header [HPXML::Header] HPXML Header object (one per HPXML file)
# @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit
# @param electric_panel [HPXML::ElectricPanel] Object that defines a single electric panel
# @return [nil]
def self.calculate(runner, hpxml_header, hpxml_bldg, electric_panel)
def self.calculate(hpxml_header, hpxml_bldg, electric_panel)
electric_panel.capacity_types = []
electric_panel.capacity_total_watts = []
electric_panel.capacity_total_amps = []
Expand All @@ -34,7 +33,7 @@ def self.calculate(runner, hpxml_header, hpxml_bldg, electric_panel)
end
end

calculate_breaker_spaces(runner, electric_panel)
calculate_breaker_spaces(electric_panel)
end

# Get the component attached to the given service feeder.
Expand Down Expand Up @@ -184,10 +183,9 @@ def self.calculate_meter_based(hpxml_bldg, electric_panel, service_feeders, serv

# Calculate the number of panel breaker spaces corresponding to rated total spaces, occupied spaces, and headroom spaces.
#
# @param runner [OpenStudio::Measure::OSRunner] Object typically used to display warnings
# @param electric_panel [HPXML::ElectricPanel] Object that defines a single electric panel
# @return [nil]
def self.calculate_breaker_spaces(runner, electric_panel)
def self.calculate_breaker_spaces(electric_panel)
occupied_spaces = electric_panel.occupied_spaces

if not electric_panel.rated_total_spaces.nil?
Expand All @@ -200,14 +198,7 @@ def self.calculate_breaker_spaces(runner, electric_panel)
end

if electric_panel.headroom_spaces.nil? # only nil if rated_total_spaces is specified
headroom_spaces = rated_total_spaces - occupied_spaces
if headroom_spaces < 0
runner.registerWarning("The sum of OccupiedSpaces (#{occupied_spaces}) exceeds RatedTotalSpaces (#{rated_total_spaces}); increasing RatedTotalSpaces by #{headroom_spaces.abs} and setting HeadroomSpaces=0.")
electric_panel.rated_total_spaces -= headroom_spaces
electric_panel.rated_total_spaces_isdefaulted = true
headroom_spaces = 0
end
electric_panel.headroom_spaces = headroom_spaces
electric_panel.headroom_spaces = rated_total_spaces - occupied_spaces
electric_panel.headroom_spaces_isdefaulted = true
end
end
Expand Down
3 changes: 2 additions & 1 deletion HPXMLtoOpenStudio/resources/hpxml_schema/HPXML.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -6734,7 +6734,7 @@
<xs:documentation>[A]</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" name="HeadroomSpaces" type="IntegerGreaterThanOrEqualToZero">
<xs:element minOccurs="0" name="HeadroomSpaces" type="HPXMLInteger">
<xs:annotation>
<xs:documentation>The number of open breaker spaces.</xs:documentation>
</xs:annotation>
Expand Down Expand Up @@ -10919,6 +10919,7 @@
<xs:enumeration value="PHIUS+"/>
<xs:enumeration value="WaterSense"/>
<xs:enumeration value="Zero Energy Ready Home"/>
<xs:enumeration value="DOE Efficient New Home"/>
<xs:enumeration value="other"/>
</xs:restriction>
</xs:simpleType>
Expand Down
12 changes: 6 additions & 6 deletions HPXMLtoOpenStudio/tests/test_electric_panel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ def test_ashp_upgrade
_model, _hpxml, hpxml_bldg = _test_measure(args_hash)
electric_panel = hpxml_bldg.electric_panels[0]

assert_equal(17, electric_panel.rated_total_spaces)
assert_equal(16, electric_panel.rated_total_spaces)
assert_equal(17, electric_panel.occupied_spaces)
assert_equal(0, electric_panel.headroom_spaces)
assert_equal(-1, electric_panel.headroom_spaces)

# Load-Based Part A
assert_in_epsilon(24662.0, electric_panel.capacity_total_watts[0], 0.001)
Expand All @@ -110,9 +110,9 @@ def test_ashp_upgrade
_model, _hpxml, hpxml_bldg = _test_measure(args_hash)
electric_panel = hpxml_bldg.electric_panels[0]

assert_equal(17, electric_panel.rated_total_spaces)
assert_equal(16, electric_panel.rated_total_spaces)
assert_equal(17, electric_panel.occupied_spaces)
assert_equal(0, electric_panel.headroom_spaces)
assert_equal(-1, electric_panel.headroom_spaces)

# Load-Based Part B
assert_in_epsilon(34827.2, electric_panel.capacity_total_watts[0], 0.001)
Expand Down Expand Up @@ -933,9 +933,9 @@ def test_electric_panel_output_file
electric_panel_path = File.absolute_path(File.join(File.dirname(__FILE__), 'results_panel.json'))
json = JSON.parse(File.read(electric_panel_path))

assert_equal(23, json['Electric Panel Breaker Spaces']['Total Count'])
assert_equal(16, json['Electric Panel Breaker Spaces']['Total Count'])
assert_equal(23, json['Electric Panel Breaker Spaces']['Occupied Count'])
assert_equal(0, json['Electric Panel Breaker Spaces']['Headroom Count'])
assert_equal(-7, json['Electric Panel Breaker Spaces']['Headroom Count'])
assert_equal(34827.2, json['Electric Panel Load']['2023 Existing Dwelling Load-Based: Total Load (W)'])
assert_equal(145.1, json['Electric Panel Load']['2023 Existing Dwelling Load-Based: Total Capacity (A)'])
assert_in_epsilon(100.0 - 145.1, json['Electric Panel Load']['2023 Existing Dwelling Load-Based: Headroom Capacity (A)'], 0.01)
Expand Down
11 changes: 0 additions & 11 deletions HPXMLtoOpenStudio/tests/test_validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,6 @@ def test_schema_schematron_error_messages
'HeatingAutosizingFactor should be greater than 0.0',
'BackupHeatingAutosizingFactor should be greater than 0.0'],
'negative-hpwh-containment-volume' => ['Expected HPWHContainmentVolume to be greater than 0.'],
'panel-negative-headroom-breaker-spaces' => ["Element 'HeadroomSpaces': [facet 'minInclusive'] The value '-1' is less than the minimum value allowed ('0')."],
'panel-zero-total-breaker-spaces' => ["Element 'RatedTotalSpaces': [facet 'minExclusive'] The value '0' must be greater than '0'."],
'panel-without-required-system' => ['Expected 1 or more element(s) for xpath: AttachedToComponent [context: /HPXML/Building/BuildingDetails/Systems/ElectricPanels/ElectricPanel/ServiceFeeders/ServiceFeeder, id: "ServiceFeeder1"]'],
'panel-with-unrequired-system' => ['Expected 0 element(s) for xpath: AttachedToComponent [context: /HPXML/Building/BuildingDetails/Systems/ElectricPanels/ElectricPanel/ServiceFeeders/ServiceFeeder, id: "ServiceFeeder1"]'],
Expand Down Expand Up @@ -869,10 +868,6 @@ def test_schema_schematron_error_messages
when 'negative-hpwh-containment-volume'
hpxml, hpxml_bldg = _create_hpxml('base-dhw-tank-heat-pump-confined-space.xml')
hpxml_bldg.water_heating_systems[0].hpwh_containment_volume = -10.0
when 'panel-negative-headroom-breaker-spaces'
hpxml, hpxml_bldg = _create_hpxml('base.xml')
hpxml_bldg.electric_panels.add(id: 'ElectricPanel1',
headroom_spaces: -1)
when 'panel-zero-total-breaker-spaces'
hpxml, hpxml_bldg = _create_hpxml('base.xml')
hpxml_bldg.electric_panels.add(id: 'ElectricPanel1',
Expand Down Expand Up @@ -1950,7 +1945,6 @@ def test_ruby_warning_messages
'multiple-inverter-efficiencies' => ['Inverters with varying efficiencies found; using a single PV size weighted-average in the model.'],
'panel-missing-default' => ["Voltage (240) for 'dishwasher' is not specified in default_panels.csv; PowerRating will be assigned according to Voltage=120.",
"Voltage (240) for 'dishwasher' is not specified in default_panels.csv; BreakerSpaces will be recalculated using Voltage=240."],
'panel-spaces-constrained' => ['The sum of OccupiedSpaces (12.0) exceeds RatedTotalSpaces (10); increasing RatedTotalSpaces by 2.0 and setting HeadroomSpaces=0.'],
'power-outage' => ['It is not possible to eliminate all HVAC energy use (e.g. crankcase/defrost energy) in EnergyPlus during an unavailable period.',
'It is not possible to eliminate all DHW energy use (e.g. water heater parasitics) in EnergyPlus during an unavailable period.'],
'schedule-file-and-weekday-weekend-multipliers' => ["Both 'occupants' schedule file and weekday fractions provided; the latter will be ignored.",
Expand Down Expand Up @@ -2160,11 +2154,6 @@ def test_ruby_warning_messages
branch_circuits.add(id: 'NewBranchCircuit',
voltage: HPXML::ElectricPanelVoltage240,
component_idrefs: [hpxml_bldg.dishwashers[0].id])
when 'panel-spaces-constrained'
hpxml, hpxml_bldg = _create_hpxml('base-detailed-electric-panel.xml')
hpxml_bldg.dishwashers.add(id: 'Dishwasher')
hpxml_bldg.electric_panels[0].headroom_spaces = nil
hpxml_bldg.electric_panels[0].rated_total_spaces = 10
when 'power-outage'
hpxml, _hpxml_bldg = _create_hpxml('base-schedules-simple-power-outage.xml')
when 'multistage-backup-more-than-4-stages'
Expand Down
11 changes: 5 additions & 6 deletions docs/source/workflow_outputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -763,9 +763,11 @@ End use categories (e.g., Heating, Cooling, Hot Water) report occupied spaces fo
Electric Panel Breaker Spaces: Other Count Sum of other occupied spaces
Electric Panel Breaker Spaces: Total Count Total number of spaces on the panel
Electric Panel Breaker Spaces: Occupied Count Total number of occupied spaces on the panel
Electric Panel Breaker Spaces: Headroom Count Total number of available (unoccupied) spaces on the panel
Electric Panel Breaker Spaces: Headroom Count Total number of available (unoccupied) spaces on the panel [#]_
================================================================================ ====================

.. [#] A positive value indicates panel availability whereas a negative value indicates panel constraint.

Loads
~~~~~

Expand All @@ -790,13 +792,10 @@ Electric panel loads, as well as calculated total loads and capacities for each
Electric Panel Load: Other (W) Sum of other loads
Electric Panel Load: <Type>: Total Load (W) Calculated NEC total load
Electric Panel Load: <Type>: Total Capacity (A) Total panel capacity
Electric Panel Load: <Type>: Headroom Capacity (A) Available panel capacity
Electric Panel Load: <Type>: Headroom Capacity (A) Available panel capacity [#]_
================================================================================ ====================

.. note::

Headroom is calculated as the panel's maximum current rating minus calculated capacity.
A positive value indicates panel availability whereas a negative value indicates panel constraint.
.. [#] A positive value indicates panel availability whereas a negative value indicates panel constraint.

.. _design_load_details:

Expand Down