Skip to content

Commit

Permalink
Merge pull request #1558 from NREL/autosizing_detailed_performance
Browse files Browse the repository at this point in the history
Allow autosizing with detailed performance data inputs for var speed systems
  • Loading branch information
shorowit authored Jan 25, 2024
2 parents ac23fdb + 19f740d commit 230a717
Show file tree
Hide file tree
Showing 22 changed files with 3,903 additions and 80 deletions.
2 changes: 1 addition & 1 deletion BuildResidentialHPXML/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2287,7 +2287,7 @@ Type of capacity values for detailed performance data if available. Applies only

- **Required:** ``false``

- **Choices:** `Absolute capacities`
- **Choices:** `Absolute capacities`, `Normalized capacity fractions`

<br/>

Expand Down
53 changes: 25 additions & 28 deletions BuildResidentialHPXML/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,7 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument

perf_data_capacity_type_choices = OpenStudio::StringVector.new
perf_data_capacity_type_choices << 'Absolute capacities'
# perf_data_capacity_type_choices << 'Normalized capacity fractions'
perf_data_capacity_type_choices << 'Normalized capacity fractions'

arg = OpenStudio::Measure::OSArgument.makeChoiceArgument('hvac_perf_data_capacity_type', perf_data_capacity_type_choices, false)
arg.setDisplayName('HVAC Detailed Performance Data: Capacity Type')
Expand Down Expand Up @@ -5232,23 +5232,23 @@ def self.set_cooling_systems(hpxml_bldg, args)
outdoor_temperature, min_speed_cap_or_frac, max_speed_cap_or_frac, min_speed_cop, max_speed_cop = cooling_perf_data_data_point

if hvac_perf_data_capacity_type == 'Absolute capacities'
min_speed_capacity = min_speed_cap_or_frac
max_speed_capacity = max_speed_cap_or_frac
min_speed_capacity = Float(min_speed_cap_or_frac)
max_speed_capacity = Float(max_speed_cap_or_frac)
elsif hvac_perf_data_capacity_type == 'Normalized capacity fractions'
min_speed_capacity_fraction_of_nominal = min_speed_cap_or_frac
max_speed_capacity_fraction_of_nominal = max_speed_cap_or_frac
min_speed_capacity_fraction_of_nominal = Float(min_speed_cap_or_frac)
max_speed_capacity_fraction_of_nominal = Float(max_speed_cap_or_frac)
end

clg_perf_data.add(outdoor_temperature: outdoor_temperature,
clg_perf_data.add(outdoor_temperature: Float(outdoor_temperature),
capacity: min_speed_capacity,
capacity_fraction_of_nominal: min_speed_capacity_fraction_of_nominal,
capacity_description: HPXML::CapacityDescriptionMinimum,
efficiency_cop: min_speed_cop)
clg_perf_data.add(outdoor_temperature: outdoor_temperature,
efficiency_cop: Float(min_speed_cop))
clg_perf_data.add(outdoor_temperature: Float(outdoor_temperature),
capacity: max_speed_capacity,
capacity_fraction_of_nominal: max_speed_capacity_fraction_of_nominal,
capacity_description: HPXML::CapacityDescriptionMaximum,
efficiency_cop: max_speed_cop)
efficiency_cop: Float(max_speed_cop))
end
end
end
Expand Down Expand Up @@ -5413,28 +5413,25 @@ def self.set_heat_pumps(hpxml_bldg, args)
outdoor_temperature, min_speed_cap_or_frac, max_speed_cap_or_frac, min_speed_cop, max_speed_cop = heating_perf_data_data_point

if hvac_perf_data_capacity_type == 'Absolute capacities'
min_speed_capacity = min_speed_cap_or_frac
max_speed_capacity = max_speed_cap_or_frac
min_speed_capacity = Float(min_speed_cap_or_frac)
max_speed_capacity = Float(max_speed_cap_or_frac)
elsif hvac_perf_data_capacity_type == 'Normalized capacity fractions'
min_speed_capacity_fraction_of_nominal = min_speed_cap_or_frac
max_speed_capacity_fraction_of_nominal = max_speed_cap_or_frac
min_speed_capacity_fraction_of_nominal = Float(min_speed_cap_or_frac)
max_speed_capacity_fraction_of_nominal = Float(max_speed_cap_or_frac)
end

