Skip to content

Commit

Permalink
Squashed 'hpxml-measures/' changes from 1a9c556e73..e29d955f19
Browse files Browse the repository at this point in the history
e29d955f19 First try.

git-subtree-dir: hpxml-measures
git-subtree-split: e29d955f19775cd392622f99e354af5603998a48
  • Loading branch information
shorowit committed Aug 8, 2024
1 parent 692c8d1 commit 532cc3b
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 83 deletions.
10 changes: 5 additions & 5 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>feaf25ee-bd63-4157-9dfb-dc205b9f6bba</version_id>
<version_modified>2024-08-07T23:34:42Z</version_modified>
<version_id>f16fb702-6d18-408b-a85f-fc3c31bc92ef</version_id>
<version_modified>2024-08-08T18:51:39Z</version_modified>
<xml_checksum>D8922A73</xml_checksum>
<class_name>HPXMLtoOpenStudio</class_name>
<display_name>HPXML to OpenStudio Translator</display_name>
Expand Down Expand Up @@ -387,7 +387,7 @@
<filename>hvac_sizing.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>F3D7066C</checksum>
<checksum>16F1A401</checksum>
</file>
<file>
<filename>lighting.rb</filename>
Expand Down Expand Up @@ -633,7 +633,7 @@
<filename>in.schedules.csv</filename>
<filetype>csv</filetype>
<usage_type>test</usage_type>
<checksum>2B9C5C95</checksum>
<checksum>1E533016</checksum>
</file>
<file>
<filename>test_airflow.rb</filename>
Expand Down Expand Up @@ -681,7 +681,7 @@
<filename>test_hvac_sizing.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>9094E7AB</checksum>
<checksum>16805567</checksum>
</file>
<file>
<filename>test_lighting.rb</filename>
Expand Down
111 changes: 51 additions & 60 deletions HPXMLtoOpenStudio/resources/hvac_sizing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def self.calculate(runner, weather, hpxml_bldg, hvac_systems, update_hpxml: true
# Calculate HVAC equipment sizes
hvac_sizings = HVACSizingValues.new
apply_hvac_loads_to_hvac_sizings(hvac_sizings, hvac_loads)
apply_hvac_heat_pump_logic(hvac_sizings, hvac_cooling, frac_zone_heat_load_served, frac_zone_cool_load_served, hpxml_bldg)
apply_hvac_heat_pump_maxload_logic(hvac_sizings, hvac_cooling, frac_zone_heat_load_served, frac_zone_cool_load_served, hpxml_bldg)
apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hvac_heating, hvac_cooling, hvac_system, hpxml_bldg)
apply_hvac_installation_quality(mj, hvac_sizings, hvac_heating, hvac_cooling, frac_zone_heat_load_served, frac_zone_cool_load_served, hpxml_bldg)
apply_hvac_autosizing_factors_and_limits(hvac_sizings, hvac_heating, hvac_cooling)
Expand Down Expand Up @@ -1747,22 +1747,22 @@ def self.apply_hvac_loads_to_hvac_sizings(hvac_sizings, hvac_loads)
hvac_sizings.Heat_Load_Supp = hvac_loads.Heat_Tot
end

# Updates the design loads for a heat pump to comply with the specified heat pump sizing methodology.
# Updates the design loads for a heat pump to comply with the MaxLoad heat pump sizing methodology.
#
# @param hvac_sizings [HVACSizingValues] Object with sizing values for a given HVAC system
# @param hvac_cooling [HPXML::CoolingSystem or HPXML::HeatPump] The cooling portion of the current HPXML HVAC system
# @param frac_zone_heat_load_served [Double] Fraction of zone heating load served by this HVAC system
# @param frac_zone_cool_load_served [Double] Fraction of zone cooling load served by this HVAC system
# @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit
# @return [void]
def self.apply_hvac_heat_pump_logic(hvac_sizings, hvac_cooling, frac_zone_heat_load_served, frac_zone_cool_load_served, hpxml_bldg)
def self.apply_hvac_heat_pump_maxload_logic(hvac_sizings, hvac_cooling, frac_zone_heat_load_served, frac_zone_cool_load_served, hpxml_bldg)
# Only apply logic to a heat pump that provides both heating and cooling
return unless hvac_cooling.is_a? HPXML::HeatPump
return if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingACCA
return if hpxml_bldg.header.heat_pump_sizing_methodology != HPXML::HeatPumpSizingMaxLoad
return if frac_zone_heat_load_served == 0
return if frac_zone_cool_load_served == 0

