Skip to content

Commit 71e7e6c

Browse files
authored
Merge pull request #2231 from NatLabRockies/hpwh_input_capacity
Change HPWH `HeatingCapacity` to be input capacity
2 parents 7c247a9 + 3d0df0f commit 71e7e6c

13 files changed

Lines changed: 47 additions & 56 deletions

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
__Features__
44
- **Breaking change**: Conditioned crawlspaces are no longer allowed; use unvented crawlspace instead.
5+
- **Breaking change**: For heat pump water heaters, ``HeatingCapacity`` is now *input* rather than *output* capacity, similar to other water heater types.
56

67
__Bugfixes__
78
- Fixes ERV supply outlet enthalpy calculation used to calculate latent effectiveness.

HPXMLtoOpenStudio/measure.xml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<schema_version>3.1</schema_version>
44
<name>hpxml_to_openstudio</name>
55
<uid>b1543b30-9465-45ff-ba04-1d1f85e763bc</uid>
6-
<version_id>f15d2212-6489-4380-9bfa-1065ab495ec6</version_id>
7-
<version_modified>2026-06-30T14:06:12Z</version_modified>
6+
<version_id>a38a2ae6-8e28-4610-b290-d0800e48bffb</version_id>
7+
<version_modified>2026-07-06T17:36:47Z</version_modified>
88
<xml_checksum>D8922A73</xml_checksum>
99
<class_name>HPXMLToOpenStudio</class_name>
1010
<display_name>HPXML to OpenStudio Translator</display_name>
@@ -367,7 +367,7 @@
367367
<filename>defaults.rb</filename>
368368
<filetype>rb</filetype>
369369
<usage_type>resource</usage_type>
370-
<checksum>413A9F47</checksum>
370+
<checksum>4350A1B4</checksum>
371371
</file>
372372
<file>
373373
<filename>electric_panel.rb</filename>
@@ -433,7 +433,7 @@
433433
<filename>hvac.rb</filename>
434434
<filetype>rb</filetype>
435435
<usage_type>resource</usage_type>
436-
<checksum>DF5A0B42</checksum>
436+
<checksum>FC78CABE</checksum>
437437
</file>
438438
<file>
439439
<filename>hvac_sizing.rb</filename>
@@ -715,7 +715,7 @@
715715
<filename>waterheater.rb</filename>
716716
<filetype>rb</filetype>
717717
<usage_type>resource</usage_type>
718-
<checksum>C428F4AB</checksum>
718+
<checksum>38BFC5B0</checksum>
719719
</file>
720720
<file>
721721
<filename>weather.rb</filename>
@@ -751,13 +751,13 @@
751751
<filename>test_defaults.rb</filename>
752752
<filetype>rb</filetype>
753753
<usage_type>test</usage_type>
754-
<checksum>BE1661EA</checksum>
754+
<checksum>2C65B351</checksum>
755755
</file>
756756
<file>
757757
<filename>test_electric_panel.rb</filename>
758758
<filetype>rb</filetype>
759759
<usage_type>test</usage_type>
760-
<checksum>91EBCCF9</checksum>
760+
<checksum>C44399FB</checksum>
761761
</file>
762762
<file>
763763
<filename>test_enclosure.rb</filename>
@@ -841,7 +841,7 @@
841841
<filename>test_water_heater.rb</filename>
842842
<filetype>rb</filetype>
843843
<usage_type>test</usage_type>
844-
<checksum>F216022C</checksum>
844+
<checksum>F2FE0274</checksum>
845845
</file>
846846
<file>
847847
<filename>test_weather.rb</filename>

HPXMLtoOpenStudio/resources/defaults.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3354,7 +3354,7 @@ def self.apply_water_heaters(hpxml_bldg, eri_version, schedules_file)
33543354
water_heating_system.additional_properties.cop = get_water_heater_heat_pump_cop(water_heating_system)
33553355

33563356
if water_heating_system.heating_capacity.nil?
3357-
water_heating_system.heating_capacity = (UnitConversions.convert(0.5, 'kW', 'Btu/hr') * water_heating_system.additional_properties.cop).round
3357+
water_heating_system.heating_capacity = UnitConversions.convert(0.5, 'kW', 'Btu/hr').round
33583358
water_heating_system.heating_capacity_isdefaulted = true
33593359
end
33603360

@@ -6493,7 +6493,7 @@ def self.get_window_ufactor_shgc(window)
64936493

64946494
# Gets the default compressor type for a HVAC system.
64956495
#
6496-
# @param [HPXML::HeatingSystem or HPXML::CoolingSystem or HPXML::HeatPump]
6496+
# @param hvac_system [HPXML::CoolingSystem or HPXML::HeatPump] The HPXML HVAC system of interest
64976497
# @return [String] Compressor type (HPXML::HVACCompressorTypeXXX)
64986498
def self.get_hvac_compressor_type(hvac_system)
64996499
if HVAC.is_room_dx_hvac_system(hvac_system)
@@ -6505,7 +6505,7 @@ def self.get_hvac_compressor_type(hvac_system)
65056505

65066506
# Gets the default EER for a HVAC system.
65076507
#
6508-
# @param [HPXML::CoolingSystem or HPXML::HeatPump]
6508+
# @param hvac_system [HPXML::CoolingSystem or HPXML::HeatPump] The HPXML HVAC system of interest
65096509
# @return [Double] Cooling EER2 (Btu/Wh)
65106510
def self.get_hvac_eer2(hvac_system)
65116511
seer2 = hvac_system.cooling_efficiency_seer2
@@ -7102,7 +7102,7 @@ def self.get_service_feeder_power_default_values(runner, hpxml_bldg, service_fee
71027102
if water_heating_system.water_heater_type == HPXML::WaterHeaterTypeStorage
71037103
watts += UnitConversions.convert(water_heating_system.heating_capacity, 'btu/hr', 'w')
71047104
elsif water_heating_system.water_heater_type == HPXML::WaterHeaterTypeHeatPump
7105-
watts += [UnitConversions.convert(Waterheater.get_heating_input_capacity(water_heating_system.heating_capacity, water_heating_system.additional_properties.cop), 'btu/hr', 'w'),
7105+
watts += [UnitConversions.convert(water_heating_system.heating_capacity, 'btu/hr', 'w'),
71067106
UnitConversions.convert(water_heating_system.backup_heating_capacity, 'btu/hr', 'w')].max
71077107
elsif water_heating_system.water_heater_type == HPXML::WaterHeaterTypeTankless
71087108
if hpxml_bldg.building_construction.number_of_bathrooms == 1

HPXMLtoOpenStudio/resources/hvac.rb

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,21 +1058,21 @@ def self.get_dx_coil_power_watts_from_capacity(capacity, voltage)
10581058
return power
10591059
end
10601060

1061-
# Get the indoor unit (air handler) power (W).
1061+
# Get the indoor unit (air handler) power.
10621062
#
1063-
# @param fan_watts_per_cfm [Double] Blower fan watts per cfm [W/cfm]
1064-
# @param airflow_cfm [Double] HVAC system airflow rate [cfm]
1065-
# @return [Double] Blower fan power [W]
1063+
# @param fan_watts_per_cfm [Double] Blower fan efficacy (W/cfm)
1064+
# @param airflow_cfm [Double] HVAC system airflow rate (cfm)
1065+
# @return [Double] Blower fan power (W)
10661066
def self.get_blower_fan_power_watts(fan_watts_per_cfm, airflow_cfm)
10671067
return 0.0 if fan_watts_per_cfm.nil? || airflow_cfm.nil?
10681068

10691069
return fan_watts_per_cfm * airflow_cfm
10701070
end
10711071

1072-
# Get the boiler or GHP pump power (W).
1072+
# Get the boiler or GHP pump power.
10731073
#
10741074
# @param hvac_system [HPXML::HeatingSystem or HPXML::HeatPump] The HPXML HVAC system of interest
1075-
# @return [Double] Pump power [W]
1075+
# @return [Double] Pump power (W)
10761076
def self.get_pump_power_watts(hvac_system)
10771077
if hvac_system.is_a?(HPXML::HeatingSystem) && (not hvac_system.electric_auxiliary_energy.nil?)
10781078
return hvac_system.electric_auxiliary_energy / 2.08
@@ -1089,10 +1089,10 @@ def self.get_pump_power_watts(hvac_system)
10891089

10901090
# Returns the heating input capacity, calculated as the heating rated (output) capacity divided by the rated efficiency.
10911091
#
1092-
# @param heating_capacity [Double] Heating output capacity [Btu/hr]
1093-
# @param heating_efficiency_afue [Double] Rated efficiency [AFUE]
1094-
# @param heating_efficiency_percent [Double] Rated efficiency [Percent]
1095-
# @return [Double] The heating input capacity [Btu/hr]
1092+
# @param heating_capacity [Double] Heating output capacity (Btu/hr)
1093+
# @param heating_efficiency_afue [Double] Rated efficiency (AFUE)
1094+
# @param heating_efficiency_percent [Double] Rated efficiency (Percent)
1095+
# @return [Double] The heating input capacity (Btu/hr)
10961096
def self.get_heating_input_capacity(heating_capacity, heating_efficiency_afue, heating_efficiency_percent)
10971097
if not heating_efficiency_afue.nil?
10981098
return heating_capacity / heating_efficiency_afue
@@ -2467,7 +2467,7 @@ def self.create_heat_pump_supplemental_heating_coil(model, obj_name, heat_pump,
24672467
#
24682468
# @param model [OpenStudio::Model::Model] OpenStudio Model object
24692469
# @param obj_name [String] Name for the OpenStudio object
2470-
# @param fan_watts_per_cfm [Double] Fan efficacy watts per cfm
2470+
# @param fan_watts_per_cfm [Double] Blower fan efficacy (W/cfm)
24712471
# @param fan_cfms [Array<Double>] Fan airflow rates at all speeds, both heating and cooling
24722472
# @param hvac_system [HPXML::HeatingSystem or HPXML::CoolingSystem or HPXML::HeatPump] The HPXML HVAC system of interest
24732473
# @return [OpenStudio::Model::FanSystemModel] OpenStudio FanSystemModel object

HPXMLtoOpenStudio/resources/waterheater.rb

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,8 @@ def self.apply_hpwh_dxcoil(runner, model, water_heating_system, elevation, obj_n
973973
)
974974

975975
# Assumptions and values
976-
cap = UnitConversions.convert(water_heating_system.heating_capacity, 'Btu/hr', 'W') * unit_multiplier # kW
976+
cop = water_heating_system.additional_properties.cop
977+
cap = UnitConversions.convert(water_heating_system.heating_capacity, 'Btu/hr', 'W') * cop * unit_multiplier # W, output capacity
977978
shr = 0.88 # unitless
978979

979980
# Calculate an altitude adjusted rated evaporator wetbulb temperature
@@ -987,8 +988,6 @@ def self.apply_hpwh_dxcoil(runner, model, water_heating_system, elevation, obj_n
987988
w_adj = Psychrometrics.w_fT_Twb_P(dp_rated, dp_rated, p_atm)
988989
twb_adj = Psychrometrics.Twb_fT_w_P(runner, rated_edb_F, w_adj, p_atm)
989990

990-
cop = water_heating_system.additional_properties.cop
991-
992991
# Adjust COP based on RESNET HERS Addendum 77
993992
cv = water_heating_system.hpwh_containment_volume
994993
if not cv.nil?
@@ -1039,15 +1038,6 @@ def self.apply_hpwh_dxcoil(runner, model, water_heating_system, elevation, obj_n
10391038
return coil
10401039
end
10411040

1042-
# Returns the heating input capacity, calculated as the heating rated (output) capacity divided by the rated efficiency.
1043-
#
1044-
# @param heating_capacity [Double]
1045-
# @param heating_efficiency_cop [Double] Rated efficiency [COP]
1046-
# @return [Double] The heating input capacity [Btu/hr]
1047-
def self.get_heating_input_capacity(heating_capacity, heating_efficiency_cop)
1048-
return heating_capacity / UnitConversions.convert(heating_efficiency_cop, 'btu/hr', 'w')
1049-
end
1050-
10511041
# Adds a WaterHeaterStratified object for the HPWH to the OpenStudio model.
10521042
#
10531043
# @param model [OpenStudio::Model::Model] OpenStudio Model object

HPXMLtoOpenStudio/tests/test_defaults.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3623,21 +3623,21 @@ def test_heat_pump_water_heaters
36233623
hpxml_bldg.water_heating_systems[0].hpwh_confined_space_without_mitigation = nil
36243624
XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path)
36253625
_default_hpxml, default_hpxml_bldg = _test_measure()
3626-
_test_default_heat_pump_water_heater_values(default_hpxml_bldg, [66.0, HPXML::WaterHeaterHPWHOperatingModeHybridAuto, 6366.0, 15355.0, false])
3626+
_test_default_heat_pump_water_heater_values(default_hpxml_bldg, [66.0, HPXML::WaterHeaterHPWHOperatingModeHybridAuto, 1706.0, 15355.0, false])
36273627

36283628
# Test defaults w/ num occupants = 1, num bedrooms = 1
36293629
hpxml_bldg.building_construction.number_of_bedrooms = 1
36303630
hpxml_bldg.building_occupancy.number_of_residents = 1
36313631
XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path)
36323632
_default_hpxml, default_hpxml_bldg = _test_measure()
3633-
_test_default_heat_pump_water_heater_values(default_hpxml_bldg, [50.0, HPXML::WaterHeaterHPWHOperatingModeHybridAuto, 6366.0, 15355.0, false])
3633+
_test_default_heat_pump_water_heater_values(default_hpxml_bldg, [50.0, HPXML::WaterHeaterHPWHOperatingModeHybridAuto, 1706.0, 15355.0, false])
36343634

36353635
# Test defaults w/ num occupants = 10, num bedrooms = 1
36363636
hpxml_bldg.building_construction.number_of_bedrooms = 1
36373637
hpxml_bldg.building_occupancy.number_of_residents = 10
36383638
XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path)
36393639
_default_hpxml, default_hpxml_bldg = _test_measure()
3640-
_test_default_heat_pump_water_heater_values(default_hpxml_bldg, [80.0, HPXML::WaterHeaterHPWHOperatingModeHybridAuto, 6366.0, 15355.0, false])
3640+
_test_default_heat_pump_water_heater_values(default_hpxml_bldg, [80.0, HPXML::WaterHeaterHPWHOperatingModeHybridAuto, 1706.0, 15355.0, false])
36413641
end
36423642

36433643
def test_indirect_water_heaters

HPXMLtoOpenStudio/tests/test_electric_panel.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ def test_water_heater_hpwh_without_backup
632632
XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path)
633633
_model, _hpxml, hpxml_bldg = _test_measure(args_hash)
634634

635-
_test_service_feeder_power(hpxml_bldg, HPXML::ElectricPanelLoadTypeWaterHeater, 804)
635+
_test_service_feeder_power(hpxml_bldg, HPXML::ElectricPanelLoadTypeWaterHeater, 879)
636636
_test_occupied_spaces(hpxml_bldg, [HPXML::ElectricPanelLoadTypeWaterHeater], 2)
637637
end
638638

HPXMLtoOpenStudio/tests/test_water_heater.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,7 @@ def test_tank_heat_pump_capacities
10341034
ther_eff = 1.0
10351035
cop = 3.731
10361036
tank_height = 1.3343
1037-
cap = UnitConversions.convert(water_heating_system.heating_capacity, 'Btu/hr', 'W') # W
1037+
cap = UnitConversions.convert(water_heating_system.heating_capacity, 'Btu/hr', 'W') * cop # W
10381038
backup_cap = UnitConversions.convert(water_heating_system.backup_heating_capacity, 'Btu/hr', 'W') # W
10391039

10401040
# Check water heater

docs/source/workflow_inputs.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4138,7 +4138,7 @@ Each conventional storage water heater is entered as a ``/HPXML/Building/Buildin
41384138
``IsSharedSystem`` boolean No false Whether it serves multiple dwelling units or shared laundry room
41394139
``TankVolume`` double gal > 0 No See [#]_ Nominal tank volume
41404140
``FractionDHWLoadServed`` double frac >= 0, <= 1 [#]_ Yes Fraction of hot water load served [#]_
4141-
``HeatingCapacity`` double Btu/hr > 0 No See [#]_ Heating capacity
4141+
``HeatingCapacity`` double Btu/hr > 0 No See [#]_ Heating input capacity
41424142
``UniformEnergyFactor`` or ``EnergyFactor`` double frac < 1 Yes EnergyGuide label rated efficiency
41434143
``UsageBin`` or ``FirstHourRating`` string or double str or gal/hr See [#]_ or > 0 No See [#]_ EnergyGuide label usage bin/first hour rating
41444144
``RecoveryEfficiency`` double frac > 0, <= 1 [#]_ No See [#]_ Recovery efficiency
@@ -4239,7 +4239,7 @@ Each heat pump water heater is entered as a ``/HPXML/Building/BuildingDetails/Sy
42394239
``IsSharedSystem`` boolean No false Whether it serves multiple dwelling units or shared laundry room
42404240
``TankVolume`` double gal > 0 No See [#]_ Nominal tank volume
42414241
``FractionDHWLoadServed`` double frac >= 0, <= 1 [#]_ Yes Fraction of hot water load served [#]_
4242-
``HeatingCapacity`` double Btu/hr > 0 No See [#]_ Heating output capacity
4242+
``HeatingCapacity`` double Btu/hr > 0 No See [#]_ Heating input capacity
42434243
``BackupHeatingCapacity`` double Btu/hr >= 0 No 15355 (4.5 kW) Heating capacity of the electric resistance backup
42444244
``UniformEnergyFactor`` or ``EnergyFactor`` double frac > 1, <= 5 Yes EnergyGuide label rated efficiency
42454245
``HPWHDucting/ExhaustAirTermination`` string See [#]_ No <none> The location where HPWH exhaust air is ducted to
@@ -4270,7 +4270,7 @@ Each heat pump water heater is entered as a ``/HPXML/Building/BuildingDetails/Sy
42704270
.. [#] The sum of all ``FractionDHWLoadServed`` (across all WaterHeatingSystems) must equal to 1.
42714271
.. [#] FractionDHWLoadServed represents only the fraction of the hot water load associated with the hot water **fixtures**.
42724272
Additional hot water load from clothes washers/dishwashers will be automatically assigned to the appropriate water heater(s).
4273-
.. [#] If HeatingCapacity not provided, defaults to 1706 Btu/hr (0.5 kW) multiplied by the heat pump COP.
4273+
.. [#] If HeatingCapacity not provided, defaults to 1706 Btu/hr (0.5 kW).
42744274
.. [#] OpenStudio-HPXML currently only supports ExhaustAirTermination="outside" for heat pump water heaters located in conditioned space.
42754275
Any other combination of ExhaustAirTermination value and water heater location will be ignored w/ a warning.
42764276
.. [#] HPWHOperatingMode choices are "hybrid/auto" or "heat pump only".

0 commit comments

Comments
 (0)