From 6d2d943e8bb375dff581e37daa879e3dd361ff17 Mon Sep 17 00:00:00 2001 From: Sashadf1 Date: Mon, 19 Aug 2024 17:19:13 -0600 Subject: [PATCH 1/7] pasting in WIP on get_hvac_size_limits and calculate_heat_pump_backup_load from acca_manual_s branch --- HPXMLtoOpenStudio/resources/hvac_sizing.rb | 49 +++++++++++++--------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb index 832db9cec8..087c02a55b 100644 --- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb +++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb @@ -1711,26 +1711,35 @@ def self.apply_fractions_load_served(hvac_heating, hvac_loads, frac_zone_heat_lo end # Returns the ACCA Manual S sizing allowances for a given type of HVAC equipment. - # These sizing allowances are used in the logic that determines how to convert heating/cooling - # design loads into corresponding equipment capacities. + # These sizing allowances are used in the logic that determines how to convert heating/cooling + # design loads into corresponding equipment capacities. + # New ACCA Manual S specifies different size limits depending on the sizing condition (Standard, Dry, Variable Speed, etc.) + # - # @param hvac_cooling [HPXML::CoolingSystem or HPXML::HeatPump] The cooling portion of the current HPXML HVAC system - # @return [Array] Oversize fraction (frac), oversize delta (Btu/hr), undersize fraction (frac) - def self.get_hvac_size_limits(hvac_cooling) - oversize_limit = 1.15 - oversize_delta = 15000.0 - undersize_limit = 0.9 + # @param hvac_cooling [HPXML::CoolingSystem or HPXML::HeatPump] The cooling portion of the current HPXML HVAC system + # @param sizing_condition [String] The sizing condition of the current HPXML HVAC system + # @return [Array] Oversize limit (frac), oversize delta (Btu/hr), undersize limit (frac) - if not hvac_cooling.nil? - if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage - oversize_limit = 1.2 - elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeVariableSpeed - oversize_limit = 1.3 - end - end + def self.get_hvac_size_limits(hvac_cooling, hvac_sizing_methodology, hvac_size_cooling_cap, sizing_condition, climate_j_shr) - return oversize_limit, oversize_delta, undersize_limit - end + if not hvac_cooling.nil? + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && + + #Table N.2.3.1 ACCA Man. S 2023 + + oversize_limit = 1.15 + oversize_delta = 15000.0 + undersize_limit = 0.9 + + if not hvac_cooling.nil? + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + oversize_limit = 1.2 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeVariableSpeed + oversize_limit = 1.3 + end + end + return oversize_factor, oversize_delta, undersize_factor + end # Transfers the design load totals from the HVAC loads object to the HVAC sizings object. # @@ -3168,8 +3177,10 @@ def self.calculate_heat_pump_adj_factor_at_outdoor_temperature(mj, hvac_heating, # @return [Double] Heat pump backup load (Btu/hr) def self.calculate_heat_pump_backup_load(mj, hvac_heating, heating_load, hp_nominal_heating_capacity, hvac_heating_speed, hpxml_bldg) if hpxml_bldg.header.heat_pump_backup_sizing_methodology == HPXML::HeatPumpBackupSizingEmergency - # Size backup to meet full design load in case heat pump fails - return heating_load + # Size backup to meet 85% of design load in case heat pump fails + # New ACCA Man S (2024)--> emergency heating load is 85% of heating load + # See Table N1.16.3.2 Electric Resistance Emergency Heat + return 0.85*heating_load elsif hpxml_bldg.header.heat_pump_backup_sizing_methodology == HPXML::HeatPumpBackupSizingSupplemental if not hvac_heating.backup_heating_switchover_temp.nil? min_compressor_temp = hvac_heating.backup_heating_switchover_temp From 7ea4e54f8291628fd5d7c09246f2f8c547ff1232 Mon Sep 17 00:00:00 2001 From: Sashadf1 Date: Tue, 20 Aug 2024 14:50:38 -0600 Subject: [PATCH 2/7] updating HVACSizingControl element to include two options for ACCA sizing --- HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml index 2cb6b07991..1b87176a33 100644 --- a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml +++ b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml @@ -338,7 +338,7 @@ [HVACSizingControl] Expected 0 or 1 element(s) for xpath: HeatPumpSizingMethodology - Expected HeatPumpSizingMethodology to be 'ACCA' or 'HERS' or 'MaxLoad' + Expected HeatPumpSizingMethodology to be 'ACCA2023' or 'ACCA2014' or 'HERS' or 'MaxLoad' Expected 0 or 1 element(s) for xpath: HeatPumpBackupSizingMethodology Expected HeatPumpBackupSizingMethodology to be 'emergency' or 'supplemental' Expected 0 or 1 element(s) for xpath: AllowIncreasedFixedCapacities From b27bf3f5ada10ac44c1b70999479f505d7bb1154 Mon Sep 17 00:00:00 2001 From: Sashadf1 Date: Tue, 20 Aug 2024 15:22:11 -0600 Subject: [PATCH 3/7] HVACSizingControl HeatPumpSizingMethodology changes to ensure old 'ACCA' options refers to 2014 --- HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml index 1b87176a33..4f6c78ab44 100644 --- a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml +++ b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml @@ -338,7 +338,7 @@ [HVACSizingControl] Expected 0 or 1 element(s) for xpath: HeatPumpSizingMethodology - Expected HeatPumpSizingMethodology to be 'ACCA2023' or 'ACCA2014' or 'HERS' or 'MaxLoad' + Expected HeatPumpSizingMethodology to be 'ACCA2023' or 'ACCA' or 'HERS' or 'MaxLoad' Expected 0 or 1 element(s) for xpath: HeatPumpBackupSizingMethodology Expected HeatPumpBackupSizingMethodology to be 'emergency' or 'supplemental' Expected 0 or 1 element(s) for xpath: AllowIncreasedFixedCapacities From 68a1dfbd3e5cecdaa7eb4802951fd00ea2165a3d Mon Sep 17 00:00:00 2001 From: Sashadf1 Date: Tue, 27 Aug 2024 17:19:02 -0600 Subject: [PATCH 4/7] progress on get_hvac_size_limits for new ACCA Manual S 2023 --- HPXMLtoOpenStudio/resources/hvac_sizing.rb | 66 ++++++++++++++++++---- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb index 087c02a55b..99982617d7 100644 --- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb +++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb @@ -1712,27 +1712,71 @@ def self.apply_fractions_load_served(hvac_heating, hvac_loads, frac_zone_heat_lo # Returns the ACCA Manual S sizing allowances for a given type of HVAC equipment. # These sizing allowances are used in the logic that determines how to convert heating/cooling - # design loads into corresponding equipment capacities. - # New ACCA Manual S specifies different size limits depending on the sizing condition (Standard, Dry, Variable Speed, etc.) + # design loads into corresponding equipment capacities. + + # New ACCA Manual S specifies different size limits for clg only/HPs depending on + # the sizing condition (Standard, Dry, Variable Speed, etc.) + # and total cooling load (24,000 BTU/hr cutoff) # # @param hvac_cooling [HPXML::CoolingSystem or HPXML::HeatPump] The cooling portion of the current HPXML HVAC system - # @param sizing_condition [String] The sizing condition of the current HPXML HVAC system - # @return [Array] Oversize limit (frac), oversize delta (Btu/hr), undersize limit (frac) - - def self.get_hvac_size_limits(hvac_cooling, hvac_sizing_methodology, hvac_size_cooling_cap, sizing_condition, climate_j_shr) - - if not hvac_cooling.nil? - if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && + # @param hvac_sizings + # @param hpxml_bldg + # @return TODO figure out appropriate variable type + + def self.get_hvac_size_limits(hvac_cooling, hvac_sizings, hpxml_bldg) + + load_shr = hvac_sizings.Cool_Load_Sens / hvac_sizings.Cool_Load_Tot + # calculate Climate JSHR to determine standard vs dry sizing condition + + if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingACCA2023 + if not hvac_cooling.nil? + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage || hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + if load_shr < 0.95 + # larger latent load + # Section N.2.3.1 ACCA Man. S 2023, Standard Sizing Condition + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot <= 24000 # BTU/hr + total_clg_oversize_limit = 1.20 + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot > 24000 # BTU/hr + total_clg_oversize_limit = 1.15 + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + total_clg_oversize_limit = 1.25 + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + end + elsif load_shr >= 0.95 # Section N.2.3.2 ACCA Man. S 2023, Dry Sizing Condition + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage + # Total Cooling Capacity / (Total Cooling Load + 6 kBtuh) <= 1.00 + # 1.00 = non-load adjusted oversize limit + # goal --> determine "load adjusted" oversize limit + # Total Cooling Capacity <= 1.00 * (Total Cooling Load + 6 kBtuh) + # Total Cooling Capacity <= 1.00 * Total Cooling Load + 1.00 * 6 kBtuh + # Total Cooling Capacity / Total Cooling Load <= 1.00 + (1.00 * 6 kBtuh) / Total Cooling Load + # Total Cooling Capacity Factor <= 1.00 + 6 kBtuh / Total Cooling Load + # Effective Total Cooling Oversize Limit = 1.00 + 6 kBtuh / Total Cooling Load + total_clg_oversize_limit = 1 + 6000 / hvac_sizings.Cool_Load_Tot + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + total_clg_oversize_limit = 1.15 # minimum compressor speed! + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 - #Table N.2.3.1 ACCA Man. S 2023 oversize_limit = 1.15 oversize_delta = 15000.0 undersize_limit = 0.9 if not hvac_cooling.nil? - if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage oversize_limit = 1.2 elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeVariableSpeed oversize_limit = 1.3 From ba5187cee6fea53bd28d015b925a1ce98466659a Mon Sep 17 00:00:00 2001 From: Sashadf1 Date: Tue, 3 Sep 2024 16:51:31 -0600 Subject: [PATCH 5/7] progress on get_hvac_size_limits --- HPXMLtoOpenStudio/resources/hvac_sizing.rb | 54 +++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb index 99982617d7..0867cfe65d 100644 --- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb +++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb @@ -1722,34 +1722,28 @@ def self.apply_fractions_load_served(hvac_heating, hvac_loads, frac_zone_heat_lo # @param hvac_cooling [HPXML::CoolingSystem or HPXML::HeatPump] The cooling portion of the current HPXML HVAC system # @param hvac_sizings # @param hpxml_bldg - # @return TODO figure out appropriate variable type + # @return [Array] total clg oversize limit (frac), + # total clg undersize limit (frac), sens. clg undersize limit (frac), lat. clg undersize limit (frac) def self.get_hvac_size_limits(hvac_cooling, hvac_sizings, hpxml_bldg) load_shr = hvac_sizings.Cool_Load_Sens / hvac_sizings.Cool_Load_Tot - # calculate Climate JSHR to determine standard vs dry sizing condition + # calculate Climate JSHR to determine standard vs dry sizing condition (new ACCA) if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingACCA2023 if not hvac_cooling.nil? - if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage || hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage if load_shr < 0.95 # larger latent load # Section N.2.3.1 ACCA Man. S 2023, Standard Sizing Condition + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot <= 24000 # BTU/hr total_clg_oversize_limit = 1.20 - total_clg_undersize_limit = 0.90 - sens_clg_undersize_limit = 0.90 - lat_clg_undersize_limit = 1.00 elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot > 24000 # BTU/hr total_clg_oversize_limit = 1.15 - total_clg_undersize_limit = 0.90 - sens_clg_undersize_limit = 0.90 - lat_clg_undersize_limit = 1.00 elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage total_clg_oversize_limit = 1.25 - total_clg_undersize_limit = 0.90 - sens_clg_undersize_limit = 0.90 - lat_clg_undersize_limit = 1.00 end elsif load_shr >= 0.95 # Section N.2.3.2 ACCA Man. S 2023, Dry Sizing Condition if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage @@ -1766,23 +1760,31 @@ def self.get_hvac_size_limits(hvac_cooling, hvac_sizings, hpxml_bldg) sens_clg_undersize_limit = 0.90 lat_clg_undersize_limit = 1.00 elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage - total_clg_oversize_limit = 1.15 # minimum compressor speed! + total_clg_oversize_limit = 1.15 # minimum compressor speed! TODO: incorporate minimum speed logic elsewhere + total_clg_undersize_limit = 0.90 # total clg undersize limit for dry climate, 2-stage compressor is as specified in ACCA 2014 + # ACCA 2023 Table N2.3.2 does not specify total cooling undersize limit. sens_clg_undersize_limit = 0.90 lat_clg_undersize_limit = 1.00 + elsif hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingACCA + # Reference "Overview of Size Limits for Residential HVAC Equipment" from Man. S 2014 + total_clg_oversize_limit = 1.15 + oversize_delta = 15000.0 #TODO get rid of oversize delta by "baking" into total_clg_oversize_limit for cold winter w/ JSHR > 0.95 + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + - oversize_limit = 1.15 - oversize_delta = 15000.0 - undersize_limit = 0.9 - - if not hvac_cooling.nil? + if not hvac_cooling.nil? if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage - oversize_limit = 1.2 - elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeVariableSpeed - oversize_limit = 1.3 - end - end - return oversize_factor, oversize_delta, undersize_factor + total_clg_oversize_limit = 1.2 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeVariableSpeed + total_clg_oversize_limit = 1.3 + end + end + + return total_clg_oversize_limit, total_clg_undersize_limit, sens_clg_undersize_limit, lat_clg_undersize_limit + end # Transfers the design load totals from the HVAC loads object to the HVAC sizings object. @@ -2161,7 +2163,7 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva hvac_cooling_ap = hvac_cooling.additional_properties is_ducted = !hvac_cooling.distribution_system.nil? cooling_delta_t = mj.cool_setpoint - hvac_cooling_ap.leaving_air_temp - oversize_limit, oversize_delta, undersize_limit = get_hvac_size_limits(hvac_cooling) + tot_clg_oversize_limit, tot_clg_undersize_limit, sens_clg_undersize_limit, lat_clg_undersize_limit = get_hvac_size_limits(hvac_cooling) end if hvac_sizings.Cool_Load_Tot <= 0 @@ -2284,7 +2286,7 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva # Determine the final sensible capacity at design using the SHR cool_sens_cap_design = cool_cap_design * design_shr - elsif cool_sens_cap_design < undersize_limit * hvac_sizings.Cool_Load_Sens + elsif cool_sens_cap_design < sens_undersize_limit * hvac_sizings.Cool_Load_Sens # Size by MJ8 Sensible Load, return to rated conditions, find rated sensible capacity with SHRRated. Limit total # capacity to oversizing limit. From e234c346a052b3d62f89e797109b9670e9d3d210 Mon Sep 17 00:00:00 2001 From: Sashadf1 Date: Tue, 10 Sep 2024 17:52:13 -0600 Subject: [PATCH 6/7] progress on get_hvac_size_limits() --- HPXMLtoOpenStudio/resources/hvac_sizing.rb | 128 ++++++++++++--------- 1 file changed, 76 insertions(+), 52 deletions(-) diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb index 0867cfe65d..a6724ba4d6 100644 --- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb +++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb @@ -1718,68 +1718,92 @@ def self.apply_fractions_load_served(hvac_heating, hvac_loads, frac_zone_heat_lo # the sizing condition (Standard, Dry, Variable Speed, etc.) # and total cooling load (24,000 BTU/hr cutoff) - # + # get_hvac_size_limits() does not address section/table N2.3.3 Two-Speed Heat Pump Sizing Condition + # or section/table N2.3.4 Variable-Capacity Equipment Sizing Condition + # since these size conditions also include heating size factors and minimum compressor heating size factors + # To maintain consistency w/ previous implementation in ACCA Man. S 2014, only cooling size limits are returned. + # Therefore, only sections/tables N2.3.1 and N2.3.2 from ACCA Man. S 2023 are addressed in this method. + # @param hvac_cooling [HPXML::CoolingSystem or HPXML::HeatPump] The cooling portion of the current HPXML HVAC system - # @param hvac_sizings - # @param hpxml_bldg + # @param hvac_sizings [HVACSizingValues] Object with sizing values for a given HVAC system + # @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit + # @param weather [WeatherFile] Weather object containing EPW information # @return [Array] total clg oversize limit (frac), # total clg undersize limit (frac), sens. clg undersize limit (frac), lat. clg undersize limit (frac) - def self.get_hvac_size_limits(hvac_cooling, hvac_sizings, hpxml_bldg) + def self.get_hvac_size_limits(hvac_cooling, hvac_sizings, hpxml_bldg, weather) load_shr = hvac_sizings.Cool_Load_Sens / hvac_sizings.Cool_Load_Tot # calculate Climate JSHR to determine standard vs dry sizing condition (new ACCA) if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingACCA2023 if not hvac_cooling.nil? - if load_shr < 0.95 - # larger latent load - # Section N.2.3.1 ACCA Man. S 2023, Standard Sizing Condition + if load_shr < 0.95 + # larger latent load + # Section N.2.3.1 ACCA Man. S 2023, Standard Sizing Condition + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot <= 24000 # BTU/hr + total_clg_oversize_limit = 1.20 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot > 24000 # BTU/hr + total_clg_oversize_limit = 1.15 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + total_clg_oversize_limit = 1.25 + end + elsif load_shr >= 0.95 # Section N.2.3.2 ACCA Man. S 2023, Dry Sizing Condition + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage + # Total Cooling Capacity / (Total Cooling Load + 6 kBtuh) <= 1.00 + # 1.00 = non-load adjusted oversize limit + # goal --> determine "load adjusted" oversize limit + # Total Cooling Capacity <= 1.00 * (Total Cooling Load + 6 kBtuh) + # Total Cooling Capacity <= 1.00 * Total Cooling Load + 1.00 * 6 kBtuh + # Total Cooling Capacity / Total Cooling Load <= 1.00 + (1.00 * 6 kBtuh) / Total Cooling Load + # Total Cooling Capacity Factor <= 1.00 + 6 kBtuh / Total Cooling Load + # Effective Total Cooling Oversize Limit = 1.00 + 6 kBtuh / Total Cooling Load + total_clg_oversize_limit = 1 + 6000 / hvac_sizings.Cool_Load_Tot total_clg_undersize_limit = 0.90 sens_clg_undersize_limit = 0.90 lat_clg_undersize_limit = 1.00 - if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot <= 24000 # BTU/hr - total_clg_oversize_limit = 1.20 - elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage && hvac_sizings.Cool_Load_Tot > 24000 # BTU/hr - total_clg_oversize_limit = 1.15 - elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage - total_clg_oversize_limit = 1.25 - end - elsif load_shr >= 0.95 # Section N.2.3.2 ACCA Man. S 2023, Dry Sizing Condition - if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage - # Total Cooling Capacity / (Total Cooling Load + 6 kBtuh) <= 1.00 - # 1.00 = non-load adjusted oversize limit - # goal --> determine "load adjusted" oversize limit - # Total Cooling Capacity <= 1.00 * (Total Cooling Load + 6 kBtuh) - # Total Cooling Capacity <= 1.00 * Total Cooling Load + 1.00 * 6 kBtuh - # Total Cooling Capacity / Total Cooling Load <= 1.00 + (1.00 * 6 kBtuh) / Total Cooling Load - # Total Cooling Capacity Factor <= 1.00 + 6 kBtuh / Total Cooling Load - # Effective Total Cooling Oversize Limit = 1.00 + 6 kBtuh / Total Cooling Load - total_clg_oversize_limit = 1 + 6000 / hvac_sizings.Cool_Load_Tot - total_clg_undersize_limit = 0.90 - sens_clg_undersize_limit = 0.90 - lat_clg_undersize_limit = 1.00 - elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage - total_clg_oversize_limit = 1.15 # minimum compressor speed! TODO: incorporate minimum speed logic elsewhere - total_clg_undersize_limit = 0.90 # total clg undersize limit for dry climate, 2-stage compressor is as specified in ACCA 2014 - # ACCA 2023 Table N2.3.2 does not specify total cooling undersize limit. - sens_clg_undersize_limit = 0.90 - lat_clg_undersize_limit = 1.00 - + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + total_clg_oversize_limit = 1.15 # minimum compressor speed! TODO: incorporate minimum speed logic elsewhere + total_clg_undersize_limit = 0.90 # total clg undersize limit for dry climate, 2-stage compressor is as specified in ACCA 2014 + # ACCA 2023 Table N2.3.2 does not specify total cooling undersize limit. + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + end + end + end elsif hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingACCA - # Reference "Overview of Size Limits for Residential HVAC Equipment" from Man. S 2014 - total_clg_oversize_limit = 1.15 - oversize_delta = 15000.0 #TODO get rid of oversize delta by "baking" into total_clg_oversize_limit for cold winter w/ JSHR > 0.95 - total_clg_undersize_limit = 0.90 - sens_clg_undersize_limit = 0.90 - lat_clg_undersize_limit = 1.00 - - - if not hvac_cooling.nil? - if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage - total_clg_oversize_limit = 1.2 - elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeVariableSpeed - total_clg_oversize_limit = 1.3 + # References "Overview of Size Limits for Residential HVAC Equipment" from Man. S 2014 + if ((weather.data.HDD65F / weather.data.CDD50F) < 2.0) || (load_shr < 0.95) + # mild winter or has latent cooling load + if not hvac_cooling.nil? + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = 0.90 + lat_clg_undersize_limit = 1.00 + if hvac_cooling.compressor_type == HPXML::HVACCompressorTypeSingleStage + total_clg_oversize_limit = 1.15 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeTwoStage + total_clg_oversize_limit = 1.20 + elsif hvac_cooling.compressor_type == HPXML::HVACCompressorTypeVariableSpeed + total_clg_oversize_limit = 1.30 + end + end + elsif ((weather.data.HDD65F / weather.data.CDD50F) >= 2.0) && (load_shr >= 0.95) + # cold winter and no latent cooling load + # Manual S 2023 doesn't specify latent/sensible capacity undersize limits in this situation. + # from software perspective, could either return zero, nil, or the same latent/sensible + # undersize limits as the situation with latent cooling load/mild winter. + total_clg_undersize_limit = 0.90 + sens_clg_undersize_limit = nil + lat_clg_undersize_limit = nil + # Max Total Cooling Capacity = Total Cooling Load + 15 kBtuh + # i.e. Total Cooling Capacity <= Total Cooling Load + 15 kBtuh + # <= means solve for oversize limit, size factor (capacity/load) <= oversize limit + # Total Cooling Capacity / Total Cooling Load <= (Total Cooling Load + 15 kBtuh) / Total Cooling Load + # Total Cooling Oversize Limit = (Total Cooling Load + 15 kBtuh) / Total Cooling Load + total_clg_oversize_limit = (hvac_sizings.Cool_Load_Tot + 15000) / hvac_sizings.Cool_Load_Tot end end @@ -2273,11 +2297,11 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva # If the adjusted equipment size is negative (occurs at altitude), use oversize limit (the adjustment # almost always hits the oversize limit in this case, making this a safe assumption) if (cool_cap_design < 0) || (cool_sens_cap_design < 0) - cool_cap_design = oversize_limit * hvac_sizings.Cool_Load_Tot + cool_cap_design = tot_clg_oversize_limit * hvac_sizings.Cool_Load_Tot end # Limit total capacity to oversize limit - cool_cap_design = [cool_cap_design, oversize_limit * hvac_sizings.Cool_Load_Tot].min + cool_cap_design = [cool_cap_design, tot_clg_oversize_limit * hvac_sizings.Cool_Load_Tot].min # Determine rated capacities hvac_sizings.Cool_Capacity = cool_cap_design / total_cap_curve_value @@ -2296,7 +2320,7 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva cool_cap_design = cool_sens_cap_design / design_shr # Limit total capacity to oversize limit - cool_cap_design = [cool_cap_design, oversize_limit * hvac_sizings.Cool_Load_Tot].min + cool_cap_design = [cool_cap_design, tot_clg_oversize_limit * hvac_sizings.Cool_Load_Tot].min # rated capacities hvac_sizings.Cool_Capacity = cool_cap_design / total_cap_curve_value @@ -2399,7 +2423,7 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva 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 + cool_cap_design = [cool_cap_design, tot_clg_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 * hvac_cooling_shr end From 1b59d86d03905c5a8194f8d42ea898655a0a22d5 Mon Sep 17 00:00:00 2001 From: Sashadf1 Date: Wed, 30 Oct 2024 19:41:12 -0600 Subject: [PATCH 7/7] progress? --- HPXMLtoOpenStudio/resources/hvac_sizing.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb index af45c68021..df9873688c 100644 --- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb +++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb @@ -1721,7 +1721,7 @@ def self.apply_hvac_fractions_load_served(hvac_loads, hvac_heating, hvac_cooling # @return [Array] total clg oversize limit (frac), # total clg undersize limit (frac), sens. clg undersize limit (frac), lat. clg undersize limit (frac) - def self.get_hvac_size_limits(hvac_cooling, hvac_sizings, hpxml_bldg, weather) + def self.get_hvac_size_limits_cooling(hvac_cooling, hvac_sizings, hpxml_bldg, weather) load_shr = hvac_sizings.Cool_Load_Sens / hvac_sizings.Cool_Load_Tot # calculate Climate JSHR to determine standard vs dry sizing condition (new ACCA) @@ -1799,7 +1799,11 @@ def self.get_hvac_size_limits(hvac_cooling, hvac_sizings, hpxml_bldg, weather) return total_clg_oversize_limit, total_clg_undersize_limit, sens_clg_undersize_limit, lat_clg_undersize_limit - end + end + + def self.get_hvac_size_limits_heating(hvac_cooling, hvac_sizings, hpxml_bldg, weather, runner) + if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingACCA + runner.registerError("No heating size limits ") # Transfers the design load totals from the HVAC loads object to the HVAC sizings object. #