htg_perf_data.add(outdoor_temperature: outdoor_temperature,
htg_perf_data.add(outdoor_temperature: Float(outdoor_temperature),
capacity: min_speed_capacity,
capacity_fraction_of_nominal: min_speed_capacity_fraction_of_nominal,
capacity_description: HPXML::CapacityDescriptionMinimum,
efficiency_cop: min_speed_cop)
htg_perf_data.add(outdoor_temperature: outdoor_temperature,
efficiency_cop: Float(min_speed_cop))
htg_perf_data.add(outdoor_temperature: Float(outdoor_temperature),
capacity: max_speed_capacity,
capacity_fraction_of_nominal: max_speed_capacity_fraction_of_nominal,
capacity_description: HPXML::CapacityDescriptionMaximum,
efficiency_cop: max_speed_cop)
efficiency_cop: Float(max_speed_cop))
end
end

if args[:hvac_perf_data_capacity_type].is_initialized
hvac_perf_data_capacity_type = args[:hvac_perf_data_capacity_type].get
hvac_perf_data_cooling_outdoor_temperatures = args[:hvac_perf_data_cooling_outdoor_temperatures].get.split(',').map(&:strip)
hvac_perf_data_cooling_min_speed_capacities = args[:hvac_perf_data_cooling_min_speed_capacities].get.split(',').map(&:strip)
hvac_perf_data_cooling_max_speed_capacities = args[:hvac_perf_data_cooling_max_speed_capacities].get.split(',').map(&:strip)
Expand All @@ -5450,23 +5447,23 @@ def self.set_heat_pumps(hpxml_bldg, args)
outdoor_temperature, min_speed_cap_or_frac, max_speed_cap_or_frac, min_speed_cop, max_speed_cop = cooling_perf_data_data_point

if hvac_perf_data_capacity_type == 'Absolute capacities'
min_speed_capacity = min_speed_cap_or_frac
max_speed_capacity = max_speed_cap_or_frac
min_speed_capacity = Float(min_speed_cap_or_frac)
max_speed_capacity = Float(max_speed_cap_or_frac)
elsif hvac_perf_data_capacity_type == 'Normalized capacity fractions'
min_speed_capacity_fraction_of_nominal = min_speed_cap_or_frac
max_speed_capacity_fraction_of_nominal = max_speed_cap_or_frac
min_speed_capacity_fraction_of_nominal = Float(min_speed_cap_or_frac)
max_speed_capacity_fraction_of_nominal = Float(max_speed_cap_or_frac)
end

clg_perf_data.add(outdoor_temperature: outdoor_temperature,
clg_perf_data.add(outdoor_temperature: Float(outdoor_temperature),
capacity: min_speed_capacity,
capacity_fraction_of_nominal: min_speed_capacity_fraction_of_nominal,
capacity_description: HPXML::CapacityDescriptionMinimum,
efficiency_cop: min_speed_cop)
clg_perf_data.add(outdoor_temperature: outdoor_temperature,
efficiency_cop: Float(min_speed_cop))
clg_perf_data.add(outdoor_temperature: Float(outdoor_temperature),
capacity: max_speed_capacity,
capacity_fraction_of_nominal: max_speed_capacity_fraction_of_nominal,
capacity_description: HPXML::CapacityDescriptionMaximum,
efficiency_cop: max_speed_cop)
efficiency_cop: Float(max_speed_cop))
end
end
end
Expand Down
14 changes: 9 additions & 5 deletions BuildResidentialHPXML/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>build_residential_hpxml</name>
<uid>a13a8983-2b01-4930-8af2-42030b6e4233</uid>
<version_id>54215a14-93ab-4f56-b310-4fdb6cc374e9</version_id>
<version_modified>2024-01-17T16:52:35Z</version_modified>
<version_id>dc0de2f1-fea3-4b8e-9df9-579c3fcc74dc</version_id>
<version_modified>2024-01-23T20:04:33Z</version_modified>
<xml_checksum>2C38F48B</xml_checksum>
<class_name>BuildResidentialHPXML</class_name>
<display_name>HPXML Builder</display_name>
Expand Down Expand Up @@ -2898,6 +2898,10 @@
<value>Absolute capacities</value>
<display_name>Absolute capacities</display_name>
</choice>
<choice>
<value>Normalized capacity fractions</value>
<display_name>Normalized capacity fractions</display_name>
</choice>
</choices>
</argument>
<argument>
Expand Down Expand Up @@ -7110,7 +7114,7 @@
<filename>README.md</filename>
<filetype>md</filetype>
<usage_type>readme</usage_type>
<checksum>3BA4B197</checksum>
<checksum>4F99980F</checksum>
</file>
<file>
<filename>README.md.erb</filename>
Expand All @@ -7127,7 +7131,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>EEE134EA</checksum>
<checksum>5D65A1D1</checksum>
</file>
<file>
<filename>geometry.rb</filename>
Expand All @@ -7139,7 +7143,7 @@
<filename>test_build_residential_hpxml.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>03168F56</checksum>
<checksum>FC9E4B75</checksum>
</file>
</files>
</measure>
22 changes: 22 additions & 0 deletions BuildResidentialHPXML/tests/test_build_residential_hpxml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def test_workflows
'extra-water-heater-attic.xml' => 'base-sfd.xml',
'extra-battery-crawlspace.xml' => 'base-sfd.xml',
'extra-battery-attic.xml' => 'base-sfd.xml',
'extra-detailed-performance-autosize.xml' => 'base-sfd.xml',

'extra-sfa-atticroof-flat.xml' => 'base-sfa.xml',
'extra-sfa-atticroof-conditioned-eaves-gable.xml' => 'extra-sfa-slab.xml',
Expand Down Expand Up @@ -915,6 +916,27 @@ def _set_measure_argument_values(hpxml_file, args)
elsif ['extra-battery-attic.xml'].include? hpxml_file
args['battery_present'] = true
args['battery_location'] = HPXML::LocationAttic
elsif ['extra-detailed-performance-autosize.xml'].include? hpxml_file
args['heating_system_type'] = 'none'
args['cooling_system_type'] = 'none'
args['heat_pump_type'] = HPXML::HVACTypeHeatPumpAirToAir
args['heat_pump_heating_efficiency'] = 10.0
args['heat_pump_cooling_efficiency'] = 17.25
args['heat_pump_cooling_compressor_type'] = HPXML::HVACCompressorTypeVariableSpeed
args['heat_pump_cooling_sensible_heat_fraction'] = 0.78
args.delete('heat_pump_heating_capacity')
args.delete('heat_pump_cooling_capacity')
args['hvac_perf_data_capacity_type'] = 'Normalized capacity fractions'
args['hvac_perf_data_heating_outdoor_temperatures'] = '47.0, 17.0, 5.0'
args['hvac_perf_data_heating_min_speed_capacities'] = '0.28, 0.12, 0.05'
args['hvac_perf_data_heating_max_speed_capacities'] = '1.0, 0.69, 0.55'
args['hvac_perf_data_heating_min_speed_cops'] = '4.73, 1.84, 0.81'
args['hvac_perf_data_heating_max_speed_cops'] = '3.44, 2.66, 2.28'
args['hvac_perf_data_cooling_outdoor_temperatures'] = '95.0, 82.0'
args['hvac_perf_data_cooling_min_speed_capacities'] = '0.325, 0.37'
args['hvac_perf_data_cooling_max_speed_capacities'] = '1.0, 1.11'
args['hvac_perf_data_cooling_min_speed_cops'] = '4.47, 6.34'
args['hvac_perf_data_cooling_max_speed_cops'] = '2.71, 3.53'
elsif ['extra-sfa-atticroof-flat.xml'].include? hpxml_file
args['geometry_attic_type'] = HPXML::AtticTypeFlatRoof
args['ducts_supply_leakage_to_outside_value'] = 0.0
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 @@ __New Features__
- Updates to HPXML v4.0-rc3.
- Replaces `BuildingSummary/Site/extension/GroundConductivity` with `BuildingSummary/Site/Soil/Conductivity`.
- Allows radiant barriers for additional locations (attic gable walls and floor); reduced emissivity due to dust assumed for radiant barriers on attic floor.
- Allows autosizing with detailed performance data inputs for variable-speed air source HVAC systems using `CapacityFractionOfNominal`.
- Ground source heat pump enhancements:
- Allows optional detailed inputs related to geothermal loop (`HVACPlant/GeothermalLoop`).
- Allows optional ground diffusivity input.
Expand Down
16 changes: 8 additions & 8 deletions HPXMLtoOpenStudio/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>hpxm_lto_openstudio</name>
<uid>b1543b30-9465-45ff-ba04-1d1f85e763bc</uid>
<version_id>bd1a7efb-d662-4948-ac8d-ca4876b763bf</version_id>
<version_modified>2024-01-25T14:12:12Z</version_modified>
<version_id>0d5b20ca-1c7f-4c69-bcbb-76c656573b2c</version_id>
<version_modified>2024-01-25T16:31:30Z</version_modified>
<xml_checksum>D8922A73</xml_checksum>
<class_name>HPXMLtoOpenStudio</class_name>
<display_name>HPXML to OpenStudio Translator</display_name>
Expand Down Expand Up @@ -310,7 +310,7 @@
<filename>hpxml_defaults.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>916525C3</checksum>
<checksum>932395EE</checksum>
</file>
<file>
<filename>hpxml_schema/HPXML.xsd</filename>
Expand All @@ -328,7 +328,7 @@
<filename>hpxml_schematron/EPvalidator.xml</filename>
<filetype>xml</filetype>
<usage_type>resource</usage_type>
<checksum>85D88CDE</checksum>
<checksum>7EE89A2E</checksum>
</file>
<file>
<filename>hpxml_schematron/iso-schematron.xsd</filename>
Expand All @@ -340,13 +340,13 @@
<filename>hvac.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>4CEA3B45</checksum>
<checksum>A060839F</checksum>
</file>
<file>
<filename>hvac_sizing.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>94E05F98</checksum>
<checksum>7CE7B6AB</checksum>
</file>
<file>
<filename>lighting.rb</filename>
Expand Down Expand Up @@ -592,7 +592,7 @@
<filename>test_defaults.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>EF0F0416</checksum>
<checksum>75775259</checksum>
</file>
<file>
<filename>test_enclosure.rb</filename>
Expand Down Expand Up @@ -664,7 +664,7 @@
<filename>test_validation.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>C564EC22</checksum>
<checksum>D799B100</checksum>
</file>
<file>
<filename>test_water_heater.rb</filename>
Expand Down
42 changes: 32 additions & 10 deletions HPXMLtoOpenStudio/resources/hpxml_defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1241,17 +1241,9 @@ def self.apply_hvac(runner, hpxml, hpxml_bldg, weather, convert_shared_systems)
next unless heat_pump.heating_capacity_retention_fraction.nil?
next unless heat_pump.heating_capacity_17F.nil?
next if [HPXML::HVACTypeHeatPumpGroundToAir, HPXML::HVACTypeHeatPumpWaterLoopToAir].include? heat_pump.heat_pump_type
next unless heat_pump.heating_detailed_performance_data.empty? # set after hvac sizing

