diff --git a/chiller/chiller.py b/chiller/chiller.py index 8d83a6c..815e14f 100644 --- a/chiller/chiller.py +++ b/chiller/chiller.py @@ -1,5 +1,10 @@ from chiller.fluid_properties import FluidState -from .conditions import AHRI_550_590_WATER_COOLED_CONDITIONS, AHRI_550_590_WATER_COOLED_CONDENSER_OUTLET, AHRI_550_590_WATER_COOLED_EVAPORATOR_INLET, OperatingConditions +from .conditions import ( + AHRI_550_590_WATER_COOLED_CONDITIONS, + AHRI_550_590_WATER_COOLED_CONDENSER_OUTLET, + AHRI_550_590_WATER_COOLED_EVAPORATOR_INLET, + OperatingConditions, +) from .models.energyplus_eir import EnergyPlusEIR from koozie import fr_u from numpy import linspace @@ -7,267 +12,360 @@ import datetime from random import Random + class ChillerMetadata: - def __init__( - self, - description="", - data_source="https://github.com/bigladder/chiller", - notes="", - compressor_type="", - has_hot_gas_bypass_installed=False, - uuid_seed=None, - data_version=1 + def __init__( + self, + description="", + data_source="https://github.com/bigladder/chiller", + notes="", + compressor_type="", + has_hot_gas_bypass_installed=False, + uuid_seed=None, + data_version=1, ): - self.description = description - self.data_source = data_source - self.notes = notes - self.compressor_type = compressor_type - self.has_hot_gas_bypass_installed = has_hot_gas_bypass_installed - self.uuid_seed = uuid_seed - self.data_version = data_version + self.description = description + self.data_source = data_source + self.notes = notes + self.compressor_type = compressor_type + self.has_hot_gas_bypass_installed = has_hot_gas_bypass_installed + self.uuid_seed = uuid_seed + self.data_version = data_version + class Chiller: - def __init__( - self, - model=None, - rated_net_evaporator_capacity=fr_u(100.0,"ton_ref"), - rated_cop=2.0, - cycling_degradation_coefficient=0.0, - standby_power=0.0, - rated_net_condenser_capacity=None, - number_of_compressor_speeds=None, - minimum_evaporator_leaving_temperature=fr_u(39.0,"°F"), - maximum_evaporator_leaving_temperature=fr_u(60.0,"°F"), - minimum_condenser_entering_temperature=fr_u(55.0,"°F"), - maximum_condenser_entering_temperature=fr_u(104.0,"°F"), - metadata=None, - **kwargs): - - self.kwargs = kwargs - - if model is None: - self.model = EnergyPlusEIR() - else: - self.model = model - - self.number_of_compressor_speeds = number_of_compressor_speeds - self.rated_net_condenser_capacity = rated_net_condenser_capacity - self.rated_net_evaporator_capacity = rated_net_evaporator_capacity - self.rated_cop = rated_cop - self.cycling_degradation_coefficient = cycling_degradation_coefficient - self.standby_power = standby_power - self.minimum_evaporator_leaving_temperature = minimum_evaporator_leaving_temperature - self.maximum_evaporator_leaving_temperature = maximum_evaporator_leaving_temperature - self.minimum_condenser_entering_temperature = minimum_condenser_entering_temperature - self.maximum_condenser_entering_temperature = maximum_condenser_entering_temperature - - if metadata is None: - self.metadata = ChillerMetadata() - else: - self.metadata = metadata - - self.model.set_system(self) - - self.set_rated_evaporator_volumetric_flow_rate() - self.set_rated_condenser_volumetric_flow_rate() - - def net_evaporator_capacity(self, conditions=None): - if conditions == None: - conditions = AHRI_550_590_WATER_COOLED_CONDITIONS - return self.model.net_evaporator_capacity(conditions) - - def input_power(self, conditions=None): - if conditions == None: - conditions = AHRI_550_590_WATER_COOLED_CONDITIONS - return self.model.input_power(conditions) - - def net_condenser_capacity(self, conditions=None): - if conditions == None: - conditions = AHRI_550_590_WATER_COOLED_CONDITIONS - return self.model.net_condenser_capacity(conditions) - - def oil_cooler_heat(self, conditions=None): - if conditions == None: - conditions = AHRI_550_590_WATER_COOLED_CONDITIONS - return self.model.oil_cooler_heat(conditions) - - def auxiliary_heat(self, conditions=None): - if conditions == None: - conditions = AHRI_550_590_WATER_COOLED_CONDITIONS - return self.model.auxiliary_heat(conditions) - - def cop(self, conditions=None): - return self.net_evaporator_capacity(conditions)/self.input_power(conditions) - - def condenser_liquid_leaving_state(self, conditions=None): - if conditions == None: - conditions = AHRI_550_590_WATER_COOLED_CONDITIONS - return conditions.condenser_inlet.add_heat(self.net_condenser_capacity(conditions)) - - def evaporator_liquid_entering_state(self, conditions=None): - if conditions == None: - conditions = AHRI_550_590_WATER_COOLED_CONDITIONS - return conditions.evaporator_outlet.add_heat(self.net_evaporator_capacity(conditions)) - - def space_loss_heat(self, conditions=None): - return (self.input_power(conditions) + self.net_evaporator_capacity(conditions)) - (self.net_condenser_capacity(conditions) + self.oil_cooler_heat(conditions) + self.auxiliary_heat(conditions)) - - def set_rated_evaporator_volumetric_flow_rate(self): - delta_T = AHRI_550_590_WATER_COOLED_EVAPORATOR_INLET.T - AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.T - m_dot = self.rated_net_evaporator_capacity/(AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.get_cp()*delta_T) - AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.set_m_dot(m_dot) - AHRI_550_590_WATER_COOLED_EVAPORATOR_INLET.set_m_dot(m_dot) - self.rated_evaporator_volumetric_flow_rate = AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.V_dot - - def set_rated_condenser_volumetric_flow_rate(self): - delta_T = AHRI_550_590_WATER_COOLED_CONDENSER_OUTLET.T - AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.T - m_dot = self.rated_net_condenser_capacity/(AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.get_cp()*delta_T) - AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.set_m_dot(m_dot) - AHRI_550_590_WATER_COOLED_CONDENSER_OUTLET.set_m_dot(m_dot) - self.rated_condenser_volumetric_flow_rate = AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.V_dot - - def generate_205_representation(self): - # Metadata - timestamp = datetime.datetime.now().isoformat("T","minutes") - rnd = Random() - if self.metadata.uuid_seed is None: - self.metadata.uuid_seed = hash(self) - rnd.seed(self.metadata.uuid_seed) - unique_id = str(uuid.UUID(int=rnd.getrandbits(128), version=4)) - - - metadata = { - "data_model": "ASHRAE_205", - "schema": "RS0001", - "schema_version": "1.0.0", - "description": self.metadata.description, - "id": unique_id, - "data_timestamp": f"{timestamp}Z", - "data_version": self.metadata.data_version, - "data_source": self.metadata.data_source, - "disclaimer": "This data is synthetic and does not represent any physical products.", - "notes": self.metadata.notes, - } - representation_description = { - "product_information": - { - "liquid_data_source": "CoolProp", - "hot_gas_bypass_installed": self.metadata.has_hot_gas_bypass_installed - } - } - - if self.metadata.compressor_type is not None: - representation_description["product_information"]["compressor_type"] = self.metadata.compressor_type - - # Create conditions - evaporator_liquid_volumetric_flow_rates = [self.rated_evaporator_volumetric_flow_rate] - evaporator_liquid_leaving_temperatures = linspace(self.minimum_evaporator_leaving_temperature, self.maximum_evaporator_leaving_temperature, 4).tolist() - condenser_liquid_volumetric_flow_rates = [self.rated_condenser_volumetric_flow_rate] - condenser_liquid_entering_temperatures = linspace(self.minimum_condenser_entering_temperature, self.maximum_condenser_entering_temperature, 4).tolist() - compressor_sequence_numbers = list(range(1,self.number_of_compressor_speeds + 1)) - - grid_variables = { - "evaporator_liquid_volumetric_flow_rate": - evaporator_liquid_volumetric_flow_rates, - "evaporator_liquid_leaving_temperature": - evaporator_liquid_leaving_temperatures, - "condenser_liquid_volumetric_flow_rate": - condenser_liquid_volumetric_flow_rates, - "condenser_liquid_entering_temperature": - condenser_liquid_entering_temperatures, - "compressor_sequence_number": - compressor_sequence_numbers - } - - input_powers = [] - net_evaporator_capacities = [] - net_condenser_capacities = [] - evaporator_liquid_entering_temperatures = [] - condenser_liquid_leaving_temperatures = [] - evaporator_liquid_differential_pressures = [] - condenser_liquid_differential_pressures = [] - oil_cooler_heats = [] - auxiliary_heats = [] - - for v_evap in evaporator_liquid_volumetric_flow_rates: - for t_evap in evaporator_liquid_leaving_temperatures: - for v_cond in condenser_liquid_volumetric_flow_rates: - for t_cond in condenser_liquid_entering_temperatures: - for speed in [self.number_of_compressor_speeds - n for n in compressor_sequence_numbers]: - conditions = OperatingConditions( - evaporator_outlet=FluidState(temperature=t_evap, volumetric_flow_rate=v_evap), - condenser_inlet=FluidState(temperature=t_cond, volumetric_flow_rate=v_cond), - compressor_speed=speed) - - input_powers.append(self.input_power(conditions)) - net_evaporator_capacities.append(self.net_evaporator_capacity(conditions)) - net_condenser_capacities.append(self.net_condenser_capacity(conditions)) - evaporator_liquid_entering_temperatures.append(self.evaporator_liquid_entering_state(conditions).T) - condenser_liquid_leaving_temperatures.append(self.condenser_liquid_leaving_state(conditions).T) - evaporator_liquid_differential_pressures.append(fr_u(15.,"kPa")) - condenser_liquid_differential_pressures.append(fr_u(15.,"kPa")) - oil_cooler_heats.append(self.oil_cooler_heat(conditions)) - auxiliary_heats.append(self.auxiliary_heat(conditions)) - - performance_map_cooling = { - "grid_variables": grid_variables, - "lookup_variables": { - "input_power": - input_powers, - "net_evaporator_capacity": - net_evaporator_capacities, - "net_condenser_capacity": - net_condenser_capacities, - "evaporator_liquid_entering_temperature": - evaporator_liquid_entering_temperatures, - "condenser_liquid_leaving_temperature": - condenser_liquid_leaving_temperatures, - "evaporator_liquid_differential_pressure": - evaporator_liquid_differential_pressures, - "condenser_liquid_differential_pressure": - condenser_liquid_differential_pressures, - "oil_cooler_heat": - oil_cooler_heats, - "auxiliary_heat": - auxiliary_heats - } - } - performance = { - "evaporator_liquid_type": { # TODO: Make consistent with model - "liquid_components": [ - { - "liquid_constituent": "WATER", - "concentration": 1.0, - } - ], - "concentration_type": "BY_VOLUME" - }, - "condenser_liquid_type": { # TODO: Make consistent with model - "liquid_components": [ - { - "liquid_constituent": "WATER", - "concentration": 1.0, - } - ], - "concentration_type": "BY_VOLUME" - }, - "evaporator_fouling_factor": 0.0, - "condenser_fouling_factor": 0.0, - "compressor_speed_control_type": "CONTINUOUS", - "maximum_power": max(input_powers), # Do something else? - "cycling_degradation_coefficient": self.cycling_degradation_coefficient, - "performance_map_cooling": performance_map_cooling, - "performance_map_standby": { - "grid_variables": { - "environment_dry_bulb_temperature": [fr_u(20.0, "°C")], - }, - "lookup_variables": { - "input_power": [self.standby_power], - }, - } - } - - representation = {"metadata": metadata, "description": representation_description, "performance": performance} - - return self.model.fixup_205_representation(representation) + def __init__( + self, + model=None, + rated_net_evaporator_capacity=fr_u(100.0, "ton_ref"), + rated_cop=2.0, + cycling_degradation_coefficient=0.0, + standby_power=0.0, + rated_net_condenser_capacity=None, + number_of_compressor_speeds=None, + minimum_evaporator_leaving_temperature=fr_u(39.0, "°F"), + maximum_evaporator_leaving_temperature=fr_u(60.0, "°F"), + minimum_condenser_entering_temperature=fr_u(55.0, "°F"), + maximum_condenser_entering_temperature=fr_u(104.0, "°F"), + metadata=None, + **kwargs, + ): + + self.kwargs = kwargs + + if model is None: + self.model = EnergyPlusEIR() + else: + self.model = model + + self.number_of_compressor_speeds = number_of_compressor_speeds + self.rated_net_condenser_capacity = rated_net_condenser_capacity + self.rated_net_evaporator_capacity = rated_net_evaporator_capacity + self.rated_cop = rated_cop + self.cycling_degradation_coefficient = cycling_degradation_coefficient + self.standby_power = standby_power + self.minimum_evaporator_leaving_temperature = ( + minimum_evaporator_leaving_temperature + ) + self.maximum_evaporator_leaving_temperature = ( + maximum_evaporator_leaving_temperature + ) + self.minimum_condenser_entering_temperature = ( + minimum_condenser_entering_temperature + ) + self.maximum_condenser_entering_temperature = ( + maximum_condenser_entering_temperature + ) + + if metadata is None: + self.metadata = ChillerMetadata() + else: + self.metadata = metadata + + self.model.set_system(self) + + self.set_rated_evaporator_volumetric_flow_rate() + self.set_rated_condenser_volumetric_flow_rate() + + def net_evaporator_capacity(self, conditions=None): + if conditions == None: + conditions = AHRI_550_590_WATER_COOLED_CONDITIONS + return self.model.net_evaporator_capacity(conditions) + + def input_power(self, conditions=None): + if conditions == None: + conditions = AHRI_550_590_WATER_COOLED_CONDITIONS + return self.model.input_power(conditions) + + def net_condenser_capacity(self, conditions=None): + if conditions == None: + conditions = AHRI_550_590_WATER_COOLED_CONDITIONS + return self.model.net_condenser_capacity(conditions) + + def oil_cooler_heat(self, conditions=None): + if conditions == None: + conditions = AHRI_550_590_WATER_COOLED_CONDITIONS + return self.model.oil_cooler_heat(conditions) + + def auxiliary_heat(self, conditions=None): + if conditions == None: + conditions = AHRI_550_590_WATER_COOLED_CONDITIONS + return self.model.auxiliary_heat(conditions) + + def cop(self, conditions=None): + return self.net_evaporator_capacity(conditions) / self.input_power(conditions) + + def condenser_liquid_leaving_state(self, conditions=None): + if conditions == None: + conditions = AHRI_550_590_WATER_COOLED_CONDITIONS + return conditions.condenser_inlet.add_heat( + self.net_condenser_capacity(conditions) + ) + + def evaporator_liquid_entering_state(self, conditions=None): + if conditions == None: + conditions = AHRI_550_590_WATER_COOLED_CONDITIONS + return conditions.evaporator_outlet.add_heat( + self.net_evaporator_capacity(conditions) + ) + + def space_loss_heat(self, conditions=None): + return ( + self.input_power(conditions) + self.net_evaporator_capacity(conditions) + ) - ( + self.net_condenser_capacity(conditions) + + self.oil_cooler_heat(conditions) + + self.auxiliary_heat(conditions) + ) + + def set_rated_evaporator_volumetric_flow_rate(self): + delta_T = ( + AHRI_550_590_WATER_COOLED_EVAPORATOR_INLET.T + - AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.T + ) + m_dot = self.rated_net_evaporator_capacity / ( + AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.get_cp() * delta_T + ) + AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.set_m_dot(m_dot) + AHRI_550_590_WATER_COOLED_EVAPORATOR_INLET.set_m_dot(m_dot) + self.rated_evaporator_volumetric_flow_rate = ( + AHRI_550_590_WATER_COOLED_CONDITIONS.evaporator_outlet.V_dot + ) + + def set_rated_condenser_volumetric_flow_rate(self): + delta_T = ( + AHRI_550_590_WATER_COOLED_CONDENSER_OUTLET.T + - AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.T + ) + m_dot = self.rated_net_condenser_capacity / ( + AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.get_cp() * delta_T + ) + AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.set_m_dot(m_dot) + AHRI_550_590_WATER_COOLED_CONDENSER_OUTLET.set_m_dot(m_dot) + self.rated_condenser_volumetric_flow_rate = ( + AHRI_550_590_WATER_COOLED_CONDITIONS.condenser_inlet.V_dot + ) + + def generate_205_representation(self): + # Metadata + timestamp = datetime.datetime.now().isoformat("T", "minutes") + rnd = Random() + if self.metadata.uuid_seed is None: + self.metadata.uuid_seed = hash(self) + rnd.seed(self.metadata.uuid_seed) + unique_id = str(uuid.UUID(int=rnd.getrandbits(128), version=4)) + + metadata = { + "data_model": "ASHRAE_205", + "schema": "RS0001", + "schema_version": "2.0.0", + "description": self.metadata.description, + "id": unique_id, + "data_timestamp": f"{timestamp}Z", + "data_version": self.metadata.data_version, + "data_source": self.metadata.data_source, + "disclaimer": "This data is synthetic and does not represent any physical products.", + "notes": self.metadata.notes, + } + representation_description = { + "product_information": { + "liquid_data_source": "CoolProp", + "hot_gas_bypass_installed": self.metadata.has_hot_gas_bypass_installed, + } + } + + if self.metadata.compressor_type is not None: + representation_description["product_information"][ + "compressor_type" + ] = self.metadata.compressor_type + + # Create conditions + evaporator_liquid_volumetric_flow_rates = [ + self.rated_evaporator_volumetric_flow_rate + ] + evaporator_liquid_leaving_temperatures = linspace( + self.minimum_evaporator_leaving_temperature, + self.maximum_evaporator_leaving_temperature, + 4, + ).tolist() + condenser_liquid_volumetric_flow_rates = [ + self.rated_condenser_volumetric_flow_rate + ] + condenser_liquid_entering_temperatures = linspace( + self.minimum_condenser_entering_temperature, + self.maximum_condenser_entering_temperature, + 4, + ).tolist() + compressor_sequence_numbers = list( + range(1, self.number_of_compressor_speeds + 1) + ) + + grid_variables = { + "evaporator_liquid_volumetric_flow_rate": evaporator_liquid_volumetric_flow_rates, + "evaporator_liquid_leaving_temperature": evaporator_liquid_leaving_temperatures, + "condenser_liquid_volumetric_flow_rate": condenser_liquid_volumetric_flow_rates, + "condenser_liquid_entering_temperature": condenser_liquid_entering_temperatures, + "compressor_sequence_number": compressor_sequence_numbers, + } + + input_powers = [] + net_evaporator_capacities = [] + net_condenser_capacities = [] + oil_cooler_heats = [] + auxiliary_heats = [] + operation_states = [] + + for v_evap in evaporator_liquid_volumetric_flow_rates: + for t_evap in evaporator_liquid_leaving_temperatures: + for v_cond in condenser_liquid_volumetric_flow_rates: + for t_cond in condenser_liquid_entering_temperatures: + for speed in [ + self.number_of_compressor_speeds - n + for n in compressor_sequence_numbers + ]: + conditions = OperatingConditions( + evaporator_outlet=FluidState( + temperature=t_evap, volumetric_flow_rate=v_evap + ), + condenser_inlet=FluidState( + temperature=t_cond, volumetric_flow_rate=v_cond + ), + compressor_speed=speed, + ) + + input_powers.append(self.input_power(conditions)) + net_evaporator_capacities.append( + self.net_evaporator_capacity(conditions) + ) + net_condenser_capacities.append( + self.net_condenser_capacity(conditions) + ) + oil_cooler_heats.append(self.oil_cooler_heat(conditions)) + auxiliary_heats.append(self.auxiliary_heat(conditions)) + operation_states.append("NORMAL") + + performance_map_cooling = { + "grid_variables": grid_variables, + "lookup_variables": { + "input_power": input_powers, + "net_evaporator_capacity": net_evaporator_capacities, + "net_condenser_capacity": net_condenser_capacities, + "oil_cooler_heat": oil_cooler_heats, + "auxiliary_heat": auxiliary_heats, + "operation_state": operation_states, + }, + } + + performance = { + "evaporator_liquid_type": { # TODO: Make consistent with model + "liquid_components": [ + { + "liquid_constituent": "WATER", + "concentration": 1.0, + } + ], + "concentration_type": "BY_VOLUME", + }, + "condenser_liquid_type": { # TODO: Make consistent with model + "liquid_components": [ + { + "liquid_constituent": "WATER", + "concentration": 1.0, + } + ], + "concentration_type": "BY_VOLUME", + }, + "evaporator_fouling_factor": 0.0, + "condenser_fouling_factor": 0.0, + "compressor_speed_control_type": "CONTINUOUS", + "cycling_degradation_coefficient": self.cycling_degradation_coefficient, + "performance_map_cooling": performance_map_cooling, + "performance_map_standby": { + "grid_variables": { + "environment_dry_bulb_temperature": [fr_u(20.0, "°C")], + }, + "lookup_variables": { + "input_power": [self.standby_power], + }, + }, + "performance_map_evaporator_liquid_pressure_differential": { + "grid_variables": { + "evaporator_liquid_volumetric_flow_rate": evaporator_liquid_volumetric_flow_rates, + "evaporator_liquid_leaving_temperature": evaporator_liquid_leaving_temperatures, + }, + "lookup_variables": { + "evaporator_liquid_differential_pressure": [fr_u(15.0, "kPa")] + * ( + len(evaporator_liquid_volumetric_flow_rates) + * len(evaporator_liquid_leaving_temperatures) + ), + }, + }, + "performance_map_condenser_liquid_pressure_differential": { + "grid_variables": { + "condenser_liquid_volumetric_flow_rate": condenser_liquid_volumetric_flow_rates, + "condenser_liquid_entering_temperature": condenser_liquid_entering_temperatures, + }, + "lookup_variables": { + "condenser_liquid_differential_pressure": [fr_u(15.0, "kPa")] + * ( + len(condenser_liquid_volumetric_flow_rates) + * len(condenser_liquid_entering_temperatures) + ), + }, + }, + } + + # Scaling + if ( + self.model.minimum_scaled_rated_capacity is not None + or self.model.maximum_scaled_rated_capacity is not None + ): + scaling = {} + + if self.model.minimum_scaled_rated_capacity is None: + scaling["minimum"] = 1.0 + elif self.model.minimum_scaled_rated_capacity > 0.0: + scaling["minimum"] = ( + self.model.minimum_scaled_rated_capacity + / self.rated_net_evaporator_capacity + ) + + if self.model.maximum_scaled_rated_capacity is None: + scaling["maximum"] = 1.0 + elif self.model.maximum_scaled_rated_capacity != float("inf"): + scaling["maximum"] = ( + self.model.maximum_scaled_rated_capacity + / self.rated_net_evaporator_capacity + ) + + performance["scaling"] = scaling + + representation = { + "metadata": metadata, + "description": representation_description, + "performance": performance, + } + + return self.model.fixup_205_representation(representation) diff --git a/chiller/models/ashrae_90_1.py b/chiller/models/ashrae_90_1.py index 915fb65..1658e90 100644 --- a/chiller/models/ashrae_90_1.py +++ b/chiller/models/ashrae_90_1.py @@ -82,6 +82,7 @@ def print_constructor(self): class ASHRAE90_1(EnergyPlusEIR): + # fmt: off chiller_curve_sets = [ ChillerCurveSet('A',CompliancePathType.ECB_A,CondenserType.AIR_COOLED,CompressorType.UNKNOWN,0.0,527528.0,2.960018222222222,4.015074222222222,[0.686206, 0.057562, -0.001835, 0.01381, -0.000338, -0.000247],[0.825618, -0.025861, 0.001396, -0.002728, 0.000381, -0.000373],[0.087789, 0.185696, 1.561411, -0.832304]), ChillerCurveSet('B',CompliancePathType.ECB_A,CondenserType.AIR_COOLED,CompressorType.UNKNOWN,527528.0,float('inf'),2.960018222222222,4.102995555555555,[0.794185, 0.060199, -0.002016, 0.006203, -0.000229, -0.000183],[0.807832, -0.029452, 0.001431, -0.002832, 0.000399, -0.000278],[0.118081, 0.107477, 1.570838, -0.794051]), @@ -111,6 +112,7 @@ class ASHRAE90_1(EnergyPlusEIR): ChillerCurveSet('AA',CompliancePathType.PRM,CondenserType.LIQUID_COOLED,CompressorType.CENTRIFUGAL,527528.0,1055056.0,5.549713323865131,5.899770731980094,[0.909633, 0.03546, -0.001881, -0.001808, -0.000158, 0.000648],[0.46433, -0.033834, 0.000731, 0.040345, -0.000592, 0.000277],[0.339494, 0.04909, 0.611582, 0.0]), ChillerCurveSet('AB',CompliancePathType.PRM,CondenserType.LIQUID_COOLED,CompressorType.CENTRIFUGAL,1055056.0,float('inf'),6.099294716152158,6.400097057931454,[0.988289, 0.031128, -0.00155, -0.003349, -0.000147, 0.000503],[0.563967, -0.034331, 0.001015, 0.033941, -0.000432, -2.5e-05],[0.309752, 0.153649, 0.536462, 0.0]) ] + # fmt: on def __init__(self): super().__init__() @@ -151,6 +153,11 @@ def set_system(self, system): system.kwargs["minimum_part_load_ratio"] = 0.25 system.kwargs["minimum_unloading_ratio"] = 0.25 + + # scaling + self.minimum_scaled_rated_capacity = self.curve_set.minimum_capacity + self.maximum_scaled_rated_capacity = self.curve_set.maximum_capacity + # set metadata system.metadata.notes = f"Based on ASHRAE 90.1-2019 Addendum 'bd' curve set '{self.curve_set.set_name}' for {compliance_path_text[self.curve_set.path_type]}" system.metadata.compressor_type = compressor_type_map[self.compressor_type] @@ -160,7 +167,11 @@ def set_system(self, system): if compressor_text is not None: type_text += f", {compressor_text} compressor" type_text += f" chiller" - system.metadata.description = f"ASHRAE 90.1-2019 Addendum 'bd' curve set '{self.curve_set.set_name}': {to_u(system.rated_net_evaporator_capacity,'ton_ref'):.1f} ton, {system.rated_cop:.2f} COP, {self.curve_set.iplv:.2f} IPLV {type_text}" + if self.maximum_scaled_rated_capacity == float('inf'): + size_description = f"{to_u(self.minimum_scaled_rated_capacity,'ton_ref'):.1f}+" + else: + size_description = f"{to_u(self.minimum_scaled_rated_capacity,'ton_ref'):.1f}-{to_u(self.maximum_scaled_rated_capacity,'ton_ref'):.1f}" + system.metadata.description = f"ASHRAE 90.1-2019 Addendum 'bd' curve set '{self.curve_set.set_name}': {size_description} ton, {system.rated_cop:.2f} COP, {self.curve_set.iplv:.2f} IPLV {type_text}" unique_characteristics = ( system.rated_net_evaporator_capacity, system.rated_cop, diff --git a/chiller/models/base_model.py b/chiller/models/base_model.py index 705d668..5bce9e9 100644 --- a/chiller/models/base_model.py +++ b/chiller/models/base_model.py @@ -1,36 +1,38 @@ class ChillerModel: - def __init__(self): - self.system = None - self.allowed_kwargs = {} - self.required_kwargs = [] + def __init__(self): + self.system = None + self.allowed_kwargs = {} + self.required_kwargs = [] + self.maximum_scaled_rated_capacity = None + self.minimum_scaled_rated_capacity = None - def set_system(self, system): - self.system = system - for kwarg in system.kwargs: - if kwarg not in self.allowed_kwargs and kwarg not in self.required_kwargs: - raise Exception(f"Unrecognized key word argument: {kwarg}") - for kwarg in self.required_kwargs: - if kwarg not in system.kwargs: - raise Exception(f"Required key word argument not provided: {kwarg}") - # Apply defaults - for kwarg in self.allowed_kwargs: - if kwarg not in system.kwargs: - system.kwargs[kwarg] = self.allowed_kwargs[kwarg] + def set_system(self, system): + self.system = system + for kwarg in system.kwargs: + if kwarg not in self.allowed_kwargs and kwarg not in self.required_kwargs: + raise Exception(f"Unrecognized key word argument: {kwarg}") + for kwarg in self.required_kwargs: + if kwarg not in system.kwargs: + raise Exception(f"Required key word argument not provided: {kwarg}") + # Apply defaults + for kwarg in self.allowed_kwargs: + if kwarg not in system.kwargs: + system.kwargs[kwarg] = self.allowed_kwargs[kwarg] - def net_evaporator_capacity(self, conditions): - raise NotImplementedError() + def net_evaporator_capacity(self, conditions): + raise NotImplementedError() - def input_power(self, conditions): - raise NotImplementedError + def input_power(self, conditions): + raise NotImplementedError - def net_condenser_capacity(self, conditions): - raise NotImplementedError() + def net_condenser_capacity(self, conditions): + raise NotImplementedError() - def oil_cooler_heat(self, conditions): - raise NotImplementedError() + def oil_cooler_heat(self, conditions): + raise NotImplementedError() - def auxiliary_heat(self, conditions): - raise NotImplementedError() + def auxiliary_heat(self, conditions): + raise NotImplementedError() - def fixup_205_representation(self, representation): - return representation + def fixup_205_representation(self, representation): + return representation diff --git a/examples/baseline_chillers.py b/examples/baseline_chillers.py index bd279d9..9988a62 100644 --- a/examples/baseline_chillers.py +++ b/examples/baseline_chillers.py @@ -8,7 +8,7 @@ import cbor2 import json -''' +""" # Use to regenerate curve set constructors in ashrae_90_1.py import csv from chiller.models.ashrae_90_1 import ChillerCurveSet, compliance_path_text, condenser_type_text, compressor_type_text @@ -34,44 +34,52 @@ )) chillers[-1].print_constructor() -''' +""" for chiller in ASHRAE90_1.chiller_curve_sets: - if chiller.condenser_type == CondenserType.LIQUID_COOLED: - if chiller.maximum_capacity == float('inf'): - size = chiller.minimum_capacity + fr_u(50., "ton_ref") - else: - size = (chiller.minimum_capacity + chiller.maximum_capacity)*0.5 - new_chiller = Chiller( - model=ASHRAE90_1(), - rated_net_evaporator_capacity=size, - rated_cop=chiller.cop, - path_type=chiller.path_type, - condenser_type=chiller.condenser_type, - compressor_type=chiller.compressor_type) - - assert abs(new_chiller.cop() - new_chiller.rated_cop) < 0.05 - assert abs(new_chiller.net_evaporator_capacity() - new_chiller.rated_net_evaporator_capacity) < 0.01*size - - new_chiller.metadata.data_version = 2 - unique_characteristics = ( - chiller.set_name, - new_chiller.rated_net_evaporator_capacity - ) - new_chiller.metadata.uuid_seed = sha256(f"{unique_characteristics}".encode()).hexdigest() - - - representation = new_chiller.generate_205_representation() - - output_directory_path = "output" - file_name = f"ASHRAE90-1-2019-bd-Curve-Set-{chiller.set_name}.RS0001.a205" - - # with open(f"{output_directory_path}/{file_name}.yaml", "w") as file: - # yaml.dump(representation, file, sort_keys=False) - - # with open(f"{output_directory_path}/{file_name}.cbor", "wb") as file: - # cbor2.dump(representation, file) - - with open(f"{output_directory_path}/{file_name}.json", "w") as file: - json.dump(representation, file, indent=4) + if chiller.condenser_type == CondenserType.LIQUID_COOLED: + if chiller.maximum_capacity == float("inf"): + size = chiller.minimum_capacity + fr_u(50.0, "ton_ref") + else: + size = (chiller.minimum_capacity + chiller.maximum_capacity) * 0.5 + new_chiller = Chiller( + model=ASHRAE90_1(), + rated_net_evaporator_capacity=size, + rated_cop=chiller.cop, + path_type=chiller.path_type, + condenser_type=chiller.condenser_type, + compressor_type=chiller.compressor_type, + ) + + assert abs(new_chiller.cop() - new_chiller.rated_cop) < 0.05 + assert ( + abs( + new_chiller.net_evaporator_capacity() + - new_chiller.rated_net_evaporator_capacity + ) + < 0.01 * size + ) + + new_chiller.metadata.data_version = 2 # TODO: Update when necessary + unique_characteristics = ( + chiller.set_name, + new_chiller.rated_net_evaporator_capacity, + ) + new_chiller.metadata.uuid_seed = sha256( + f"{unique_characteristics}".encode() + ).hexdigest() + + representation = new_chiller.generate_205_representation() + + output_directory_path = "output" + file_name = f"ASHRAE90-1-2019-bd-Curve-Set-{chiller.set_name}.RS0001.a205" + + # with open(f"{output_directory_path}/{file_name}.yaml", "w") as file: + # yaml.dump(representation, file, sort_keys=False) + + # with open(f"{output_directory_path}/{file_name}.cbor", "wb") as file: + # cbor2.dump(representation, file) + + with open(f"{output_directory_path}/{file_name}.json", "w") as file: + json.dump(representation, file, indent=4)