Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building Energy Standards Air Conditioner Data Update #1682

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
cc23547
data_update (unitary_air_conditioners_only) 99d14b7
leijerry888 Feb 9, 2024
a8c35aa
Merge branch 'master' into data_update_99d14b7
lymereJ Apr 1, 2024
0288d3e
Move crac unit data to their own set of JSON files, add IEER to EER c…
lymereJ Apr 5, 2024
d0cfb67
Merge branch 'master' into data_update_99d14b7
lymereJ Apr 5, 2024
f97b622
Merge branch 'data_update_99d14b7' of https://github.com/NREL/openstu…
lymereJ Apr 5, 2024
09da582
Merge branch 'master' into data_update_99d14b7
lymereJ Apr 29, 2024
0c3a009
Rename method call.
lymereJ Apr 29, 2024
66f3918
Remove rounding in naming.
lymereJ Apr 30, 2024
298c5c5
Attempt to adress test failures.
lymereJ Apr 30, 2024
7b1f69e
branch 'master' into data_update_99d14b7
lymereJ Aug 20, 2024
4dbaf44
Merge branch 'master' into data_update_99d14b7
lymereJ Aug 20, 2024
6243b0a
Merge branch 'master' into data_update_99d14b7
lymereJ Oct 23, 2024
46f63af
Add placeholder for "2" ratings.
lymereJ Oct 25, 2024
336663d
Merge branch 'data_update_99d14b7' of https://github.com/NREL/openstu…
lymereJ Oct 25, 2024
4cd98c1
Merge branch 'master' into data_update_99d14b7
lymereJ Oct 28, 2024
426d22d
Fix dates.
lymereJ Oct 28, 2024
6979adc
Remove comments.
lymereJ Oct 28, 2024
e6c2ab8
Add missing reference.
lymereJ Oct 31, 2024
ce8667d
Merge branch 'master' into data_update_99d14b7
lymereJ Oct 31, 2024
de235f2
Clarification of changes and general clean-up. New unit tests.
lymereJ Nov 1, 2024
9704e8a
Remove unused argument.
lymereJ Nov 1, 2024
fea6968
Add default value for argument.
lymereJ Nov 1, 2024
6e8e232
Add additional search criteria.
lymereJ Nov 2, 2024
5490087
Address NRCan test failures, temporarily deactivate a PRM test.
lymereJ Nov 2, 2024
a25a910
NRCan tests #2.
lymereJ Nov 5, 2024
d0f31bc
PRM test fix.
lymereJ Nov 5, 2024
3532e35
Address PRM test failure #2.
lymereJ Nov 6, 2024
cc59b63
Missing fields.
lymereJ Nov 11, 2024
d8c1cfd
Fix multiplier issue identified by Kamel.
lymereJ Nov 20, 2024
ea9279e
Merge branch 'master' into data_update_99d14b7
lymereJ Nov 20, 2024
889bf7b
Bump up maximum capacity of AC entries and update minimum EER require…
lymereJ Dec 2, 2024
e605746
Give priority to EER over IEER.
lymereJ Dec 3, 2024
98a891c
Fix clause.
lymereJ Dec 4, 2024
75d1f6b
Correct clause #2.
lymereJ Dec 5, 2024
677d9c9
Fix clause #3.
lymereJ Dec 6, 2024
ba67d03
Merge branch 'master' into data_update_99d14b7
mdahlhausen Dec 23, 2024
7273dbc
Merge branch 'master' into data_update_99d14b7
lymereJ Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions data/standards/manage_OpenStudio_Standards.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ def unique_properties(sheet_name)
['template', 'cooling_type', 'subcategory', 'minimum_capacity', 'maximum_capacity', 'start_date', 'end_date']
when 'unitary_acs'
['template', 'cooling_type', 'heating_type', 'subcategory', 'minimum_capacity', 'maximum_capacity', 'start_date', 'end_date']
when 'computer_room_acs'
['template', 'cooling_type', 'heating_type', 'subcategory', 'minimum_capacity', 'maximum_capacity', 'start_date', 'end_date']
when 'water_heaters'
['template', 'equipment_type', 'fuel_type', 'minimum_capacity', 'maximum_capacity', 'minimum_storage', 'maximum_storage', 'minimum_capacity_per_storage', 'maximum_capacity_per_storage', 'draw_profile', 'start_date', 'end_date']
when 'elevators'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def hspf_to_cop(hspf)
return cop
end

