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: