Hi,
I am a university student working on the electrification of heating systems. I want to model the coefficient of performance curves for ASHPs, and I was looking at how ResStock does it. Each of the air source heat pumps uses the corresponding performance curve for EIR based on how many stages it has. Then it is scaled based on some data on COP values.
Here is an excerpt from the code. Could anyone help me understand how to use these coefficients--what would be the variables associated with them or point me towards relevant documentation that might aid my understanding? I could not find their source:
require_relative "constants" require_relative "geometry" require_relative "util" require_relative "unit_conversions" require_relative "psychrometrics" require_relative "schedules"
class HVAC def self.apply_central_ac_1speed(model, unit, runner, seer, eers, shrs, fan_power_rated, fan_power_installed, crankcase_capacity, crankcase_temp, eer_capacity_derates, capacity, dse, frac_cool_load_served)
return true if frac_cool_load_served <= 0
num_speeds = 1
# Performance curves
# NOTE: These coefficients are in IP UNITS
curves_in_ip = true
cOOL_CAP_FT_SPEC = [[3.670270705, -0.098652414, 0.000955906, 0.006552414, -0.0000156, -0.000131877]]
cOOL_EIR_FT_SPEC = [[-3.302695861, 0.137871531, -0.001056996, -0.012573945, 0.000214638, -0.000145054]]
cOOL_CAP_FFLOW_SPEC = [[0.718605468, 0.410099989, -0.128705457]]
cOOL_EIR_FFLOW_SPEC = [[1.32299905, -0.477711207, 0.154712157]]
capacity_ratios = [1.0]
fan_speed_ratios = [1.0]
# Cooling Coil
rated_airflow_rate = 386.1 # cfm
cfms_ton_rated = calc_cfms_ton_rated(rated_airflow_rate, fan_speed_ratios, capacity_ratios)
cooling_eirs = calc_cooling_eirs(num_speeds, eers, fan_power_rated)
shrs_rated_gross = calc_shrs_rated_gross(num_speeds, shrs, fan_power_rated, cfms_ton_rated)
cOOL_CLOSS_FPLR_SPEC = [calc_plr_coefficients_cooling(num_speeds, seer)]
obj_name = Constants.ObjectNameCentralAirConditioner(unit.name.to_s)
thermal_zones = Geometry.get_thermal_zones_from_spaces(unit.spaces)
control_slave_zones_hash = get_control_and_slave_zones(thermal_zones)
control_slave_zones_hash.each do |control_zone, slave_zones|
# _processCurvesDXCooling
clg_coil_stage_data = calc_coil_stage_data_cooling(model, capacity, (0...num_speeds).to_a, cooling_eirs, shrs_rated_gross, cOOL_CAP_FT_SPEC, cOOL_EIR_FT_SPEC, cOOL_CLOSS_FPLR_SPEC, cOOL_CAP_FFLOW_SPEC, cOOL_EIR_FFLOW_SPEC, curves_in_ip, dse)
# _processSystemFan
fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
fan_eff = 0.75 # Overall Efficiency of the Fan, Motor and Drive
fan.setName(obj_name + " clg supply fan")
fan.setEndUseSubcategory(obj_name + " clg supply fan")
fan.setFanEfficiency(fan_eff)
fan.setPressureRise(calculate_fan_pressure_rise(fan_eff, fan_power_installed / dse))
fan.setMotorEfficiency(1.0)
fan.setMotorInAirstreamFraction(1.0)
# _processSystemAir
air_loop_unitary = OpenStudio::Model::AirLoopHVACUnitarySystem.new(model)
air_loop_unitary.setName(obj_name + " unitary system")
air_loop_unitary.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
air_loop_unitary.setCoolingCoil(clg_coil)
air_loop_unitary.setSupplyAirFlowRateDuringHeatingOperation(0.0)
air_loop_unitary.setSupplyFan(fan)
air_loop_unitary.setFanPlacement("BlowThrough")
air_loop_unitary.setSupplyAirFanOperatingModeSchedule(model.alwaysOffDiscreteSchedule)
air_loop_unitary.setMaximumSupplyAirTemperature(UnitConversions.convert(120.0, "F", "C"))
air_loop_unitary.setSupplyAirFlowRateWhenNoCoolingorHeatingisRequired(0)
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
air_loop.setName(obj_name + " asys")
air_supply_inlet_node = air_loop.supplyInletNode
air_supply_outlet_node = air_loop.supplyOutletNode
air_demand_inlet_node = air_loop.demandInletNode
air_demand_outlet_node = air_loop.demandOutletNode
air_loop_unitary.addToNode(air_supply_inlet_node)
runner.registerInfo("Added '#{fan.name}' to '#{air_loop_unitary.name}' of '#{air_loop.name}'")
runner.registerInfo("Added '#{clg_coil.name}' to '#{air_loop_unitary.name}' of '#{air_loop.name}'")
air_loop_unitary.setControllingZoneorThermostatLocation(control_zone)
# _processSystemDemandSideAir
# Demand Side
# Supply Air
zone_splitter = air_loop.zoneSplitter
zone_splitter.setName(obj_name + " zone splitter")
zone_mixer = air_loop.zoneMixer
zone_mixer.setName(obj_name + " zone mixer")
diffuser_living = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
diffuser_living.setName(obj_name + " #{control_zone.name} direct air")
air_loop.multiAddBranchForZone(control_zone, diffuser_living)
air_loop.multiAddBranchForZone(control_zone)
runner.registerInfo("Added '#{air_loop.name}' to '#{control_zone.name}' of #{unit.name}")
prioritize_zone_hvac(model, runner, control_zone)
slave_zones.each do |slave_zone|
diffuser_fbsmt = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
diffuser_fbsmt.setName(obj_name + " #{slave_zone.name} direct air")
air_loop.multiAddBranchForZone(slave_zone, diffuser_fbsmt)
air_loop.multiAddBranchForZone(slave_zone)
runner.registerInfo("Added '#{air_loop.name}' to '#{slave_zone.name}' of #{unit.name}")
prioritize_zone_hvac(model, runner, slave_zone)
end # slave_zone
# Store info for HVAC Sizing measure
air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCapacityDerateFactorEER, eer_capacity_derates.join(","))
air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACRatedCFMperTonCooling, cfms_ton_rated.join(","))
air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, frac_cool_load_served)
end # control_zone
return true
end
def self.apply_central_ac_2speed(model, unit, runner, seer, eers, shrs, capacity_ratios, fan_speed_ratios, fan_power_rated, fan_power_installed, crankcase_capacity, crankcase_temp, eer_capacity_derates, capacity, dse, frac_cool_load_served)
return true if frac_cool_load_served <= 0
num_speeds = 2
# Performance curves
# NOTE: These coefficients are in IP UNITS
curves_in_ip = true
cOOL_CAP_FT_SPEC = [[3.940185508, -0.104723455, 0.001019298, 0.006471171, -0.00000953, -0.000161658],
[3.109456535, -0.085520461, 0.000863238, 0.00863049, -0.0000210, -0.000140186]]
cOOL_EIR_FT_SPEC = [[-3.877526888, 0.164566276, -0.001272755, -0.019956043, 0.000256512, -0.000133539],
[-1.990708931, 0.093969249, -0.00073335, -0.009062553, 0.000165099, -0.0000997]]
cOOL_CAP_FFLOW_SPEC = [[0.65673024, 0.516470835, -0.172887149],
[0.690334551, 0.464383753, -0.154507638]]
cOOL_EIR_FFLOW_SPEC = [[1.562945114, -0.791859997, 0.230030877],
[1.31565404, -0.482467162, 0.166239001]]
# Cooling Coil
rated_airflow_rate = 355.2 # cfm
cfms_ton_rated = calc_cfms_ton_rated(rated_airflow_rate, fan_speed_ratios, capacity_ratios)
cooling_eirs = calc_cooling_eirs(num_speeds, eers, fan_power_rated)
shrs_rated_gross = calc_shrs_rated_gross(num_speeds, shrs, fan_power_rated, cfms_ton_rated)
cOOL_CLOSS_FPLR_SPEC = [calc_plr_coefficients_cooling(num_speeds, seer)] * num_speeds
obj_name = Constants.ObjectNameCentralAirConditioner(unit.name.to_s)
thermal_zones = Geometry.get_thermal_zones_from_spaces(unit.spaces)
control_slave_zones_hash = get_control_and_slave_zones(thermal_zones)
control_slave_zones_hash.each do |control_zone, slave_zones|
I looked at this study for some information: https://www.nrel.gov/docs/fy13osti/56354.pdf and this paper: https://www.sciencedirect.com/science/article/pii/S0306261921005559
I would appreciate it if anyone could guide me to gain a better understanding of how to model COP curves using this information.