if not heat_pump.heating_detailed_performance_data.empty?
# Calculate heating capacity retention at 5F outdoor drybulb
target_odb = 5.0
max_capacity_47 = heat_pump.heating_detailed_performance_data.find { |dp| dp.outdoor_temperature == HVAC::AirSourceHeatRatedODB && dp.capacity_description == HPXML::CapacityDescriptionMaximum }.capacity
heat_pump.heating_capacity_retention_fraction = (HVAC.interpolate_to_odb_table_point(heat_pump.heating_detailed_performance_data, HPXML::CapacityDescriptionMaximum, target_odb, :capacity) / max_capacity_47).round(5)
heat_pump.heating_capacity_retention_fraction = 0.0 if heat_pump.heating_capacity_retention_fraction < 0
heat_pump.heating_capacity_retention_temp = target_odb
else
heat_pump.heating_capacity_retention_temp, heat_pump.heating_capacity_retention_fraction = HVAC.get_default_heating_capacity_retention(heat_pump.compressor_type, heat_pump.heating_efficiency_hspf)
end
heat_pump.heating_capacity_retention_temp, heat_pump.heating_capacity_retention_fraction = HVAC.get_default_heating_capacity_retention(heat_pump.compressor_type, heat_pump.heating_efficiency_hspf)
heat_pump.heating_capacity_retention_fraction_isdefaulted = true
heat_pump.heating_capacity_retention_temp_isdefaulted = true
end
Expand Down Expand Up @@ -1672,6 +1664,14 @@ def self.apply_detailed_performance_data_for_var_speed_systems(hpxml_bldg)
if hvac_system.cooling_detailed_performance_data.empty?
HVAC.set_cool_detailed_performance_data(hvac_system)
else
# process capacity fraction of nominal
hvac_system.cooling_detailed_performance_data.each do |dp|
next unless dp.capacity.nil?

