diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml
index 2d55c560c5..d82552a337 100644
--- a/HPXMLtoOpenStudio/measure.xml
+++ b/HPXMLtoOpenStudio/measure.xml
@@ -3,8 +3,8 @@
3.1
hpxm_lto_openstudio
b1543b30-9465-45ff-ba04-1d1f85e763bc
- 889d304f-d469-460a-bf8a-52dd5017cc64
- 2025-12-02T20:23:54Z
+ a7d95e29-2b50-4ab1-9305-6b45a9a40c97
+ 2025-12-03T00:23:38Z
D8922A73
HPXMLtoOpenStudio
HPXML to OpenStudio Translator
@@ -348,13 +348,13 @@
defaults.rb
rb
resource
- AEE3B3DF
+ 73012C00
electric_panel.rb
rb
resource
- 1A0EEA02
+ CBC36507
energyplus.rb
@@ -390,7 +390,7 @@
hpxml_schema/HPXML.xsd
xsd
resource
- 1F53ED27
+ 8CE42BA2
hpxml_schema/README.md
@@ -738,7 +738,7 @@
test_electric_panel.rb
rb
test
- 8B8F26FB
+ 1C83DE0B
test_enclosure.rb
@@ -810,7 +810,7 @@
test_validation.rb
rb
test
- 70A4508D
+ 4654A43C
test_vehicle.rb
diff --git a/HPXMLtoOpenStudio/resources/defaults.rb b/HPXMLtoOpenStudio/resources/defaults.rb
index 5c27da4599..d0a9085eaf 100644
--- a/HPXMLtoOpenStudio/resources/defaults.rb
+++ b/HPXMLtoOpenStudio/resources/defaults.rb
@@ -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
diff --git a/HPXMLtoOpenStudio/resources/electric_panel.rb b/HPXMLtoOpenStudio/resources/electric_panel.rb
index 169867c328..7bad88bae3 100644
--- a/HPXMLtoOpenStudio/resources/electric_panel.rb
+++ b/HPXMLtoOpenStudio/resources/electric_panel.rb
@@ -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 = []
@@ -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.
@@ -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?
@@ -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
diff --git a/HPXMLtoOpenStudio/resources/hpxml_schema/HPXML.xsd b/HPXMLtoOpenStudio/resources/hpxml_schema/HPXML.xsd
index 1f5a2411ef..c7f62ab093 100644
--- a/HPXMLtoOpenStudio/resources/hpxml_schema/HPXML.xsd
+++ b/HPXMLtoOpenStudio/resources/hpxml_schema/HPXML.xsd
@@ -6734,7 +6734,7 @@
[A]
-
+
The number of open breaker spaces.
@@ -10919,6 +10919,7 @@
+
diff --git a/HPXMLtoOpenStudio/tests/test_electric_panel.rb b/HPXMLtoOpenStudio/tests/test_electric_panel.rb
index ab24035925..29a4da5ef1 100644
--- a/HPXMLtoOpenStudio/tests/test_electric_panel.rb
+++ b/HPXMLtoOpenStudio/tests/test_electric_panel.rb
@@ -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)
@@ -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)
@@ -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)
diff --git a/HPXMLtoOpenStudio/tests/test_validation.rb b/HPXMLtoOpenStudio/tests/test_validation.rb
index da612f9d4c..a74f7c0292 100644
--- a/HPXMLtoOpenStudio/tests/test_validation.rb
+++ b/HPXMLtoOpenStudio/tests/test_validation.rb
@@ -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"]'],
@@ -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',
@@ -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.",
@@ -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'
diff --git a/docs/source/workflow_outputs.rst b/docs/source/workflow_outputs.rst
index 8c98a433a4..fcaca8c1c2 100644
--- a/docs/source/workflow_outputs.rst
+++ b/docs/source/workflow_outputs.rst
@@ -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
~~~~~
@@ -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: : Total Load (W) Calculated NEC total load
Electric Panel Load: : Total Capacity (A) Total panel capacity
- Electric Panel Load: : Headroom Capacity (A) Available panel capacity
+ Electric Panel Load: : 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: