diff --git a/BuildResidentialHPXML/README.md b/BuildResidentialHPXML/README.md
index ca91d3caac..72dd74dfa2 100644
--- a/BuildResidentialHPXML/README.md
+++ b/BuildResidentialHPXML/README.md
@@ -2544,7 +2544,7 @@ The type of heat pump. Use 'none' if there is no heat pump.
- **Required:** ``true``
-- **Choices:** `none`, `air-to-air`, `mini-split`, `ground-to-air`, `packaged terminal heat pump`, `room air conditioner with reverse cycle`
+- **Choices:** `none`, `air-to-air`, `mini-split`, `ground-to-air`, `ground-to-water w/ Ductless Fan Coil`, `packaged terminal heat pump`, `room air conditioner with reverse cycle`
- **Default:** `none`
@@ -2567,7 +2567,7 @@ The compressor type of the heat pump. Required for air-to-air, mini-split and gr
**Heat Pump: Heating Efficiency Type**
-The heating efficiency type of heat pump. System types air-to-air and mini-split use HSPF or HSPF2. System types ground-to-air, packaged terminal heat pump and room air conditioner with reverse cycle use COP.
+The heating efficiency type of heat pump. System types air-to-air and mini-split use HSPF or HSPF2. System types ground-to-air, ground-to-water, packaged terminal heat pump and room air conditioner with reverse cycle use COP.
- **Name:** ``heat_pump_heating_efficiency_type``
- **Type:** ``Choice``
@@ -2597,7 +2597,7 @@ The rated heating efficiency value of the heat pump.
**Heat Pump: Cooling Efficiency Type**
-The cooling efficiency type of heat pump. System types air-to-air and mini-split use SEER or SEER2. System types ground-to-air, packaged terminal heat pump and room air conditioner with reverse cycle use EER.
+The cooling efficiency type of heat pump. System types air-to-air and mini-split use SEER or SEER2. System types ground-to-air, ground-to-water, packaged terminal heat pump and room air conditioner with reverse cycle use EER.
- **Name:** ``heat_pump_cooling_efficiency_type``
- **Type:** ``Choice``
@@ -2667,7 +2667,7 @@ The maximum capacity limit applied to the auto-sizing methodology. If not provid
**Heat Pump: Heating Capacity Fraction at 17F**
-The output heating capacity of the heat pump at 17F divided by the above nominal heating capacity at 47F. Applies to all heat pump types except ground-to-air. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.
+The output heating capacity of the heat pump at 17F divided by the above nominal heating capacity at 47F. Applies to all heat pump types except ground-to-air and ground-to-water. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.
- **Name:** ``heat_pump_heating_capacity_fraction_17_f``
- **Type:** ``Double``
@@ -2753,7 +2753,7 @@ The cooling load served by the heat pump.
**Heat Pump: Compressor Lockout Temperature**
-The temperature below which the heat pump compressor is disabled. If both this and Backup Heating Lockout Temperature are provided and use the same value, it essentially defines a switchover temperature (for, e.g., a dual-fuel heat pump). Applies to all heat pump types other than ground-to-air. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.
+The temperature below which the heat pump compressor is disabled. If both this and Backup Heating Lockout Temperature are provided and use the same value, it essentially defines a switchover temperature (for, e.g., a dual-fuel heat pump). Applies to all heat pump types other than ground-to-air and ground-to-water. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.
- **Name:** ``heat_pump_compressor_lockout_temp``
- **Type:** ``Double``
@@ -2895,7 +2895,7 @@ The auto-sizing methodology to use when the heat pump backup capacity is not pro
**Heat Pump: Is Ducted**
-Whether the heat pump is ducted or not. Only used for mini-split. It's assumed that air-to-air and ground-to-air are ducted, and packaged terminal heat pump and room air conditioner with reverse cycle are not ducted. If not provided, assumes not ducted.
+Whether the heat pump is ducted or not. Only used for mini-split. It's assumed that air-to-air and ground-to-air are ducted, and packaged terminal heat pump, room air conditioner with reverse cycle, and ground-to-water are not ducted. If not provided, assumes not ducted.
- **Name:** ``heat_pump_is_ducted``
- **Type:** ``Boolean``
@@ -3159,7 +3159,7 @@ Maximum speed efficiency COP values of cooling detailed performance data if avai
**Geothermal Loop: Configuration**
-Configuration of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see Ground-to-Air Heat Pump) is used.
+Configuration of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see Ground-to-Air Heat Pump) is used.
- **Name:** ``geothermal_loop_configuration``
- **Type:** ``Choice``
@@ -3173,7 +3173,7 @@ Configuration of the geothermal loop. Only applies to ground-to-air heat pump ty
**Geothermal Loop: Borefield Configuration**
-Borefield configuration of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
+Borefield configuration of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_borefield_configuration``
- **Type:** ``Choice``
@@ -3187,7 +3187,7 @@ Borefield configuration of the geothermal loop. Only applies to ground-to-air he
**Geothermal Loop: Loop Flow**
-Water flow rate through the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.
+Water flow rate through the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_loop_flow``
- **Type:** ``Double``
@@ -3201,7 +3201,7 @@ Water flow rate through the geothermal loop. Only applies to ground-to-air heat
**Geothermal Loop: Boreholes Count**
-Number of boreholes. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.
+Number of boreholes. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_boreholes_count``
- **Type:** ``Integer``
@@ -3215,7 +3215,7 @@ Number of boreholes. Only applies to ground-to-air heat pump type. If not provid
**Geothermal Loop: Boreholes Length**
-Average length of each borehole (vertical). Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.
+Average length of each borehole (vertical). Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_boreholes_length``
- **Type:** ``Double``
@@ -3229,7 +3229,7 @@ Average length of each borehole (vertical). Only applies to ground-to-air heat p
**Geothermal Loop: Boreholes Spacing**
-Distance between bores. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
+Distance between bores. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_boreholes_spacing``
- **Type:** ``Double``
@@ -3243,7 +3243,7 @@ Distance between bores. Only applies to ground-to-air heat pump type. If not pro
**Geothermal Loop: Boreholes Diameter**
-Diameter of bores. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
+Diameter of bores. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_boreholes_diameter``
- **Type:** ``Double``
@@ -3257,7 +3257,7 @@ Diameter of bores. Only applies to ground-to-air heat pump type. If not provided
**Geothermal Loop: Grout Type**
-Grout type of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
+Grout type of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_grout_type``
- **Type:** ``Choice``
@@ -3271,7 +3271,7 @@ Grout type of the geothermal loop. Only applies to ground-to-air heat pump type.
**Geothermal Loop: Pipe Type**
-Pipe type of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
+Pipe type of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_pipe_type``
- **Type:** ``Choice``
@@ -3285,7 +3285,7 @@ Pipe type of the geothermal loop. Only applies to ground-to-air heat pump type.
**Geothermal Loop: Pipe Diameter**
-Pipe diameter of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
+Pipe diameter of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.
- **Name:** ``geothermal_loop_pipe_diameter``
- **Type:** ``Choice``
@@ -4433,7 +4433,7 @@ Number of bedrooms served (directly or indirectly) by the water heater. Only nee
**Water Heater: Uses Desuperheater**
-Requires that the dwelling unit has a air-to-air, mini-split, or ground-to-air heat pump or a central air conditioner or mini-split air conditioner. If not provided, assumes no desuperheater.
+Requires that the dwelling unit has a air-to-air, mini-split, ground-to-air, or ground-to-water heat pump or a central air conditioner or mini-split air conditioner. If not provided, assumes no desuperheater.
- **Name:** ``water_heater_uses_desuperheater``
- **Type:** ``Boolean``
diff --git a/BuildResidentialHPXML/measure.rb b/BuildResidentialHPXML/measure.rb
index fec02ea5d6..1815028293 100644
--- a/BuildResidentialHPXML/measure.rb
+++ b/BuildResidentialHPXML/measure.rb
@@ -1358,6 +1358,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
heat_pump_type_choices << HPXML::HVACTypeHeatPumpAirToAir
heat_pump_type_choices << HPXML::HVACTypeHeatPumpMiniSplit
heat_pump_type_choices << HPXML::HVACTypeHeatPumpGroundToAir
+ heat_pump_type_choices << "#{HPXML::HVACTypeHeatPumpGroundToWater} w/ Ductless Fan Coil"
heat_pump_type_choices << HPXML::HVACTypeHeatPumpPTHP
heat_pump_type_choices << HPXML::HVACTypeHeatPumpRoom
@@ -1399,7 +1400,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('heat_pump_heating_efficiency_type', heat_pump_heating_efficiency_type_choices, true)
arg.setDisplayName('Heat Pump: Heating Efficiency Type')
- arg.setDescription("The heating efficiency type of heat pump. System types #{HPXML::HVACTypeHeatPumpAirToAir} and #{HPXML::HVACTypeHeatPumpMiniSplit} use #{HPXML::UnitsHSPF} or #{HPXML::UnitsHSPF2}. System types #{HPXML::HVACTypeHeatPumpGroundToAir}, #{HPXML::HVACTypeHeatPumpPTHP} and #{HPXML::HVACTypeHeatPumpRoom} use #{HPXML::UnitsCOP}.")
+ arg.setDescription("The heating efficiency type of heat pump. System types #{HPXML::HVACTypeHeatPumpAirToAir} and #{HPXML::HVACTypeHeatPumpMiniSplit} use #{HPXML::UnitsHSPF} or #{HPXML::UnitsHSPF2}. System types #{HPXML::HVACTypeHeatPumpGroundToAir}, #{HPXML::HVACTypeHeatPumpGroundToWater}, #{HPXML::HVACTypeHeatPumpPTHP} and #{HPXML::HVACTypeHeatPumpRoom} use #{HPXML::UnitsCOP}.")
arg.setDefaultValue(HPXML::UnitsHSPF)
args << arg
@@ -1411,7 +1412,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('heat_pump_cooling_efficiency_type', cooling_efficiency_type_choices, true)
arg.setDisplayName('Heat Pump: Cooling Efficiency Type')
- arg.setDescription("The cooling efficiency type of heat pump. System types #{HPXML::HVACTypeHeatPumpAirToAir} and #{HPXML::HVACTypeHeatPumpMiniSplit} use #{HPXML::UnitsSEER} or #{HPXML::UnitsSEER2}. System types #{HPXML::HVACTypeHeatPumpGroundToAir}, #{HPXML::HVACTypeHeatPumpPTHP} and #{HPXML::HVACTypeHeatPumpRoom} use #{HPXML::UnitsEER}.")
+ arg.setDescription("The cooling efficiency type of heat pump. System types #{HPXML::HVACTypeHeatPumpAirToAir} and #{HPXML::HVACTypeHeatPumpMiniSplit} use #{HPXML::UnitsSEER} or #{HPXML::UnitsSEER2}. System types #{HPXML::HVACTypeHeatPumpGroundToAir}, #{HPXML::HVACTypeHeatPumpGroundToWater}, #{HPXML::HVACTypeHeatPumpPTHP} and #{HPXML::HVACTypeHeatPumpRoom} use #{HPXML::UnitsEER}.")
arg.setDefaultValue(HPXML::UnitsSEER)
args << arg
@@ -1440,7 +1441,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('heat_pump_heating_capacity_fraction_17_f', false)
arg.setDisplayName('Heat Pump: Heating Capacity Fraction at 17F')
- arg.setDescription("The output heating capacity of the heat pump at 17F divided by the above nominal heating capacity at 47F. Applies to all heat pump types except #{HPXML::HVACTypeHeatPumpGroundToAir}. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.")
+ arg.setDescription("The output heating capacity of the heat pump at 17F divided by the above nominal heating capacity at 47F. Applies to all heat pump types except #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater}. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.")
arg.setUnits('Frac')
args << arg
@@ -1477,7 +1478,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('heat_pump_compressor_lockout_temp', false)
arg.setDisplayName('Heat Pump: Compressor Lockout Temperature')
- arg.setDescription("The temperature below which the heat pump compressor is disabled. If both this and Backup Heating Lockout Temperature are provided and use the same value, it essentially defines a switchover temperature (for, e.g., a dual-fuel heat pump). Applies to all heat pump types other than #{HPXML::HVACTypeHeatPumpGroundToAir}. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.")
+ arg.setDescription("The temperature below which the heat pump compressor is disabled. If both this and Backup Heating Lockout Temperature are provided and use the same value, it essentially defines a switchover temperature (for, e.g., a dual-fuel heat pump). Applies to all heat pump types other than #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater}. If not provided, the OS-HPXML default (see Air-to-Air Heat Pump, Mini-Split Heat Pump, Packaged Terminal Heat Pump, Room Air Conditioner w/ Reverse Cycle) is used.")
arg.setUnits('F')
args << arg
@@ -1534,7 +1535,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeBoolArgument('heat_pump_is_ducted', false)
arg.setDisplayName('Heat Pump: Is Ducted')
- arg.setDescription("Whether the heat pump is ducted or not. Only used for #{HPXML::HVACTypeHeatPumpMiniSplit}. It's assumed that #{HPXML::HVACTypeHeatPumpAirToAir} and #{HPXML::HVACTypeHeatPumpGroundToAir} are ducted, and #{HPXML::HVACTypeHeatPumpPTHP} and #{HPXML::HVACTypeHeatPumpRoom} are not ducted. If not provided, assumes not ducted.")
+ arg.setDescription("Whether the heat pump is ducted or not. Only used for #{HPXML::HVACTypeHeatPumpMiniSplit}. It's assumed that #{HPXML::HVACTypeHeatPumpAirToAir} and #{HPXML::HVACTypeHeatPumpGroundToAir} are ducted, and #{HPXML::HVACTypeHeatPumpPTHP}, #{HPXML::HVACTypeHeatPumpRoom}, and #{HPXML::HVACTypeHeatPumpGroundToWater} are not ducted. If not provided, assumes not ducted.")
args << arg
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('heat_pump_airflow_defect_ratio', false)
@@ -1673,7 +1674,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_configuration', geothermal_loop_configuration_choices, false)
arg.setDisplayName('Geothermal Loop: Configuration')
- arg.setDescription("Configuration of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see Ground-to-Air Heat Pump) is used.")
+ arg.setDescription("Configuration of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML default (see Ground-to-Air Heat Pump) is used.")
args << arg
geothermal_loop_borefield_configuration_choices = OpenStudio::StringVector.new
@@ -1684,36 +1685,36 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_borefield_configuration', geothermal_loop_borefield_configuration_choices, false)
arg.setDisplayName('Geothermal Loop: Borefield Configuration')
- arg.setDescription("Borefield configuration of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Borefield configuration of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
args << arg
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_loop_flow', false)
arg.setDisplayName('Geothermal Loop: Loop Flow')
- arg.setDescription("Water flow rate through the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Water flow rate through the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.")
arg.setUnits('gpm')
args << arg
arg = OpenStudio::Measure::OSArgument::makeIntegerArgument('geothermal_loop_boreholes_count', false)
arg.setDisplayName('Geothermal Loop: Boreholes Count')
- arg.setDescription("Number of boreholes. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Number of boreholes. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.")
arg.setUnits('#')
args << arg
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_length', false)
arg.setDisplayName('Geothermal Loop: Boreholes Length')
- arg.setDescription("Average length of each borehole (vertical). Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Average length of each borehole (vertical). Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML autosized default (see HPXML Geothermal Loops) is used.")
arg.setUnits('ft')
args << arg
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_spacing', false)
arg.setDisplayName('Geothermal Loop: Boreholes Spacing')
- arg.setDescription("Distance between bores. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Distance between bores. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
arg.setUnits('ft')
args << arg
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_diameter', false)
arg.setDisplayName('Geothermal Loop: Boreholes Diameter')
- arg.setDescription("Diameter of bores. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Diameter of bores. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
arg.setUnits('in')
args << arg
@@ -1723,12 +1724,12 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_grout_type', geothermal_loop_grout_or_pipe_type_choices, false)
arg.setDisplayName('Geothermal Loop: Grout Type')
- arg.setDescription("Grout type of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Grout type of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
args << arg
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_pipe_type', geothermal_loop_grout_or_pipe_type_choices, false)
arg.setDisplayName('Geothermal Loop: Pipe Type')
- arg.setDescription("Pipe type of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Pipe type of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
args << arg
geothermal_loop_pipe_diameter_choices = OpenStudio::StringVector.new
@@ -1738,7 +1739,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_pipe_diameter', geothermal_loop_pipe_diameter_choices, false)
arg.setDisplayName('Geothermal Loop: Pipe Diameter')
- arg.setDescription("Pipe diameter of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
+ arg.setDescription("Pipe diameter of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} and #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump types. If not provided, the OS-HPXML default (see HPXML Geothermal Loops) is used.")
arg.setUnits('in')
args << arg
@@ -2331,7 +2332,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg = OpenStudio::Measure::OSArgument::makeBoolArgument('water_heater_uses_desuperheater', false)
arg.setDisplayName('Water Heater: Uses Desuperheater')
- arg.setDescription("Requires that the dwelling unit has a #{HPXML::HVACTypeHeatPumpAirToAir}, #{HPXML::HVACTypeHeatPumpMiniSplit}, or #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump or a #{HPXML::HVACTypeCentralAirConditioner} or #{HPXML::HVACTypeMiniSplitAirConditioner} air conditioner. If not provided, assumes no desuperheater.")
+ arg.setDescription("Requires that the dwelling unit has a #{HPXML::HVACTypeHeatPumpAirToAir}, #{HPXML::HVACTypeHeatPumpMiniSplit}, #{HPXML::HVACTypeHeatPumpGroundToAir}, or #{HPXML::HVACTypeHeatPumpGroundToWater} heat pump or a #{HPXML::HVACTypeCentralAirConditioner} or #{HPXML::HVACTypeMiniSplitAirConditioner} air conditioner. If not provided, assumes no desuperheater.")
args << arg
water_heater_tank_model_type_choices = OpenStudio::StringVector.new
@@ -4028,7 +4029,7 @@ def argument_warnings(args)
warning = (args[:geometry_attic_type] == HPXML::AtticTypeConditioned) && (args[:ceiling_assembly_r] > max_uninsulated_ceiling_rvalue)
warnings << 'Home with conditioned attic has ceiling insulation.' if warning
- warning = (args[:heat_pump_type] != HPXML::HVACTypeHeatPumpGroundToAir) && (!args[:geothermal_loop_configuration].nil? && args[:geothermal_loop_configuration] != Constants::None)
+ warning = (args[:heat_pump_type] != HPXML::HVACTypeHeatPumpGroundToAir) && (args[:heat_pump_type] != HPXML::HVACTypeHeatPumpGroundToWater) && (!args[:geothermal_loop_configuration].nil? && args[:geothermal_loop_configuration] != Constants::None)
warnings << 'Specified an attached geothermal loop but home has no ground source heat pump.' if warning
return warnings
@@ -6195,7 +6196,9 @@ def self.set_heat_pumps(hpxml_bldg, args)
end
end
- if [HPXML::HVACTypeHeatPumpAirToAir, HPXML::HVACTypeHeatPumpMiniSplit, HPXML::HVACTypeHeatPumpGroundToAir].include? heat_pump_type
+ if [HPXML::HVACTypeHeatPumpAirToAir,
+ HPXML::HVACTypeHeatPumpMiniSplit,
+ HPXML::HVACTypeHeatPumpGroundToAir].include?(heat_pump_type) || heat_pump_type.include?(HPXML::HVACTypeHeatPumpGroundToWater)
compressor_type = args[:heat_pump_compressor_type]
end
@@ -6232,6 +6235,10 @@ def self.set_heat_pumps(hpxml_bldg, args)
heat_pump_pan_heater_control_type = args[:heat_pump_pan_heater_control_type]
end
+ if heat_pump_type.include?(HPXML::HVACTypeHeatPumpGroundToWater)
+ heat_pump_type = HPXML::HVACTypeHeatPumpGroundToWater
+ end
+
hpxml_bldg.heat_pumps.add(id: "HeatPump#{hpxml_bldg.heat_pumps.size + 1}",
heat_pump_type: heat_pump_type,
heat_pump_fuel: HPXML::FuelTypeElectricity,
@@ -6511,6 +6518,13 @@ def self.set_hvac_distribution(hpxml_bldg, args)
fan_coil_distribution_systems << heating_system
end
end
+ hpxml_bldg.heat_pumps.each do |heat_pump|
+ next unless heat_pump.primary_system
+
+ if args[:heat_pump_type].include?('Fan Coil')
+ fan_coil_distribution_systems << heat_pump
+ end
+ end
# HydronicDistribution?
hpxml_bldg.heating_systems.each do |heating_system|
diff --git a/BuildResidentialHPXML/measure.xml b/BuildResidentialHPXML/measure.xml
index 3d6aab7333..d6657056d1 100644
--- a/BuildResidentialHPXML/measure.xml
+++ b/BuildResidentialHPXML/measure.xml
@@ -3,8 +3,8 @@
3.1
build_residential_hpxml
a13a8983-2b01-4930-8af2-42030b6e4233
- 6e33a723-8fe3-4382-be64-1ba9beb5dfb6
- 2025-08-26T22:05:09Z
+ 8f4636c3-982c-47eb-a3d1-e69d82de664f
+ 2025-09-02T22:59:47Z
2C38F48B
BuildResidentialHPXML
HPXML Builder
@@ -2824,6 +2824,10 @@
ground-to-air
ground-to-air
+
+ ground-to-water w/ Ductless Fan Coil
+ ground-to-water w/ Ductless Fan Coil
+
packaged terminal heat pump
packaged terminal heat pump
@@ -2859,7 +2863,7 @@
heat_pump_heating_efficiency_type
Heat Pump: Heating Efficiency Type
- The heating efficiency type of heat pump. System types air-to-air and mini-split use HSPF or HSPF2. System types ground-to-air, packaged terminal heat pump and room air conditioner with reverse cycle use COP.
+ The heating efficiency type of heat pump. System types air-to-air and mini-split use HSPF or HSPF2. System types ground-to-air, ground-to-water, packaged terminal heat pump and room air conditioner with reverse cycle use COP.
Choice
true
false
@@ -2891,7 +2895,7 @@
heat_pump_cooling_efficiency_type
Heat Pump: Cooling Efficiency Type
- The cooling efficiency type of heat pump. System types air-to-air and mini-split use SEER or SEER2. System types ground-to-air, packaged terminal heat pump and room air conditioner with reverse cycle use EER.
+ The cooling efficiency type of heat pump. System types air-to-air and mini-split use SEER or SEER2. System types ground-to-air, ground-to-water, packaged terminal heat pump and room air conditioner with reverse cycle use EER.
Choice
true
false
@@ -2953,7 +2957,7 @@
heat_pump_heating_capacity_fraction_17_f
Heat Pump: Heating Capacity Fraction at 17F
- The output heating capacity of the heat pump at 17F divided by the above nominal heating capacity at 47F. Applies to all heat pump types except ground-to-air. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#air-to-air-heat-pump'>Air-to-Air Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#mini-split-heat-pump'>Mini-Split Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#packaged-terminal-heat-pump'>Packaged Terminal Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#room-air-conditioner-w-reverse-cycle'>Room Air Conditioner w/ Reverse Cycle</a>) is used.
+ The output heating capacity of the heat pump at 17F divided by the above nominal heating capacity at 47F. Applies to all heat pump types except ground-to-air and ground-to-water. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#air-to-air-heat-pump'>Air-to-Air Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#mini-split-heat-pump'>Mini-Split Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#packaged-terminal-heat-pump'>Packaged Terminal Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#room-air-conditioner-w-reverse-cycle'>Room Air Conditioner w/ Reverse Cycle</a>) is used.
Double
Frac
false
@@ -3008,7 +3012,7 @@
heat_pump_compressor_lockout_temp
Heat Pump: Compressor Lockout Temperature
- The temperature below which the heat pump compressor is disabled. If both this and Backup Heating Lockout Temperature are provided and use the same value, it essentially defines a switchover temperature (for, e.g., a dual-fuel heat pump). Applies to all heat pump types other than ground-to-air. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#air-to-air-heat-pump'>Air-to-Air Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#mini-split-heat-pump'>Mini-Split Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#packaged-terminal-heat-pump'>Packaged Terminal Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#room-air-conditioner-w-reverse-cycle'>Room Air Conditioner w/ Reverse Cycle</a>) is used.
+ The temperature below which the heat pump compressor is disabled. If both this and Backup Heating Lockout Temperature are provided and use the same value, it essentially defines a switchover temperature (for, e.g., a dual-fuel heat pump). Applies to all heat pump types other than ground-to-air and ground-to-water. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#air-to-air-heat-pump'>Air-to-Air Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#mini-split-heat-pump'>Mini-Split Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#packaged-terminal-heat-pump'>Packaged Terminal Heat Pump</a>, <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#room-air-conditioner-w-reverse-cycle'>Room Air Conditioner w/ Reverse Cycle</a>) is used.
Double
F
false
@@ -3151,7 +3155,7 @@
heat_pump_is_ducted
Heat Pump: Is Ducted
- Whether the heat pump is ducted or not. Only used for mini-split. It's assumed that air-to-air and ground-to-air are ducted, and packaged terminal heat pump and room air conditioner with reverse cycle are not ducted. If not provided, assumes not ducted.
+ Whether the heat pump is ducted or not. Only used for mini-split. It's assumed that air-to-air and ground-to-air are ducted, and packaged terminal heat pump, room air conditioner with reverse cycle, and ground-to-water are not ducted. If not provided, assumes not ducted.
Boolean
false
false
@@ -3368,7 +3372,7 @@
geothermal_loop_configuration
Geothermal Loop: Configuration
- Configuration of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#ground-to-air-heat-pump'>Ground-to-Air Heat Pump</a>) is used.
+ Configuration of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#ground-to-air-heat-pump'>Ground-to-Air Heat Pump</a>) is used.
Choice
false
false
@@ -3386,7 +3390,7 @@
geothermal_loop_borefield_configuration
Geothermal Loop: Borefield Configuration
- Borefield configuration of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Borefield configuration of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Choice
false
false
@@ -3420,7 +3424,7 @@
geothermal_loop_loop_flow
Geothermal Loop: Loop Flow
- Water flow rate through the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Water flow rate through the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Double
gpm
false
@@ -3429,7 +3433,7 @@
geothermal_loop_boreholes_count
Geothermal Loop: Boreholes Count
- Number of boreholes. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Number of boreholes. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Integer
#
false
@@ -3438,7 +3442,7 @@
geothermal_loop_boreholes_length
Geothermal Loop: Boreholes Length
- Average length of each borehole (vertical). Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Average length of each borehole (vertical). Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Double
ft
false
@@ -3447,7 +3451,7 @@
geothermal_loop_boreholes_spacing
Geothermal Loop: Boreholes Spacing
- Distance between bores. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Distance between bores. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Double
ft
false
@@ -3456,7 +3460,7 @@
geothermal_loop_boreholes_diameter
Geothermal Loop: Boreholes Diameter
- Diameter of bores. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Diameter of bores. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Double
in
false
@@ -3465,7 +3469,7 @@
geothermal_loop_grout_type
Geothermal Loop: Grout Type
- Grout type of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Grout type of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Choice
false
false
@@ -3483,7 +3487,7 @@
geothermal_loop_pipe_type
Geothermal Loop: Pipe Type
- Pipe type of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Pipe type of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Choice
false
false
@@ -3501,7 +3505,7 @@
geothermal_loop_pipe_diameter
Geothermal Loop: Pipe Diameter
- Pipe diameter of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
+ Pipe diameter of the geothermal loop. Only applies to ground-to-air and ground-to-water heat pump types. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.11.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.
Choice
in
false
@@ -4786,7 +4790,7 @@
water_heater_uses_desuperheater
Water Heater: Uses Desuperheater
- Requires that the dwelling unit has a air-to-air, mini-split, or ground-to-air heat pump or a central air conditioner or mini-split air conditioner. If not provided, assumes no desuperheater.
+ Requires that the dwelling unit has a air-to-air, mini-split, ground-to-air, or ground-to-water heat pump or a central air conditioner or mini-split air conditioner. If not provided, assumes no desuperheater.
Boolean
false
false
@@ -8396,7 +8400,7 @@
README.md
md
readme
- AFA1C510
+ 40625875
README.md.erb
@@ -8413,7 +8417,7 @@
measure.rb
rb
script
- 3BF2C51B
+ 2F23596A
constants.rb
diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml
index 10a4ab12cf..4e24e20bd1 100644
--- a/HPXMLtoOpenStudio/measure.xml
+++ b/HPXMLtoOpenStudio/measure.xml
@@ -3,8 +3,8 @@
3.1
hpxm_lto_openstudio
b1543b30-9465-45ff-ba04-1d1f85e763bc
- c17fea11-5360-49b1-928e-22fe6122fd51
- 2025-08-28T03:34:02Z
+ 01ac3d88-9b68-4c6d-a84c-2941565a4191
+ 2025-09-08T21:59:26Z
D8922A73
HPXMLtoOpenStudio
HPXML to OpenStudio Translator
@@ -348,7 +348,7 @@
defaults.rb
rb
resource
- CCE4785C
+ B358A1CA
electric_panel.rb
@@ -384,7 +384,7 @@
hpxml.rb
rb
resource
- 0F94A077
+ 2F8A1285
hpxml_schema/HPXML.xsd
@@ -402,7 +402,7 @@
hpxml_schematron/EPvalidator.sch
sch
resource
- 4BBE1448
+ 813783B0
hpxml_schematron/iso-schematron.xsd
@@ -414,13 +414,13 @@
hvac.rb
rb
resource
- 1275B557
+ 0E49877A
hvac_sizing.rb
rb
resource
- 30537BFF
+ EEF8EC23
internal_gains.rb
@@ -438,7 +438,7 @@
location.rb
rb
resource
- 7DB56BD8
+ 815CA656
materials.rb
diff --git a/HPXMLtoOpenStudio/resources/defaults.rb b/HPXMLtoOpenStudio/resources/defaults.rb
index 8360166c55..ce79a7a3d3 100644
--- a/HPXMLtoOpenStudio/resources/defaults.rb
+++ b/HPXMLtoOpenStudio/resources/defaults.rb
@@ -2015,7 +2015,7 @@ def self.apply_hvac(runner, hpxml_bldg, weather, convert_shared_systems, unit_nu
hpxml_bldg.heat_pumps.each do |heat_pump|
next unless heat_pump.compressor_lockout_temp.nil?
next unless heat_pump.backup_heating_switchover_temp.nil?
- next if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ next if [HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater].include?(heat_pump.heat_pump_type)
if heat_pump.backup_type == HPXML::HeatPumpBackupTypeIntegrated
hp_backup_fuel = heat_pump.backup_heating_fuel
@@ -2042,7 +2042,7 @@ def self.apply_hvac(runner, hpxml_bldg, weather, convert_shared_systems, unit_nu
next if heat_pump.backup_type.nil?
next unless heat_pump.backup_heating_lockout_temp.nil?
next unless heat_pump.backup_heating_switchover_temp.nil?
- next if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ next if [HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater].include?(heat_pump.heat_pump_type)
if heat_pump.backup_type == HPXML::HeatPumpBackupTypeIntegrated
hp_backup_fuel = heat_pump.backup_heating_fuel
@@ -2080,13 +2080,22 @@ def self.apply_hvac(runner, hpxml_bldg, weather, convert_shared_systems, unit_nu
# GSHP pump power
hpxml_bldg.heat_pumps.each do |heat_pump|
- next unless heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ next unless [HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater].include?(heat_pump.heat_pump_type)
next unless heat_pump.pump_watts_per_ton.nil?
heat_pump.pump_watts_per_ton = get_gshp_pump_power()
heat_pump.pump_watts_per_ton_isdefaulted = true
end
+ # GSHP fan coil power
+ hpxml_bldg.heat_pumps.each do |heat_pump|
+ next unless [HPXML::HVACTypeHeatPumpGroundToWater].include?(heat_pump.heat_pump_type)
+ next unless heat_pump.fan_coil_watts.nil?
+
+ heat_pump.fan_coil_watts = get_gshp_fan_coil_power()
+ heat_pump.fan_coil_watts_isdefaulted = true
+ end
+
# Charge defect ratio
hpxml_bldg.cooling_systems.each do |cooling_system|
next unless [HPXML::HVACTypeCentralAirConditioner,
@@ -2099,7 +2108,8 @@ def self.apply_hvac(runner, hpxml_bldg, weather, convert_shared_systems, unit_nu
hpxml_bldg.heat_pumps.each do |heat_pump|
next unless [HPXML::HVACTypeHeatPumpAirToAir,
HPXML::HVACTypeHeatPumpMiniSplit,
- HPXML::HVACTypeHeatPumpGroundToAir].include? heat_pump.heat_pump_type
+ HPXML::HVACTypeHeatPumpGroundToAir,
+ HPXML::HVACTypeHeatPumpGroundToWater].include? heat_pump.heat_pump_type
next unless heat_pump.charge_defect_ratio.nil?
heat_pump.charge_defect_ratio = 0.0
@@ -2343,7 +2353,7 @@ def self.apply_hvac(runner, hpxml_bldg, weather, convert_shared_systems, unit_nu
set_hvac_cooling_performance(heat_pump, hpxml_header)
set_hvac_heating_performance(heat_pump, hpxml_header)
- when HPXML::HVACTypeHeatPumpGroundToAir
+ when HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater
set_heat_pump_control_temperatures(heat_pump, runner)
set_hvac_cooling_performance(heat_pump, hpxml_header)
set_hvac_heating_performance(heat_pump, hpxml_header)
@@ -6558,6 +6568,13 @@ def self.get_gshp_pump_power()
return 80.0 # Rough estimate based on a literature review of different studies/websites
end
+ # Gets the default fan coil power for a closed loop ground-source heat pump.
+ #
+ # @return [Double] Fan coil power (W)
+ def self.get_gshp_fan_coil_power()
+ return 150.0 # FIXME: default this, or require this?
+ end
+
# Gets the default Electric Auxiliary Energy (EAE) for a boiler.
#
# @param heating_system [HPXML::HeatingSystem] The HPXML heating system of interest
@@ -7768,6 +7785,36 @@ def self.set_ground_to_air_heat_pump_cops(heat_pump, cop_ratios, mode)
end
end
+ # TODO
+ #
+ # @param heat_pump [HPXML::HeatPump] The HPXML heat pump of interest
+ # @param cop_ratios [Array] Heating or cooling COP ratios for each speed
+ # @param mode [Symbol] Heating or cooling
+ # @return [nil]
+ def self.set_ground_to_water_heat_pump_cops(heat_pump, cop_ratios, mode)
+ hp_ap = heat_pump.additional_properties
+ # Fan/pump adjustments calculations
+ # Fan power to overcome the static pressure adjustment
+ # rated_fan_watts_per_cfm = 0.5 * heat_pump.fan_watts_per_cfm # Calculate rated fan power by assuming the power to overcome the ductwork is approximately 50% of the total fan power (ANSI/RESNET/ICC 301 says 0.2 W/cfm is the fan power associated with ductwork, but we don't know if that was a PSC or BPM fan)
+ rated_fan_watts_per_cfm = 0.25 # FIXME
+ power_f = rated_fan_watts_per_cfm * HVAC::RatedCFMPerTon / UnitConversions.convert(1.0, 'ton', 'Btu/hr') # W per Btu/hr of capacity
+ rated_pump_watts_per_ton = 30.0 # ANSI/RESNET/ICC 301, estimated pump power required to overcome the internal resistance of the ground-water heat exchanger under AHRI test conditions for a closed loop system
+ power_p = rated_pump_watts_per_ton / UnitConversions.convert(1.0, 'ton', 'Btu/hr') # result is in W per Btu/hr of capacity
+ if mode == :clg
+ eir_rated = UnitConversions.convert(((1 - UnitConversions.convert(power_f, 'Wh', 'Btu')) / heat_pump.cooling_efficiency_eer - power_f - power_p), 'Wh', 'Btu')
+ hp_ap.cool_rated_cops = []
+ for i in 0..(cop_ratios.size - 1)
+ hp_ap.cool_rated_cops << 1.0 / eir_rated * cop_ratios[i]
+ end
+ elsif mode == :htg
+ eir_rated = (1 + UnitConversions.convert(power_f, 'Wh', 'Btu')) / heat_pump.heating_efficiency_cop - UnitConversions.convert(power_f + power_p, 'Wh', 'Btu')
+ hp_ap.heat_rated_cops = []
+ for i in 0..(cop_ratios.size - 1)
+ hp_ap.heat_rated_cops << 1.0 / eir_rated * cop_ratios[i]
+ end
+ end
+ end
+
# Sets default HVAC cooling performance values.
#
# @param cooling_system [HPXML::CoolingSystem or HPXML::HeatPump] The HPXML cooling system or heat pump of interest
@@ -7804,14 +7851,105 @@ def self.interpolate_seer2(seer2, eer2, seer2_array, seer2_eer2_ratio_array, cop
clg_ap.cool_cap_fflow_spec_iq = [0.718664047, 0.41797409, -0.136638137]
clg_ap.cool_eir_fflow_spec_iq = [1.143487507, -0.13943972, -0.004047787]
- if cooling_system.is_a?(HPXML::HeatPump) && cooling_system.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
- # Based on RESNET HERS Addendum 82
- clg_ap.cool_rated_shr_gross = 0.708
- clg_ap.cool_rated_cfm_per_ton = HVAC::RatedCFMPerTon
+ if cooling_system.is_a?(HPXML::HeatPump)
+ if cooling_system.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ # Based on RESNET HERS Addendum 82
+ clg_ap.cool_rated_shr_gross = 0.708
+ clg_ap.cool_rated_cfm_per_ton = HVAC::RatedCFMPerTon
+
+ case hpxml_header.ground_to_air_heat_pump_model_type
+ when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeStandard
+ clg_ap.cool_capacity_ratios = [1.0]
+
+ # E+ equation fit coil coefficients generated following approach in Tang's thesis:
+ # See Appendix B of https://shareok.org/bitstream/handle/11244/10075/Tang_okstate_0664M_1318.pdf?sequence=1&isAllowed=y
+ # Coefficients generated by catalog data: https://files.climatemaster.com/Genesis-GS-Series-Product-Catalog.pdf, p180
+ # Data point taken as rated condition:
+ # EWT: 80F EAT:80/67F, AFR: 1200cfm, WFR: 4.5gpm
+
+ # Cooling Curves
+ clg_ap.cool_cap_curve_spec = [[-5.45013866666657, 7.42301402824225, -1.43760846638838, 0.249103937703341, 0.0378875477019811]]
+ clg_ap.cool_power_curve_spec = [[-4.21572180554818, 0.322682268675807, 4.56870615863483, 0.154605773589744, -0.167531037948482]]
+ clg_ap.cool_sh_curve_spec = [[0.56143829895505, 18.7079597251858, -19.1482655264078, -0.138154731772664, 0.4823357726442, -0.00164644360129174]]
+
+ cool_cop_ratios = [1.0]
+
+ when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental
+ case cooling_system.compressor_type
+ when HPXML::HVACCompressorTypeSingleStage
+ clg_ap.cool_capacity_ratios = [1.0]
+ # Cooling Curves
+ # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
+ # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
+ # Catalog data from : https://files.climatemaster.com/Genesis-GS-Series-Product-Catalog.pdf, p180
+ # Using E+ rated conditions:
+ # Cooling: Indoor air at 67F WB, 80F DB; Entering water temperature: 85F
+ clg_ap.cool_cap_ft_spec = [[0.3926140238, 0.0297981297, 0.0000000582, 0.0123906803, -0.0003014284, -0.0001113698]]
+ clg_ap.cool_eir_ft_spec = [[1.1828664909, -0.0450835550, 0.0009273315, 0.0056194113, 0.0006683467, -0.0007256237]]
+ clg_ap.cool_cap_fflow_spec = [[0.5068, 0.8099, -0.3165]]
+ clg_ap.cool_eir_fflow_spec = [[2.0184, -1.6182, 0.5789]]
+ clg_ap.cool_cap_fwf_spec = [[1.0, 0.0, 0.0]]
+ clg_ap.cool_eir_fwf_spec = [[1.0, 0.0, 0.0]]
+ cool_cop_ratios = [1.0]
+ when HPXML::HVACCompressorTypeTwoStage
+ clg_ap.cool_capacity_ratios = [0.7353, 1.0]
+ # Cooling Curves
+ # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
+ # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
+ # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
+ # Using E+ rated conditions:
+ # Cooling: Indoor air at 67F WB, 80F DB; Entering water temperature: 85F
+ clg_ap.cool_cap_ft_spec = [[0.4091067504, 0.0387481208, -0.0000003491, 0.0039166842, -0.0001299475, -0.0002883229],
+ [0.4423161030, 0.0346534683, 0.0000043691, 0.0046060534, -0.0001393465, -0.0002316000]]
+ clg_ap.cool_eir_ft_spec = [[1.0242580586, -0.0549907581, 0.0017735749, 0.0186562274, 0.0008900852, -0.0016973518],
+ [1.0763155558, -0.0396246303, 0.0010677382, 0.0074160145, 0.0006781567, -0.0009009811]]
+ clg_ap.cool_cap_fflow_spec = [[0.9064, 0.0793, 0.0143],
+ [0.8551, 0.1688, -0.0238]]
+ clg_ap.cool_eir_fflow_spec = [[0.7931, 0.2623, -0.0552],
+ [0.8241, 0.1523, 0.0234]]
+ clg_ap.cool_cap_fwf_spec = [[0.8387, 0.2903, -0.129],
+ [0.815, 0.325, -0.14]]
+ clg_ap.cool_eir_fwf_spec = [[1.7131, -1.3055, 0.5924],
+ [1.5872, -1.055, 0.4678]]
+
+ # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
+ cool_cop_ratios = [1.102827763, 1.0]
+ when HPXML::HVACCompressorTypeVariableSpeed
+ clg_ap.cool_capacity_ratios = [0.4802, 1.0]
+ # Cooling Curves
+ # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
+ # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
+ # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
+ # Using E+ rated conditions:
+ # Cooling: Indoor air at 67F WB, 80F DB; Entering water temperature: 85F
+ clg_ap.cool_cap_ft_spec = [[1.3397293008, -0.0474800765, 0.0021636831, 0.0055773535, -0.0002350114, -0.0002458509],
+ [1.2143128834, -0.0459226877, 0.0020331628, 0.0086998093, -0.0002669140, -0.0001763187]]
+ clg_ap.cool_eir_ft_spec = [[-0.0049682877, 0.0554193005, -0.0015790347, -0.0010670650, 0.0011493038, -0.0008236210],
+ [0.0569949694, 0.0527820535, -0.0015763180, 0.0077339260, 0.0008175629, -0.0007157989]]
+ clg_ap.cool_cap_fflow_spec = [[1.1092, -0.5299, 0.4312],
+ [0.9216, -0.1021, 0.1874]]
+ clg_ap.cool_eir_fflow_spec = [[2.2938, -2.2648, 0.9631],
+ [1.9175, -1.374, 0.4646]]
+ clg_ap.cool_cap_fwf_spec = [[1.0386, -0.2037, 0.1651],
+ [0.8606, 0.2687, -0.1293]]
+ clg_ap.cool_eir_fwf_spec = [[1.066, 0.052, -0.118],
+ [1.2961, -0.4762, 0.18]]
+
+ # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
+ cool_cop_ratios = [1.059467645, 1.0]
+ end
+ end
- case hpxml_header.ground_to_air_heat_pump_model_type
- when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeStandard
- clg_ap.cool_capacity_ratios = [1.0]
+ set_ground_to_air_heat_pump_cops(cooling_system, cool_cop_ratios, :clg)
+ return
+ elsif cooling_system.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToWater
+ # FIXME
+
+ # Based on RESNET HERS Addendum 82
+ clg_ap.cool_rated_shr_gross = 0.708
+ # clg_ap.cool_rated_cfm_per_ton = HVAC::RatedCFMPerTon
+
+ # clg_ap.cool_capacity_ratios = [1.0]
# E+ equation fit coil coefficients generated following approach in Tang's thesis:
# See Appendix B of https://shareok.org/bitstream/handle/11244/10075/Tang_okstate_0664M_1318.pdf?sequence=1&isAllowed=y
@@ -7821,79 +7959,14 @@ def self.interpolate_seer2(seer2, eer2, seer2_array, seer2_eer2_ratio_array, cop
# Cooling Curves
clg_ap.cool_cap_curve_spec = [[-5.45013866666657, 7.42301402824225, -1.43760846638838, 0.249103937703341, 0.0378875477019811]]
- clg_ap.cool_power_curve_spec = [[-4.21572180554818, 0.322682268675807, 4.56870615863483, 0.154605773589744, -0.167531037948482]]
+ # clg_ap.cool_power_curve_spec = [[-4.21572180554818, 0.322682268675807, 4.56870615863483, 0.154605773589744, -0.167531037948482]]
clg_ap.cool_sh_curve_spec = [[0.56143829895505, 18.7079597251858, -19.1482655264078, -0.138154731772664, 0.4823357726442, -0.00164644360129174]]
cool_cop_ratios = [1.0]
- when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental
- case cooling_system.compressor_type
- when HPXML::HVACCompressorTypeSingleStage
- clg_ap.cool_capacity_ratios = [1.0]
- # Cooling Curves
- # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
- # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
- # Catalog data from : https://files.climatemaster.com/Genesis-GS-Series-Product-Catalog.pdf, p180
- # Using E+ rated conditions:
- # Cooling: Indoor air at 67F WB, 80F DB; Entering water temperature: 85F
- clg_ap.cool_cap_ft_spec = [[0.3926140238, 0.0297981297, 0.0000000582, 0.0123906803, -0.0003014284, -0.0001113698]]
- clg_ap.cool_eir_ft_spec = [[1.1828664909, -0.0450835550, 0.0009273315, 0.0056194113, 0.0006683467, -0.0007256237]]
- clg_ap.cool_cap_fflow_spec = [[0.5068, 0.8099, -0.3165]]
- clg_ap.cool_eir_fflow_spec = [[2.0184, -1.6182, 0.5789]]
- clg_ap.cool_cap_fwf_spec = [[1.0, 0.0, 0.0]]
- clg_ap.cool_eir_fwf_spec = [[1.0, 0.0, 0.0]]
- cool_cop_ratios = [1.0]
- when HPXML::HVACCompressorTypeTwoStage
- clg_ap.cool_capacity_ratios = [0.7353, 1.0]
- # Cooling Curves
- # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
- # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
- # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
- # Using E+ rated conditions:
- # Cooling: Indoor air at 67F WB, 80F DB; Entering water temperature: 85F
- clg_ap.cool_cap_ft_spec = [[0.4091067504, 0.0387481208, -0.0000003491, 0.0039166842, -0.0001299475, -0.0002883229],
- [0.4423161030, 0.0346534683, 0.0000043691, 0.0046060534, -0.0001393465, -0.0002316000]]
- clg_ap.cool_eir_ft_spec = [[1.0242580586, -0.0549907581, 0.0017735749, 0.0186562274, 0.0008900852, -0.0016973518],
- [1.0763155558, -0.0396246303, 0.0010677382, 0.0074160145, 0.0006781567, -0.0009009811]]
- clg_ap.cool_cap_fflow_spec = [[0.9064, 0.0793, 0.0143],
- [0.8551, 0.1688, -0.0238]]
- clg_ap.cool_eir_fflow_spec = [[0.7931, 0.2623, -0.0552],
- [0.8241, 0.1523, 0.0234]]
- clg_ap.cool_cap_fwf_spec = [[0.8387, 0.2903, -0.129],
- [0.815, 0.325, -0.14]]
- clg_ap.cool_eir_fwf_spec = [[1.7131, -1.3055, 0.5924],
- [1.5872, -1.055, 0.4678]]
-
- # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
- cool_cop_ratios = [1.102827763, 1.0]
- when HPXML::HVACCompressorTypeVariableSpeed
- clg_ap.cool_capacity_ratios = [0.4802, 1.0]
- # Cooling Curves
- # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
- # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
- # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
- # Using E+ rated conditions:
- # Cooling: Indoor air at 67F WB, 80F DB; Entering water temperature: 85F
- clg_ap.cool_cap_ft_spec = [[1.3397293008, -0.0474800765, 0.0021636831, 0.0055773535, -0.0002350114, -0.0002458509],
- [1.2143128834, -0.0459226877, 0.0020331628, 0.0086998093, -0.0002669140, -0.0001763187]]
- clg_ap.cool_eir_ft_spec = [[-0.0049682877, 0.0554193005, -0.0015790347, -0.0010670650, 0.0011493038, -0.0008236210],
- [0.0569949694, 0.0527820535, -0.0015763180, 0.0077339260, 0.0008175629, -0.0007157989]]
- clg_ap.cool_cap_fflow_spec = [[1.1092, -0.5299, 0.4312],
- [0.9216, -0.1021, 0.1874]]
- clg_ap.cool_eir_fflow_spec = [[2.2938, -2.2648, 0.9631],
- [1.9175, -1.374, 0.4646]]
- clg_ap.cool_cap_fwf_spec = [[1.0386, -0.2037, 0.1651],
- [0.8606, 0.2687, -0.1293]]
- clg_ap.cool_eir_fwf_spec = [[1.066, 0.052, -0.118],
- [1.2961, -0.4762, 0.18]]
-
- # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
- cool_cop_ratios = [1.059467645, 1.0]
- end
- end
-
- set_ground_to_air_heat_pump_cops(cooling_system, cool_cop_ratios, :clg)
- return
+ set_ground_to_water_heat_pump_cops(cooling_system, cool_cop_ratios, :clg)
+ return
+ end
end
# Based on RESNET HERS Addendum 82
@@ -8011,13 +8084,95 @@ def self.interpolate_hspf2(hspf2, qm17full, hspf2_array, qm17full_array, cop47fu
htg_ap.heat_cap_fflow_spec_iq = [0.694045465, 0.474207981, -0.168253446]
htg_ap.heat_eir_fflow_spec_iq = [2.185418751, -1.942827919, 0.757409168]
- if heating_system.is_a?(HPXML::HeatPump) && heating_system.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
- # Based on RESNET HERS Addendum 82
- htg_ap.heat_rated_cfm_per_ton = HVAC::RatedCFMPerTon
+ if heating_system.is_a?(HPXML::HeatPump)
+ if heating_system.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ # Based on RESNET HERS Addendum 82
+ htg_ap.heat_rated_cfm_per_ton = HVAC::RatedCFMPerTon
+
+ case hpxml_header.ground_to_air_heat_pump_model_type
+ when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeStandard
+ htg_ap.heat_capacity_ratios = [1.0]
+ # E+ equation fit coil coefficients following approach from Tang's thesis:
+ # See Appendix B Figure B.3 of https://shareok.org/bitstream/handle/11244/10075/Tang_okstate_0664M_1318.pdf?sequence=1&isAllowed=y
+ # Coefficients generated by catalog data: https://www.climatemaster.com/download/18.274be999165850ccd5b5b73/1535543867815/lc377-climatemaster-commercial-tranquility-20-single-stage-ts-series-water-source-heat-pump-submittal-set.pdf
+ # Data point taken as rated condition:
+ # EWT: 60F EAT: 70F AFR: 1200 cfm, WFR: 4.5 gpm
+
+ # Heating Curves
+ htg_ap.heat_cap_curve_spec = [[-3.75031847962047, -2.18062040443483, 6.8363364819032, 0.188376814356582, 0.0869274802923634]]
+ htg_ap.heat_power_curve_spec = [[-8.4754723813072, 8.10952801956388, 1.38771494628738, -0.33766445915032, 0.0223085217874051]]
+ heat_cop_ratios = [1.0]
+ when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental
+ case heating_system.compressor_type
+ when HPXML::HVACCompressorTypeSingleStage
+ htg_ap.heat_capacity_ratios = [1.0]
+ # Heating Curves
+ # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
+ # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
+ # Catalog data from : https://files.climatemaster.com/Genesis-GS-Series-Product-Catalog.pdf, p180
+ # Using E+ rated conditions:
+ # Heating: Indoor air at 70F DB; Entering water temperature: 70F
+ htg_ap.heat_cap_ft_spec = [[0.7353127278, -0.0035056759, -0.0000439615, 0.0204411095, -0.0000320781, -0.0001322685]]
+ htg_ap.heat_eir_ft_spec = [[0.6273820540, 0.0124891750, 0.0012720188, -0.0151581268, 0.0004164343, -0.0007259611]]
+ htg_ap.heat_cap_fflow_spec = [[0.7594, 0.3642, -0.1234]]
+ htg_ap.heat_eir_fflow_spec = [[2.796, -3.0886, 1.3858]]
+ htg_ap.heat_cap_fwf_spec = [[1.0, 0.0, 0.0]]
+ htg_ap.heat_eir_fwf_spec = [[1.0, 0.0, 0.0]]
+ heat_cop_ratios = [1.0]
+ when HPXML::HVACCompressorTypeTwoStage
+ htg_ap.heat_capacity_ratios = [0.7374, 1.0]
+ # Heating Curves
+ # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
+ # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
+ # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
+ # Using E+ rated conditions:
+ # Heating: Indoor air at 70F DB; Entering water temperature: 70F
+ htg_ap.heat_cap_ft_spec = [[0.6523957849, -0.0011387222, 0.0000000000, 0.0191295958, -0.0000411533, -0.0000311030],
+ [0.6668920089, -0.0015817909, 0.0000027692, 0.0189198107, -0.0000372655, -0.0000393615]]
+ htg_ap.heat_eir_ft_spec = [[0.8057698794, 0.0316014252, 0.0000380531, -0.0228123504, 0.0004336379, -0.0004522084],
+ [0.8046419585, 0.0233384227, 0.0000376912, -0.0170224134, 0.0003382804, -0.0002368130]]
+ htg_ap.heat_cap_fflow_spec = [[0.8649, 0.1112, 0.0238],
+ [0.8264, 0.1593, 0.0143]]
+ htg_ap.heat_eir_fflow_spec = [[1.2006, -0.1943, -0.0062],
+ [1.2568, -0.2856, 0.0288]]
+ htg_ap.heat_cap_fwf_spec = [[0.7112, 0.5027, -0.2139],
+ [0.769, 0.399, -0.168]]
+ htg_ap.heat_eir_fwf_spec = [[1.3457, -0.6658, 0.3201],
+ [1.1679, -0.3215, 0.1535]]
+ # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
+ heat_cop_ratios = [1.161791639, 1.0]
+ when HPXML::HVACCompressorTypeVariableSpeed
+ htg_ap.heat_capacity_ratios = [0.4473, 1.0]
+ # Heating Curves
+ # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
+ # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
+ # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
+ # Using E+ rated conditions:
+ # Heating: Indoor air at 70F DB; Entering water temperature: 70F
+ htg_ap.heat_cap_ft_spec = [[0.6955336002, -0.0028528869, -0.0000005012, 0.0201138223, -0.0000590002, -0.0000749701],
+ [0.6975737864, -0.0028810803, -0.0000005015, 0.0206468583, -0.0000891526, -0.0000733087]]
+ htg_ap.heat_eir_ft_spec = [[0.8755777079, 0.0309984461, 0.0001099592, -0.0174543325, 0.0001819203, -0.0004948405],
+ [0.7627294076, 0.0273612308, 0.0001023412, -0.0145638547, 0.0001886431, -0.0003647958]]
+ htg_ap.heat_cap_fflow_spec = [[0.8676, 0.1122, 0.0195],
+ [0.9498, -0.0298, 0.0812]]
+ htg_ap.heat_eir_fflow_spec = [[1.4426, -0.4465, 0.0064],
+ [1.1158, 0.282, -0.4071]]
+ htg_ap.heat_cap_fwf_spec = [[0.8364, 0.197, -0.0333],
+ [0.727, 0.55, -0.277]]
+ htg_ap.heat_eir_fwf_spec = [[1.3491, -0.7744, 0.4253],
+ [1.0833, -0.1351, 0.0517]]
+ # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
+ heat_cop_ratios = [1.15012987, 1.0]
+ end
+ end
- case hpxml_header.ground_to_air_heat_pump_model_type
- when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeStandard
- htg_ap.heat_capacity_ratios = [1.0]
+ set_ground_to_air_heat_pump_cops(heating_system, heat_cop_ratios, :htg)
+ return
+ elsif heating_system.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToWater
+ # Based on RESNET HERS Addendum 82
+ # htg_ap.heat_rated_cfm_per_ton = HVAC::RatedCFMPerTon
+
+ # htg_ap.heat_capacity_ratios = [1.0]
# E+ equation fit coil coefficients following approach from Tang's thesis:
# See Appendix B Figure B.3 of https://shareok.org/bitstream/handle/11244/10075/Tang_okstate_0664M_1318.pdf?sequence=1&isAllowed=y
# Coefficients generated by catalog data: https://www.climatemaster.com/download/18.274be999165850ccd5b5b73/1535543867815/lc377-climatemaster-commercial-tranquility-20-single-stage-ts-series-water-source-heat-pump-submittal-set.pdf
@@ -8026,74 +8181,12 @@ def self.interpolate_hspf2(hspf2, qm17full, hspf2_array, qm17full_array, cop47fu
# Heating Curves
htg_ap.heat_cap_curve_spec = [[-3.75031847962047, -2.18062040443483, 6.8363364819032, 0.188376814356582, 0.0869274802923634]]
- htg_ap.heat_power_curve_spec = [[-8.4754723813072, 8.10952801956388, 1.38771494628738, -0.33766445915032, 0.0223085217874051]]
+ # htg_ap.heat_power_curve_spec = [[-8.4754723813072, 8.10952801956388, 1.38771494628738, -0.33766445915032, 0.0223085217874051]]
heat_cop_ratios = [1.0]
- when HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental
- case heating_system.compressor_type
- when HPXML::HVACCompressorTypeSingleStage
- htg_ap.heat_capacity_ratios = [1.0]
- # Heating Curves
- # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
- # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
- # Catalog data from : https://files.climatemaster.com/Genesis-GS-Series-Product-Catalog.pdf, p180
- # Using E+ rated conditions:
- # Heating: Indoor air at 70F DB; Entering water temperature: 70F
- htg_ap.heat_cap_ft_spec = [[0.7353127278, -0.0035056759, -0.0000439615, 0.0204411095, -0.0000320781, -0.0001322685]]
- htg_ap.heat_eir_ft_spec = [[0.6273820540, 0.0124891750, 0.0012720188, -0.0151581268, 0.0004164343, -0.0007259611]]
- htg_ap.heat_cap_fflow_spec = [[0.7594, 0.3642, -0.1234]]
- htg_ap.heat_eir_fflow_spec = [[2.796, -3.0886, 1.3858]]
- htg_ap.heat_cap_fwf_spec = [[1.0, 0.0, 0.0]]
- htg_ap.heat_eir_fwf_spec = [[1.0, 0.0, 0.0]]
- heat_cop_ratios = [1.0]
- when HPXML::HVACCompressorTypeTwoStage
- htg_ap.heat_capacity_ratios = [0.7374, 1.0]
- # Heating Curves
- # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
- # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
- # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
- # Using E+ rated conditions:
- # Heating: Indoor air at 70F DB; Entering water temperature: 70F
- htg_ap.heat_cap_ft_spec = [[0.6523957849, -0.0011387222, 0.0000000000, 0.0191295958, -0.0000411533, -0.0000311030],
- [0.6668920089, -0.0015817909, 0.0000027692, 0.0189198107, -0.0000372655, -0.0000393615]]
- htg_ap.heat_eir_ft_spec = [[0.8057698794, 0.0316014252, 0.0000380531, -0.0228123504, 0.0004336379, -0.0004522084],
- [0.8046419585, 0.0233384227, 0.0000376912, -0.0170224134, 0.0003382804, -0.0002368130]]
- htg_ap.heat_cap_fflow_spec = [[0.8649, 0.1112, 0.0238],
- [0.8264, 0.1593, 0.0143]]
- htg_ap.heat_eir_fflow_spec = [[1.2006, -0.1943, -0.0062],
- [1.2568, -0.2856, 0.0288]]
- htg_ap.heat_cap_fwf_spec = [[0.7112, 0.5027, -0.2139],
- [0.769, 0.399, -0.168]]
- htg_ap.heat_eir_fwf_spec = [[1.3457, -0.6658, 0.3201],
- [1.1679, -0.3215, 0.1535]]
- # Catalog data from ClimateMaster residential tranquility 30 premier two-stage series Model SE036: https://files.climatemaster.com/RP3001-Residential-SE-Product-Catalog.pdf
- heat_cop_ratios = [1.161791639, 1.0]
- when HPXML::HVACCompressorTypeVariableSpeed
- htg_ap.heat_capacity_ratios = [0.4473, 1.0]
- # Heating Curves
- # E+ Capacity and EIR as function of temperature curves(bi-quadratic) generated using E+ HVACCurveFitTool
- # See: https://bigladdersoftware.com/epx/docs/24-2/auxiliary-programs/hvac-performance-curve-fit-tool.html#hvac-performance-curve-fit-tool
- # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
- # Using E+ rated conditions:
- # Heating: Indoor air at 70F DB; Entering water temperature: 70F
- htg_ap.heat_cap_ft_spec = [[0.6955336002, -0.0028528869, -0.0000005012, 0.0201138223, -0.0000590002, -0.0000749701],
- [0.6975737864, -0.0028810803, -0.0000005015, 0.0206468583, -0.0000891526, -0.0000733087]]
- htg_ap.heat_eir_ft_spec = [[0.8755777079, 0.0309984461, 0.0001099592, -0.0174543325, 0.0001819203, -0.0004948405],
- [0.7627294076, 0.0273612308, 0.0001023412, -0.0145638547, 0.0001886431, -0.0003647958]]
- htg_ap.heat_cap_fflow_spec = [[0.8676, 0.1122, 0.0195],
- [0.9498, -0.0298, 0.0812]]
- htg_ap.heat_eir_fflow_spec = [[1.4426, -0.4465, 0.0064],
- [1.1158, 0.282, -0.4071]]
- htg_ap.heat_cap_fwf_spec = [[0.8364, 0.197, -0.0333],
- [0.727, 0.55, -0.277]]
- htg_ap.heat_eir_fwf_spec = [[1.3491, -0.7744, 0.4253],
- [1.0833, -0.1351, 0.0517]]
- # Catalog data from WaterFurnace 7 Series 700A11: https://www.waterfurnace.com/literature/7series/SDW7-0018W.pdf
- heat_cop_ratios = [1.15012987, 1.0]
- end
- end
-
- set_ground_to_air_heat_pump_cops(heating_system, heat_cop_ratios, :htg)
- return
+
+ set_ground_to_water_heat_pump_cops(heating_system, heat_cop_ratios, :htg)
+ return
+ end
end
htg_ap.heat_cap_fflow_spec = htg_ap.heat_cap_fflow_spec_iq
diff --git a/HPXMLtoOpenStudio/resources/hpxml.rb b/HPXMLtoOpenStudio/resources/hpxml.rb
index 6be98943da..50d39d09a7 100644
--- a/HPXMLtoOpenStudio/resources/hpxml.rb
+++ b/HPXMLtoOpenStudio/resources/hpxml.rb
@@ -252,6 +252,7 @@ class HPXML < Object
HVACTypeFurnace = 'Furnace'
HVACTypeHeatPumpAirToAir = 'air-to-air'
HVACTypeHeatPumpGroundToAir = 'ground-to-air'
+ HVACTypeHeatPumpGroundToWater = 'ground-to-water'
HVACTypeHeatPumpMiniSplit = 'mini-split'
HVACTypeHeatPumpWaterLoopToAir = 'water-loop-to-air'
HVACTypeHeatPumpPTHP = 'packaged terminal heat pump'
@@ -7045,6 +7046,7 @@ def initialize(hpxml_element, *args, **kwargs)
:pump_watts_per_ton, # [Double] extension/PumpPowerWattsPerTon (W/ton)
:shared_loop_watts, # [Double] extension/SharedLoopWatts (W)
:shared_loop_motor_efficiency, # [Double] extension/SharedLoopMotorEfficiency (frac)
+ :fan_coil_watts, # [Double] extension/FanCoilWatts (W)
:crankcase_heater_watts, # [Double] extension/CrankcaseHeaterPowerWatts (W)
:pan_heater_watts, # [Double] extension/PanHeaterPowerWatts (W)
:pan_heater_control_type, # [String] extension/PanHeaterControlType (HPXML::HVACPanHeaterControlTypeXXX)
@@ -7306,6 +7308,7 @@ def to_doc(building)
XMLHelper.add_extension(heat_pump, 'PumpPowerWattsPerTon', @pump_watts_per_ton, :float, @pump_watts_per_ton_isdefaulted) unless @pump_watts_per_ton.nil?
XMLHelper.add_extension(heat_pump, 'SharedLoopWatts', @shared_loop_watts, :float) unless @shared_loop_watts.nil?
XMLHelper.add_extension(heat_pump, 'SharedLoopMotorEfficiency', @shared_loop_motor_efficiency, :float) unless @shared_loop_motor_efficiency.nil?
+ XMLHelper.add_extension(heat_pump, 'FanCoilWatts', @fan_coil_watts, :float) unless @fan_coil_watts.nil?
XMLHelper.add_extension(heat_pump, 'CrankcaseHeaterPowerWatts', @crankcase_heater_watts, :float, @crankcase_heater_watts_isdefaulted) unless @crankcase_heater_watts.nil?
XMLHelper.add_extension(heat_pump, 'PanHeaterPowerWatts', @pan_heater_watts, :float, @pan_heater_watts_isdefaulted) unless @pan_heater_watts.nil?
XMLHelper.add_extension(heat_pump, 'PanHeaterControlType', @pan_heater_control_type, :string, @pan_heater_control_type_isdefaulted) unless @pan_heater_control_type.nil?
@@ -7382,6 +7385,7 @@ def from_doc(heat_pump)
@pump_watts_per_ton = XMLHelper.get_value(heat_pump, 'extension/PumpPowerWattsPerTon', :float)
@shared_loop_watts = XMLHelper.get_value(heat_pump, 'extension/SharedLoopWatts', :float)
@shared_loop_motor_efficiency = XMLHelper.get_value(heat_pump, 'extension/SharedLoopMotorEfficiency', :float)
+ @fan_coil_watts = XMLHelper.get_value(heat_pump, 'extension/FanCoilWatts', :float)
@crankcase_heater_watts = XMLHelper.get_value(heat_pump, 'extension/CrankcaseHeaterPowerWatts', :float)
@pan_heater_watts = XMLHelper.get_value(heat_pump, 'extension/PanHeaterPowerWatts', :float)
@pan_heater_control_type = XMLHelper.get_value(heat_pump, 'extension/PanHeaterControlType', :string)
diff --git a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.sch b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.sch
index 127cea9d40..9a5a93606f 100644
--- a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.sch
+++ b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.sch
@@ -1484,8 +1484,8 @@
Expected 0 or 1 element(s) for xpath: AttachedToZone
Expected 1 element(s) for xpath: ../../HVACControl
- Expected 1 element(s) for xpath: HeatPumpType
- Expected HeatPumpType to be 'air-to-air' or 'mini-split' or 'ground-to-air' or 'water-loop-to-air' or 'packaged terminal heat pump' or 'room air conditioner with reverse cycle'
+ Expected 1 element(s) for xpath: HeatPumpType
+ Expected HeatPumpType to be 'air-to-air' or 'mini-split' or 'ground-to-air' or 'water-loop-to-air' or 'packaged terminal heat pump' or 'room air conditioner with reverse cycle'
Expected 0 or 1 element(s) for xpath: extension/CoolingAutosizingFactor
Expected 0 or 1 element(s) for xpath: extension/HeatingAutosizingFactor
CoolingAutosizingFactor should be greater than 0.0
@@ -1628,19 +1628,19 @@
- [HeatPumpType=GroundSource]
+ [HeatPumpType=GroundSourceToAir]
Expected 1 or more element(s) for xpath: ../../HVACDistribution/DistributionSystemType/AirDistribution/AirDistributionType[text()="regular velocity"] | ../../HVACDistribution/DistributionSystemType/Other[text()="DSE"]
Expected 0 or 1 element(s) for xpath: UnitLocation
Expected UnitLocation to be 'conditioned space' or 'basement - unconditioned' or 'basement - conditioned' or 'attic - unvented' or 'attic - vented' or 'garage' or 'crawlspace - unvented' or 'crawlspace - vented' or 'crawlspace - conditioned' or 'other exterior' or 'other housing unit' or 'other heated space' or 'other multifamily buffer space' or 'other non-freezing space' or 'roof deck' or 'unconditioned space' or 'manufactured home belly'
Expected 1 element(s) for xpath: DistributionSystem
- Expected 0 or 1 element(s) for xpath: IsSharedSystem
+ Expected 0 or 1 element(s) for xpath: IsSharedSystem
Expected 1 element(s) for xpath: HeatPumpFuel
Expected HeatPumpFuel to be 'electricity'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
Expected 0 or 1 element(s) for xpath: CoolingCapacity
Expected 1 element(s) for xpath: CompressorType
- Expected CompressorType to be 'single stage' or 'two stage' or 'variable speed'
+ Expected CompressorType to be 'single stage' or 'two stage' or 'variable speed'
Expected 0 or 1 element(s) for xpath: BackupType
Expected BackupType to be 'integrated' or 'separate'
Expected 0 element(s) for xpath: BackupHeatingSwitchoverTemperature
@@ -1674,13 +1674,61 @@
- [HeatPumpType=GroundSourceWithSharedLoop]
+ [HeatPumpType=GroundSourceToWater]
+
+ Expected 1 or more element(s) for xpath: ../../HVACDistribution/DistributionSystemType/AirDistribution/AirDistributionType[text()="fan coil"] | ../../HVACDistribution/DistributionSystemType/Other[text()="DSE"]
+ Expected 0 or 1 element(s) for xpath: UnitLocation
+ Expected UnitLocation to be 'conditioned space' or 'basement - unconditioned' or 'basement - conditioned' or 'attic - unvented' or 'attic - vented' or 'garage' or 'crawlspace - unvented' or 'crawlspace - vented' or 'crawlspace - conditioned' or 'other exterior' or 'other housing unit' or 'other heated space' or 'other multifamily buffer space' or 'other non-freezing space' or 'roof deck' or 'unconditioned space' or 'manufactured home belly'
+ Expected 1 element(s) for xpath: DistributionSystem
+ Expected 0 or 1 element(s) for xpath: IsSharedSystem
+ Expected 1 element(s) for xpath: HeatPumpFuel
+ Expected HeatPumpFuel to be 'electricity'
+ Expected 0 or 1 element(s) for xpath: HeatingCapacity
+ Expected 0 or 1 element(s) for xpath: CoolingCapacity
+ Expected 1 element(s) for xpath: CompressorType
+ Expected CompressorType to be 'single stage'
+ Expected 0 or 1 element(s) for xpath: BackupType
+ Expected BackupType to be 'integrated' or 'separate'
+ Expected 0 element(s) for xpath: BackupHeatingSwitchoverTemperature
+ Expected 1 element(s) for xpath: FractionHeatLoadServed
+ Expected 1 element(s) for xpath: FractionCoolLoadServed
+ Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="EER"]/Value
+ Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="COP"]/Value
+ Expected 0 or 1 element(s) for xpath: AttachedToGeothermalLoop
+ Expected 0 or 1 element(s) for xpath: extension/PumpPowerWattsPerTon
+ Expected extension/PumpPowerWattsPerTon to be greater than or equal to 0
+ Expected 0 or 1 element(s) for xpath: extension/FanCoilWatts
+ Expected extension/FanCoilWatts to be greater than or equal to 0
+ Expected 0 or 1 element(s) for xpath: extension/ChargeDefectRatio
+ Expected extension/ChargeDefectRatio to be greater than or equal to -0.9
+ Expected extension/ChargeDefectRatio to be less than or equal to 9
+
+ EER should typically be greater than or equal to 6.
+ COP should typically be greater than or equal to 2.
+ Heating capacity should typically be greater than or equal to 1000 Btu/hr.
+ Cooling capacity should typically be greater than or equal to 1000 Btu/hr.
+
+
+
+
+ [HeatPumpType=GroundSourceToAirWithSharedLoop]
Expected 1 element(s) for xpath: ../../../../BuildingSummary/BuildingConstruction[ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]]
Expected 1 element(s) for xpath: NumberofUnitsServed
Expected NumberofUnitsServed to be greater than 1
Expected 1 element(s) for xpath: extension/SharedLoopWatts
- Expected extension/SharedLoopWatts to be greater than or equal to 0
+ Expected extension/SharedLoopWatts to be greater than or equal to 0
+
+
+
+
+ [HeatPumpType=GroundSourceToWaterWithSharedLoop]
+
+ Expected 1 element(s) for xpath: ../../../../BuildingSummary/BuildingConstruction[ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]]
+ Expected 1 element(s) for xpath: NumberofUnitsServed
+ Expected NumberofUnitsServed to be greater than 1
+ Expected 1 element(s) for xpath: extension/SharedLoopWatts
+ Expected extension/SharedLoopWatts to be greater than or equal to 0
diff --git a/HPXMLtoOpenStudio/resources/hvac.rb b/HPXMLtoOpenStudio/resources/hvac.rb
index a5a4611044..3dade1169a 100644
--- a/HPXMLtoOpenStudio/resources/hvac.rb
+++ b/HPXMLtoOpenStudio/resources/hvac.rb
@@ -221,7 +221,7 @@ def self.apply_heat_pump(runner, model, weather, spaces, hpxml_bldg, hpxml_heade
HPXML::HVACTypeHeatPumpPTHP, HPXML::HVACTypeHeatPumpRoom
airloop_map[sys_id] = apply_air_source_hvac_systems(runner, model, weather, hpxml_bldg, hpxml_header, heat_pump, heat_pump,
hvac_sequential_load_fracs, conditioned_zone, hvac_unavailable_periods, schedules_file)
- when HPXML::HVACTypeHeatPumpGroundToAir
+ when HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater
airloop_map[sys_id] = apply_ground_source_heat_pump(runner, model, weather, hpxml_bldg, hpxml_header, heat_pump,
hvac_sequential_load_fracs, conditioned_zone, hvac_unavailable_periods)
end
@@ -534,7 +534,7 @@ def self.apply_evaporative_cooler(model, hpxml_bldg, cooling_system, hvac_sequen
# @param hvac_sequential_load_fracs [Hash>] Map of htg/clg => Array of daily fractions of remaining heating/cooling load to be met by the HVAC system
# @param control_zone [OpenStudio::Model::ThermalZone] Conditioned space thermal zone
# @param hvac_unavailable_periods [Hash] Map of htg/clg => HPXML::UnavailablePeriods for heating/cooling
- # @return [OpenStudio::Model::AirLoopHVAC] The newly created air loop hvac object
+ # @return [OpenStudio::Model::AirLoopHVAC or OpenStudio::Model::ZoneHVACFourPipeFanCoil] The newly created air loop or zone hvac object
def self.apply_ground_source_heat_pump(runner, model, weather, hpxml_bldg, hpxml_header, heat_pump,
hvac_sequential_load_fracs, control_zone, hvac_unavailable_periods)
@@ -550,11 +550,6 @@ def self.apply_ground_source_heat_pump(runner, model, weather, hpxml_bldg, hpxml
geothermal_loop = heat_pump.geothermal_loop
hp_ap = heat_pump.additional_properties
- htg_cfm = hp_ap.heating_actual_airflow_cfm
- clg_cfm = hp_ap.cooling_actual_airflow_cfm
- htg_air_flow_rated = calc_rated_airflow(heat_pump.heating_capacity, hp_ap.heat_rated_cfm_per_ton, 'm^3/s')
- clg_air_flow_rated = calc_rated_airflow(heat_pump.cooling_capacity, hp_ap.cool_rated_cfm_per_ton, 'm^3/s')
-
if hp_ap.frac_glycol == 0
hp_ap.fluid_type = EPlus::FluidWater
runner.registerWarning("Specified #{hp_ap.fluid_type} fluid type and 0 fraction of glycol, so assuming #{EPlus::FluidWater} fluid type.")
@@ -564,212 +559,245 @@ def self.apply_ground_source_heat_pump(runner, model, weather, hpxml_bldg, hpxml
geothermal_loop.loop_flow *= unit_multiplier
geothermal_loop.num_bore_holes *= unit_multiplier
- if [HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeStandard].include? hpxml_header.ground_to_air_heat_pump_model_type
- # Cooling Coil
- clg_total_cap_curve = Model.add_curve_quad_linear(
- model,
- name: "#{obj_name} clg total cap curve",
- coeff: hp_ap.cool_cap_curve_spec[0]
- )
- clg_sens_cap_curve = Model.add_curve_quint_linear(
- model,
- name: "#{obj_name} clg sens cap curve",
- coeff: hp_ap.cool_sh_curve_spec[0]
- )
- clg_power_curve = Model.add_curve_quad_linear(
- model,
- name: "#{obj_name} clg power curve",
- coeff: hp_ap.cool_power_curve_spec[0]
- )
- clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model, clg_total_cap_curve, clg_sens_cap_curve, clg_power_curve)
- clg_coil.setName(obj_name + ' clg coil')
- clg_coil.setRatedCoolingCoefficientofPerformance(hp_ap.cool_rated_cops[0])
- clg_coil.setNominalTimeforCondensateRemovaltoBegin(1000)
- clg_coil.setRatioofInitialMoistureEvaporationRateandSteadyStateLatentCapacity(1.5)
- clg_coil.setRatedAirFlowRate(clg_air_flow_rated)
- clg_coil.setRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
- clg_coil.setRatedEnteringWaterTemperature(UnitConversions.convert(80, 'F', 'C'))
- clg_coil.setRatedEnteringAirDryBulbTemperature(UnitConversions.convert(80, 'F', 'C'))
- clg_coil.setRatedEnteringAirWetBulbTemperature(UnitConversions.convert(67, 'F', 'C'))
- # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
- clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W'))
- clg_coil.setRatedSensibleCoolingCapacity(UnitConversions.convert(heat_pump.cooling_capacity * hp_ap.cool_rated_shr_gross, 'Btu/hr', 'W'))
- # Heating Coil
- htg_cap_curve = Model.add_curve_quad_linear(
- model,
- name: "#{obj_name} htg cap curve",
- coeff: hp_ap.heat_cap_curve_spec[0]
- )
- htg_power_curve = Model.add_curve_quad_linear(
- model,
- name: "#{obj_name} htg power curve",
- coeff: hp_ap.heat_power_curve_spec[0]
- )
- htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model, htg_cap_curve, htg_power_curve)
- htg_coil.setName(obj_name + ' htg coil')
- htg_coil.setRatedHeatingCoefficientofPerformance(hp_ap.heat_rated_cops[0])
- htg_coil.setRatedAirFlowRate(htg_air_flow_rated)
- htg_coil.setRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
- htg_coil.setRatedEnteringWaterTemperature(UnitConversions.convert(60, 'F', 'C'))
- htg_coil.setRatedEnteringAirDryBulbTemperature(UnitConversions.convert(70, 'F', 'C'))
- # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
- htg_coil.setRatedHeatingCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
- elsif [HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental].include? hpxml_header.ground_to_air_heat_pump_model_type
- num_speeds = hp_ap.cool_capacity_ratios.size
- if heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
- plf_fplr_curve = Model.add_curve_quadratic(
- model,
- name: 'Cool-PLF-fPLR',
- coeff: [1.0, 0.0, 0.0],
- min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
- )
- else
- # Derived from: https://www.e3s-conferences.org/articles/e3sconf/pdf/2018/19/e3sconf_eko-dok2018_00139.pdf
- plf_fplr_curve = Model.add_curve_cubic(
- model,
- name: 'Cool-PLF-fPLR',
- coeff: [0.4603, 1.6416, -1.8588, 0.7605],
- min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
- )
- end
- clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.new(model, plf_fplr_curve)
- clg_coil.setName(obj_name + ' clg coil')
- clg_coil.setNominalTimeforCondensatetoBeginLeavingtheCoil(1000)
- clg_coil.setInitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity(1.5)
- clg_coil.setNominalSpeedLevel(num_speeds)
- clg_coil.setRatedAirFlowRateAtSelectedNominalSpeedLevel(clg_air_flow_rated)
- clg_coil.setRatedWaterFlowRateAtSelectedNominalSpeedLevel(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
- # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
- clg_coil.setGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W'))
- for i in 0..(num_speeds - 1)
- cap_ft_curve = Model.add_curve_biquadratic(
- model,
- name: "Cool-CAP-fT#{i + 1}",
- coeff: hp_ap.cool_cap_ft_spec[i],
- min_x: -100, max_x: 100, min_y: -100, max_y: 100
- )
- cap_faf_curve = Model.add_curve_quadratic(
- model,
- name: "Cool-CAP-fAF#{i + 1}",
- coeff: hp_ap.cool_cap_fflow_spec[i],
- min_x: 0, max_x: 2, min_y: 0, max_y: 2
- )
- cap_fwf_curve = Model.add_curve_quadratic(
- model,
- name: "Cool-CAP-fWF#{i + 1}",
- coeff: hp_ap.cool_cap_fwf_spec[i],
- min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
- )
- eir_ft_curve = Model.add_curve_biquadratic(
- model,
- name: "Cool-EIR-fT#{i + 1}",
- coeff: hp_ap.cool_eir_ft_spec[i],
- min_x: -100, max_x: 100, min_y: -100, max_y: 100
- )
- eir_faf_curve = Model.add_curve_quadratic(
+ if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+
+ htg_cfm = hp_ap.heating_actual_airflow_cfm
+ clg_cfm = hp_ap.cooling_actual_airflow_cfm
+ htg_air_flow_rated = calc_rated_airflow(heat_pump.heating_capacity, hp_ap.heat_rated_cfm_per_ton, 'm^3/s')
+ clg_air_flow_rated = calc_rated_airflow(heat_pump.cooling_capacity, hp_ap.cool_rated_cfm_per_ton, 'm^3/s')
+
+ if [HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeStandard].include? hpxml_header.ground_to_air_heat_pump_model_type
+ # Cooling Coil
+ clg_total_cap_curve = Model.add_curve_quad_linear(
model,
- name: "Cool-EIR-fAF#{i + 1}",
- coeff: hp_ap.cool_eir_fflow_spec[i],
- min_x: 0, max_x: 2, min_y: 0, max_y: 2
+ name: "#{obj_name} clg total cap curve",
+ coeff: hp_ap.cool_cap_curve_spec[0]
)
- eir_fwf_curve = Model.add_curve_quadratic(
+ clg_sens_cap_curve = Model.add_curve_quint_linear(
model,
- name: "Cool-EIR-fWF#{i + 1}",
- coeff: hp_ap.cool_eir_fwf_spec[i],
- min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
+ name: "#{obj_name} clg sens cap curve",
+ coeff: hp_ap.cool_sh_curve_spec[0]
)
- # Recoverable heat modifier as a function of indoor wet-bulb and water entering temperatures.
- waste_heat_ft = Model.add_curve_biquadratic(
+ clg_power_curve = Model.add_curve_quad_linear(
model,
- name: "WasteHeat-FT#{i + 1}",
- coeff: [1, 0, 0, 0, 0, 0]
+ name: "#{obj_name} clg power curve",
+ coeff: hp_ap.cool_power_curve_spec[0]
)
- speed = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData.new(model, cap_ft_curve, cap_faf_curve, cap_fwf_curve, eir_ft_curve, eir_faf_curve, eir_fwf_curve, waste_heat_ft)
+ clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model, clg_total_cap_curve, clg_sens_cap_curve, clg_power_curve)
+ clg_coil.setName(obj_name + ' clg coil')
+ clg_coil.setRatedCoolingCoefficientofPerformance(hp_ap.cool_rated_cops[0])
+ clg_coil.setNominalTimeforCondensateRemovaltoBegin(1000)
+ clg_coil.setRatioofInitialMoistureEvaporationRateandSteadyStateLatentCapacity(1.5)
+ clg_coil.setRatedAirFlowRate(clg_air_flow_rated)
+ clg_coil.setRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
+ clg_coil.setRatedEnteringWaterTemperature(UnitConversions.convert(80, 'F', 'C'))
+ clg_coil.setRatedEnteringAirDryBulbTemperature(UnitConversions.convert(80, 'F', 'C'))
+ clg_coil.setRatedEnteringAirWetBulbTemperature(UnitConversions.convert(67, 'F', 'C'))
# TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
- speed.setReferenceUnitGrossRatedTotalCoolingCapacity(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W') * hp_ap.cool_capacity_ratios[i])
- speed.setReferenceUnitGrossRatedSensibleHeatRatio(hp_ap.cool_rated_shr_gross)
- speed.setReferenceUnitGrossRatedCoolingCOP(hp_ap.cool_rated_cops[i])
- speed.setReferenceUnitRatedAirFlowRate(UnitConversions.convert(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'ton') * hp_ap.cool_capacity_ratios[i] * hp_ap.cool_rated_cfm_per_ton, 'cfm', 'm^3/s'))
- speed.setReferenceUnitRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s') * hp_ap.cool_capacity_ratios[i])
- speed.setReferenceUnitWasteHeatFractionofInputPowerAtRatedConditions(0.0)
- clg_coil.addSpeed(speed)
- end
- if heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
- plf_fplr_curve = Model.add_curve_quadratic(
- model,
- name: 'Heat-PLF-fPLR',
- coeff: [1.0, 0.0, 0.0],
- min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
- )
- else
- # Derived from: https://www.e3s-conferences.org/articles/e3sconf/pdf/2018/19/e3sconf_eko-dok2018_00139.pdf
- plf_fplr_curve = Model.add_curve_cubic(
- model,
- name: 'Heat-PLF-fPLR',
- coeff: [0.4603, 1.6416, -1.8588, 0.7605],
- min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
- )
- end
- htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.new(model, plf_fplr_curve)
- htg_coil.setName(obj_name + ' htg coil')
- htg_coil.setNominalSpeedLevel(num_speeds)
- htg_coil.setRatedAirFlowRateAtSelectedNominalSpeedLevel(htg_air_flow_rated)
- htg_coil.setRatedWaterFlowRateAtSelectedNominalSpeedLevel(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
- # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
- htg_coil.setRatedHeatingCapacityAtSelectedNominalSpeedLevel(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
- for i in 0..(num_speeds - 1)
- cap_ft_curve = Model.add_curve_biquadratic(
- model,
- name: "Heat-CAP-fT#{i + 1}",
- coeff: hp_ap.heat_cap_ft_spec[i],
- min_x: -100, max_x: 100, min_y: -100, max_y: 100
- )
- cap_faf_curve = Model.add_curve_quadratic(
- model,
- name: "Heat-CAP-fAF#{i + 1}",
- coeff: hp_ap.heat_cap_fflow_spec[i],
- min_x: 0, max_x: 2, min_y: 0, max_y: 2
- )
- cap_fwf_curve = Model.add_curve_quadratic(
- model,
- name: "Heat-CAP-fWF#{i + 1}",
- coeff: hp_ap.heat_cap_fwf_spec[i],
- min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
- )
- eir_ft_curve = Model.add_curve_biquadratic(
- model,
- name: "Heat-EIR-fT#{i + 1}",
- coeff: hp_ap.heat_eir_ft_spec[i],
- min_x: -100, max_x: 100, min_y: -100, max_y: 100
- )
- eir_faf_curve = Model.add_curve_quadratic(
- model,
- name: "Heat-EIR-fAF#{i + 1}",
- coeff: hp_ap.heat_eir_fflow_spec[i],
- min_x: 0, max_x: 2, min_y: 0, max_y: 2
- )
- eir_fwf_curve = Model.add_curve_quadratic(
+ clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W'))
+ clg_coil.setRatedSensibleCoolingCapacity(UnitConversions.convert(heat_pump.cooling_capacity * hp_ap.cool_rated_shr_gross, 'Btu/hr', 'W'))
+ # Heating Coil
+ htg_cap_curve = Model.add_curve_quad_linear(
model,
- name: "Heat-EIR-fWF#{i + 1}",
- coeff: hp_ap.heat_eir_fwf_spec[i],
- min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
+ name: "#{obj_name} htg cap curve",
+ coeff: hp_ap.heat_cap_curve_spec[0]
)
- # Recoverable heat modifier as a function of indoor wet-bulb and water entering temperatures.
- waste_heat_ft = Model.add_curve_biquadratic(
+ htg_power_curve = Model.add_curve_quad_linear(
model,
- name: "WasteHeat-FT#{i + 1}",
- coeff: [1, 0, 0, 0, 0, 0]
+ name: "#{obj_name} htg power curve",
+ coeff: hp_ap.heat_power_curve_spec[0]
)
- speed = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData.new(model, cap_ft_curve, cap_faf_curve, cap_fwf_curve, eir_ft_curve, eir_faf_curve, eir_fwf_curve, waste_heat_ft)
+ htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model, htg_cap_curve, htg_power_curve)
+ htg_coil.setName(obj_name + ' htg coil')
+ htg_coil.setRatedHeatingCoefficientofPerformance(hp_ap.heat_rated_cops[0])
+ htg_coil.setRatedAirFlowRate(htg_air_flow_rated)
+ htg_coil.setRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
+ htg_coil.setRatedEnteringWaterTemperature(UnitConversions.convert(60, 'F', 'C'))
+ htg_coil.setRatedEnteringAirDryBulbTemperature(UnitConversions.convert(70, 'F', 'C'))
+ # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
+ htg_coil.setRatedHeatingCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
+ elsif [HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental].include? hpxml_header.ground_to_air_heat_pump_model_type
+ num_speeds = hp_ap.cool_capacity_ratios.size
+ if heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
+ plf_fplr_curve = Model.add_curve_quadratic(
+ model,
+ name: 'Cool-PLF-fPLR',
+ coeff: [1.0, 0.0, 0.0],
+ min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
+ )
+ else
+ # Derived from: https://www.e3s-conferences.org/articles/e3sconf/pdf/2018/19/e3sconf_eko-dok2018_00139.pdf
+ plf_fplr_curve = Model.add_curve_cubic(
+ model,
+ name: 'Cool-PLF-fPLR',
+ coeff: [0.4603, 1.6416, -1.8588, 0.7605],
+ min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
+ )
+ end
+ clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.new(model, plf_fplr_curve)
+ clg_coil.setName(obj_name + ' clg coil')
+ clg_coil.setNominalTimeforCondensatetoBeginLeavingtheCoil(1000)
+ clg_coil.setInitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity(1.5)
+ clg_coil.setNominalSpeedLevel(num_speeds)
+ clg_coil.setRatedAirFlowRateAtSelectedNominalSpeedLevel(clg_air_flow_rated)
+ clg_coil.setRatedWaterFlowRateAtSelectedNominalSpeedLevel(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
# TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
- speed.setReferenceUnitGrossRatedHeatingCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W') * hp_ap.heat_capacity_ratios[i])
- speed.setReferenceUnitGrossRatedHeatingCOP(hp_ap.heat_rated_cops[i])
- speed.setReferenceUnitRatedAirFlow(UnitConversions.convert(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'ton') * hp_ap.heat_capacity_ratios[i] * hp_ap.heat_rated_cfm_per_ton, 'cfm', 'm^3/s'))
- speed.setReferenceUnitRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s') * hp_ap.heat_capacity_ratios[i])
- speed.setReferenceUnitWasteHeatFractionofInputPowerAtRatedConditions(0.0)
- htg_coil.addSpeed(speed)
+ clg_coil.setGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W'))
+ for i in 0..(num_speeds - 1)
+ cap_ft_curve = Model.add_curve_biquadratic(
+ model,
+ name: "Cool-CAP-fT#{i + 1}",
+ coeff: hp_ap.cool_cap_ft_spec[i],
+ min_x: -100, max_x: 100, min_y: -100, max_y: 100
+ )
+ cap_faf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Cool-CAP-fAF#{i + 1}",
+ coeff: hp_ap.cool_cap_fflow_spec[i],
+ min_x: 0, max_x: 2, min_y: 0, max_y: 2
+ )
+ cap_fwf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Cool-CAP-fWF#{i + 1}",
+ coeff: hp_ap.cool_cap_fwf_spec[i],
+ min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
+ )
+ eir_ft_curve = Model.add_curve_biquadratic(
+ model,
+ name: "Cool-EIR-fT#{i + 1}",
+ coeff: hp_ap.cool_eir_ft_spec[i],
+ min_x: -100, max_x: 100, min_y: -100, max_y: 100
+ )
+ eir_faf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Cool-EIR-fAF#{i + 1}",
+ coeff: hp_ap.cool_eir_fflow_spec[i],
+ min_x: 0, max_x: 2, min_y: 0, max_y: 2
+ )
+ eir_fwf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Cool-EIR-fWF#{i + 1}",
+ coeff: hp_ap.cool_eir_fwf_spec[i],
+ min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
+ )
+ # Recoverable heat modifier as a function of indoor wet-bulb and water entering temperatures.
+ waste_heat_ft = Model.add_curve_biquadratic(
+ model,
+ name: "WasteHeat-FT#{i + 1}",
+ coeff: [1, 0, 0, 0, 0, 0]
+ )
+ speed = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData.new(model, cap_ft_curve, cap_faf_curve, cap_fwf_curve, eir_ft_curve, eir_faf_curve, eir_fwf_curve, waste_heat_ft)
+ # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
+ speed.setReferenceUnitGrossRatedTotalCoolingCapacity(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W') * hp_ap.cool_capacity_ratios[i])
+ speed.setReferenceUnitGrossRatedSensibleHeatRatio(hp_ap.cool_rated_shr_gross)
+ speed.setReferenceUnitGrossRatedCoolingCOP(hp_ap.cool_rated_cops[i])
+ speed.setReferenceUnitRatedAirFlowRate(UnitConversions.convert(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'ton') * hp_ap.cool_capacity_ratios[i] * hp_ap.cool_rated_cfm_per_ton, 'cfm', 'm^3/s'))
+ speed.setReferenceUnitRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s') * hp_ap.cool_capacity_ratios[i])
+ speed.setReferenceUnitWasteHeatFractionofInputPowerAtRatedConditions(0.0)
+ clg_coil.addSpeed(speed)
+ end
+ if heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
+ plf_fplr_curve = Model.add_curve_quadratic(
+ model,
+ name: 'Heat-PLF-fPLR',
+ coeff: [1.0, 0.0, 0.0],
+ min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
+ )
+ else
+ # Derived from: https://www.e3s-conferences.org/articles/e3sconf/pdf/2018/19/e3sconf_eko-dok2018_00139.pdf
+ plf_fplr_curve = Model.add_curve_cubic(
+ model,
+ name: 'Heat-PLF-fPLR',
+ coeff: [0.4603, 1.6416, -1.8588, 0.7605],
+ min_x: 0, max_x: 1, min_y: 0.7, max_y: 1
+ )
+ end
+ htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.new(model, plf_fplr_curve)
+ htg_coil.setName(obj_name + ' htg coil')
+ htg_coil.setNominalSpeedLevel(num_speeds)
+ htg_coil.setRatedAirFlowRateAtSelectedNominalSpeedLevel(htg_air_flow_rated)
+ htg_coil.setRatedWaterFlowRateAtSelectedNominalSpeedLevel(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s'))
+ # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
+ htg_coil.setRatedHeatingCapacityAtSelectedNominalSpeedLevel(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
+ for i in 0..(num_speeds - 1)
+ cap_ft_curve = Model.add_curve_biquadratic(
+ model,
+ name: "Heat-CAP-fT#{i + 1}",
+ coeff: hp_ap.heat_cap_ft_spec[i],
+ min_x: -100, max_x: 100, min_y: -100, max_y: 100
+ )
+ cap_faf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Heat-CAP-fAF#{i + 1}",
+ coeff: hp_ap.heat_cap_fflow_spec[i],
+ min_x: 0, max_x: 2, min_y: 0, max_y: 2
+ )
+ cap_fwf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Heat-CAP-fWF#{i + 1}",
+ coeff: hp_ap.heat_cap_fwf_spec[i],
+ min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
+ )
+ eir_ft_curve = Model.add_curve_biquadratic(
+ model,
+ name: "Heat-EIR-fT#{i + 1}",
+ coeff: hp_ap.heat_eir_ft_spec[i],
+ min_x: -100, max_x: 100, min_y: -100, max_y: 100
+ )
+ eir_faf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Heat-EIR-fAF#{i + 1}",
+ coeff: hp_ap.heat_eir_fflow_spec[i],
+ min_x: 0, max_x: 2, min_y: 0, max_y: 2
+ )
+ eir_fwf_curve = Model.add_curve_quadratic(
+ model,
+ name: "Heat-EIR-fWF#{i + 1}",
+ coeff: hp_ap.heat_eir_fwf_spec[i],
+ min_x: 0.45, max_x: 2, min_y: 0, max_y: 2
+ )
+ # Recoverable heat modifier as a function of indoor wet-bulb and water entering temperatures.
+ waste_heat_ft = Model.add_curve_biquadratic(
+ model,
+ name: "WasteHeat-FT#{i + 1}",
+ coeff: [1, 0, 0, 0, 0, 0]
+ )
+ speed = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData.new(model, cap_ft_curve, cap_faf_curve, cap_fwf_curve, eir_ft_curve, eir_faf_curve, eir_fwf_curve, waste_heat_ft)
+ # TODO: Add net to gross conversion after RESNET PR: https://github.com/NREL/OpenStudio-HPXML/pull/1879
+ speed.setReferenceUnitGrossRatedHeatingCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W') * hp_ap.heat_capacity_ratios[i])
+ speed.setReferenceUnitGrossRatedHeatingCOP(hp_ap.heat_rated_cops[i])
+ speed.setReferenceUnitRatedAirFlow(UnitConversions.convert(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'ton') * hp_ap.heat_capacity_ratios[i] * hp_ap.heat_rated_cfm_per_ton, 'cfm', 'm^3/s'))
+ speed.setReferenceUnitRatedWaterFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s') * hp_ap.heat_capacity_ratios[i])
+ speed.setReferenceUnitWasteHeatFractionofInputPowerAtRatedConditions(0.0)
+ htg_coil.addSpeed(speed)
+ end
end
+
+ elsif heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToWater
+ htg_coil = OpenStudio::Model::HeatPumpPlantLoopEIRHeating.new(model)
+ htg_coil.setName(obj_name + ' htg coil')
+ htg_coil.setReferenceCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
+ htg_coil.setSourceSideReferenceFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s')) # ComStock autosizes
+ # htg_coil.setLoadSideReferenceFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s')) # ComStock autosizes
+ # htg_coil.setCapacityModifierFunctionofTemperatureCurve() # ComStock uses TableLookup for Carrier_61WG_Glycol_90kW_htg.csv
+ # htg_coil.setElectricInputtoOutputRatioModifierFunctionofTemperatureCurve() # ComStock uses TableLookup for Carrier_61WG_Glycol_90kW_htg.csv
+ # htg_coil.setElectricInputtoOutputRatioModifierFunctionofPartLoadRatioCurve() # ComStock assumes a standard EIR vs. PLR line
+ htg_coil.setReferenceCoefficientofPerformance(1 / 0.23419) # ComStock uses 1 / rated_heating_eir
+
+ clg_coil = OpenStudio::Model::HeatPumpPlantLoopEIRCooling.new(model)
+ clg_coil.setName(obj_name + ' clg coil')
+ clg_coil.setReferenceCapacity(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W'))
+ clg_coil.setSourceSideReferenceFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s')) # ComStock autosizes
+ # clg_coil.setLoadSideReferenceFlowRate(UnitConversions.convert(geothermal_loop.loop_flow, 'gal/min', 'm^3/s')) # ComStock autosizes
+ # clg_coil.setCapacityModifierFunctionofTemperatureCurve() # ComStock uses TableLookup for Carrier_30WG_90kW_clg.csv
+ # clg_coil.setElectricInputtoOutputRatioModifierFunctionofTemperatureCurve() # ComStock uses TableLookup for Carrier_30WG_90kW_clg.csv
+ # clg_coil.setElectricInputtoOutputRatioModifierFunctionofPartLoadRatioCurve() # ComStock assumes a standard EIR vs. PLR line
+ clg_coil.setReferenceCoefficientofPerformance(1 / 0.21505) # ComStock uses 1 / rated_cooling_eir
+
+ htg_coil.setCompanionCoolingHeatPump(clg_coil)
+ clg_coil.setCompanionHeatingHeatPump(htg_coil)
end
+
clg_coil.additionalProperties.setFeature('HPXML_ID', heat_pump.id) # Used by reporting measure
htg_coil.additionalProperties.setFeature('HPXML_ID', heat_pump.id) # Used by reporting measure
@@ -867,21 +895,152 @@ def self.apply_ground_source_heat_pump(runner, model, weather, hpxml_bldg, hpxml
demand_outlet_pipe.addToNode(plant_loop.demandOutletNode)
# Fan
- fan_cfms = []
- hp_ap.cool_capacity_ratios.each do |capacity_ratio|
- fan_cfms << clg_cfm * capacity_ratio
- end
- hp_ap.heat_capacity_ratios.each do |capacity_ratio|
- fan_cfms << htg_cfm * capacity_ratio
+ if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ fan_cfms = []
+ hp_ap.cool_capacity_ratios.each do |capacity_ratio|
+ fan_cfms << clg_cfm * capacity_ratio
+ end
+ hp_ap.heat_capacity_ratios.each do |capacity_ratio|
+ fan_cfms << htg_cfm * capacity_ratio
+ end
+ fan_watts_per_cfm = heat_pump.fan_watts_per_cfm
+ elsif heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToWater
+ if heat_pump.cooling_capacity > 1.0
+ fan_cfm = RatedCFMPerTon * UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'ton') # CFM
+ else
+ fan_cfm = RatedCFMPerTon * UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'ton') # CFM
+ end
+ fan_watts_per_cfm = 0.0
+ fan_cfms = [fan_cfm]
end
- fan = create_supply_fan(model, obj_name, heat_pump.fan_watts_per_cfm, fan_cfms, heat_pump)
+
+ fan = create_supply_fan(model, obj_name, fan_watts_per_cfm, fan_cfms, heat_pump) # fan coil energy included in above pump via Fan Coil Watts
add_fan_pump_disaggregation_ems_program(model, fan, htg_coil, clg_coil, htg_supp_coil, heat_pump)
- # Unitary System
- air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, clg_cfm, 40.0)
- add_pump_power_ems_program(model, pump, air_loop_unitary, heat_pump)
- if (heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed) && (hpxml_header.ground_to_air_heat_pump_model_type == HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental)
- add_ghp_pump_mass_flow_rate_ems_program(model, pump, control_zone, htg_coil, clg_coil)
+ if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ # Unitary System
+ air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, clg_cfm, 40.0)
+ add_pump_power_ems_program(model, pump, air_loop_unitary, heat_pump)
+ if (heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed) && (hpxml_header.ground_to_air_heat_pump_model_type == HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeExperimental)
+ add_ghp_pump_mass_flow_rate_ems_program(model, pump, control_zone, htg_coil, clg_coil)
+ end
+ elsif heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToWater
+ add_pump_power_ems_program(model, pump, htg_coil, heat_pump)
+
+ htg_design_temp = 140.0 # F; ComStock uses this value
+ clg_design_temp = 44.0 # F; ComStock uses this value
+
+ htg_temp_diff = 20.0 # deltaF; ComStock uses this value
+ clg_temp_diff = 11.0 # deltaF; what does ComStock use?
+
+ htg_max_water_flow = UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W') / UnitConversions.convert(htg_temp_diff, 'deltaF', 'deltaC') / 4.186 / 998.2 / 1000.0 * 2.0 # m^3/s
+ clg_max_water_flow = UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W') / UnitConversions.convert(clg_temp_diff, 'deltaF', 'deltaC') / 4.186 / 998.2 / 1000.0 * 2.0 # m^3/s
+
+ plant_loop.addDemandBranchForComponent(htg_coil)
+ plant_loop.addDemandBranchForComponent(clg_coil)
+
+ hw_loop = Model.add_plant_loop(
+ model,
+ name: "#{obj_name} hot water"
+ )
+
+ chw_loop = Model.add_plant_loop(
+ model,
+ name: "#{obj_name} chilled water"
+ )
+
+ hw_loop.addSupplyBranchForComponent(htg_coil)
+ chw_loop.addSupplyBranchForComponent(clg_coil)
+
+ supply_setpoint = Model.add_schedule_constant(
+ model,
+ name: "#{obj_name} hot water supply setpoint",
+ value: UnitConversions.convert(htg_design_temp, 'F', 'C'),
+ limits: EPlus::ScheduleTypeLimitsTemperature
+ )
+
+ setpoint_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, supply_setpoint)
+ setpoint_manager.setName(obj_name + ' hot water setpoint manager')
+ setpoint_manager.setControlVariable('Temperature')
+ setpoint_manager.addToNode(hw_loop.supplyOutletNode)
+
+ loop_sizing = hw_loop.sizingPlant
+ loop_sizing.setLoopType('Heating')
+ loop_sizing.setDesignLoopExitTemperature(UnitConversions.convert(htg_design_temp, 'F', 'C'))
+ loop_sizing.setLoopDesignTemperatureDifference(UnitConversions.convert(htg_temp_diff, 'deltaF', 'deltaC'))
+
+ pump = Model.add_pump_variable_speed(
+ model,
+ name: "#{obj_name} hot water pump",
+ rated_power: pump_w
+ )
+ pump.addToNode(hw_loop.supplyInletNode)
+ add_fan_pump_disaggregation_ems_program(model, pump, htg_coil, nil, nil, heat_pump)
+ add_pump_power_ems_program(model, pump, htg_coil, heat_pump)
+
+ bb_ua = UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W') / UnitConversions.convert(UnitConversions.convert(loop_sizing.designLoopExitTemperature, 'C', 'F') - 10.0 - 95.0, 'deltaF', 'deltaC') * 3.0 # W/K
+
+ htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
+ htg_coil.setName(obj_name + ' htg coil')
+ htg_coil.setRatedCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
+ htg_coil.setPerformanceInputMethod('NominalCapacity')
+ htg_coil.setUFactorTimesAreaValue(bb_ua)
+ htg_coil.setMaximumWaterFlowRate(htg_max_water_flow)
+ htg_coil.setRatedInletWaterTemperature(UnitConversions.convert(htg_design_temp, 'F', 'C'))
+ htg_coil.setRatedOutletWaterTemperature(UnitConversions.convert(htg_design_temp - htg_temp_diff, 'F', 'C'))
+ # htg_coil.setRatedInletAirTemperature()
+ # htg_coil.setRatedOutletAirTemperature()
+ hw_loop.addDemandBranchForComponent(htg_coil)
+
+ supply_setpoint = Model.add_schedule_constant(
+ model,
+ name: "#{obj_name} chilled water supply setpoint",
+ value: UnitConversions.convert(clg_design_temp, 'F', 'C'),
+ limits: EPlus::ScheduleTypeLimitsTemperature
+ )
+
+ setpoint_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, supply_setpoint)
+ setpoint_manager.setName(obj_name + ' chilled water setpoint manager')
+ setpoint_manager.setControlVariable('Temperature')
+ setpoint_manager.addToNode(chw_loop.supplyOutletNode)
+
+ loop_sizing = chw_loop.sizingPlant
+ loop_sizing.setLoopType('Cooling')
+ loop_sizing.setDesignLoopExitTemperature(UnitConversions.convert(clg_design_temp, 'F', 'C'))
+ loop_sizing.setLoopDesignTemperatureDifference(UnitConversions.convert(clg_temp_diff, 'deltaF', 'deltaC'))
+
+ pump = Model.add_pump_variable_speed(
+ model,
+ name: "#{obj_name} chilled water pump",
+ rated_power: pump_w
+ )
+ pump.addToNode(chw_loop.supplyInletNode)
+ add_fan_pump_disaggregation_ems_program(model, pump, nil, clg_coil, nil, heat_pump)
+ add_pump_power_ems_program(model, pump, clg_coil, heat_pump)
+
+ clg_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
+ clg_coil.setName(obj_name + ' clg coil')
+ clg_coil.setDesignWaterFlowRate(clg_max_water_flow)
+ clg_coil.setDesignAirFlowRate(UnitConversions.convert(fan_cfms[0], 'cfm', 'm^3/s'))
+ clg_coil.setDesignInletWaterTemperature(UnitConversions.convert(clg_design_temp, 'F', 'C'))
+ clg_coil.setDesignInletAirTemperature(25.0)
+ clg_coil.setDesignOutletAirTemperature(10.0)
+ clg_coil.setDesignInletAirHumidityRatio(0.012)
+ clg_coil.setDesignOutletAirHumidityRatio(0.008)
+ chw_loop.addDemandBranchForComponent(clg_coil)
+
+ zone_hvac = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model, model.alwaysOnDiscreteSchedule, fan, clg_coil, htg_coil)
+ zone_hvac.setCapacityControlMethod('CyclingFan')
+ zone_hvac.setName(obj_name + ' fan coil')
+ zone_hvac.setMaximumSupplyAirTemperatureInHeatingMode(UnitConversions.convert(120.0, 'F', 'C'))
+ zone_hvac.setHeatingConvergenceTolerance(0.001)
+ zone_hvac.setMinimumSupplyAirTemperatureInCoolingMode(UnitConversions.convert(55.0, 'F', 'C'))
+ zone_hvac.setMaximumColdWaterFlowRate(clg_max_water_flow)
+ zone_hvac.setCoolingConvergenceTolerance(0.001)
+ zone_hvac.setMaximumOutdoorAirFlowRate(0.0)
+ zone_hvac.setMaximumSupplyAirFlowRate(UnitConversions.convert(fan_cfms[0], 'cfm', 'm^3/s'))
+ zone_hvac.setMaximumHotWaterFlowRate(htg_max_water_flow)
+ zone_hvac.addToThermalZone(control_zone)
end
if heat_pump.is_shared_system
@@ -902,13 +1061,19 @@ def self.apply_ground_source_heat_pump(runner, model, weather, hpxml_bldg, hpxml
equip.additionalProperties.setFeature('HPXML_ID', heat_pump.id) # Used by reporting measure
end
- # Air Loop
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, hvac_sequential_load_fracs, [htg_cfm, clg_cfm].max, heat_pump, hvac_unavailable_periods)
+ if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir
+ # Air Loop
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, hvac_sequential_load_fracs, [htg_cfm, clg_cfm].max, heat_pump, hvac_unavailable_periods)
- # HVAC Installation Quality
- apply_installation_quality_ems_program(model, heat_pump, heat_pump, air_loop_unitary, htg_coil, clg_coil, control_zone)
+ # HVAC Installation Quality
+ apply_installation_quality_ems_program(model, heat_pump, heat_pump, air_loop_unitary, htg_coil, clg_coil, control_zone)
- return air_loop
+ return air_loop
+ elsif heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToWater
+ set_sequential_load_fractions(model, control_zone, zone_hvac, hvac_sequential_load_fracs, hvac_unavailable_periods, heat_pump)
+
+ return zone_hvac
+ end
end
# Adds the HPXML water-loop heat pump system to the OpenStudio model.
@@ -1003,10 +1168,14 @@ def self.get_pump_power_watts(hvac_system)
return hvac_system.electric_auxiliary_energy / 2.08
elsif hvac_system.is_a?(HPXML::HeatPump) && (not hvac_system.pump_watts_per_ton.nil?)
if hvac_system.cooling_capacity > 1.0
- return hvac_system.pump_watts_per_ton * UnitConversions.convert(hvac_system.cooling_capacity, 'Btu/hr', 'ton')
+ pump_power_watts = hvac_system.pump_watts_per_ton * UnitConversions.convert(hvac_system.cooling_capacity, 'Btu/hr', 'ton')
else
- return hvac_system.pump_watts_per_ton * UnitConversions.convert(hvac_system.heating_capacity, 'Btu/hr', 'ton')
+ pump_power_watts = hvac_system.pump_watts_per_ton * UnitConversions.convert(hvac_system.heating_capacity, 'Btu/hr', 'ton')
end
+ if (not hvac_system.fan_coil_watts.nil?)
+ pump_power_watts += hvac_system.fan_coil_watts
+ end
+ return pump_power_watts
end
return 0.0
@@ -1853,27 +2022,27 @@ def self.add_fan_power_ems_program(model, fan, hp_min_temp)
)
end
- # Create EMS program to correctly account for pump power consumption based on heating object part load ratio
+ # Create EMS program to correctly account for pump power consumption based on heating (or cooling) object part load ratio
# Without EMS, the pump power will vary according to the plant loop part load ratio
# (based on flow rate) rather than the component part load ratio (based on load).
#
# @param model [OpenStudio::Model::Model] OpenStudio Model object
# @param pump [OpenStudio::Model::PumpVariableSpeed] OpenStudio variable-speed pump object
- # @param heating_object [OpenStudio::Model::AirLoopHVACUnitarySystem or OpenStudio::Model::BoilerHotWater] OpenStudio unitary system object or boiler object
+ # @param heating_object [OpenStudio::Model::AirLoopHVACUnitarySystem or OpenStudio::Model::BoilerHotWater or OpenStudio::Model::HeatPumpPlantLoopEIRHeating] OpenStudio unitary system object or boiler object or plant loop heat pump object
# @param hvac_system [HPXML::HeatPump or HPXML::HeatingSystem] HPXML heat pump or heating system object
# @return [nil]
- def self.add_pump_power_ems_program(model, pump, heating_object, hvac_system)
+ def self.add_pump_power_ems_program(model, pump, heating_or_cooling_object, hvac_system)
# Sensors
- if heating_object.is_a? OpenStudio::Model::BoilerHotWater
+ if heating_or_cooling_object.is_a? OpenStudio::Model::BoilerHotWater
heating_plr_sensor = Model.add_ems_sensor(
model,
- name: "#{heating_object.name} plr s",
+ name: "#{heating_or_cooling_object.name} plr s",
output_var_or_meter_name: 'Boiler Part Load Ratio',
- key_name: heating_object.name
+ key_name: heating_or_cooling_object.name
)
- elsif heating_object.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem
- htg_coil = heating_object.heatingCoil.get
- clg_coil = heating_object.coolingCoil.get
+ elsif heating_or_cooling_object.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem
+ htg_coil = heating_or_cooling_object.heatingCoil.get
+ clg_coil = heating_or_cooling_object.coolingCoil.get
# GHP model, variable speed coils
if htg_coil.to_CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.is_initialized
htg_coil = htg_coil.to_CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.get
@@ -1918,11 +2087,41 @@ def self.add_pump_power_ems_program(model, pump, heating_object, hvac_system)
else
heating_plr_sensor = Model.add_ems_sensor(
model,
- name: "#{heating_object.name} plr s",
+ name: "#{heating_or_cooling_object.name} plr s",
output_var_or_meter_name: 'Unitary System Part Load Ratio',
- key_name: heating_object.name
+ key_name: heating_or_cooling_object.name
)
end
+ elsif heating_or_cooling_object.is_a? OpenStudio::Model::HeatPumpPlantLoopEIRHeating
+ htg_coil = heating_or_cooling_object
+ clg_coil = htg_coil.companionCoolingHeatPump.get
+ heating_plr_sensor = Model.add_ems_sensor(
+ model,
+ name: "#{htg_coil.name} plr s",
+ output_var_or_meter_name: 'Heat Pump Part Load Ratio',
+ key_name: htg_coil.name
+ )
+ cooling_plr_sensor = Model.add_ems_sensor(
+ model,
+ name: "#{clg_coil.name} plr s",
+ output_var_or_meter_name: 'Heat Pump Part Load Ratio',
+ key_name: clg_coil.name
+ )
+ elsif heating_or_cooling_object.is_a? OpenStudio::Model::HeatPumpPlantLoopEIRCooling
+ clg_coil = heating_or_cooling_object
+ htg_coil = clg_coil.companionHeatingHeatPump.get
+ cooling_plr_sensor = Model.add_ems_sensor(
+ model,
+ name: "#{clg_coil.name} plr s",
+ output_var_or_meter_name: 'Heat Pump Part Load Ratio',
+ key_name: clg_coil.name
+ )
+ heating_plr_sensor = Model.add_ems_sensor(
+ model,
+ name: "#{htg_coil.name} plr s",
+ output_var_or_meter_name: 'Heat Pump Part Load Ratio',
+ key_name: htg_coil.name
+ )
end
pump_mfr_sensor = Model.add_ems_sensor(
@@ -1956,50 +2155,54 @@ def self.add_pump_power_ems_program(model, pump, heating_object, hvac_system)
if cooling_plr_sensor.nil?
pump_program.addLine("Set hvac_plr = #{heating_plr_sensor.name}")
else
- hvac_ap = hvac_system.additional_properties
- pump_program.addLine("Set heating_pump_vfr_max = #{htg_coil.speeds[-1].referenceUnitRatedWaterFlowRate}")
- pump_program.addLine("Set cooling_pump_vfr_max = #{clg_coil.speeds[-1].referenceUnitRatedWaterFlowRate}")
- pump_program.addLine('Set htg_flow_rate = 0.0')
- pump_program.addLine('Set clg_flow_rate = 0.0')
- (1..htg_coil.speeds.size).each do |i|
- # Initialization
- pump_program.addLine("Set heating_pump_vfr_#{i} = heating_pump_vfr_max * #{hvac_ap.heat_capacity_ratios[i - 1]}")
- pump_program.addLine("Set heating_fraction_time_#{i} = 0.0")
- end
- pump_program.addLine("If #{heating_usl_sensor.name} == 1")
- pump_program.addLine(" Set heating_fraction_time_1 = #{heating_plr_sensor.name}")
- (1..(htg_coil.speeds.size - 1)).each do |i|
- pump_program.addLine("ElseIf #{heating_usl_sensor.name} == #{i + 1}")
- pump_program.addLine(" Set heating_fraction_time_#{i} = 1.0 - #{heating_nsl_sensor.name}")
- pump_program.addLine(" Set heating_fraction_time_#{i + 1} = #{heating_nsl_sensor.name}")
- end
- pump_program.addLine('EndIf')
- # sum up to get the actual flow rate
- (1..htg_coil.speeds.size).each do |i|
- pump_program.addLine("Set htg_flow_rate = htg_flow_rate + heating_fraction_time_#{i} * heating_pump_vfr_#{i}")
- end
- pump_program.addLine('Set heating_plr = htg_flow_rate / heating_pump_vfr_max')
+ if cooling_nsl_sensor.nil?
+ pump_program.addLine("Set hvac_plr = @Max #{heating_plr_sensor.name} #{cooling_plr_sensor.name}")
+ else
+ hvac_ap = hvac_system.additional_properties
+ pump_program.addLine("Set heating_pump_vfr_max = #{htg_coil.speeds[-1].referenceUnitRatedWaterFlowRate}")
+ pump_program.addLine("Set cooling_pump_vfr_max = #{clg_coil.speeds[-1].referenceUnitRatedWaterFlowRate}")
+ pump_program.addLine('Set htg_flow_rate = 0.0')
+ pump_program.addLine('Set clg_flow_rate = 0.0')
+ (1..htg_coil.speeds.size).each do |i|
+ # Initialization
+ pump_program.addLine("Set heating_pump_vfr_#{i} = heating_pump_vfr_max * #{hvac_ap.heat_capacity_ratios[i - 1]}")
+ pump_program.addLine("Set heating_fraction_time_#{i} = 0.0")
+ end
+ pump_program.addLine("If #{heating_usl_sensor.name} == 1")
+ pump_program.addLine(" Set heating_fraction_time_1 = #{heating_plr_sensor.name}")
+ (1..(htg_coil.speeds.size - 1)).each do |i|
+ pump_program.addLine("ElseIf #{heating_usl_sensor.name} == #{i + 1}")
+ pump_program.addLine(" Set heating_fraction_time_#{i} = 1.0 - #{heating_nsl_sensor.name}")
+ pump_program.addLine(" Set heating_fraction_time_#{i + 1} = #{heating_nsl_sensor.name}")
+ end
+ pump_program.addLine('EndIf')
+ # sum up to get the actual flow rate
+ (1..htg_coil.speeds.size).each do |i|
+ pump_program.addLine("Set htg_flow_rate = htg_flow_rate + heating_fraction_time_#{i} * heating_pump_vfr_#{i}")
+ end
+ pump_program.addLine('Set heating_plr = htg_flow_rate / heating_pump_vfr_max')
- # Cooling
- (1..clg_coil.speeds.size).each do |i|
- # Initialization
- pump_program.addLine("Set cooling_pump_vfr_#{i} = cooling_pump_vfr_max * #{hvac_ap.cool_capacity_ratios[i - 1]}")
- pump_program.addLine("Set cooling_fraction_time_#{i} = 0.0")
- end
- pump_program.addLine("If #{cooling_usl_sensor.name} == 1")
- pump_program.addLine(" Set cooling_fraction_time_1 = #{cooling_plr_sensor.name}")
- (1..(clg_coil.speeds.size - 1)).each do |i|
- pump_program.addLine("ElseIf (#{cooling_usl_sensor.name}) == #{i + 1}")
- pump_program.addLine(" Set cooling_fraction_time_#{i} = 1.0 - #{cooling_nsl_sensor.name}")
- pump_program.addLine(" Set cooling_fraction_time_#{i + 1} = #{cooling_nsl_sensor.name}")
- end
- pump_program.addLine('EndIf')
- # sum up to get the actual flow rate
- (1..clg_coil.speeds.size).each do |i|
- pump_program.addLine("Set clg_flow_rate = clg_flow_rate + cooling_fraction_time_#{i} * heating_pump_vfr_#{i}")
+ # Cooling
+ (1..clg_coil.speeds.size).each do |i|
+ # Initialization
+ pump_program.addLine("Set cooling_pump_vfr_#{i} = cooling_pump_vfr_max * #{hvac_ap.cool_capacity_ratios[i - 1]}")
+ pump_program.addLine("Set cooling_fraction_time_#{i} = 0.0")
+ end
+ pump_program.addLine("If #{cooling_usl_sensor.name} == 1")
+ pump_program.addLine(" Set cooling_fraction_time_1 = #{cooling_plr_sensor.name}")
+ (1..(clg_coil.speeds.size - 1)).each do |i|
+ pump_program.addLine("ElseIf (#{cooling_usl_sensor.name}) == #{i + 1}")
+ pump_program.addLine(" Set cooling_fraction_time_#{i} = 1.0 - #{cooling_nsl_sensor.name}")
+ pump_program.addLine(" Set cooling_fraction_time_#{i + 1} = #{cooling_nsl_sensor.name}")
+ end
+ pump_program.addLine('EndIf')
+ # sum up to get the actual flow rate
+ (1..clg_coil.speeds.size).each do |i|
+ pump_program.addLine("Set clg_flow_rate = clg_flow_rate + cooling_fraction_time_#{i} * heating_pump_vfr_#{i}")
+ end
+ pump_program.addLine('Set cooling_plr = clg_flow_rate / cooling_pump_vfr_max')
+ pump_program.addLine('Set hvac_plr = @Max cooling_plr heating_plr')
end
- pump_program.addLine('Set cooling_plr = clg_flow_rate / cooling_pump_vfr_max')
- pump_program.addLine('Set hvac_plr = @Max cooling_plr heating_plr')
end
pump_program.addLine("Set pump_total_eff = #{pump_rated_mfr_var.name} / 1000 * #{pump.ratedPumpHead} / #{pump.ratedPowerConsumption.get}")
pump_program.addLine("Set pump_vfr = #{pump_mfr_sensor.name} / 1000")
@@ -2120,6 +2323,8 @@ def self.add_fan_pump_disaggregation_ems_program(model, fan_or_pump, htg_object,
else
if clg_object.is_a? OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial
var = 'Evaporative Cooler Water Volume'
+ elsif clg_object.is_a?(OpenStudio::Model::HeatPumpPlantLoopEIRCooling)
+ var = 'Heat Pump Electricity Energy'
else
var = 'Cooling Coil Total Cooling Energy'
end
@@ -2139,6 +2344,8 @@ def self.add_fan_pump_disaggregation_ems_program(model, fan_or_pump, htg_object,
var = 'Baseboard Total Heating Energy'
elsif htg_object.is_a? OpenStudio::Model::ZoneHVACFourPipeFanCoil
var = 'Fan Coil Heating Energy'
+ elsif htg_object.is_a?(OpenStudio::Model::HeatPumpPlantLoopEIRHeating)
+ var = 'Heat Pump Electricity Energy'
else
var = 'Heating Coil Heating Energy'
end
@@ -5027,11 +5234,11 @@ def self.apply_unit_multiplier(hpxml_bldg, hpxml_header)
hpxml_bldg.heat_pumps.each do |hp_sys|
hp_ap = hp_sys.additional_properties
hp_sys.cooling_capacity *= unit_multiplier
- hp_sys.cooling_design_airflow_cfm *= unit_multiplier
- hp_ap.cooling_actual_airflow_cfm *= unit_multiplier
+ hp_sys.cooling_design_airflow_cfm *= unit_multiplier unless hp_sys.cooling_design_airflow_cfm.nil?
+ hp_ap.cooling_actual_airflow_cfm *= unit_multiplier unless hp_ap.cooling_actual_airflow_cfm.nil?
hp_sys.heating_capacity *= unit_multiplier
- hp_sys.heating_design_airflow_cfm *= unit_multiplier
- hp_ap.heating_actual_airflow_cfm *= unit_multiplier
+ hp_sys.heating_design_airflow_cfm *= unit_multiplier unless hp_sys.heating_design_airflow_cfm.nil?
+ hp_ap.heating_actual_airflow_cfm *= unit_multiplier unless hp_ap.heating_actual_airflow_cfm.nil?
hp_sys.heating_capacity_17F *= unit_multiplier unless hp_sys.heating_capacity_17F.nil?
hp_sys.backup_heating_capacity *= unit_multiplier unless hp_sys.backup_heating_capacity.nil?
hp_sys.crankcase_heater_watts *= unit_multiplier unless hp_sys.crankcase_heater_watts.nil?
@@ -5243,6 +5450,7 @@ def self.check_distribution_system(hvac_system, system_type)
HPXML::HVACTypeHeatPumpAirToAir => [HPXML::HVACDistributionTypeAir, HPXML::HVACDistributionTypeDSE],
HPXML::HVACTypeHeatPumpMiniSplit => [HPXML::HVACDistributionTypeAir, HPXML::HVACDistributionTypeDSE],
HPXML::HVACTypeHeatPumpGroundToAir => [HPXML::HVACDistributionTypeAir, HPXML::HVACDistributionTypeDSE],
+ HPXML::HVACTypeHeatPumpGroundToWater => [HPXML::HVACDistributionTypeAir, HPXML::HVACDistributionTypeDSE],
HPXML::HVACTypeHeatPumpWaterLoopToAir => [HPXML::HVACDistributionTypeAir, HPXML::HVACDistributionTypeDSE],
HPXML::HVACTypeHeatPumpPTHP => [HPXML::HVACDistributionTypeDSE],
HPXML::HVACTypeHeatPumpRoom => [HPXML::HVACDistributionTypeDSE],
diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb
index 4f0b88e4c5..ac44f083f5 100644
--- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb
+++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb
@@ -2818,6 +2818,36 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
total_cap_curve_value = MathTools.biquadratic(UnitConversions.convert(mj.cool_indoor_wetbulb, 'F', 'C'), UnitConversions.convert(entering_temp, 'F', 'C'), clg_ap.cool_cap_ft_spec[hvac_cooling_speed])
calculate_cooling_capacities(mj, clg_ap, hvac_sizings, hpxml_bldg.header.manualj_humidity_setpoint, total_cap_curve_value, undersize_limit, oversize_limit, HVAC::GroundSourceCoolRatedIDB, HVAC::GroundSourceCoolRatedIWB, hvac_cooling, hpxml_bldg)
end
+ elsif HPXML::HVACTypeHeatPumpGroundToWater == cooling_type
+
+ # FIXME
+ entering_temp = clg_ap.design_chw
+ hvac_cooling_speed = get_nominal_speed(clg_ap, true)
+
+ gshp_coil_bf = 0.0806
+ gshp_coil_bf_ft_spec = [1.21005458, -0.00664200, 0.00000000, 0.00348246, 0.00000000, 0.00000000]
+ bypass_factor_curve_value = MathTools.biquadratic(mj.cool_indoor_wetbulb, mj.cool_setpoint, gshp_coil_bf_ft_spec)
+ total_cap_curve_value, sensible_cap_curve_value = calc_gshp_clg_curve_value(clg_ap, mj.cool_indoor_wetbulb, mj.cool_setpoint, entering_temp, hvac_cooling_speed)
+
+ cool_cap_rated = hvac_sizings.Cool_Load_Tot / total_cap_curve_value # Note: cool_cap_design = hvac_sizings.Cool_Load_Tot
+ cool_sens_cap_rated = cool_cap_rated * clg_ap.cool_rated_shr_gross
+ curve_sens_cap_at_design = cool_sens_cap_rated * sensible_cap_curve_value
+ cool_load_sens_cap_design = (curve_sens_cap_at_design / \
+ (1.0 + (1.0 - gshp_coil_bf * bypass_factor_curve_value) *
+ (80.0 - mj.cool_setpoint) / cooling_delta_t))
+ cool_load_lat_cap_design = hvac_sizings.Cool_Load_Tot - cool_load_sens_cap_design
+
+ # Adjust Sizing so that coil sensible at design >= CoolingLoad_Sens, and coil latent at design >= CoolingLoad_Lat, and equipment SHRRated is maintained.
+ cool_load_sens_cap_design = [cool_load_sens_cap_design, hvac_sizings.Cool_Load_Sens].max
+ cool_load_lat_cap_design = [cool_load_lat_cap_design, hvac_sizings.Cool_Load_Lat].max
+ cool_cap_design = cool_load_sens_cap_design + cool_load_lat_cap_design
+
+ # Limit total capacity via oversizing limit
+ cool_cap_design = [cool_cap_design, oversize_limit * hvac_sizings.Cool_Load_Tot].min
+ hvac_sizings.Cool_Capacity = cool_cap_design / total_cap_curve_value
+ hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * clg_ap.cool_rated_shr_gross
+ hvac_sizings.Cool_Airflow = 0.0
+
elsif HPXML::HVACTypeEvaporativeCooler == cooling_type
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot
@@ -2851,7 +2881,8 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
htg_ap = hvac_heating.additional_properties
if hvac_heating.is_a?(HPXML::HeatingSystem) && hvac_heating.is_heat_pump_backup_system
hvac_hp = hvac_heating.primary_heat_pump
- if hvac_hp.heat_pump_type != HPXML::HVACTypeHeatPumpGroundToAir
+ if (hvac_hp.heat_pump_type != HPXML::HVACTypeHeatPumpGroundToAir) &&
+ (hvac_hp.heat_pump_type != HPXML::HVACTypeHeatPumpGroundToWater)
# Adjust heating load using the HP backup calculation
hp_sizing_values = @all_hvac_sizings[{ heating: hvac_hp, cooling: hvac_hp }]
if hp_sizing_values.nil?
@@ -2898,6 +2929,35 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
end
hvac_sizings.Heat_Airflow = calc_airflow_rate(:htg, hvac_heating, hvac_sizings.Heat_Capacity, hpxml_bldg)
+ elsif [HPXML::HVACTypeHeatPumpGroundToWater].include? heating_type
+ hvac_heating_speed = get_nominal_speed(htg_ap, false)
+
+ # htg_cap_curve_value = calc_gshp_htg_curve_value(htg_ap, hpxml_header, mj.heat_setpoint, htg_ap.design_hw, hvac_heating_speed)
+ # Reference conditions in thesis with largest capacity:
+ # See Appendix B Figure B.3 of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
+ ref_temp = 283 # K
+
+ db_temp = UnitConversions.convert(mj.heat_setpoint, 'F', 'K')
+ w_temp = UnitConversions.convert(htg_ap.design_hw, 'F', 'K')
+
+ htg_cap_curve_value = MathTools.quadlinear(db_temp / ref_temp, w_temp / ref_temp, 1.0, 1.0, htg_ap.heat_cap_curve_spec[hvac_heating_speed])
+
+ hvac_sizings.Heat_Capacity = hvac_sizings.Heat_Load / htg_cap_curve_value
+ hvac_sizings.Heat_Capacity_Supp = hvac_sizings.Heat_Load_Supp
+ if hvac_sizings.Cool_Capacity > 0
+ # if (hpxml_header.ground_to_air_heat_pump_model_type == HPXML::AdvancedResearchGroundToAirHeatPumpModelTypeStandard) && (hvac_heating.compressor_type == HPXML::HVACCompressorTypeSingleStage)
+ # For single stage compressor, when heating capacity is much larger than cooling capacity,
+ # in order to avoid frequent cycling in cooling mode, heating capacity is derated to 75%.
+ # Currently only keep it for standard ghp models
+ hvac_sizings.Heat_Capacity *= 0.75 if (hvac_sizings.Heat_Capacity >= 1.5 * hvac_sizings.Cool_Capacity)
+ # end
+ hvac_sizings.Cool_Capacity = [hvac_sizings.Cool_Capacity, hvac_sizings.Heat_Capacity].max
+ hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * clg_ap.cool_rated_shr_gross
+ hvac_sizings.Cool_Airflow = 0.0
+ hvac_sizings.Heat_Capacity = hvac_sizings.Cool_Capacity
+ end
+ hvac_sizings.Heat_Airflow = 0.0
+
elsif [HPXML::HVACTypeHeatPumpWaterLoopToAir].include? heating_type
hvac_sizings.Heat_Capacity = hvac_sizings.Heat_Load
@@ -3283,7 +3343,7 @@ def self.apply_hvac_final_capacities(hvac_sizings, hvac_heating, hvac_cooling, h
def self.apply_hvac_ground_loop(mj, runner, hvac_sizings, weather, hvac_cooling, hpxml_bldg)
cooling_type = get_hvac_cooling_type(hvac_cooling)
- return if cooling_type != HPXML::HVACTypeHeatPumpGroundToAir
+ return unless [HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater].include? cooling_type
geothermal_loop = hvac_cooling.geothermal_loop
@@ -5222,9 +5282,11 @@ def self.assign_to_hpxml_system(hvac_heating, hvac_cooling, hvac_sizings)
end
# Heating design airflow rate
- if not (hvac_heating.is_a?(HPXML::HeatingSystem) &&
+ if not ((hvac_heating.is_a?(HPXML::HeatingSystem) &&
[HPXML::HVACTypeBoiler,
- HPXML::HVACTypeElectricResistance].include?(hvac_heating.heating_system_type))
+ HPXML::HVACTypeElectricResistance].include?(hvac_heating.heating_system_type))) ||
+ ((hvac_heating.is_a?(HPXML::HeatPump) &&
+ [HPXML::HVACTypeHeatPumpGroundToWater].include?(hvac_heating.heat_pump_type)))
if hvac_heating.heating_design_airflow_cfm.nil? || ((hvac_heating.heating_design_airflow_cfm - hvac_sizings.Heat_Airflow).abs >= 1.0)
hvac_heating.heating_design_airflow_cfm = Float(hvac_sizings.Heat_Airflow.round)
hvac_heating.heating_design_airflow_cfm_isdefaulted = true
@@ -5298,9 +5360,12 @@ def self.assign_to_hpxml_system(hvac_heating, hvac_cooling, hvac_sizings)
end
# Cooling design airflow rate
- if hvac_cooling.cooling_design_airflow_cfm.nil? || ((hvac_cooling.cooling_design_airflow_cfm - hvac_sizings.Cool_Airflow).abs >= 1.0)
- hvac_cooling.cooling_design_airflow_cfm = Float(hvac_sizings.Cool_Airflow.round)
- hvac_cooling.cooling_design_airflow_cfm_isdefaulted = true
+ if not (hvac_cooling.is_a?(HPXML::HeatPump) &&
+ [HPXML::HVACTypeHeatPumpGroundToWater].include?(hvac_cooling.heat_pump_type))
+ if hvac_cooling.cooling_design_airflow_cfm.nil? || ((hvac_cooling.cooling_design_airflow_cfm - hvac_sizings.Cool_Airflow).abs >= 1.0)
+ hvac_cooling.cooling_design_airflow_cfm = Float(hvac_sizings.Cool_Airflow.round)
+ hvac_cooling.cooling_design_airflow_cfm_isdefaulted = true
+ end
end
# Cooling installed/actual airflow rate
diff --git a/HPXMLtoOpenStudio/resources/location.rb b/HPXMLtoOpenStudio/resources/location.rb
index 8e0d0e05b7..10ae46ca8f 100644
--- a/HPXMLtoOpenStudio/resources/location.rb
+++ b/HPXMLtoOpenStudio/resources/location.rb
@@ -92,7 +92,7 @@ def self.apply_ground_temps(model, weather, hpxml_bldg)
sgts.resetAllMonths
sgts.setAllMonthlyTemperatures(weather.data.ShallowGroundMonthlyTemps.map { |t| UnitConversions.convert(t, 'F', 'C') })
- if hpxml_bldg.heat_pumps.count { |h| h.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir } > 0
+ if hpxml_bldg.heat_pumps.count { |h| [HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater].include?(h.heat_pump_type) } > 0
# Deep ground temperatures used by GSHP setpoint manager
dgts = model.getSiteGroundTemperatureDeep
dgts.resetAllMonths
diff --git a/ReportSimulationOutput/measure.rb b/ReportSimulationOutput/measure.rb
index e9ddc68bce..070386b0c7 100644
--- a/ReportSimulationOutput/measure.rb
+++ b/ReportSimulationOutput/measure.rb
@@ -2977,6 +2977,9 @@ def get_object_outputs_by_key(model, object, class_type)
elsif object.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized || object.to_CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.is_initialized
return { [FT::Elec, EUT::Heating] => ['Heating Coil Electricity Energy'] }
+ elsif object.to_HeatPumpWaterToWaterEquationFitHeating.is_initialized || object.to_HeatPumpPlantLoopEIRHeating.is_initialized
+ return { [FT::Elec, EUT::Heating] => ["Heat Pump #{EPlus::FuelTypeElectricity} Energy"] }
+
elsif object.to_ZoneHVACBaseboardConvectiveElectric.is_initialized
if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
return { [FT::Elec, EUT::HeatingHeatPumpBackup] => ['Baseboard Electricity Energy'] }
@@ -3026,6 +3029,9 @@ def get_object_outputs_by_key(model, object, class_type)
elsif object.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized || object.to_CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.is_initialized
return { [FT::Elec, EUT::Cooling] => ['Cooling Coil Electricity Energy'] }
+ elsif object.to_HeatPumpWaterToWaterEquationFitCooling.is_initialized || object.to_HeatPumpPlantLoopEIRCooling.is_initialized
+ return { [FT::Elec, EUT::Cooling] => ["Heat Pump #{EPlus::FuelTypeElectricity} Energy"] }
+
elsif object.to_EvaporativeCoolerDirectResearchSpecial.is_initialized
return { [FT::Elec, EUT::Cooling] => ['Evaporative Cooler Electricity Energy'] }
diff --git a/ReportSimulationOutput/measure.xml b/ReportSimulationOutput/measure.xml
index 798416f271..a589a90579 100644
--- a/ReportSimulationOutput/measure.xml
+++ b/ReportSimulationOutput/measure.xml
@@ -3,8 +3,8 @@
3.1
report_simulation_output
df9d170c-c21a-4130-866d-0d46b06073fd
- d2815bb5-3851-437a-84ad-0747dfd93113
- 2025-08-25T16:51:58Z
+ d77169e3-539a-4920-88f3-b5d228f9c811
+ 2025-08-27T20:55:30Z
9BF1E6AC
ReportSimulationOutput
HPXML Simulation Output Report
@@ -1991,7 +1991,7 @@
measure.rb
rb
script
- 0B89F7D1
+ 4D36A836
test_report_sim_output.rb
diff --git a/docs/source/workflow_inputs.rst b/docs/source/workflow_inputs.rst
index 79261e5136..d4968b1256 100644
--- a/docs/source/workflow_inputs.rst
+++ b/docs/source/workflow_inputs.rst
@@ -3218,6 +3218,75 @@ Each ground-to-air heat pump is entered as a ``/HPXML/Building/BuildingDetails/S
A non-zero charge defect should typically only be applied for systems that are charged on site, not for systems that have pre-charged line sets.
See `ANSI/RESNET/ACCA 310-2020 `_ for more information.
+.. _hvac_hp_ground_to_water:
+
+Ground-to-Water Heat Pump
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each ground-to-water heat pump is entered as a ``/HPXML/Building/BuildingDetails/Systems/HVAC/HVACPlant/HeatPump``.
+
+ =============================================== ======== ====== =============== ======== ============== ==============================================
+ Element Type Units Constraints Required Default Notes
+ =============================================== ======== ====== =============== ======== ============== ==============================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``AttachedToZone`` idref See [#]_ See [#]_ ID of attached zone
+ ``UnitLocation`` string See [#]_ No See [#]_ Location of heat pump
+ ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
+ ``IsSharedSystem`` boolean No false Whether it has a shared hydronic circulation loop [#]_
+ ``HeatPumpType`` string ground-to-water Yes Type of heat pump
+ ``HeatPumpFuel`` string electricity Yes Fuel type
+ ``HeatingCapacity`` double Btu/hr >= 0 No autosized [#]_ Heating output capacity
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized [#]_ Cooling output capacity
+ ``CompressorType`` string single stage Yes Type of compressor
+ ``BackupType`` string See [#]_ No Type of backup heating
+ ``FractionHeatLoadServed`` double frac >= 0, <= 1 [#]_ Yes Fraction of heating load served
+ ``FractionCoolLoadServed`` double frac >= 0, <= 1 [#]_ Yes Fraction of cooling load served
+ ``AnnualCoolingEfficiency[Units="EER"]/Value`` double Btu/Wh > 0 Yes Rated cooling efficiency
+ ``AnnualHeatingEfficiency[Units="COP"]/Value`` double W/W > 0 Yes Rated heating efficiency
+ ``NumberofUnitsServed`` integer > 0 See [#]_ Number of dwelling units served
+ ``AttachedToGeothermalLoop`` idref See [#]_ No [#]_ ID of attached geothermal loop
+ ``extension/PumpPowerWattsPerTon`` double W/ton >= 0 No See [#]_ Pump power [#]_
+ ``extension/SharedLoopWatts`` double W >= 0 See [#]_ Shared pump power [#]_
+ ``extension/FanCoilWatts`` double W >= 0 No 150.0 Fan coil power
+ ``extension/ChargeDefectRatio`` double frac >= -0.9, <= 9 No 0.0 Deviation between design/installed refrigerant charges [#]_
+ ``extension/CoolingAutosizingFactor`` double frac > 0 No 1.0 Cooling autosizing capacity multiplier
+ ``extension/HeatingAutosizingFactor`` double frac > 0 No 1.0 Heating autosizing capacity multiplier
+ ``extension/CoolingAutosizingLimit`` double Btu/hr > 0 No Cooling autosizing capacity limit
+ ``extension/HeatingAutosizingLimit`` double Btu/hr > 0 No Heating autosizing capacity limit
+ =============================================== ======== ====== =============== ======== ============== ==============================================
+
+ .. [#] If AttachedToZone provided, it must reference a conditioned ``Zone``.
+ .. [#] AttachedToZone only required if zone-level and space-level HVAC design load calculations are desired (see :ref:`zones_spaces`).
+ .. [#] UnitLocation choices are "conditioned space", "basement - unconditioned", "basement - conditioned", "attic - unvented", "attic - vented", "garage", "crawlspace - unvented", "crawlspace - vented", "crawlspace - conditioned", "other exterior", "other housing unit", "other heated space", "other multifamily buffer space", "other non-freezing space", "roof deck", "manufactured home belly", or "unconditioned space".
+ .. [#] If UnitLocation not provided, defaults based on the distribution system:
+
+ \- **Air**: same default logic as :ref:`waterheatingsystems`
+
+ \- **DSE**: "conditioned space" if ``FractionHeatLoadServed`` is 1, otherwise "unconditioned space"
+
+ .. [#] HVACDistribution type must be :ref:`hvac_distribution_air` (type: "fan coil") or :ref:`hvac_distribution_dse`.
+ .. [#] IsSharedSystem should be true if the SFA/MF building has multiple ground source heat pumps connected to a shared hydronic circulation loop.
+ .. [#] Heating capacity autosized per ACCA Manual J/S based on heating design load.
+ .. [#] Cooling capacity autosized per ACCA Manual J/S based on cooling design load.
+ .. [#] BackupType choices are "integrated" or "separate".
+ Heat pump backup will only operate during colder temperatures when the heat pump runs out of heating capacity or is disabled due to a switchover/lockout temperature.
+ Use "integrated" if the heat pump's distribution system and blower fan power applies to the backup heating (e.g., built-in electric strip heat or an integrated backup furnace, i.e., a dual-fuel heat pump).
+ Use "separate" if the backup system has its own distribution system (e.g., electric baseboard or a boiler).
+ Additional backup inputs are described in :ref:`hvac_hp_backup`.
+ .. [#] The sum of all ``FractionHeatLoadServed`` (across all HVAC systems) must be less than or equal to 1.
+ .. [#] The sum of all ``FractionCoolLoadServed`` (across all HVAC systems) must be less than or equal to 1.
+ .. [#] NumberofUnitsServed only required if IsSharedSystem is true, in which case it must be > 1.
+ .. [#] AttachedToGeothermalLoop must reference a ``GeothermalLoop``.
+ .. [#] If AttachedToGeothermalLoop not provided, the ground-to-air heat pump will be automatically attached to a geothermal loop that is entirely defaulted.
+ .. [#] If PumpPowerWattsPerTon not provided, defaults to 80 W/ton for a closed loop system.
+ .. [#] Pump power is calculated using PumpPowerWattsPerTon and the cooling capacity in tons, unless the system only provides heating, in which case the heating capacity in tons is used instead.
+ Any pump power that is shared by multiple dwelling units should be included in SharedLoopWatts, *not* PumpPowerWattsPerTon, so that shared loop pump power attributed to the dwelling unit is calculated.
+ .. [#] SharedLoopWatts only required if IsSharedSystem is true.
+ .. [#] Shared loop pump power attributed to the dwelling unit is calculated as SharedLoopWatts / NumberofUnitsServed.
+ .. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
+ A non-zero charge defect should typically only be applied for systems that are charged on site, not for systems that have pre-charged line sets.
+ See `ANSI/RESNET/ACCA 310-2020 `_ for more information.
+
.. _hvac_hp_water_loop:
Water-Loop-to-Air Heat Pump
diff --git a/workflow/hpxml_inputs.json b/workflow/hpxml_inputs.json
index 89d4cd715b..d8324a5426 100644
--- a/workflow/hpxml_inputs.json
+++ b/workflow/hpxml_inputs.json
@@ -2718,6 +2718,10 @@
"parent_hpxml": "sample_files/base-hvac-ground-to-air-heat-pump-1-speed.xml",
"simulation_control_ground_to_air_heat_pump_model_type": "experimental"
},
+ "sample_files/base-hvac-ground-to-water-heat-pump.xml": {
+ "parent_hpxml": "sample_files/base-hvac-ground-to-air-heat-pump-1-speed.xml",
+ "heat_pump_type": "ground-to-water w/ Ductless Fan Coil"
+ },
"sample_files/base-hvac-ground-to-air-heat-pump-2-speed.xml": {
"parent_hpxml": "sample_files/base-hvac-ground-to-air-heat-pump-1-speed.xml",
"heat_pump_heating_efficiency": 4.0,
diff --git a/workflow/sample_files/base-hvac-ground-to-water-heat-pump.xml b/workflow/sample_files/base-hvac-ground-to-water-heat-pump.xml
new file mode 100644
index 0000000000..c2a1b48ee7
--- /dev/null
+++ b/workflow/sample_files/base-hvac-ground-to-water-heat-pump.xml
@@ -0,0 +1,478 @@
+
+
+
+ HPXML
+ tasks.rb
+ 2000-01-01T00:00:00-07:00
+ create
+
+
+
+
+
+ Default
+
+
+
+
+
+
+
+
+
+ CO
+
+
+
+ proposed workscope
+
+
+
+
+ stand-alone
+ no units above or below
+ 180
+
+ electricity
+ natural gas
+
+
+
+ single-family detached
+ 2.0
+ 1.0
+ 8.0
+ 3
+ 2
+ 2700.0
+ 21600.0
+
+
+
+
+ 2006
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ 50.0
+
+ ACH
+ 3.0
+
+ 21600.0
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ attic - unvented
+ 1509.3
+ asphalt or fiberglass shingles
+ 0.7
+ 0.92
+ 6.0
+
+
+ 2.3
+
+
+
+
+
+
+ outside
+ basement - conditioned
+ 115.6
+ wood siding
+ 0.7
+ 0.92
+
+
+ 13.9
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 1200.0
+ wood siding
+ 0.7
+ 0.92
+
+ gypsum board
+
+
+
+ 22.7
+
+
+
+
+ outside
+ attic - unvented
+ gable
+
+
+
+ 225.0
+ wood siding
+ 0.7
+ 0.92
+
+
+ 4.0
+
+
+
+
+
+
+ ground
+ basement - conditioned
+ solid concrete
+ 8.0
+ 1200.0
+ 7.0
+
+ gypsum board
+
+
+
+
+ continuous - exterior
+ 10.0
+
+
+ continuous - interior
+ 0.0
+
+
+
+
+
+
+
+ attic - unvented
+ conditioned space
+ ceiling
+
+
+
+ 1350.0
+
+ gypsum board
+
+
+
+ 39.6
+
+
+
+
+
+
+ basement - conditioned
+ 1350.0
+ 150.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+ 0.0
+ 0.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+
+ 108.0
+ 0
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 72.0
+ 90
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 108.0
+ 180
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 72.0
+ 270
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+
+
+
+ 40.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ground-to-water
+ electricity
+ 36000.0
+ 36000.0
+ single stage
+ 1.0
+ 1.0
+
+ EER
+ 16.6
+
+
+ COP
+ 3.6
+
+
+
+
+
+ 68.0
+ 78.0
+
+
+
+
+
+ fan coil
+
+
+
+
+
+
+
+ electricity
+ storage water heater
+ conditioned space
+ 1.0
+ 0.94
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ false
+
+
+
+ faucet
+ false
+
+
+
+
+
+
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ electricity
+ conventional
+ 3.73
+
+
+
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ 650.0
+
+
+
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
+ TV other
+
+
+
+ other
+
+
+
+
+
\ No newline at end of file
diff --git a/workflow/tests/base_results/results_simulations_bills.csv b/workflow/tests/base_results/results_simulations_bills.csv
index 6485a33864..13cf4576bc 100644
--- a/workflow/tests/base_results/results_simulations_bills.csv
+++ b/workflow/tests/base_results/results_simulations_bills.csv
@@ -298,6 +298,7 @@ base-hvac-ground-to-air-heat-pump-detailed-geothermal-loop.xml,1842.25,144.0,169
base-hvac-ground-to-air-heat-pump-heating-only.xml,1630.21,144.0,1486.21,0.0,1630.21,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed-experimental.xml,1779.47,144.0,1635.47,0.0,1779.47,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed.xml,1695.58,144.0,1551.58,0.0,1695.58,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+base-hvac-ground-to-water-heat-pump.xml,1640.02,144.0,1496.02,0.0,1640.02,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml,2391.78,144.0,2247.78,0.0,2391.78,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml,2306.39,144.0,2162.39,0.0,2306.39,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-var-speed-detailed-performance.xml,2429.04,144.0,2285.04,0.0,2429.04,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
diff --git a/workflow/tests/base_results/results_simulations_energy.csv b/workflow/tests/base_results/results_simulations_energy.csv
index e3f61e2882..bc9acbede8 100644
--- a/workflow/tests/base_results/results_simulations_energy.csv
+++ b/workflow/tests/base_results/results_simulations_energy.csv
@@ -298,6 +298,7 @@ base-hvac-ground-to-air-heat-pump-detailed-geothermal-loop.xml,46.656,46.656,46.
base-hvac-ground-to-air-heat-pump-heating-only.xml,40.831,40.831,40.831,40.831,0.0,0.0,0.0,0.0,0.0,0.0,7.046,1.958,0.0,0.0,0.0,0.0,10.735,0.0,0.0,4.507,0.0,0.334,0.0,0.0,0.0,0.0,2.156,0.0,0.0,0.284,0.347,1.436,1.529,0.0,2.116,8.384,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed-experimental.xml,44.931,44.931,44.931,44.931,0.0,0.0,0.0,0.0,0.0,0.0,8.555,2.413,0.0,0.0,1.164,1.019,10.771,0.0,0.0,4.507,0.0,0.334,0.0,0.0,0.0,0.0,2.073,0.0,0.0,0.284,0.347,1.436,1.529,0.0,2.116,8.384,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed.xml,42.626,42.626,42.626,42.626,0.0,0.0,0.0,0.0,0.0,0.0,5.977,1.855,0.0,0.0,1.505,1.509,10.771,0.0,0.0,4.507,0.0,0.334,0.0,0.0,0.0,0.0,2.073,0.0,0.0,0.284,0.347,1.436,1.529,0.0,2.116,8.384,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+base-hvac-ground-to-water-heat-pump.xml,41.1,41.1,41.1,41.1,0.0,0.0,0.0,0.0,0.0,0.0,4.133,1.312,0.0,0.0,2.898,0.977,10.771,0.0,0.0,4.507,0.0,0.334,0.0,0.0,0.0,0.0,2.073,0.0,0.0,0.284,0.347,1.436,1.529,0.0,2.116,8.384,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml,61.753,61.753,61.753,61.753,0.0,0.0,0.0,0.0,0.0,0.0,16.67,1.592,5.304,0.182,5.46,0.765,10.771,0.0,0.0,4.507,0.0,0.334,0.0,0.0,0.0,0.0,2.073,0.0,0.0,0.284,0.347,1.436,1.529,0.0,2.116,8.384,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml,59.407,59.407,59.407,59.407,0.0,0.0,0.0,0.0,0.0,0.0,15.431,1.294,5.123,0.17,5.111,0.498,10.771,0.0,0.0,4.507,0.0,0.334,0.0,0.0,0.0,0.0,2.073,0.0,0.0,0.284,0.347,1.436,1.529,0.0,2.116,8.384,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-var-speed-detailed-performance.xml,62.777,62.777,62.777,62.777,0.0,0.0,0.0,0.0,0.0,0.0,18.165,1.473,3.998,0.107,6.761,0.493,10.77,0.0,0.0,4.507,0.0,0.334,0.0,0.0,0.0,0.0,2.073,0.0,0.0,0.284,0.347,1.436,1.529,0.0,2.116,8.384,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
diff --git a/workflow/tests/base_results/results_simulations_hvac.csv b/workflow/tests/base_results/results_simulations_hvac.csv
index dc270b2143..97efea1f69 100644
--- a/workflow/tests/base_results/results_simulations_hvac.csv
+++ b/workflow/tests/base_results/results_simulations_hvac.csv
@@ -298,6 +298,7 @@ base-hvac-ground-to-air-heat-pump-detailed-geothermal-loop.xml,6.8,91.76,36000.0
base-hvac-ground-to-air-heat-pump-heating-only.xml,6.8,91.76,36000.0,0.0,0.0,39372.0,15488.0,7963.0,0.0,575.0,6834.0,0.0,0.0,1738.0,2155.0,4620.0,0.0,0.0,14683.0,0.0,7750.0,0.0,207.0,507.0,0.0,0.0,0.0,2276.0,622.0,0.0,3320.0,0.0,0.0,139.0,0.0,-661.0,0.0,800.0
base-hvac-ground-to-air-heat-pump-var-speed-experimental.xml,6.8,91.76,36000.0,36000.0,0.0,39372.0,15488.0,7963.0,0.0,575.0,6834.0,0.0,0.0,1738.0,2155.0,4620.0,0.0,0.0,27993.0,13311.0,7750.0,0.0,207.0,507.0,0.0,0.0,0.0,2276.0,622.0,0.0,3320.0,0.0,0.0,265.0,126.0,-661.0,0.0,800.0
base-hvac-ground-to-air-heat-pump-var-speed.xml,6.8,91.76,36000.0,36000.0,0.0,39372.0,15488.0,7963.0,0.0,575.0,6834.0,0.0,0.0,1738.0,2155.0,4620.0,0.0,0.0,27993.0,13311.0,7750.0,0.0,207.0,507.0,0.0,0.0,0.0,2276.0,622.0,0.0,3320.0,0.0,0.0,265.0,126.0,-661.0,0.0,800.0
+base-hvac-ground-to-water-heat-pump.xml,6.8,91.76,36000.0,36000.0,0.0,23885.0,0.0,7963.0,0.0,575.0,6834.0,0.0,0.0,1738.0,2155.0,4620.0,0.0,0.0,14683.0,0.0,7750.0,0.0,207.0,507.0,0.0,0.0,0.0,2276.0,622.0,0.0,3320.0,0.0,0.0,139.0,0.0,-661.0,0.0,800.0
base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml,6.8,91.76,36000.0,36000.0,34121.0,39372.0,15488.0,7963.0,0.0,575.0,6834.0,0.0,0.0,1738.0,2155.0,4620.0,0.0,0.0,27993.0,13311.0,7750.0,0.0,207.0,507.0,0.0,0.0,0.0,2276.0,622.0,0.0,3320.0,0.0,0.0,265.0,126.0,-661.0,0.0,800.0
base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml,6.8,91.76,36000.0,36000.0,34121.0,39372.0,15488.0,7963.0,0.0,575.0,6834.0,0.0,0.0,1738.0,2155.0,4620.0,0.0,0.0,27993.0,13311.0,7750.0,0.0,207.0,507.0,0.0,0.0,0.0,2276.0,622.0,0.0,3320.0,0.0,0.0,265.0,126.0,-661.0,0.0,800.0
base-hvac-install-quality-air-to-air-heat-pump-var-speed-detailed-performance.xml,6.8,91.76,35800.0,36000.0,34121.0,39372.0,15488.0,7963.0,0.0,575.0,6834.0,0.0,0.0,1738.0,2155.0,4620.0,0.0,0.0,27993.0,13311.0,7750.0,0.0,207.0,507.0,0.0,0.0,0.0,2276.0,622.0,0.0,3320.0,0.0,0.0,265.0,126.0,-661.0,0.0,800.0
diff --git a/workflow/tests/base_results/results_simulations_loads.csv b/workflow/tests/base_results/results_simulations_loads.csv
index 3145769d29..89476f1bae 100644
--- a/workflow/tests/base_results/results_simulations_loads.csv
+++ b/workflow/tests/base_results/results_simulations_loads.csv
@@ -298,6 +298,7 @@ base-hvac-ground-to-air-heat-pump-detailed-geothermal-loop.xml,32.852,0.0,17.9,9
base-hvac-ground-to-air-heat-pump-heating-only.xml,27.353,0.0,0.0,9.917,0.815,0.0,0.0,0.0,3.518,3.855,0.876,7.002,0.667,11.442,-12.745,0.0,0.0,0.0,8.085,-0.103,5.397,0.0,0.505,0.0,9.53,-8.425,-2.62,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed-experimental.xml,37.354,0.0,19.792,9.917,0.849,0.0,0.0,0.0,3.138,3.89,0.885,7.023,0.674,11.539,-12.85,0.0,0.0,0.0,8.249,-0.115,5.793,0.0,0.509,0.0,19.369,-8.495,-2.637,0.0,-0.221,-0.253,-0.024,2.483,0.022,-0.335,12.647,0.0,0.0,0.0,-6.374,-0.11,-0.925,-4.124,-0.083,0.0,8.06,7.296,1.87
base-hvac-ground-to-air-heat-pump-var-speed.xml,28.608,0.0,17.431,9.917,0.849,0.0,0.0,0.0,3.504,3.888,0.884,7.016,0.673,11.533,-12.85,0.0,0.0,0.0,8.234,-0.114,5.448,0.0,0.509,0.0,10.65,-8.495,-2.637,0.0,-0.127,-0.254,-0.024,2.481,0.021,-0.336,12.647,0.0,0.0,0.0,-6.379,-0.11,-0.929,-4.118,-0.083,0.0,5.62,7.296,1.87
+base-hvac-ground-to-water-heat-pump.xml,18.196,0.0,12.0,9.917,0.849,0.0,0.0,0.0,4.027,3.883,0.883,7.004,0.673,11.522,-12.85,0.0,0.0,0.0,8.212,-0.116,5.224,0.0,0.509,0.0,0.0,-8.496,-2.637,0.0,0.11,-0.256,-0.024,2.476,0.021,-0.34,12.647,0.0,0.0,0.0,-6.385,-0.112,-0.946,-4.109,-0.083,0.0,0.0,7.295,1.87
base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml,35.979,4.268,18.804,9.917,0.849,0.0,0.0,0.0,3.209,3.89,0.885,7.023,0.674,11.54,-12.85,0.0,0.0,0.0,8.249,-0.115,5.986,0.0,0.509,0.0,17.725,-8.495,-2.637,0.0,-0.184,-0.253,-0.024,2.482,0.021,-0.336,12.647,0.0,0.0,0.0,-6.376,-0.11,-0.924,-4.124,-0.083,0.0,7.038,7.296,1.87
base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml,38.514,3.982,20.276,9.917,0.849,0.0,0.0,0.0,3.101,3.891,0.885,7.025,0.674,11.541,-12.85,0.0,0.0,0.0,8.253,-0.115,6.041,0.0,0.509,0.0,20.302,-8.495,-2.637,0.0,-0.241,-0.253,-0.024,2.483,0.022,-0.334,12.647,0.0,0.0,0.0,-6.374,-0.11,-0.921,-4.127,-0.083,0.0,8.557,7.296,1.87
base-hvac-install-quality-air-to-air-heat-pump-var-speed-detailed-performance.xml,42.352,2.65,22.381,9.917,0.849,0.0,0.0,0.0,2.927,3.89,0.885,7.022,0.674,11.537,-12.85,0.0,0.0,0.0,8.249,-0.115,6.074,0.0,0.508,0.0,24.291,-8.495,-2.637,0.0,-0.337,-0.253,-0.024,2.483,0.022,-0.334,12.647,0.0,0.0,0.0,-6.374,-0.11,-0.921,-4.15,-0.083,0.0,10.782,7.296,1.87
diff --git a/workflow/tests/base_results/results_simulations_misc.csv b/workflow/tests/base_results/results_simulations_misc.csv
index 61b3d79dee..3e0366c78f 100644
--- a/workflow/tests/base_results/results_simulations_misc.csv
+++ b/workflow/tests/base_results/results_simulations_misc.csv
@@ -298,6 +298,7 @@ base-hvac-ground-to-air-heat-pump-detailed-geothermal-loop.xml,0.0,0.0,0.0,1286.
base-hvac-ground-to-air-heat-pump-heating-only.xml,0.0,0.0,0.0,1286.4,890.5,11468.6,3942.3,4487.7,1890.2,4487.7,4487.7,1890.2,4487.7,30.981,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed-experimental.xml,10.0,0.0,0.0,1286.4,890.5,11468.5,3942.3,4354.5,2470.6,4354.5,4354.5,2470.6,4354.5,27.899,25.563,0.0
base-hvac-ground-to-air-heat-pump-var-speed.xml,0.0,0.0,0.0,1286.4,890.5,11468.5,3942.3,4016.2,2628.3,4016.2,4016.2,2628.3,4016.2,31.346,24.084,0.0
+base-hvac-ground-to-water-heat-pump.xml,0.0,0.0,0.0,1286.4,890.5,11468.5,3942.3,3197.5,2760.2,3197.5,3197.5,2760.2,3197.5,17.113,13.107,0.0
base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml,0.0,0.0,0.0,1286.4,890.5,11468.5,3942.3,10233.3,4592.1,10233.3,10233.3,4592.1,10233.3,33.093,26.404,0.0
base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml,0.0,0.0,0.0,1286.4,890.5,11468.5,3942.3,9996.3,4294.6,9996.3,9996.3,4294.6,9996.3,33.089,26.109,0.0
base-hvac-install-quality-air-to-air-heat-pump-var-speed-detailed-performance.xml,0.0,0.0,0.0,1286.4,890.5,11468.5,3942.3,9289.7,5573.8,9289.7,9289.7,5573.8,9289.7,33.092,25.461,0.0
diff --git a/workflow/tests/base_results/results_simulations_panel.csv b/workflow/tests/base_results/results_simulations_panel.csv
index cdfb2cd58c..c44d9df2fd 100644
--- a/workflow/tests/base_results/results_simulations_panel.csv
+++ b/workflow/tests/base_results/results_simulations_panel.csv
@@ -298,6 +298,7 @@ base-hvac-ground-to-air-heat-pump-detailed-geothermal-loop.xml,0.0,0.0,0.0,0.0,0
base-hvac-ground-to-air-heat-pump-heating-only.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed-experimental.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-ground-to-air-heat-pump-var-speed.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+base-hvac-ground-to-water-heat-pump.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-hvac-install-quality-air-to-air-heat-pump-var-speed-detailed-performance.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
diff --git a/workflow/tests/base_results/results_sizing.csv b/workflow/tests/base_results/results_sizing.csv
index 00deb0d2eb..4f46d0a1da 100644
--- a/workflow/tests/base_results/results_sizing.csv
+++ b/workflow/tests/base_results/results_sizing.csv
@@ -244,6 +244,9 @@ denver-hvac-autosize-ground-to-air-heat-pump-var-speed-experimental-sizing-metho
denver-hvac-autosize-ground-to-air-heat-pump-var-speed-sizing-methodology-ACCA.xml,43930.0,43930.0,0.0,1318.0,1318.0
denver-hvac-autosize-ground-to-air-heat-pump-var-speed-sizing-methodology-HERS.xml,43930.0,43930.0,0.0,1318.0,1318.0
denver-hvac-autosize-ground-to-air-heat-pump-var-speed-sizing-methodology-MaxLoad.xml,58384.0,58384.0,0.0,1752.0,1752.0
+denver-hvac-autosize-ground-to-water-heat-pump-sizing-methodology-ACCA.xml,26650.0,26650.0,0.0,0.0,0.0
+denver-hvac-autosize-ground-to-water-heat-pump-sizing-methodology-HERS.xml,26650.0,26650.0,0.0,0.0,0.0
+denver-hvac-autosize-ground-to-water-heat-pump-sizing-methodology-MaxLoad.xml,31331.0,31331.0,0.0,0.0,0.0
denver-hvac-autosize-install-quality-air-to-air-heat-pump-1-speed-sizing-methodology-ACCA-backup-emergency.xml,39042.0,40904.0,39372.0,1171.0,1227.0
denver-hvac-autosize-install-quality-air-to-air-heat-pump-1-speed-sizing-methodology-ACCA-backup-supplemental.xml,39042.0,40904.0,23805.0,1171.0,1227.0
denver-hvac-autosize-install-quality-air-to-air-heat-pump-1-speed-sizing-methodology-HERS-backup-emergency.xml,44495.0,46618.0,39372.0,1334.0,1398.0
@@ -649,6 +652,9 @@ houston-hvac-autosize-ground-to-air-heat-pump-var-speed-experimental-sizing-meth
houston-hvac-autosize-ground-to-air-heat-pump-var-speed-sizing-methodology-ACCA.xml,49352.0,49352.0,0.0,1481.0,1481.0
houston-hvac-autosize-ground-to-air-heat-pump-var-speed-sizing-methodology-HERS.xml,49352.0,49352.0,0.0,1481.0,1481.0
houston-hvac-autosize-ground-to-air-heat-pump-var-speed-sizing-methodology-MaxLoad.xml,49352.0,49352.0,0.0,1481.0,1481.0
+houston-hvac-autosize-ground-to-water-heat-pump-sizing-methodology-ACCA.xml,22707.0,22707.0,0.0,0.0,0.0
+houston-hvac-autosize-ground-to-water-heat-pump-sizing-methodology-HERS.xml,22707.0,22707.0,0.0,0.0,0.0
+houston-hvac-autosize-ground-to-water-heat-pump-sizing-methodology-MaxLoad.xml,22707.0,22707.0,0.0,0.0,0.0
houston-hvac-autosize-install-quality-air-to-air-heat-pump-1-speed-sizing-methodology-ACCA-backup-emergency.xml,50396.0,48528.0,24742.0,1511.0,1455.0
houston-hvac-autosize-install-quality-air-to-air-heat-pump-1-speed-sizing-methodology-ACCA-backup-supplemental.xml,50396.0,48528.0,0.0,1511.0,1455.0
houston-hvac-autosize-install-quality-air-to-air-heat-pump-1-speed-sizing-methodology-HERS-backup-emergency.xml,50396.0,48528.0,24742.0,1511.0,1455.0
diff --git a/workflow/tests/util.rb b/workflow/tests/util.rb
index 1345b555ad..7a5acf5a4e 100644
--- a/workflow/tests/util.rb
+++ b/workflow/tests/util.rb
@@ -43,7 +43,7 @@ def _run_xml(xml, worker_num, apply_unit_multiplier = false, annual_results_1x =
if hpxml_bldg.dehumidifiers.size > 0
# FUTURE: Dehumidifiers currently don't give desired results w/ unit multipliers
# https://github.com/NREL/OpenStudio-HPXML/issues/1499
- elsif hpxml_bldg.heat_pumps.count { |hp| hp.heat_pump_type == HPXML::HVACTypeHeatPumpGroundToAir } > 0
+ elsif hpxml_bldg.heat_pumps.count { |hp| [HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater].include?(hp.heat_pump_type) } > 0
# FUTURE: GSHPs currently don't give desired results w/ unit multipliers
# https://github.com/NREL/OpenStudio-HPXML/issues/1499
elsif hpxml_bldg.batteries.size > 0
@@ -1041,7 +1041,7 @@ def _verify_outputs(rundir, hpxml_path, results, hpxml, unit_multiplier)
assert_equal(0, energy_htg)
end
if htg_backup_fuels.include? fuel
- has_ashp = hpxml_bldg.heat_pumps.count { |hp| hp.heat_pump_type != HPXML::HVACTypeHeatPumpGroundToAir } > 0
+ has_ashp = hpxml_bldg.heat_pumps.count { |hp| ![HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpGroundToWater].include?(hp.heat_pump_type) } > 0
if (not hpxml_path.include? 'autosize') && (not is_warm_climate) && has_ashp
assert_operator(energy_hp_backup, :>, 0)
end