# Convert from EER to COP
# Convert from EER to COP (no fan)
# @ref [References::USDOEPrototypeBuildings] If capacity is not supplied, use DOE Prototype Building method.
# @ref [References::ASHRAE9012013] If capacity is supplied, use the 90.1-2013 method
#
Expand All @@ -345,7 +345,7 @@ def eer_to_cop_no_fan(eer, capacity_w = nil)
return cop
end

# Convert from COP to EER
# Convert from COP (no fan) to EER
# @ref [References::USDOEPrototypeBuildings]
#
# @param cop [Double] COP
Expand All @@ -367,6 +367,22 @@ def cop_no_fan_to_eer(cop, capacity_w = nil)
return eer
end

# Convert from IEER to COP (no fan)
#
# @note IEER is a weighted-average efficiency metrics at different load percentages, operataional and environemental conditions
# @note IEER should be modeled by using performance curves that match a targeted efficiency values
# @note This method estimates what a reasonable full load rated EER would be for a targeted IEER value
# @note The regression used in this method is based on a survey of over 1,000 rated AHRI units with IEER ranging from 11.8 to 25.6
# @todo Implement methods to handle IEER modeling
#
# @param ieer [Double] Energy Efficiency Ratio (EER)
# @return [Double] Coefficient of Performance (COP)
def ieer_to_cop_no_fan(ieer)
eer = 0.0183 * ieer * ieer - 0.4552 * ieer + 13.21

return eer_to_cop_no_fan(eer)
end

Comment on lines +370 to +385
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New method to convert an IEER to a COP no fan. Note that this is just to estimate what would a reasonable full load gross COP would be for a specific IEER value. IEER-specific performance curves should then be applied. Copper could be used when it supports IEER rated equipment.

# Convert from EER to COP
#
# @param eer [Double] Energy Efficiency Ratio (EER)
Expand Down
155 changes: 102 additions & 53 deletions lib/openstudio-standards/standards/Standards.CoilCoolingDXMultiSpeed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,24 @@ def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_mult
capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get

# Lookup efficiencies depending on whether it is a unitary AC or a heat pump
ac_props = nil
ac_props = if heat_pump == true
model_find_object(standards_data['heat_pumps'], search_criteria, capacity_btu_per_hr, Date.today)
else
model_find_object(standards_data['unitary_acs'], search_criteria, capacity_btu_per_hr, Date.today)
end
# Get efficiencies data depending on whether it is a unitary AC or a heat pump
coil_efficiency_data = if coil_dx_heat_pump?(coil_cooling_dx_multi_speed)
standards_data['heat_pumps']
else
standards_data['unitary_acs']
end

# Additional search criteria
if (coil_efficiency_data[0].keys.include?('equipment_type') || ((template == 'NECB2011') || (template == 'NECB2015') || (template == 'NECB2017') || (template == 'NECB2020') || (template == 'BTAPPRE1980') ||
(template == 'BTAP1980TO2010'))) && !coil_dx_heat_pump?(coil_cooling_dx_multi_speed)
search_criteria['equipment_type'] = 'Air Conditioners'
end
if coil_efficiency_data[0].keys.include?('region')
search_criteria['region'] = nil # non-nil values are currently used for residential products
end

# Lookup efficiency
ac_props = model_find_object(coil_efficiency_data, search_criteria, capacity_btu_per_hr, Date.today)

# Check to make sure properties were found
if ac_props.nil?
Expand All @@ -100,7 +111,13 @@ def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_mult
end

# Make the COOL-CAP-FT curve
cool_cap_ft = model_add_curve(model, ac_props['cool_cap_ft'], standards)
cool_cap_ft = nil
if ac_props['cool_cap_ft']
cool_cap_ft = model_add_curve(coil_cooling_dx_multi_speed.model, ac_props['cool_cap_ft'])
else
cool_cap_ft_curve_name = coil_dx_cap_ft(coil_cooling_dx_multi_speed)
cool_cap_ft = model_add_curve(coil_cooling_dx_multi_speed.model, cool_cap_ft_curve_name)
end
if cool_cap_ft
clg_stages.each do |stage|
stage.setTotalCoolingCapacityFunctionofTemperatureCurve(cool_cap_ft)
Expand All @@ -111,7 +128,13 @@ def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_mult
end