# If HERS/MaxLoad methodology, use at least the larger of heating/cooling loads for heat pump sizing.
# If MaxLoad methodology, use at least the larger of heating/cooling loads for heat pump sizing.
# Note: Heat_Load_Supp should NOT be adjusted; we only want to adjust the HP capacity, not the HP backup heating capacity.
max_load = [hvac_sizings.Heat_Load, hvac_sizings.Cool_Load_Tot].max
hvac_sizings.Heat_Load = max_load
Expand Down Expand Up @@ -2155,13 +2155,7 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
d_sens = shr_biquadratic[5]

# Adjust Sizing
if hvac_cooling.is_a?(HPXML::HeatPump) && (hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingHERS)
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr

cool_load_sens_cap_design = hvac_sizings.Cool_Capacity_Sens * sensible_cap_curve_value

elsif lat_cap_design < hvac_sizings.Cool_Load_Lat
if lat_cap_design < hvac_sizings.Cool_Load_Lat
# Size by MJ8 Latent load, return to rated conditions

# Solve for the new sensible and total capacity at design conditions:
Expand Down Expand Up @@ -2239,18 +2233,13 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
hvac_cooling_speed = get_nominal_speed(hvac_cooling_ap, true)
hvac_cooling_shr = hvac_cooling_ap.cool_rated_shrs_gross[hvac_cooling_speed]

if hvac_cooling.is_a?(HPXML::HeatPump) && (hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingHERS)
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr
else
entering_temp = hpxml_bldg.header.manualj_cooling_design_temp
idb_adj = adjust_indoor_condition_var_speed(entering_temp, mj.cool_indoor_wetbulb, :clg)
odb_adj = adjust_outdoor_condition_var_speed(entering_temp, hvac_cooling, :clg)
total_cap_curve_value = odb_adj * idb_adj
entering_temp = hpxml_bldg.header.manualj_cooling_design_temp
idb_adj = adjust_indoor_condition_var_speed(entering_temp, mj.cool_indoor_wetbulb, :clg)
odb_adj = adjust_outdoor_condition_var_speed(entering_temp, hvac_cooling, :clg)
total_cap_curve_value = odb_adj * idb_adj

hvac_sizings.Cool_Capacity = (hvac_sizings.Cool_Load_Tot / total_cap_curve_value)
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr
end
hvac_sizings.Cool_Capacity = (hvac_sizings.Cool_Load_Tot / total_cap_curve_value)
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr

hvac_sizings.Cool_Airflow = calc_airflow_rate_user(hvac_sizings.Cool_Capacity, hvac_cooling_ap.cool_rated_cfm_per_ton[hvac_cooling_speed])

Expand All @@ -2262,16 +2251,11 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
hvac_cooling_speed = get_nominal_speed(hvac_cooling_ap, true)
hvac_cooling_shr = hvac_cooling_ap.cool_rated_shrs_gross[hvac_cooling_speed]

if hvac_cooling.is_a?(HPXML::HeatPump) && (hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingHERS)
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr
else
entering_temp = hpxml_bldg.header.manualj_cooling_design_temp
total_cap_curve_value = MathTools.biquadratic(mj.cool_indoor_wetbulb, entering_temp, hvac_cooling_ap.cool_cap_ft_spec[hvac_cooling_speed])
entering_temp = hpxml_bldg.header.manualj_cooling_design_temp
total_cap_curve_value = MathTools.biquadratic(mj.cool_indoor_wetbulb, entering_temp, hvac_cooling_ap.cool_cap_ft_spec[hvac_cooling_speed])

hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot / total_cap_curve_value
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr
end
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot / total_cap_curve_value
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr

hvac_sizings.Cool_Airflow = calc_airflow_rate_user(hvac_sizings.Cool_Capacity, hvac_cooling_ap.cool_rated_cfm_per_ton[0])

Expand All @@ -2293,28 +2277,23 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
bypass_factor_curve_value = MathTools.biquadratic(mj.cool_indoor_wetbulb, mj.cool_setpoint, gshp_coil_bf_ft_spec)
hvac_cooling_shr = hvac_cooling_ap.cool_rated_shrs_gross[hvac_cooling_speed]

if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingHERS
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr
else
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot / total_cap_curve_value # Note: cool_cap_design = hvac_sizings.Cool_Load_Tot
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr
hvac_sizings.Cool_Capacity = hvac_sizings.Cool_Load_Tot / total_cap_curve_value # Note: cool_cap_design = hvac_sizings.Cool_Load_Tot
hvac_sizings.Cool_Capacity_Sens = hvac_sizings.Cool_Capacity * hvac_cooling_shr

cool_load_sens_cap_design = (hvac_sizings.Cool_Capacity_Sens * sensible_cap_curve_value /
(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
cool_load_sens_cap_design = (hvac_sizings.Cool_Capacity_Sens * sensible_cap_curve_value /
(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
# 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 * hvac_cooling_shr
end
# 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 * hvac_cooling_shr

# Recalculate the air flow rate in case the oversizing limit has been used
cool_load_sens_cap_design = (hvac_sizings.Cool_Capacity_Sens * sensible_cap_curve_value /
Expand Down Expand Up @@ -2388,11 +2367,7 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
HPXML::HVACTypeHeatPumpRoom].include? heating_type

hvac_heating_speed = get_nominal_speed(hvac_heating_ap, false)
if hvac_heating.is_a?(HPXML::HeatPump) && (hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingHERS)
hvac_sizings.Heat_Capacity = hvac_sizings.Heat_Load
else
process_heat_pump_adjustment(mj, runner, hvac_sizings, weather, hvac_heating, total_cap_curve_value, hvac_system, hvac_heating_speed, oversize_limit, oversize_delta, hpxml_bldg)
end
process_heat_pump_adjustment(mj, runner, hvac_sizings, weather, hvac_heating, total_cap_curve_value, hvac_system, hvac_heating_speed, oversize_limit, oversize_delta, hpxml_bldg)

hvac_sizings.Heat_Capacity_Supp = calculate_heat_pump_backup_load(mj, hvac_heating, hvac_sizings.Heat_Load_Supp, hvac_sizings.Heat_Capacity, hvac_heating_speed, hpxml_bldg)
if (heating_type == HPXML::HVACTypeHeatPumpAirToAir) || (heating_type == HPXML::HVACTypeHeatPumpMiniSplit && is_ducted)
Expand All @@ -2403,10 +2378,7 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva

elsif [HPXML::HVACTypeHeatPumpGroundToAir].include? heating_type

if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingHERS
hvac_sizings.Heat_Capacity = hvac_sizings.Heat_Load
hvac_sizings.Heat_Capacity_Supp = hvac_sizings.Heat_Load_Supp
elsif hvac_sizings.Cool_Capacity > 0
if hvac_sizings.Cool_Capacity > 0
hvac_sizings.Heat_Capacity = hvac_sizings.Heat_Load
hvac_sizings.Heat_Capacity_Supp = hvac_sizings.Heat_Load_Supp

Expand Down Expand Up @@ -2479,6 +2451,25 @@ def self.apply_hvac_equipment_adjustments(mj, runner, hvac_sizings, weather, hva
fail "Unexpected heating type: #{heating_type}."

end

# If HERS sizing methodology, ensure HP capacity is at least equal to larger of
# heating and sensible cooling loads.
if hpxml_bldg.header.heat_pump_sizing_methodology == HPXML::HeatPumpSizingHERS
if (not hvac_cooling.nil?) && hvac_cooling.is_a?(HPXML::HeatPump) && (hvac_cooling.fraction_heat_load_served > 0) && (hvac_cooling.fraction_cool_load_served > 0)
min_capacity = [hvac_sizings.Heat_Load, hvac_sizings.Cool_Load_Sens].max
if hvac_sizings.Cool_Capacity < min_capacity
scaling_factor = min_capacity / hvac_sizings.Cool_Capacity
hvac_sizings.Cool_Capacity *= scaling_factor
hvac_sizings.Cool_Capacity_Sens *= scaling_factor
hvac_sizings.Cool_Airflow *= scaling_factor
end
if hvac_sizings.Heat_Capacity < min_capacity
scaling_factor = min_capacity / hvac_sizings.Heat_Capacity
hvac_sizings.Heat_Capacity *= scaling_factor
hvac_sizings.Heat_Airflow *= scaling_factor
end
end
end
end

# Calculates the heat pump's heating or cooling capacity at the specified indoor temperature, as a fraction
Expand Down
28 changes: 11 additions & 17 deletions HPXMLtoOpenStudio/tests/test_hvac_sizing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,24 +121,18 @@ def test_hvac_configurations

if (charge_defect_ratio != 0) || (airflow_defect_ratio != 0)
# Check HP capacity is greater than max(htg_load, clg_load)
if hp.fraction_heat_load_served == 0
assert_operator(clg_cap, :>, clg_load)
elsif hp.fraction_cool_load_served == 0
assert_operator(htg_cap, :>, htg_load)
else
assert_operator(htg_cap, :>, [htg_load, clg_load].max)
assert_operator(clg_cap, :>, [htg_load, clg_load].max)
end
operator = :>
else
# Check HP capacity equals max(htg_load, clg_load)
if hp.fraction_heat_load_served == 0
assert_in_delta(clg_cap, clg_load, 1.0)
elsif hp.fraction_cool_load_served == 0
assert_in_delta(htg_cap, htg_load, 1.0)
else
assert_in_delta(htg_cap, [htg_load, clg_load].max, 1.0)
assert_in_delta(clg_cap, [htg_load, clg_load].max, 1.0)
end
# Check HP capacity equals at least max(htg_load, clg_load)
operator = :>=
end
if hp.fraction_heat_load_served == 0
assert_operator(clg_cap, operator, clg_load)
elsif hp.fraction_cool_load_served == 0
assert_operator(htg_cap, operator, htg_load)
else
assert_operator(htg_cap, operator, [htg_load, clg_load].max)
assert_operator(clg_cap, operator, [htg_load, clg_load].max)
end
end

Expand Down
2 changes: 1 addition & 1 deletion docs/source/workflow_inputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ Additional autosizing factor inputs are available at the system level, see :ref:
\- **ACCA**: autosized heat pumps have their nominal capacity sized per ACCA Manual J/S based on cooling design loads, with some oversizing allowances for larger heating design loads.
\- **HERS**: autosized heat pumps have their nominal capacity sized equal to the larger of heating/cooling design loads.
\- **HERS**: same as **ACCA** except autosized heat pumps have their nominal capacity sized equal to at least the larger of heating and sensible cooling design loads.
\- **MaxLoad**: autosized heat pumps have their nominal capacity sized based on the larger of heating/cooling design loads, while taking into account the heat pump's reduced capacity at the design temperature, such that no backup heating should be necessary.
Expand Down

0 comments on commit 532cc3b

Please sign in to comment.