Skip to content

Commit

Permalink
Merge pull request #1074 from NREL/retain-hp-backup-size
Browse files Browse the repository at this point in the history
Heating system -> heat pump backup
  • Loading branch information
joseph-robertson committed Aug 18, 2023
2 parents 60af434 + 4ce68ae commit e346c36
Show file tree
Hide file tree
Showing 18 changed files with 35,699 additions and 35,254 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ jobs:
path: |
project_national/national_baseline/results_csvs/results_up00.csv
project_testing/testing_baseline/results_csvs/results_up00.csv
project_national/national_upgrades/results_csvs/results_up15.csv
project_testing/testing_upgrades/results_csvs/results_up15.csv
project_national/national_upgrades/results_csvs/results_up16.csv
project_testing/testing_upgrades/results_csvs/results_up16.csv
name: buildstockbatch_results_csvs

compare-tools:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Features
- Add 2022 Cambium emissions data ([#1038](https://github.com/NREL/resstock/pull/1038))
- Update characteristics to use EIA 2020 RECS ([#1031](https://github.com/NREL/resstock/pull/1031))
- Include HVAC secondary heating capabilities for project_testing ([#1090](https://github.com/NREL/resstock/pull/1090))
- For heat pump upgrades, adds the ability to set the existing primary (non-shared) heating system as the backup system using only a single option from the lookup ([#1074](https://github.com/NREL/resstock/pull/1074))

Fixes
- Set standard format for options_lookup ([#962](https://github.com/NREL/resstock/pull/962))
Expand Down
109 changes: 109 additions & 0 deletions docs/read_the_docs/source/advanced_tutorial/heat_pump_upgrades.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
Heat Pump Upgrades
==================

The following information is relevant for when a heat pump -related upgrade is defined in a project definition file.

Types of Backup
---------------

The ResStock workflow allows modeling heat pumps with either "integrated" or "separate" backup heating.
Definitions for each are given below.
See `HPXML Heat Pumps <https://openstudio-hpxml.readthedocs.io/en/latest/workflow_inputs.html#hpxml-heat-pumps>`_ for more information.

- *integrated*: 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).
- *separate*: the backup system has its own distribution system (e.g., electric baseboard or a boiler).

Lockout Temperatures
--------------------

The ResStock workflow allows for controlling the compressor and/or backup heating lockout temperatures.
Definitions for each are given below.
See the `Backup <https://openstudio-hpxml.readthedocs.io/en/latest/workflow_inputs.html#backup>`_ section of the OpenStudio-HPXML documentation for more information.

- *compressor*: minimum outdoor temperature for compressor operation.
- *backup heating*: maximum outdoor temperature for backup operation.

For example, a heat pump upgrade option could be defined with a compressor lockout temperature of 5F and a backup heating lockout temperature of 40F.
See below the argument assignments that would need to be added to the ``options_lookup.tsv`` file.
These values would override the OpenStudio-HPXML defaults.

.. code::
heat_pump_compressor_lockout_temp=5
heat_pump_backup_heating_lockout_temp=40
Replacement Scenarios
---------------------

When defining a heat pump upgrade, the new heat pump can either (a) replace the primary (existing) system, or (b) retain the primary (existing) system as its backup heating system.
In the latter case, all properties (e.g., capacity) of the primary (existing) system are retained as properties of the heat pump backup heating system.

Replace Primary System with New Heat Pump
*****************************************

For example:

.. code-block:: yaml
- upgrade_name: ASHP
options:
- option: HVAC Heating Efficiency|ASHP, SEER 22, 10 HSPF
apply_logic:
- HVAC Has Ducts|Yes
costs:
- value: 50.0
multiplier: Size, Heating System Primary (kBtu/h)
lifetime: 30
- option: HVAC Cooling Efficiency|Ducted Heat Pump
Primary System becomes Backup to New Heat Pump
**********************************************

Use the ``Heat Pump Backup|Use Existing System`` option from the lookup.
The following properties are retained:

- fuel type
- efficiency
- capacity

For example:

.. code-block:: yaml
- upgrade_name: ASHP
options:
- option: HVAC Heating Efficiency|ASHP, SEER 22, 10 HSPF
apply_logic:
- HVAC Has Ducts|Yes
costs:
- value: 50.0
multiplier: Size, Heating System Primary (kBtu/h)
lifetime: 30
- option: HVAC Cooling Efficiency|Ducted Heat Pump
- option: Heat Pump Backup|Use Existing System
For this scenario, the type of the backup is (automatically) determined based on information in the table below:

============= ============= =========== =============================
New Heat Pump Backup System Backup Type Example
============= ============= =========== =============================
ducted ducted integrated ASHP w/Furnace [#]_
ducted ductless separate ASHP w/Boiler
ductless ducted separate Ductless MSHP w/Furnace
ductless ductless separate Ductless MSHP w/Boiler
============= ============= =========== =============================

.. [#] When furnace is fuel-fired (i.e., non-electric).
When furnace is electric, it likely wouldn't be used as integrated backup.
Other situations and considerations:

- The primary (existing) system does not become backup to the heat pump when:

- the primary system is a heat pump
- the primary system is a shared system

- When a secondary (existing) system exists:

- it remains secondary if the heat pump upgrade is integrated backup
- it is removed if the heat pump upgrade is separate backup
3 changes: 2 additions & 1 deletion docs/read_the_docs/source/advanced_tutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ If your changes are intended to be merged into the ``develop`` branch of the `Re
tasks
options_lookup
increasing_upgrade_options
upgrade_scenario_config
upgrade_scenario_config
heat_pump_upgrades
2 changes: 1 addition & 1 deletion docs/read_the_docs/source/advanced_tutorial/tasks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Run ``openstudio tasks.rb download_weather`` to download available EPW weather f

.. code:: bash
$ /c/openstudio-3.4.0/bin/openstudio.exe tasks.rb download_weather
$ openstudio tasks.rb download_weather
Downloading /files/156/BuildStock_TMY3_FIPS.zip ( 1%)
Downloading /files/156/BuildStock_TMY3_FIPS.zip ( 2%)
Downloading /files/156/BuildStock_TMY3_FIPS.zip ( 3%)
Expand Down
129 changes: 105 additions & 24 deletions measures/ApplyUpgrade/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ def run(model, runner, user_arguments)
new_runner.result.stepValues.each do |step_value|
value = get_value_from_workflow_step_value(step_value)
next if value == ''
next if step_value.name == 'heat_pump_backup_use_existing_system'

measures['BuildResidentialHPXML'][0][step_value.name] = value
end
Expand All @@ -339,31 +340,66 @@ def run(model, runner, user_arguments)
measures['BuildResidentialHPXML'][0]['additional_properties'] = additional_properties.join('|') unless additional_properties.empty?

# Retain HVAC capacities

capacities = get_system_capacities(hpxml, system_upgrades)
measures['BuildResidentialHPXML'][0]['heating_system_heating_capacity'] = capacities['heating_system_heating_capacity']
measures['BuildResidentialHPXML'][0]['heating_system_2_heating_capacity'] = capacities['heating_system_2_heating_capacity']
measures['BuildResidentialHPXML'][0]['cooling_system_cooling_capacity'] = capacities['cooling_system_cooling_capacity']
measures['BuildResidentialHPXML'][0]['heat_pump_heating_capacity'] = capacities['heat_pump_heating_capacity']
measures['BuildResidentialHPXML'][0]['heat_pump_cooling_capacity'] = capacities['heat_pump_cooling_capacity']
measures['BuildResidentialHPXML'][0]['heat_pump_backup_heating_capacity'] = capacities['heat_pump_backup_heating_capacity']

# Retain Existing Heating System as Heat Pump Backup
heat_pump_backup_use_existing_system = measures['ResStockArguments'][0]['heat_pump_backup_use_existing_system']
if heat_pump_backup_use_existing_system == 'true'
heating_system = get_heating_system(hpxml)
heat_pump_type = measures['BuildResidentialHPXML'][0]['heat_pump_type']
heat_pump_is_ducted = measures['BuildResidentialHPXML'][0]['heat_pump_is_ducted']

# Only set the backup if the heat pump is applied and there is an existing heating system
if (heat_pump_type != 'none') && (not heating_system.nil?)
heat_pump_backup_type = get_heat_pump_backup_type(heating_system, heat_pump_type, heat_pump_is_ducted)
heat_pump_backup_values = get_heat_pump_backup_values(heating_system)

heating_system_type = heat_pump_backup_values['heating_system_type']
heat_pump_backup_fuel = heat_pump_backup_values['heat_pump_backup_fuel']
heat_pump_backup_heating_efficiency = heat_pump_backup_values['heat_pump_backup_heating_efficiency']
heat_pump_backup_heating_capacity = heat_pump_backup_values['heat_pump_backup_heating_capacity']

# Integrated; heat pump's distribution system and blower fan power applies to the backup heating
# e.g., ducted heat pump (e.g., ashp, gshp, ducted minisplit) with ducted (e.g., furnace) backup
if heat_pump_backup_type == HPXML::HeatPumpBackupTypeIntegrated

# Likely only fuel-fired furnace as integrated backup
if heat_pump_backup_fuel != HPXML::FuelTypeElectricity
measures['BuildResidentialHPXML'][0]['heat_pump_backup_type'] = heat_pump_backup_type
measures['BuildResidentialHPXML'][0]['heat_pump_backup_fuel'] = heat_pump_backup_fuel
measures['BuildResidentialHPXML'][0]['heat_pump_backup_heating_efficiency'] = heat_pump_backup_heating_efficiency
measures['BuildResidentialHPXML'][0]['heat_pump_backup_heating_capacity'] = heat_pump_backup_heating_capacity

runner.registerInfo("Found '#{heating_system_type}' heating system type; setting it as 'heat_pump_backup_type=#{measures['BuildResidentialHPXML'][0]['heat_pump_backup_type']}'.")
else # Likely would not have electric furnace as integrated backup
runner.registerInfo("Found '#{heating_system_type}' heating system type with '#{heat_pump_backup_fuel}' fuel type; not setting it as integrated backup.")
end

unless capacities['heating_system_heating_capacity'].nil?
measures['BuildResidentialHPXML'][0]['heating_system_heating_capacity'] = capacities['heating_system_heating_capacity']
end

unless capacities['heating_system_2_heating_capacity'].nil?
measures['BuildResidentialHPXML'][0]['heating_system_2_heating_capacity'] = capacities['heating_system_2_heating_capacity']
end

unless capacities['cooling_system_cooling_capacity'].nil?
measures['BuildResidentialHPXML'][0]['cooling_system_cooling_capacity'] = capacities['cooling_system_cooling_capacity']
end

unless capacities['heat_pump_heating_capacity'].nil?
measures['BuildResidentialHPXML'][0]['heat_pump_heating_capacity'] = capacities['heat_pump_heating_capacity']
end

unless capacities['heat_pump_cooling_capacity'].nil?
measures['BuildResidentialHPXML'][0]['heat_pump_cooling_capacity'] = capacities['heat_pump_cooling_capacity']
end

unless capacities['heat_pump_backup_heating_capacity'].nil?
measures['BuildResidentialHPXML'][0]['heat_pump_backup_heating_capacity'] = capacities['heat_pump_backup_heating_capacity']
# Separate; backup system has its own distribution system
# e.g., ductless heat pump (e.g., ductless minisplit) with ducted (e.g., furnace) or ductless (e.g., boiler) backup
# e.g., ducted heat pump (e.g., ashp, gshp) with ductless (e.g., boiler) backup
elsif heat_pump_backup_type == HPXML::HeatPumpBackupTypeSeparate
# It's possible this was < 1.0 due to adjustment for secondary heating system
measures['BuildResidentialHPXML'][0]['heat_pump_fraction_heat_load_served'] = 1.0

measures['BuildResidentialHPXML'][0]['heat_pump_backup_type'] = heat_pump_backup_type
measures['BuildResidentialHPXML'][0]['heating_system_2_type'] = heating_system_type
measures['BuildResidentialHPXML'][0]['heating_system_2_fuel'] = heat_pump_backup_fuel
measures['BuildResidentialHPXML'][0]['heating_system_2_heating_efficiency'] = heat_pump_backup_heating_efficiency
measures['BuildResidentialHPXML'][0]['heating_system_2_heating_capacity'] = heat_pump_backup_heating_capacity

runner.registerInfo("Found '#{heating_system_type}' heating system type; setting it as 'heat_pump_backup_type=#{measures['BuildResidentialHPXML'][0]['heat_pump_backup_type']}'.")
else
runner.registerError("Unknown heat pump backup type '#{heat_pump_backup_type}'.")
return false
end
end
end

# Get software program used and version
Expand Down Expand Up @@ -458,6 +494,44 @@ def halt_workflow(runner, measures)
return false
end

def get_heating_system(hpxml)
hpxml.heating_systems.each do |heating_system|
next unless heating_system.primary_system
next if heating_system.is_shared_system

return heating_system
end
return
end

def get_heat_pump_backup_type(heating_system, heat_pump_type, heat_pump_is_ducted)
ducted_backup = [HPXML::HVACTypeFurnace].include?(heating_system.heating_system_type)
if (ducted_backup && (heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit) && (heat_pump_is_ducted == 'true')) ||
(ducted_backup && [HPXML::HVACTypeHeatPumpAirToAir, HPXML::HVACTypeHeatPumpGroundToAir].include?(heat_pump_type))
return HPXML::HeatPumpBackupTypeIntegrated
end

return HPXML::HeatPumpBackupTypeSeparate
end

def get_heat_pump_backup_values(heating_system)
heating_system_type = heating_system.heating_system_type
heat_pump_backup_fuel = heating_system.heating_system_fuel
if not heating_system.heating_efficiency_afue.nil?
heat_pump_backup_heating_efficiency = heating_system.heating_efficiency_afue
elsif not heating_system.heating_efficiency_percent.nil?
heat_pump_backup_heating_efficiency = heating_system.heating_efficiency_percent
end
heat_pump_backup_heating_capacity = heating_system.heating_capacity
values = {
'heating_system_type' => heating_system_type,
'heat_pump_backup_fuel' => heat_pump_backup_fuel,
'heat_pump_backup_heating_efficiency' => heat_pump_backup_heating_efficiency,
'heat_pump_backup_heating_capacity' => heat_pump_backup_heating_capacity
}
return values
end

def get_system_upgrades(hpxml, system_upgrades, args_hash)
args_hash.keys.each do |arg|
# Detect whether we are upgrading the heating system
Expand Down Expand Up @@ -497,7 +571,14 @@ def get_system_upgrades(hpxml, system_upgrades, args_hash)
end

def get_system_capacities(hpxml, system_upgrades)
capacities = {}
capacities = {
'heating_system_heating_capacity' => nil,
'heating_system_2_heating_capacity' => nil,
'cooling_system_cooling_capacity' => nil,
'heat_pump_heating_capacity' => nil,
'heat_pump_cooling_capacity' => nil,
'heat_pump_backup_heating_capacity' => nil
}

hpxml.heating_systems.each do |heating_system|
next unless heating_system.primary_system
Expand Down
8 changes: 4 additions & 4 deletions measures/ApplyUpgrade/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<schema_version>3.1</schema_version>
<name>apply_upgrade</name>
<uid>33f1654c-f734-43d1-b35d-9d2856e41b5a</uid>
<version_id>ccefea08-b9fa-4fc9-86f3-df7f8c25b2a9</version_id>
<version_modified>2023-07-26T21:20:25Z</version_modified>
<version_id>e4c3bd24-2fb7-4810-8416-8df29a622c4a</version_id>
<version_modified>2023-07-26T22:17:02Z</version_modified>
<xml_checksum>9339BE01</xml_checksum>
<class_name>ApplyUpgrade</class_name>
<display_name>Apply Upgrade</display_name>
Expand Down Expand Up @@ -6330,7 +6330,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>0743C8DE</checksum>
<checksum>4AA761B5</checksum>
</file>
<file>
<filename>constants.rb</filename>
Expand All @@ -6342,7 +6342,7 @@
<filename>apply_upgrade_test.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>A9826856</checksum>
<checksum>B5242812</checksum>
</file>
</files>
</measure>

0 comments on commit e346c36

Please sign in to comment.