# Make the COOL-CAP-FFLOW curve
cool_cap_fflow = model_add_curve(model, ac_props['cool_cap_fflow'], standards)
cool_cap_fflow = nil
if ac_props['cool_cap_fflow']
cool_cap_fflow = model_add_curve(coil_coolingcoil_cooling_dx_multi_speed_dx_two_speed.model, ac_props['cool_cap_fflow'])
else
cool_cap_fflow_curve_name = coil_dx_cap_fff(coil_cooling_dx_multi_speed)
cool_cap_fflow = model_add_curve(coil_cooling_dx_multi_speed.model, cool_cap_fflow_curve_name)
end
if cool_cap_fflow
clg_stages.each do |stage|
stage.setTotalCoolingCapacityFunctionofFlowFractionCurve(cool_cap_fflow)
Expand All @@ -122,7 +145,13 @@ def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_mult
end

# Make the COOL-EIR-FT curve
cool_eir_ft = model_add_curve(model, ac_props['cool_eir_ft'], standards)
cool_eir_ft = nil
if ac_props['cool_eir_ft']
cool_eir_ft = model_add_curve(coil_cooling_dx_multi_speed.model, ac_props['cool_eir_ft'])
else
cool_eir_ft_curve_name = coil_dx_eir_ft(coil_cooling_dx_multi_speed)
cool_eir_ft = model_add_curve(coil_cooling_dx_multi_speed.model, cool_eir_ft_curve_name)
end
if cool_eir_ft
clg_stages.each do |stage|
stage.setEnergyInputRatioFunctionofTemperatureCurve(cool_eir_ft)
Expand All @@ -133,7 +162,13 @@ def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_mult
end

# Make the COOL-EIR-FFLOW curve
cool_eir_fflow = model_add_curve(model, ac_props['cool_eir_fflow'], standards)
cool_eir_fflow = nil
if ac_props['cool_eir_fflow']
cool_eir_fflow = model_add_curve(coil_cooling_dx_multi_speed.model, ac_props['cool_eir_fflow'])
else
cool_eir_fflow_curve_name = coil_dx_eir_fff(coil_cooling_dx_multi_speed)
cool_eir_fflow = model_add_curve(coil_cooling_dx_multi_speed.model, cool_eir_fflow_curve_name)
end
if cool_eir_fflow
clg_stages.each do |stage|
stage.setEnergyInputRatioFunctionofFlowFractionCurve(cool_eir_fflow)
Expand All @@ -144,7 +179,13 @@ def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_mult
end

# Make the COOL-PLF-FPLR curve
cool_plf_fplr = model_add_curve(model, ac_props['cool_plf_fplr'], standards)
cool_plf_fplr = nil
if ac_props['cool_plf_fplr']
cool_plf_fplr = model_add_curve(coil_cooling_dx_multi_speed.model, ac_props['cool_plf_fplr'])
else
cool_plf_fplr_curve_name = coil_dx_plf_fplr(coil_cooling_dx_multi_speed)
cool_plf_fplr = model_add_curve(coil_cooling_dx_multi_speed.model, cool_plf_fplr_curve_name)
end
if cool_plf_fplr
clg_stages.each do |stage|
stage.setPartLoadFractionCorrelationCurve(cool_plf_fplr)
Expand All @@ -164,50 +205,22 @@ def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_mult
capacity_btu_per_hr = 15_000 if capacity_btu_per_hr > 15_000
ptac_eer = ptac_eer_coeff_1 + (ptac_eer_coeff_2 * capacity_btu_per_hr)
cop = eer_to_cop_no_fan(ptac_eer)
# self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{ptac_eer}EER")
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{ptac_eer}EER"
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{ptac_eer}")
end

