"""
File with HVAC systems classes
"""
__author__ = "Enrico Prataviera"
__credits__ = ["Enrico Prataviera"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Enrico Prataviera"
import abc
import os
import io
import logging
import pandas as pd
import numpy as np
from eureca_building.systems_info import systems_info
from eureca_building.fluids_properties import fuels_pci
from eureca_building.config import CONFIG
# including Systems info from system_info json
global systems_info_dict
systems_info_dict = {}
for k,v in systems_info.items():
systems_info_dict[k] = pd.read_csv(io.StringIO(v), sep = "\t")
if "Type" in systems_info_dict[k].columns:
systems_info_dict[k].set_index("Type", drop=True, inplace = True)
[docs]class System(metaclass=abc.ABCMeta):
"""
Father class for HVAC systems classes
Defines an interface to force inherited class to implement mandatory methods
"""
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
@classmethod
def __subclasshook__(cls, C):
if cls is System:
attrs = set(dir(C))
if set(cls.__abstractmethods__) <= attrs:
return True
return NotImplemented
[docs] @abc.abstractmethod
def __init__(self, *args, **kwargs):
# raise NotImplementedError(
# f"""
# When creating a class for systems __init__, set, and solve methods must be created and overwritten
# """
# )
pass
[docs] @abc.abstractmethod
def set_system_capacity(self):
# raise NotImplementedError(
# f"""
# When creating a class for systems __init__, set, and solve methods must be created and overwritten
# """
# )
pass
[docs] @abc.abstractmethod
def solve_system(self):
# raise NotImplementedError(
# f"""
# When creating a class for systems __init__, set, and solve methods must be created and overwritten
# """
# )
pass
@property
@abc.abstractmethod
def electric_consumption(self):
pass
@property
@abc.abstractmethod
def gas_consumption(self):
pass
@property
@abc.abstractmethod
def wood_consumption(self):
pass
@property
@abc.abstractmethod
def oil_consumption(self):
pass
@property
def system_type(self):
return self._system_type
@system_type.setter
def system_type(self, value: str):
if not isinstance(value, str):
raise TypeError(
f"HVAC System, system type not string: {type(value)}"
)
self._system_type = value
# %%---------------------------------------------------------------------------------------------------
# %% IdealLoad class
[docs]class IdealLoad(System):
'''Class IdealLoad is for the ideal zone balance. This class passes all methods.
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
"""IdealLoad init method. No input needed
Parameters
----------
args
kwargs
"""
self.convective_fraction = 0.65
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
[docs] def set_system_capacity(self, design_power, weather):
"""Set system capacity method.
Parameters
----------
design_power : float
Design Heating power [W]
weather : eureca_building.weather.WeatherFile
WeatherFile object
"""
pass
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
"""Solve the system power for the time step
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
"""
pass
# %%---------------------------------------------------------------------------------------------------
# %% CondensingBoiler class
[docs]class CondensingBoiler(System):
'''Class CondensingBoiler. This method considers a generic Condensing Boiler as the heating system
of the entire building following UNI-TS 11300:2 - 2008
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
'''init method. Set some attributes for the method are initialized
Parameters
----------
args
kwargs
'''
# Input Data
self.system_type = "CondensingBoiler"
self.theta_gn_test_Pn = 70 # [°C]
self.theta_gn_test_Pint = 35 # [°C]
self.theta_a_test = 20 # [°C]
self.PCI_natural_gas = fuels_pci["Natural Gas"] # Wh/Nm3
self.system_info = systems_info_dict["CondensingBoiler"]
self.convective_fraction = 0.5
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
# Vectors initialization
# self.phi_gn_i_Px = np.zeros(l) # [kW]
# self.W_aux_Px = np.zeros(l) # [kW]
# self.phi_gn_i_Px_1 = np.zeros(l) # [kW]
# self.phi_gn_i_Px_2 = np.zeros(l) # [kW]
[docs] def set_system_capacity(self, design_power, weather):
'''Sets system design power
Parameters
----------
design_power : float
Design Heating power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
'''
# Choise of system size based on estimated nominal Power
Size_0 = 0
self.design_power = design_power # [W]
for i in self.system_info.index:
if Size_0 < self.design_power <= self.system_info['Size [kW]'][i] * 1000:
self.ID = i
Size_0 = self.system_info['Size [kW]'][i] * 1000
if self.design_power > self.system_info['Size [kW]'][self.system_info.index[-1]] * 1000:
self.ID = len(self.system_info) - 1
self.Pint = self.system_info['P_int [%]'][self.ID] * self.design_power # [W]
if self.system_info['location [str]'][self.ID] == 'tech_room':
self.theta_a_gn = 15 # [°C]
elif self.system_info['location [str]'][self.ID] == 'internal':
self.theta_a_gn = 20 # [°C]
elif self.system_info['location [str]'][self.ID] == 'external':
self.theta_a_gn = weather.general_data['average_out_air_db_temperature_heating_season'] # [°C]
# Minimum Condensing Boiler efficiency check based on Directive
# 92/42/CEE'''
if self.design_power > 400000:
self.design_power_check = 400000 # [W]
else:
self.design_power_check = self.design_power
self.eta_gn_Pn_min = (91 + 1 * np.log(self.design_power_check / 1000)) # [%]
self.eta_gn_Pint_min = (97 + 1 * np.log(self.design_power_check / 1000)) # [%]
if self.system_info['eta_nom [%]'][self.ID] < self.eta_gn_Pn_min or \
self.system_info['eta_int [%]'][self.ID] < self.eta_gn_Pint_min:
logging.warning('Warning: Condensing Boiler efficiencies are lower than minimum')
# No load losses estimation
self.phi_gn_I_P0 = (self.design_power_check * 4.8 / 100 * (self.design_power_check / 1000) ** (-0.35)) # [W]
# Auxiliary power input data
self.W_aux_Pn = (45 * (self.design_power/1000) ** 0.48) # [W]
self.W_aux_Pint = (15 * (self.design_power/1000) ** 0.48) # [W]
self.W_aux_P0 = (15) # [W]
self.FC_Pint = self.Pint / self.design_power
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
'''This method allows to calculate Condensing Boiler power and losses following
the Standard UNI-TS 11300:2 - 2008
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
'''
# Corrected efficiency and losses at nominal power
self.eta_gn_Pn_cor = self.system_info['eta_nom [%]'][self.ID] + \
self.system_info['f_cor_Pn [-]'][self.ID] * (
self.theta_gn_test_Pn - self.system_info['T_gn_w [°C]'][self.ID])
self.phi_gn_i_Pn_cor = (100 - self.eta_gn_Pn_cor) / self.eta_gn_Pn_cor * self.design_power # [W]
# Corrected efficiency and losses at intermadiate power
self.eta_gn_Pint_cor = self.system_info['eta_int [%]'][self.ID] + \
self.system_info['f_cor_Pint [-]'][self.ID] * (
self.theta_gn_test_Pint - self.system_info['T_gn_Pint [°C]'][self.ID])
self.phi_gn_i_Pint_cor = (100 - self.eta_gn_Pint_cor) / self.eta_gn_Pint_cor * self.Pint # [W]
# Corrected no-load losses
self.phi_gn_i_P0_cor = self.phi_gn_I_P0 * (
(self.system_info['T_gn_w [°C]'][self.ID] - self.theta_a_gn) / (self.theta_gn_test_Pn - self.theta_a_test)) ** 1.25
# Total losses at current power
if heat_flow <= 0:
self.phi_gn_i_Px = 0
else:
self.phi_gn_i_Px_1 = ((heat_flow/1000) ** 2) * (((self.Pint/1000) * (
self.phi_gn_i_Pn_cor/1000 - self.phi_gn_i_P0_cor/1000) - self.design_power/1000 * (
self.phi_gn_i_Pint_cor/1000 - self.phi_gn_i_P0_cor/1000)) / (
self.design_power/1000 * self.Pint/1000 * (self.design_power/1000 - self.Pint/1000)))*1000 #[W]
self.phi_gn_i_Px_2 = heat_flow/1000 * ((((self.design_power/1000) ** 2) * (self.phi_gn_i_Pint_cor/1000 - self.phi_gn_i_P0_cor/1000) - (
(self.Pint/1000) ** 2) * (self.phi_gn_i_Pn_cor/1000 - self.phi_gn_i_P0_cor/1000)) / (
self.design_power/1000 * self.Pint/1000 * (self.design_power/1000 - self.Pint/1000))) * 1000 # [W]
self.phi_gn_i_Px = self.phi_gn_i_Px_1 + self.phi_gn_i_Px_2 + self.phi_gn_i_P0_cor # [W]
# Auxiliary power estimation
if heat_flow <= 0:
self.FC_Px = 0
self.W_aux_Px = 0
else:
self.FC_Px = heat_flow / self.design_power
if 0 < self.FC_Px <= self.FC_Pint:
self.W_aux_Px = self.W_aux_P0 + self.FC_Px / self.FC_Pint * (self.W_aux_Pint - self.W_aux_P0) # [W]
elif self.FC_Pint < self.FC_Px <= 1:
self.W_aux_Px = self.W_aux_Pint + (self.FC_Px - self.FC_Pint) * (self.W_aux_Pn - self.W_aux_Pint) / (
1 - self.FC_Pint) # [W]
elif self.FC_Px > 1:
self.FC_Px = 1
self.W_aux_Px = self.W_aux_Pint + (self.FC_Px - self.FC_Pint) * (self.W_aux_Pn - self.W_aux_Pint) / (
1 - self.FC_Pint) # [W]
total_energy = heat_flow + self.phi_gn_i_Px
self.gas_consumption = total_energy / CONFIG.ts_per_hour /self.PCI_natural_gas
self.electric_consumption = self.W_aux_Px / CONFIG.ts_per_hour
# %%---------------------------------------------------------------------------------------------------
# %% TraditionalBoiler class
[docs]class TraditionalBoiler(System):
'''Class TraditionalBoiler. This class considers a generic Traditional Boiler as the heating system
of the entire building following UNI-TS 11300:2 - 2008
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
'''init method. Set some attributes for the method
Parameters
----------
args
kwargs
'''
# Input Data
self.system_type = "TraditionalBoiler"
self.theta_gn_test_Pn = 70 # [°C]
self.theta_gn_test_Pint = 50 # [°C]
self.theta_a_test = 20 # [°C]
self.PCI_natural_gas = fuels_pci["Natural Gas"] # [Wh/Nm3]
self.system_info = systems_info_dict["TraditionalBoiler"]
self.convective_fraction = 0.5
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
# Vectors initialization
# self.phi_gn_i_Px = np.zeros(l) # [kW]
# self.W_aux_Px = np.zeros(l) # [kW]
# self.phi_gn_i_Px_1 = np.zeros(l) # [kW]
# self.phi_gn_i_Px_2 = np.zeros(l) # [kW]
[docs] def set_system_capacity(self, design_power, weather):
'''Sets system design power
Parameters
----------
design_power : float
Design Heating power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
'''
# Choise of system size based on estimated nominal Power
Size_0 = 0
self.design_power = design_power # [W]
for i in self.system_info.index:
if Size_0 < self.design_power <= self.system_info['Size [kW]'][i] * 1000:
self.ID = i
Size_0 = self.system_info['Size [kW]'][i] * 1000
if self.design_power > self.system_info['Size [kW]'][self.system_info.index[-1]] * 1000:
self.ID = len(self.system_info) - 1
self.Pint = self.system_info['P_int [%]'][self.ID] * self.design_power # [W]
if self.system_info['location [str]'][self.ID] == 'tech_room':
self.theta_a_gn = 15 # [°C]
elif self.system_info['location [str]'][self.ID] == 'internal':
self.theta_a_gn = 20 # [°C]
elif self.system_info['location [str]'][self.ID] == 'external':
self.theta_a_gn = weather.general_data['average_out_air_db_temperature_heating_season'] # [°C]
# Minimum Traditional Boiler efficiency check based on Directive
# 92/42/CEE'''
if self.design_power > 400000:
self.design_power_check = 400000 # [W]
else:
self.design_power_check = self.design_power
self.eta_gn_Pn_min = (84 + 2 * np.log(self.design_power_check / 1000)) # [%]
self.eta_gn_Pint_min = (80 + 3 * np.log(self.design_power_check / 1000)) # [%]
if self.system_info['eta_nom [%]'][self.ID] < self.eta_gn_Pn_min or \
self.system_info['eta_int [%]'][self.ID] < self.eta_gn_Pint_min:
logging.warning('Warning: Traditional Boiler efficiencies are lower than minimum')
# No load losses estimation
self.phi_gn_I_P0 = (self.design_power_check / 1000 * 10 * 8.5 * (self.design_power_check / 1000) ** (-0.4)) # [W]
# Auxiliary power input data
self.W_aux_Pn = (45 * (self.design_power / 1000) ** 0.48) # [W]
self.W_aux_Pint = (15 * (self.design_power/ 1000) ** 0.48) # [W]
self.W_aux_P0 = (15) # [W]
self.FC_Pint = self.Pint / self.design_power
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
'''This method allows to calculate Traditional Boiler losses following
the Standard UNI-TS 11300:2 - 2008
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
'''
# Corrected efficiency and losses at nominal power
self.eta_gn_Pn_cor = self.system_info['eta_nom [%]'][self.ID] + \
self.system_info['f_cor_Pn [-]'][self.ID] * (
self.theta_gn_test_Pn - self.system_info['T_gn_w [°C]'][self.ID])
self.phi_gn_i_Pn_cor = (100 - self.eta_gn_Pn_cor) / self.eta_gn_Pn_cor * self.design_power # [W]
# Corrected efficiency and losses at intermadiate power
self.eta_gn_Pint_cor = self.system_info['eta_int [%]'][self.ID] + \
self.system_info['f_cor_Pint [-]'][self.ID] * (
self.theta_gn_test_Pint - self.system_info['T_gn_Pint [°C]'][self.ID])
self.phi_gn_i_Pint_cor = (100 - self.eta_gn_Pint_cor) / self.eta_gn_Pint_cor * self.Pint # [W]
# Corrected no-load losses
self.phi_gn_i_P0_cor = self.phi_gn_I_P0 * (
(self.system_info['T_gn_w [°C]'][self.ID] - self.theta_a_gn) / (self.theta_gn_test_Pn - self.theta_a_test)) ** 1.25
# Total losses at current power
if heat_flow <= 0:
self.phi_gn_i_Px = 0
else:
self.phi_gn_i_Px_1 = ((heat_flow/1000) ** 2) * (
(
(self.Pint/1000) * (
self.phi_gn_i_Pn_cor/1000 - self.phi_gn_i_P0_cor/1000) - self.design_power/1000 * (
self.phi_gn_i_Pint_cor/1000 - self.phi_gn_i_P0_cor/1000))
/ (self.design_power/1000 * self.Pint/1000 * (self.design_power/1000 - self.Pint/1000)))*1000 #[W]
self.phi_gn_i_Px_2 = heat_flow/1000 * \
((
((self.design_power/1000) ** 2) *(self.phi_gn_i_Pint_cor/1000 - self.phi_gn_i_P0_cor/1000)
- ((self.Pint/1000) ** 2) * (self.phi_gn_i_Pn_cor/1000 - self.phi_gn_i_P0_cor/1000))
/ (self.design_power/1000 * self.Pint/1000 * (self.design_power/1000 - self.Pint/1000))) * 1000 # [W]
self.phi_gn_i_Px = self.phi_gn_i_Px_1 + self.phi_gn_i_Px_2 + self.phi_gn_i_P0_cor # [W]
# Auxiliary power estimation
if heat_flow <= 0:
self.FC_Px = 0
self.W_aux_Px = 0
else:
self.FC_Px = heat_flow / self.design_power
if 0 < self.FC_Px <= self.FC_Pint:
self.W_aux_Px = self.W_aux_P0 + self.FC_Px / self.FC_Pint * (self.W_aux_Pint - self.W_aux_P0) # [W]
elif self.FC_Pint < self.FC_Px <= 1:
self.W_aux_Px = self.W_aux_Pint + (self.FC_Px - self.FC_Pint) * (self.W_aux_Pn - self.W_aux_Pint) / (
1 - self.FC_Pint) # [W]
elif self.FC_Px > 1:
self.FC_Px = 1
self.W_aux_Px = self.W_aux_Pint + (self.FC_Px - self.FC_Pint) * (self.W_aux_Pn - self.W_aux_Pint) / (
1 - self.FC_Pint) # [W]
total_energy = heat_flow + self.phi_gn_i_Px
self.gas_consumption = total_energy / CONFIG.ts_per_hour /self.PCI_natural_gas
self.electric_consumption = self.W_aux_Px / CONFIG.ts_per_hour
# %%---------------------------------------------------------------------------------------------------
# %% SplitAirCooler class
[docs]class SplitAirCooler(System):
'''SplitAirCooler class. This class considers a generic Split Air Conditioner as the cooling system
of the entire building following UNI-TS 11300:3 - 2010
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
'''init method. Set some attributes for the method
Parameters
----------
args
kwargs
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
# Input Data
self.C_system_type = "SplitAirCooler"
self.T_ext_rif_100 = 35 # [°C]
self.T_ext_rif_75 = 30 # [°C]
self.T_ext_rif_50 = 25 # [°C]
self.T_ext_rif_25 = 20 # [°C]
self.T_int_rif = 27 # [°C]
self.W_aux_gn = 0.04 # [kW/kW_cond]
self.Conversion_fac = 2.17
self.system_info = systems_info_dict["SplitAirCooler"]
self.convective_fraction = 1.
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
# Vectors initialization
# self.W_el = np.zeros(l) # [kWe]
# self.W_aux = np.zeros(l) # [kWe]
# self.H_waste = np.zeros(l) # [kW]
# self.eta_mm = np.zeros(l)
# self.eta_1 = np.zeros(l)
[docs] def set_system_capacity(self, design_power, weather):
'''Choice of system size based on estimated nominal Power
Parameters
----------
design_power : float
Design Heating power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
'''
Size_0 = 0.
self.design_power = -1 * design_power # [W]
for i in self.system_info.index:
if Size_0 <= self.design_power <= self.system_info['Size [kW]'][i] * 1000:
self.ID = i
Size_0 = self.system_info['Size [kW]'][i] * 1000
if self.design_power > self.system_info['Size [kW]'][self.system_info.index[-1]] * 1000:
self.ID = len(self.system_info) - 1
self.Q_max = design_power # [W]
# EER curve in case of Air-to-Air unit
self.EER_100 = self.system_info['EER_100 [-]'][self.ID]
self.EER_75 = self.system_info['EER_75 [-]'][self.ID]
self.EER_50 = self.system_info['EER_50 [-]'][self.ID]
self.EER_25 = self.system_info['EER_25 [-]'][self.ID]
self.EER_20 = self.EER_25 * 0.94
self.EER_15 = self.EER_25 * 0.85
self.EER_10 = self.EER_25 * 0.73
self.EER_5 = self.EER_25 * 0.50
self.EER_2 = self.EER_25 * 0.26
self.EER_1 = self.EER_25 * 0.14
self.x = np.array([1, 0.75, 0.5, 0.25, 0.2, 0.15, 0.1, 0.05, 0.02, 0.01, 0.0])
self.y = np.array(
[self.EER_100, self.EER_75, self.EER_50, self.EER_25, self.EER_20, self.EER_15, self.EER_10, self.EER_5,
self.EER_2, self.EER_1, 0.0])
self.prosp_C_100 = np.array([[1.634, 1.457, 1.281, 1.105, 0.928, 0.807, 0.685], \
[1.720, 1.518, 1.327, 1.148, 0.979, 0.856, 0.736], \
[1.756, 1.534, 1.332, 1.155, 1.000, 0.871, 0.750], \
[1.782, 1.569, 1.370, 1.187, 1.018, 0.890, 0.767], \
[1.834, 1.639, 1.444, 1.249, 1.054, 0.928, 0.802]])
self.prosp_C_75 = np.array([[1.457, 1.281, 1.105, 0.928, 0.807, 0.685, 0.585], \
[1.518, 1.327, 1.148, 0.979, 0.856, 0.736, 0.636], \
[1.534, 1.332, 1.155, 1.000, 0.871, 0.750, 0.650], \
[1.569, 1.370, 1.187, 1.018, 0.890, 0.767, 0.667], \
[1.639, 1.444, 1.249, 1.054, 0.928, 0.802, 0.700]])
self.prosp_C_50 = np.array([[1.281, 1.105, 0.928, 0.807, 0.685, 0.585, 0.505], \
[1.327, 1.148, 0.979, 0.856, 0.736, 0.636, 0.556], \
[1.332, 1.155, 1.000, 0.871, 0.750, 0.650, 0.672], \
[1.370, 1.187, 1.018, 0.890, 0.767, 0.667, 0.587], \
[1.444, 1.249, 1.054, 0.928, 0.802, 0.700, 0.698]])
self.prosp_C_25 = np.array([[1.062, 0.962, 0.871, 0.788, 0.714, 0.646, 0.585], \
[1.083, 0.981, 0.888, 0.804, 0.728, 0.659, 0.596], \
[1.105, 1.000, 0.905, 0.820, 0.742, 0.672, 0.608], \
[1.126, 1.020, 0.923, 0.836, 0.757, 0.685, 0.620], \
[1.149, 1.040, 0.941, 0.852, 0.771, 0.698, 0.632]])
self.prosp_C_0 = self.prosp_C_25
self.prosp_C = np.array([self.prosp_C_100, self.prosp_C_75, self.prosp_C_50, self.prosp_C_25, self.prosp_C_0])
self.fx = np.array([1, 0.75, 0.5, 0.25, 0])
self.pcfx = np.array([15, 20, 25, 30, 35, 40, 45])
self.pcfy = np.array([16, 18, 19, 20, 22])
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
'''This method allows to calculate Split Air Cooler electrical power
following the Standard UNI-TS 11300:3 - 2010
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
self.T_ext_solve = weather.hourly_data["out_air_db_temperature"][t]
if self.T_ext_solve <= 15:
self.T_ext_solve = 15.1
elif self.T_ext_solve > 45:
self.T_ext_solve = 45
self.prosp_C_F = np.zeros([5, 7])
# Wet bulb temperature
self.T_wb = T_int * np.arctan(0.151977 * (RH_int + 8.313659) ** (0.5)) + np.arctan(T_int + RH_int) - np.arctan(
RH_int - 1.676331) + 0.00391838 * (RH_int) ** (3 / 2) * np.arctan(0.023101 * RH_int) - 4.686035
if self.T_wb <= 16:
self.T_wb = 16.1
elif self.T_wb > 22:
self.T_wb = 22
# Load Factor and EER in real conditions estimation
if heat_flow >= 0:
self.W_el = 0. # [We]
self.H_waste = 0. # [W]
self.W_aux = 0. # [We]
else:
self.F = heat_flow / (self.Q_max)
xa = self.x[1]
xb = self.x[0]
self.EER = (self.F - xb) / (xa - xb) * self.y[0] - (self.F - xa) / (xa - xb) * self.y[0]
for i in range(len(self.x) - 1):
xa = self.x[i + 1]
xb = self.x[i]
if xa <= self.F <= xb:
self.EER = (self.F - xb) / (xa - xb) * self.y[i + 1] - (self.F - xa) / (xa - xb) * self.y[i]
elif self.F > 1:
self.EER = self.EER_100
else:
pass
for i in range(len(self.fx) - 1):
n_prosp_a = i + 1
n_prosp_b = i
fxa = self.fx[i + 1]
fxb = self.fx[i]
if fxa < self.F <= fxb:
for n in range(5):
for m in range(7):
self.prosp_C_F[n][m] = (self.F - fxb) / (fxa - fxb) * self.prosp_C[n_prosp_a][n][m] - (
self.F - fxa) / (fxa - fxb) * self.prosp_C[n_prosp_b][n][m]
elif self.F > 1:
self.prosp_C_F = self.prosp_C_100
else:
pass
for n in range(4):
y1 = self.pcfy[n]
y2 = self.pcfy[n + 1]
if y1 < self.T_wb <= y2:
for m in range(6):
x1 = self.pcfx[m]
x2 = self.pcfx[m + 1]
if x1 < self.T_ext_solve <= x2:
self.eta_1= 1 / ((x2 - x1) * (y2 - y1)) * (
self.prosp_C_F[n + 1][m + 1] * (x2 - self.T_ext_solve) * (y2 - self.T_wb) +
self.prosp_C_F[n][m + 1] * (self.T_ext_solve - x1) * (y2 - self.T_wb) +
self.prosp_C_F[n + 1][m] * (x2 - self.T_ext_solve) * (self.T_wb - y1) +
self.prosp_C_F[n][m] * (self.T_ext_solve - x1) * (self.T_wb - y1))
# Electrical power required in real conditions
self.eta_mm = self.EER * self.eta_1
self.W_el = abs(heat_flow) / self.eta_mm # [We]
self.H_waste = abs(heat_flow) + self.W_el # [W]
self.W_aux = self.W_aux_gn * (self.H_waste) # [We]
self.electric_consumption = (self.W_el + self.W_aux) / CONFIG.ts_per_hour
# %%---------------------------------------------------------------------------------------------------
# %% ChillerAirtoWater class
[docs]class ChillerAirtoWater(System):
'''ChillerAirtoWater class. This method considers a generic Air-to-water Chiller as the cooling system
of the entire building following UNI-TS 11300:3 - 2010
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
'''init method. Set some attributes for the method
Parameters
----------
args
kwargs
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
# Input Data
self.C_system_type = "ChillerAirtoWater"
self.T_ext_rif_100 = 35 # [°C]
self.T_ext_rif_75 = 30 # [°C]
self.T_ext_rif_50 = 25 # [°C]
self.T_ext_rif_25 = 20 # [°C]
self.T_w_out_rif = 7 # [°C]
self.W_aux_gn = 0.04 # [kW/kW_cond]
self.Conversion_fac = 2.17
self.system_info = systems_info_dict["ChillerAirtoWater"]
self.convective_fraction = 0.5
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
# Vectors initialization
# self.W_el = np.zeros(l) # [kWe]
# self.W_aux = np.zeros(l) # [kWe]
# self.H_waste = np.zeros(l) # [kW]
# self.eta_mm = np.zeros(l)
# self.eta_1 = np.zeros(l)
[docs] def set_system_capacity(self, design_power, weather):
'''Choice of system size based on estimated nominal Power
Parameters
----------
design_power : float
Design Heating power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
# Choise of system size based on estimated nominal Power
Size_0 = 0
self.Pnom = abs(design_power) # [W]
for i in self.system_info.index:
if Size_0 <= self.Pnom <= self.system_info['Size [kW]'][i] * 1000:
self.ID = i
Size_0 = self.system_info['Size [kW]'][i] * 1000
if self.Pnom > self.system_info['Size [kW]'][self.system_info.index[-1]] * 1000:
self.ID = len(self.system_info) - 1
self.Q_max = design_power # [W]
# EER curve in case of Air-to-Water chiller
self.EER_100 = self.system_info['EER_100 [-]'][self.ID]
self.EER_75 = self.system_info['EER_75 [-]'][self.ID]
self.EER_50 = self.system_info['EER_50 [-]'][self.ID]
self.EER_25 = self.system_info['EER_25 [-]'][self.ID]
self.EER_20 = self.EER_25 * 0.95
self.EER_15 = self.EER_25 * 0.94
self.EER_10 = self.EER_25 * 0.87
self.EER_5 = self.EER_25 * 0.71
self.EER_2 = self.EER_25 * 0.46
self.EER_1 = self.EER_25 * 0.29
self.x = np.array([1, 0.75, 0.5, 0.25, 0.2, 0.15, 0.1, 0.05, 0.02, 0.01, 0.0])
self.y = np.array(
[self.EER_100, self.EER_75, self.EER_50, self.EER_25, self.EER_20, self.EER_15, self.EER_10, self.EER_5,
self.EER_2, self.EER_1, 0.0])
# Assumption: T_water_out = 7°C and delta(T) = 5°C
self.prosp_C_100 = np.array([1.756, 1.534, 1.332, 1.155, 1.000, 0.871, 0.750])
self.prosp_C_75 = np.array([1.534, 1.332, 1.155, 1.000, 0.871, 0.750, 0.650])
self.prosp_C_50 = np.array([1.332, 1.155, 1.000, 0.871, 0.750, 0.650, 0.570])
self.prosp_C_25 = np.array([1.155, 1.000, 0.871, 0.750, 0.650, 0.570, 0.500])
self.prosp_C_0 = self.prosp_C_25
self.prosp_C = np.array([self.prosp_C_100, self.prosp_C_75, self.prosp_C_50, self.prosp_C_25, self.prosp_C_0])
self.fx = np.array([1, 0.75, 0.5, 0.25, 0])
self.pcfx = np.array([15, 20, 25, 30, 35, 40, 45])
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
'''This method allows to calculates Air to Water Chiller electrical power
following the Standard UNI-TS 11300:3 - 2010
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
self.T_ext_solve = weather.hourly_data["out_air_db_temperature"][t]
if self.T_ext_solve <= 15:
self.T_ext_solve = 15.1
elif self.T_ext_solve > 45:
self.T_ext_solve = 45
self.prosp_C_F = np.zeros(7)
# Load Factor and EER in real conditions estimation
if heat_flow >= 0:
self.W_el = 0. # [We]
self.H_waste = 0. # [W]
self.W_aux = 0. # [We]
else:
self.F = heat_flow / (self.Q_max)
xa = self.x[1]
xb = self.x[0]
self.EER = (self.F - xb) / (xa - xb) * self.y[0] - (self.F - xa) / (xa - xb) * self.y[0]
for i in range(len(self.x) - 1):
xa = self.x[i + 1]
xb = self.x[i]
if xa <= self.F <= xb:
self.EER = (self.F - xb) / (xa - xb) * self.y[i + 1] - (self.F - xa) / (xa - xb) * self.y[i]
elif self.F > 1:
self.EER = self.EER_100
else:
pass
for i in range(len(self.fx) - 1):
fxa = self.fx[i + 1]
fxb = self.fx[i]
if fxa < self.F <= fxb:
for m in range(7):
self.prosp_C_F[m] = (self.F - fxb) / (fxa - fxb) * self.prosp_C[i + 1][m] - (self.F - fxa) / (
fxa - fxb) * self.prosp_C[i][m]
elif self.F > 1:
self.prosp_C_F = self.prosp_C_100
else:
pass
for m in range(6):
x1 = self.pcfx[m]
x2 = self.pcfx[m + 1]
if x1 < self.T_ext_solve <= x2:
self.eta_1 = (self.T_ext_solve - x1) / (x2 - x1) * self.prosp_C_F[m + 1] - (
self.T_ext_solve - x2) / (x2 - x1) * self.prosp_C_F[m]
# Electrical power required in real conditions
self.eta_mm = self.EER * self.eta_1
self.W_el = abs(heat_flow) / self.eta_mm # [We]
self.H_waste = abs(heat_flow) + self.W_el # [W]
self.W_aux = self.W_aux_gn * (self.H_waste) # [We]
self.electric_consumption = (self.W_el + self.W_aux) / CONFIG.ts_per_hour
# %%---------------------------------------------------------------------------------------------------
# %% SplitAirConditioner class
[docs]class SplitAirConditioner(System):
'''SplitAirConditioner class
This method considers a generic Split Air Conditioner as the cooling system
of the entire building following two documents of literature
Berend Jan Christiaan van Putten, Nariman Mahdavi, Julio H. Braslavsky,
An Analytical Model for Demand Response of Variable-Speed Air Conditioners,
IFAC-PapersOnLine,
Volume 51, Issue 28,
2018,
Pages 426-431,
ISSN 2405-8963,
https://doi.org/10.1016/j.ifacol.2018.11.740.
(https://www.sciencedirect.com/science/article/pii/S2405896318334608)
https://ieeexplore.ieee.org/document/7515217
N. Mahdavi, J. H. Braslavsky and C. Perfumo,
"Mapping the Effect of Ambient Temperature on the Power Demand of Populations of Air Conditioners,"
in IEEE Transactions on Smart Grid, vol. 9, no. 3, pp. 1540-1550, May 2018,
doi: 10.1109/TSG.2016.2592522.
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
'''init method. Set some attributes for the method
Parameters
----------
args
kwargs
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
# Input Data
self.system_type = "SplitAirConditioner" # system_type è una stringa
self.T_ext_rif = 35 # [°C]
self.T_int_rif = 27 # [°C]
self.W_aux_gn = 0.04 # [kW/kW_cond]
self.system_info = systems_info_dict["SplitAirConditioner"]
self.convective_fraction = 1.
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
# self.W_el = np.zeros(l) # [kWe]
# self.W_aux = np.zeros(l) # [kWe]
# self.H_waste = np.zeros(l) # [kW]
# self.eta_mm = np.zeros(l)
# self.EER = np.zeros(l)
# self.F = np.zeros(l)
[docs] def set_system_capacity(self, design_power, weather): # da modificare dentro il file excel di impianti
'''Choice of system size based on estimated nominal Power for air conditioner WITHOUT inverter
Parameters
----------
design_power : float
Design Heating power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
Size_0 = 0
self.Pnom = abs(design_power) # [W]
for i in self.system_info.index:
if Size_0 < self.Pnom <= self.system_info['Size [kW]'][i] * 1000:
self.ID = i
Size_0 = self.system_info['Size [kW]'][i] * 1000
if self.Pnom > self.system_info['Size [kW]'][self.system_info.index[-1]] * 1000:
self.ID = len(self.system_info) - 1
self.Q_max = design_power # [W]
if self.system_info['inverter [str]'][self.ID] == 'no':
self.EER_targa = self.system_info['EER_medio [-]'][self.ID]
elif self.system_info['inverter [str]'][self.ID] == 'yes': # Choise of system size based on estimated nominal Power for air conditioner WITH inverter
self.a = 11.2
self.b = -0.363
self.c = 2.6 * pow(10, -3)
self.d = 0.829
self.e = 6.9 * pow(10, -3)
self.f = -0.159
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
'''This method allows to calculate from literature: Split Air Cooler condensing power
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
'''
# Check input data type
# The quality control is implemented in the System class.. Here is not necessary
T_ext = weather.hourly_data["out_air_db_temperature"][t]
if heat_flow >= 0:
self.W_el = 0. # [We]
self.H_waste = 0. # [W]
else:
self.F = heat_flow / (self.Q_max)
if self.system_info['inverter [str]'][self.ID] == 'no':
self.T_ext_solve = T_ext
if self.T_ext_solve <= 20:
self.T_ext_solve = 20.1
elif self.T_ext_solve > 35:
self.T_ext_solve = 35
self.EER = -0.14 * (self.T_ext_solve - 35) + self.EER_targa
elif self.system_info['inverter [str]'][self.ID] == 'yes': # Choise of system size based on estimated nominal Power for air conditioner WITH inverter'
self.Pnom_cond = 7000 # [W] P_nom conditioner
self.number_cond = heat_flow / self.Pnom_cond # number of air conditioners suppose in each thermal zone
self.EER = self.a + self.b * T_ext + self.c * T_ext ** 2 + self.d * (
heat_flow / self.number_cond / 1000) + self.e * T_ext * (heat_flow / self.number_cond / 1000) + self.f * (
heat_flow / self.number_cond / 1000) ** 2
self.H_waste = (abs(heat_flow) * (1 + self.EER)) / self.EER
self.W_el = self.H_waste - abs(heat_flow)
self.electric_consumption = (self.W_el) / CONFIG.ts_per_hour
[docs]class Heating_EN15316(System):
'''Class Heating_EN15316. This method considers a generic heating system as the heating system
of the entire building following EN 15316.
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
'''init method. Set some attributes are set
The heating_system_key label must be passed as kwargs. Example:
Heating_EN15316(heating_system_key = "Traditional Gas Boiler, Single, Low Temp Radiator")
Parameters
----------
args : list
list of optional arguments
kwargs : dict
kwargs must include {heating_system_key : string_of_heating_system}
'''
self.system_type = kwargs["heating_system_key"]
info_heating = kwargs["heating_system_key"].split(", ")
self.generation_type = info_heating[0]
try:
self.distribution_type = info_heating[1]
self.emitter_type = info_heating[2]
self.emission_control_efficiency = systems_info_dict["EN_15316_emission_control_heating_efficiency"]["Efficiency [-]"][self.emitter_type]
self.distribution_efficiency = systems_info_dict["EN_15316_distribution_heating_efficiency"]["Efficiency [-]"][self.distribution_type]
self.convective_fraction = systems_info_dict["EN_15316_emission_control_heating_efficiency"]["Convective fraction [-]"][self.emitter_type]
except IndexError:
# Stove
self.distribution_type = None
self.emitter_type = None
self.emission_control_efficiency = 1.
self.distribution_efficiency = 1.
self.convective_fraction = 0.5
self.generation_efficiency_profile = systems_info_dict["EN_15316_generation_heating_efficiency"].loc[self.generation_type]
self.generation_auxiliary_electric_load_profile = systems_info_dict["EN_15316_generation_heating_auxiliary_electric_load"].loc[self.generation_type]
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
# Input Data
# self.PCI_natural_gas = fuels_pci["Natural Gas"] # [Wh/Nm3]
[docs] def set_system_capacity(self, design_power, weather):
''''Choice of system size based on estimated nominal Power
Parameters
----------
design_power : float
Design Heating power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
'''
loads = self.generation_efficiency_profile.index
generation_efficiency_profile_capacity = np.array([float(load[:-2]) for load in loads])
loads = self.generation_auxiliary_electric_load_profile.index
generation_auxiliary_electric_load_profile_capacity = np.array([float(load[:-2]) for load in loads])
self.generation_efficiency = np.interp(design_power/1000, generation_efficiency_profile_capacity, self.generation_efficiency_profile.values) # [-]
self.generation_auxiliary_electric_load = np.interp(design_power/1000, generation_auxiliary_electric_load_profile_capacity, self.generation_auxiliary_electric_load_profile.values)*1000 # [W]
self.total_efficiency = self.emission_control_efficiency * self.distribution_efficiency * self.generation_efficiency
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
'''This method allows to calculate the system power for each time step
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
'''
# Corrected efficiency and losses at nominal power
total_energy = heat_flow / self.total_efficiency
if "Oil" in self.generation_type:
self.oil_consumption = total_energy / CONFIG.ts_per_hour / fuels_pci["Oil"]
self.electric_consumption = self.generation_auxiliary_electric_load / CONFIG.ts_per_hour
elif "Stove" in self.generation_type:
self.wood_consumption = total_energy / CONFIG.ts_per_hour / fuels_pci["Wood"]
self.electric_consumption = self.generation_auxiliary_electric_load / CONFIG.ts_per_hour
elif "Heat Pump" in self.generation_type:
self.electric_consumption = total_energy / CONFIG.ts_per_hour
elif "Gas" in self.generation_type:
self.gas_consumption = total_energy / CONFIG.ts_per_hour / fuels_pci["Natural Gas"]
self.electric_consumption = self.generation_auxiliary_electric_load / CONFIG.ts_per_hour
[docs]class Cooling_EN15316(System):
'''Class Cooling_EN15316. This method considers a generic cooling system as the heating system
of the entire building following EN 15316.
'''
gas_consumption = 0
electric_consumption = 0
wood_consumption = 0
oil_consumption = 0
[docs] def __init__(self, *args, **kwargs):
'''init method. Set some attributes are set
The cooling_system_key label must be passed as kwargs. Example:
Cooling_EN15316(cooling_system_key = "A-W chiller, Centralized, Radiant surface")
Parameters
----------
args
kwargs
kwargs must include {cooling_system_key : string_of_cooling_system}
'''
self.system_type = kwargs["cooling_system_key"]
info_cooling = kwargs["cooling_system_key"].split(", ")
self.generation_type = info_cooling[0]
try:
self.distribution_type = info_cooling[1]
self.emitter_type = info_cooling[2]
self.emission_control_efficiency = systems_info_dict["EN_15316_emission_control_cooling_efficiency"]["Efficiency [-]"][self.emitter_type]
self.distribution_efficiency = systems_info_dict["EN_15316_distribution_cooling_efficiency"]["Efficiency [-]"][self.distribution_type]
self.convective_fraction = systems_info_dict["EN_15316_emission_control_cooling_efficiency"]["Convective fraction [-]"][self.emitter_type]
except IndexError:
self.distribution_type = None
self.emitter_type = None
self.emission_control_efficiency = 1.
self.distribution_efficiency = 1.
self.convective_fraction = 1.
self.generation_seasonal_performance_factor = systems_info_dict["EN_15316_generation_cooling_seasonal_performance_factor"]["SPF [-]"].loc[self.generation_type]
self.total_efficiency = self.emission_control_efficiency * self.distribution_efficiency * self.generation_seasonal_performance_factor
self.sigma = {
"1C" : (1-self.convective_fraction, self.convective_fraction),
"2C" : (
(1-self.convective_fraction)/2, # Radiative IW
(1-self.convective_fraction)/2, # Radiative AW
self.convective_fraction) # Convective
}
[docs] def set_system_capacity(self, design_power, weather):
''''Choice of system size based on estimated nominal Power
Parameters
----------
design_power : float
Design Heating power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
'''
pass
[docs] def solve_system(self, heat_flow, weather, t, T_int, RH_int):
'''This method allows to calculate the system power for each time step
Parameters
----------
heat_flow : float
required power [W]
Weather : eureca_building.weather.WeatherFile
WeatherFile object
t : int
Simulation time step
T_int : float
Zone temperature [°]
RH_int : float
Zone relative humidity [%]
'''
# Corrected efficiency and losses at nominal power
total_energy = abs(heat_flow) / self.total_efficiency
self.electric_consumption = total_energy / CONFIG.ts_per_hour
hvac_heating_systems_classes = {
"IdealLoad":IdealLoad,
"CondensingBoiler":CondensingBoiler,
"TraditionalBoiler":TraditionalBoiler,
"Traditional Gas Boiler, Centralized, Low Temp Radiator":Heating_EN15316,
"Traditional Gas Boiler, Single, Low Temp Radiator":Heating_EN15316,
"Traditional Gas Boiler, Centralized, High Temp Radiator":Heating_EN15316,
"Traditional Gas Boiler, Single, High Temp Radiator":Heating_EN15316,
"Traditional Gas Boiler, Centralized, Fan coil":Heating_EN15316,
"Traditional Gas Boiler, Single, Fan coil":Heating_EN15316,
"Traditional Gas Boiler, Centralized, Radiant surface":Heating_EN15316,
"Traditional Gas Boiler, Single, Radiant surface":Heating_EN15316,
"Condensing Gas Boiler, Centralized, Low Temp Radiator":Heating_EN15316,
"Condensing Gas Boiler, Single, Low Temp Radiator":Heating_EN15316,
"Condensing Gas Boiler, Centralized, High Temp Radiator":Heating_EN15316,
"Condensing Gas Boiler, Single, High Temp Radiator":Heating_EN15316,
"Condensing Gas Boiler, Centralized, Fan coil":Heating_EN15316,
"Condensing Gas Boiler, Single, Fan coil":Heating_EN15316,
"Condensing Gas Boiler, Centralized, Radiant surface":Heating_EN15316,
"Condensing Gas Boiler, Single, Radiant surface":Heating_EN15316,
"Oil Boiler, Centralized, High Temp Radiator":Heating_EN15316,
"Oil Boiler, Single, High Temp Radiator":Heating_EN15316,
"Stove":Heating_EN15316,
"A-W Heat Pump, Centralized, Low Temp Radiator":Heating_EN15316,
"A-W Heat Pump, Single, Low Temp Radiator":Heating_EN15316,
"A-W Heat Pump, Centralized, Fan coil":Heating_EN15316,
"A-W Heat Pump, Single, Fan coil":Heating_EN15316,
"A-W Heat Pump, Centralized, Radiant surface":Heating_EN15316,
"A-W Heat Pump, Single, Radiant surface":Heating_EN15316,
}
hvac_cooling_systems_classes = {
"IdealLoad":IdealLoad,
"SplitAirCooler":SplitAirCooler,
"ChillerAirtoWater":ChillerAirtoWater,
"SplitAirConditioner":SplitAirConditioner,
"A-A split":Cooling_EN15316,
"A-W chiller, Centralized, Fan coil":Cooling_EN15316,
"A-W chiller, Centralized, Radiant surface":Cooling_EN15316,
"A-W chiller, Single, Fan coil":Cooling_EN15316,
"A-W chiller, Single, Radiant surface":Cooling_EN15316,
}