dp.capacity = (dp.capacity_fraction_of_nominal * hvac_system.cooling_capacity).round(3)
dp.capacity_isdefaulted = true
end

# override some properties based on detailed performance data
cool_rated_capacity = [hvac_system.cooling_capacity, 1.0].max
cool_max_capacity = [hvac_system.cooling_detailed_performance_data.find { |dp| (dp.outdoor_temperature == HVAC::AirSourceCoolRatedODB) && (dp.capacity_description == HPXML::CapacityDescriptionMaximum) }.capacity, 1.0].max
Expand All @@ -1683,6 +1683,24 @@ def self.apply_detailed_performance_data_for_var_speed_systems(hpxml_bldg)
if hvac_system.heating_detailed_performance_data.empty?
HVAC.set_heat_detailed_performance_data(hvac_system)
else
# process capacity fraction of nominal
hvac_system.heating_detailed_performance_data.each do |dp|
next unless dp.capacity.nil?

dp.capacity = (dp.capacity_fraction_of_nominal * hvac_system.heating_capacity).round(3)
dp.capacity_isdefaulted = true
end

if hvac_system.heating_capacity_retention_fraction.nil? && hvac_system.heating_capacity_17F.nil?
# Calculate heating capacity retention at 5F outdoor drybulb
target_odb = 5.0
max_capacity_47 = hvac_system.heating_detailed_performance_data.find { |dp| dp.outdoor_temperature == HVAC::AirSourceHeatRatedODB && dp.capacity_description == HPXML::CapacityDescriptionMaximum }.capacity
hvac_system.heating_capacity_retention_fraction = (HVAC.interpolate_to_odb_table_point(hvac_system.heating_detailed_performance_data, HPXML::CapacityDescriptionMaximum, target_odb, :capacity) / max_capacity_47).round(5)
hvac_system.heating_capacity_retention_fraction = 0.0 if hvac_system.heating_capacity_retention_fraction < 0
hvac_system.heating_capacity_retention_temp = target_odb
hvac_system.heating_capacity_retention_fraction_isdefaulted = true
hvac_system.heating_capacity_retention_temp_isdefaulted = true
end
# override some properties based on detailed performance data
heat_rated_capacity = [hvac_system.heating_capacity, 1.0].max
heat_max_capacity = [hvac_system.heating_detailed_performance_data.find { |dp| (dp.outdoor_temperature == HVAC::AirSourceHeatRatedODB) && (dp.capacity_description == HPXML::CapacityDescriptionMaximum) }.capacity, 1.0].max
Expand Down Expand Up @@ -3071,6 +3089,8 @@ def self.apply_hvac_sizing(runner, hpxml_bldg, weather, cfa)
if not htg_sys.heating_detailed_performance_data.empty?
# Fixed values entered; Scale w/ heating_capacity in case allow_increased_fixed_capacities=true
htg_sys.heating_detailed_performance_data.each do |dp|
next if dp.capacity.nil? # using autosized values, process later

htg_cap_dp = dp.capacity * scaling_factor
if (dp.capacity - htg_cap_dp).abs >= 1.0
dp.capacity = Float(htg_cap_dp.round)
Expand Down Expand Up @@ -3135,6 +3155,8 @@ def self.apply_hvac_sizing(runner, hpxml_bldg, weather, cfa)
scaling_factor = Float(hvac_sizing_values.Cool_Capacity.round) / clg_sys.cooling_capacity unless clg_sys.cooling_capacity.nil?
# Fixed values entered; Scale w/ cooling_capacity in case allow_increased_fixed_capacities=true
clg_sys.cooling_detailed_performance_data.each do |dp|
next if dp.capacity.nil? # using autosized values

clg_cap_dp = dp.capacity * scaling_factor
if (dp.capacity - clg_cap_dp).abs >= 1.0
dp.capacity = Float(clg_cap_dp.round)
Expand Down
Loading

0 comments on commit 230a717

Please sign in to comment.