# If specified as SEER
unless ac_props['minimum_seasonal_energy_efficiency_ratio'].nil?
min_seer = ac_props['minimum_seasonal_energy_efficiency_ratio']
cop = seer_to_cop_no_fan(min_seer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER"
# self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER")
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; SEER = #{min_seer}")
end
# Preserve the original name
orig_name = coil_cooling_dx_single_speed.name.to_s

# If specified as EER
unless ac_props['minimum_energy_efficiency_ratio'].nil?
min_eer = ac_props['minimum_energy_efficiency_ratio']
cop = eer_to_cop_no_fan(min_eer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_eer}EER"
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{min_eer}")
end
# Find the minimum COP and rename with efficiency rating
new_comp_name, cop = coil_cooling_dx_multi_speed_standard_minimum_cop(coil_cooling_dx_multi_speed)

# if specified as SEER (heat pump)
unless ac_props['minimum_seasonal_efficiency'].nil?
min_seer = ac_props['minimum_seasonal_efficiency']
cop = seer_to_cop_no_fan(min_seer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER"
# self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER")
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; SEER = #{min_seer}")
end

# If specified as EER (heat pump)
unless ac_props['minimum_full_load_efficiency'].nil?
min_eer = ac_props['minimum_full_load_efficiency']
cop = eer_to_cop_no_fan(min_eer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_eer}EER"
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{min_eer}")
end
sql_db_vars_map[new_comp_name] = orig_name

sql_db_vars_map[new_comp_name] = name.to_s
# Set the new name
coil_cooling_dx_multi_speed.setName(new_comp_name)

# Set the efficiency values

unless cop.nil?
clg_stages.each do |istage|
istage.setGrossRatedCoolingCOP(cop)
Expand Down Expand Up @@ -258,13 +271,25 @@ def coil_cooling_dx_multi_speed_standard_minimum_cop(coil_cooling_dx_multi_speed
capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get

# Define database
if coil_dx_heat_pump?(coil_cooling_dx_multi_speed)
database = standards_data['heat_pumps']
else
database = standards_data['unitary_acs']
end

# Additional search criteria
if (database[0].keys.include?('equipment_type') || ((template == 'NECB2011') || (template == 'NECB2015') || (template == 'NECB2017') || (template == 'NECB2020') || (template == 'BTAPPRE1980') ||
(template == 'BTAP1980TO2010'))) && !coil_dx_heat_pump?(coil_cooling_dx_multi_speed)
search_criteria['equipment_type'] = 'Air Conditioners'
end
if database[0].keys.include?('region')
search_criteria['region'] = nil # non-nil values are currently used for residential products
end

# Lookup efficiencies depending on whether it is a unitary AC or a heat pump
ac_props = nil
ac_props = if coil_dx_heat_pump?(coil_cooling_dx_multi_speed)
model_find_object(standards_data['heat_pumps'], search_criteria, capacity_btu_per_hr, Date.today)
else
model_find_object(standards_data['unitary_acs'], search_criteria, capacity_btu_per_hr, Date.today)
end
ac_props = model_find_object(database, search_criteria, capacity_btu_per_hr, Date.today)

# Get the minimum efficiency standards
cop = nil
Expand All @@ -274,10 +299,18 @@ def coil_cooling_dx_multi_speed_standard_minimum_cop(coil_cooling_dx_multi_speed
min_seer = ac_props['minimum_seasonal_energy_efficiency_ratio']
cop = seer_to_cop_no_fan(min_seer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER"
# self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER")
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{coil_dx_subcategory(coil_cooling_dx_multi_speed)} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; SEER = #{min_seer}")
end

# If specified as SEER2
# TODO: assumed to be the same as SEER for now
unless ac_props['minimum_seasonal_energy_efficiency_ratio_2'].nil?
min_seer = ac_props['minimum_seasonal_energy_efficiency_ratio_2']
cop = seer_to_cop_no_fan(min_seer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER"
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXTwoSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{coil_dx_subcategory(coil_cooling_dx_multi_speed)} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; SEER = #{min_seer}")
end

# If specified as EER
unless ac_props['minimum_energy_efficiency_ratio'].nil?
min_eer = ac_props['minimum_energy_efficiency_ratio']
Expand All @@ -286,12 +319,28 @@ def coil_cooling_dx_multi_speed_standard_minimum_cop(coil_cooling_dx_multi_speed
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{coil_dx_subcategory(coil_cooling_dx_multi_speed)} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{min_eer}")
end

# If specified as EER2
# TODO: assumed to be the same as EER for now
unless ac_props['minimum_energy_efficiency_ratio_2'].nil?
min_eer = ac_props['minimum_energy_efficiency_ratio_2']
cop = eer_to_cop_no_fan(min_eer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_eer}EER"
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXTwoSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{coil_dx_subcategory(coil_cooling_dx_multi_speed)} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{min_eer}")
end

# If specific as IEER
if !ac_props['minimum_integrated_energy_efficiency_ratio'].nil? && cop.nil?
min_ieer = ac_props['minimum_integrated_energy_efficiency_ratio']
cop = ieer_to_cop_no_fan(min_ieer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_ieer}IEER"
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXTwoSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{sub_category} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; IEER = #{min_ieer}")
end

# if specified as SEER (heat pump)
unless ac_props['minimum_seasonal_efficiency'].nil?
min_seer = ac_props['minimum_seasonal_efficiency']
cop = seer_to_cop_no_fan(min_seer)
new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER"
# self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER")
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{coil_dx_subcategory(coil_cooling_dx_multi_speed)} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; SEER = #{min_seer}")
end

Expand Down
Loading