From cb842b59176c4e12b521d0147958b330cc5e8f79 Mon Sep 17 00:00:00 2001 From: s_ranjbar Date: Thu, 30 May 2024 17:26:50 -0400 Subject: [PATCH] feat: PV sizing module is added fix: bugs in catalogue and building are fixed feat: new archetype completed fix: building enrichment with results from archetype 13 is completed --- .../montreal_future_system_catalogue.py | 4 +- hub/city_model_structure/building.py | 61 ++-- .../energy_systems/thermal_storage_system.py | 19 +- .../montreal_future_systems.xml | 22 +- ...ntreal_future_energy_systems_parameters.py | 1 + main.py | 6 - scripts/random_assignation.py | 4 +- .../system_simulation_models/archetype1.py | 2 +- .../system_simulation_models/archetype13.py | 339 +++++++++++++++--- 9 files changed, 361 insertions(+), 97 deletions(-) diff --git a/hub/catalog_factories/energy_systems/montreal_future_system_catalogue.py b/hub/catalog_factories/energy_systems/montreal_future_system_catalogue.py index d8910960..625e362c 100644 --- a/hub/catalog_factories/energy_systems/montreal_future_system_catalogue.py +++ b/hub/catalog_factories/energy_systems/montreal_future_system_catalogue.py @@ -298,7 +298,7 @@ class MontrealFutureSystemCatalogue(Catalog): layers = [insulation_layer, tank_layer] nominal_capacity = tes['nominal_capacity'] losses_ratio = tes['losses_ratio'] - heating_coil_capacity = None + heating_coil_capacity = tes['heating_coil_capacity'] storage_component = ThermalStorageSystem(storage_id=storage_id, model_name=model_name, type_energy_stored=type_energy_stored, @@ -338,7 +338,7 @@ class MontrealFutureSystemCatalogue(Catalog): nominal_capacity = template['nominal_capacity'] losses_ratio = template['losses_ratio'] volume = template['physical_characteristics']['volume'] - heating_coil_capacity = None + heating_coil_capacity = template['heating_coil_capacity'] storage_component = ThermalStorageSystem(storage_id=storage_id, model_name=model_name, type_energy_stored=type_energy_stored, diff --git a/hub/city_model_structure/building.py b/hub/city_model_structure/building.py index 09b5e2b1..b928535b 100644 --- a/hub/city_model_structure/building.py +++ b/hub/city_model_structure/building.py @@ -450,7 +450,7 @@ class Building(CityObject): monthly_values = PeakLoads(self).heating_peak_loads_from_methodology if monthly_values is None: return None - results[cte.MONTH] = [x * cte.WATTS_HOUR_TO_JULES for x in monthly_values] + results[cte.MONTH] = [x for x in monthly_values] results[cte.YEAR] = [max(monthly_values)] return results @@ -876,37 +876,38 @@ class Building(CityObject): if demand_type in generation_system.energy_consumption: fuel_breakdown[f'{generation_system.fuel_type}'][f'{demand_type}'] = ( generation_system.energy_consumption)[f'{demand_type}'][cte.YEAR][0] + storage_systems = generation_system.energy_storage_systems + if storage_systems: + for storage_system in storage_systems: + if storage_system.type_energy_stored == 'thermal' and storage_system.heating_coil_energy_consumption: + fuel_breakdown[cte.ELECTRICITY][f'{demand_type}'] += storage_system.heating_coil_energy_consumption[cte.YEAR][0] #TODO: When simulation models of all energy system archetypes are created, this part can be removed - heating = 0 - cooling = 0 - dhw = 0 + heating_fuels = [] + dhw_fuels = [] + for energy_system in self.energy_systems: + if cte.HEATING in energy_system.demand_types: + for generation_system in energy_system.generation_systems: + heating_fuels.append(generation_system.fuel_type) + if cte.DOMESTIC_HOT_WATER in energy_system.demand_types: + for generation_system in energy_system.generation_systems: + dhw_fuels.append(generation_system.fuel_type) for key in fuel_breakdown: - if cte.HEATING not in fuel_breakdown[key]: - heating += 1 if key == cte.ELECTRICITY and cte.COOLING not in fuel_breakdown[key]: - cooling += 1 - if cte.DOMESTIC_HOT_WATER not in fuel_breakdown[key]: - dhw += 1 - if heating > 0: - for energy_system in energy_systems: - if cte.HEATING in energy_system.demand_types: - for generation_system in energy_system.generation_systems: - fuel_breakdown[generation_system.fuel_type][cte.HEATING] = self.heating_consumption[cte.YEAR][0] / 3600 - if dhw > 0: - for energy_system in energy_systems: - if cte.DOMESTIC_HOT_WATER in energy_system.demand_types: - for generation_system in energy_system.generation_systems: - fuel_breakdown[generation_system.fuel_type][cte.DOMESTIC_HOT_WATER] = \ - self.domestic_hot_water_consumption[cte.YEAR][0] / 3600 - if cooling > 0: - for energy_system in energy_systems: - if cte.COOLING in energy_system.demand_types: - for generation_system in energy_system.generation_systems: - fuel_breakdown[generation_system.fuel_type][cte.COOLING] = self.cooling_consumption[cte.YEAR][0] / 3600 - - - - - + for energy_system in energy_systems: + if cte.COOLING in energy_system.demand_types and cte.COOLING not in fuel_breakdown[key]: + for generation_system in energy_system.generation_systems: + fuel_breakdown[generation_system.fuel_type][cte.COOLING] = self.cooling_consumption[cte.YEAR][0] / 3600 + for fuel in heating_fuels: + if cte.HEATING not in fuel_breakdown[fuel]: + for energy_system in energy_systems: + if cte.HEATING in energy_system.demand_types: + for generation_system in energy_system.generation_systems: + fuel_breakdown[generation_system.fuel_type][cte.HEATING] = self.heating_consumption[cte.YEAR][0] / 3600 + for fuel in dhw_fuels: + if cte.DOMESTIC_HOT_WATER not in fuel_breakdown[fuel]: + for energy_system in energy_systems: + if cte.DOMESTIC_HOT_WATER in energy_system.demand_types: + for generation_system in energy_system.generation_systems: + fuel_breakdown[generation_system.fuel_type][cte.DOMESTIC_HOT_WATER] = self.domestic_hot_water_consumption[cte.YEAR][0] self._fuel_consumption_breakdown = fuel_breakdown return self._fuel_consumption_breakdown diff --git a/hub/city_model_structure/energy_systems/thermal_storage_system.py b/hub/city_model_structure/energy_systems/thermal_storage_system.py index 01a910f7..fd9b8f81 100644 --- a/hub/city_model_structure/energy_systems/thermal_storage_system.py +++ b/hub/city_model_structure/energy_systems/thermal_storage_system.py @@ -24,6 +24,7 @@ class ThermalStorageSystem(EnergyStorageSystem): self._maximum_operating_temperature = None self._heating_coil_capacity = None self._temperature = None + self._heating_coil_energy_consumption = None @property def volume(self): @@ -95,7 +96,7 @@ class ThermalStorageSystem(EnergyStorageSystem): Get heating coil capacity in Watts :return: float """ - return self._maximum_operating_temperature + return self._heating_coil_capacity @heating_coil_capacity.setter def heating_coil_capacity(self, value): @@ -120,3 +121,19 @@ class ThermalStorageSystem(EnergyStorageSystem): :param value: dict{[float]} """ self._temperature = value + + @property + def heating_coil_energy_consumption(self) -> dict: + """ + Get fuel consumption in W, m3, or kg + :return: dict{[float]} + """ + return self._heating_coil_energy_consumption + + @heating_coil_energy_consumption.setter + def heating_coil_energy_consumption(self, value): + """ + Set fuel consumption in W, m3, or kg + :param value: dict{[float]} + """ + self._heating_coil_energy_consumption = value diff --git a/hub/data/energy_systems/montreal_future_systems.xml b/hub/data/energy_systems/montreal_future_systems.xml index b42993d4..455235ae 100644 --- a/hub/data/energy_systems/montreal_future_systems.xml +++ b/hub/data/energy_systems/montreal_future_systems.xml @@ -911,7 +911,7 @@ - + 4.5 @@ -931,7 +931,13 @@ - + + bi-quadratic + COP + source_temperature + supply_temperature + + True @@ -1049,7 +1055,7 @@ 3.5 electricity - Water + Air Water @@ -1065,7 +1071,13 @@ - + + bi-quadratic + COP + source_temperature + supply_temperature + + @@ -1259,7 +1271,7 @@ sensible - + 5000 diff --git a/hub/imports/energy_systems/montreal_future_energy_systems_parameters.py b/hub/imports/energy_systems/montreal_future_energy_systems_parameters.py index 27c2f1cd..1bcde834 100644 --- a/hub/imports/energy_systems/montreal_future_energy_systems_parameters.py +++ b/hub/imports/energy_systems/montreal_future_energy_systems_parameters.py @@ -160,6 +160,7 @@ class MontrealFutureEnergySystemParameters: _generic_storage_system.height = storage_system.height _generic_storage_system.layers = storage_system.layers _generic_storage_system.storage_medium = storage_system.storage_medium + _generic_storage_system.heating_coil_capacity = storage_system.heating_coil_capacity _storage_systems.append(_generic_storage_system) _generation_system.energy_storage_systems = _storage_systems if archetype_generation_system.domestic_hot_water: diff --git a/main.py b/main.py index 6fb66a5e..e69de29b 100644 --- a/main.py +++ b/main.py @@ -1,6 +0,0 @@ - - - - - - diff --git a/scripts/random_assignation.py b/scripts/random_assignation.py index 38831b66..958f269d 100644 --- a/scripts/random_assignation.py +++ b/scripts/random_assignation.py @@ -28,8 +28,8 @@ residential_systems_percentage = {'system 1 gas': 44, 'system 8 gas': 44, 'system 8 electricity': 6} -residential_new_systems_percentage = {'PV+ASHP+GasBoiler+TES': 100, - 'PV+4Pipe+DHW': 0, +residential_new_systems_percentage = {'PV+ASHP+GasBoiler+TES': 0, + 'PV+4Pipe+DHW': 100, 'PV+ASHP+ElectricBoiler+TES': 0, 'PV+GSHP+GasBoiler+TES': 0, 'PV+GSHP+ElectricBoiler+TES': 0, diff --git a/scripts/system_simulation_models/archetype1.py b/scripts/system_simulation_models/archetype1.py index 19af7eed..6e8bc4f1 100644 --- a/scripts/system_simulation_models/archetype1.py +++ b/scripts/system_simulation_models/archetype1.py @@ -128,7 +128,7 @@ class Archetype1: hp = self.hvac_sizing()[0] eer_curve_coefficients = [float(coefficient) for coefficient in hp.cooling_efficiency_curve.coefficients] cooling_efficiency = float(hp.cooling_efficiency) - demand = self._hourly_heating_demand + demand = self._hourly_cooling_demand hp.source_temperature = self._t_out variable_names = ["t_sup_hp", "t_ret", "m", "q_hp", "hp_electricity", "hp_eer"] num_hours = len(demand) diff --git a/scripts/system_simulation_models/archetype13.py b/scripts/system_simulation_models/archetype13.py index 03057cdc..13904273 100644 --- a/scripts/system_simulation_models/archetype13.py +++ b/scripts/system_simulation_models/archetype13.py @@ -1,49 +1,67 @@ import math - import hub.helpers.constants as cte - - +import csv +from hub.helpers.monthly_values import MonthlyValues class Archetype13: def __init__(self, building, output_path): + self._building = building + self._name = building.name self._pv_system = building.energy_systems[0] self._hvac_system = building.energy_systems[1] self._dhw_system = building.energy_systems[-1] + self._dhw_peak_flow_rate = (building.thermal_zones_from_internal_zones[0].total_floor_area * + building.thermal_zones_from_internal_zones[0].domestic_hot_water.peak_flow * + cte.WATER_DENSITY) self._heating_peak_load = building.heating_peak_load[cte.YEAR][0] self._cooling_peak_load = building.cooling_peak_load[cte.YEAR][0] self._domestic_hot_water_peak_load = building.domestic_hot_water_peak_load[cte.YEAR][0] self._hourly_heating_demand = [0] + [demand / 3600 for demand in building.heating_demand[cte.HOUR]] self._hourly_cooling_demand = [demand / 3600 for demand in building.cooling_demand[cte.HOUR]] - self._hourly_dhw_demand = building.domestic_hot_water_heat_demand[cte.HOUR] + self._hourly_dhw_demand = [0] + building.domestic_hot_water_heat_demand[cte.HOUR] self._output_path = output_path - self._t_out = building.external_temperature + self._t_out = [0] + building.external_temperature[cte.HOUR] + self.results = {} def hvac_sizing(self): storage_factor = 3 - heat_pump = self._hvac_system.generation_systems[0] - boiler = self._hvac_system.generation_systems[1] - thermal_storage = heat_pump.energy_storage_systems[0] + heat_pump = self._hvac_system.generation_systems[1] + boiler = self._hvac_system.generation_systems[0] + thermal_storage = boiler.energy_storage_systems[0] heat_pump.nominal_heat_output = round(0.5 * self._heating_peak_load / 3600) heat_pump.nominal_cooling_output = round(self._cooling_peak_load / 3600) boiler.nominal_heat_output = round(0.5 * self._heating_peak_load / 3600) thermal_storage.volume = round( - (self._heating_peak_load * storage_factor) / (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 30)) + (self._heating_peak_load * storage_factor) / (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 25)) return heat_pump, boiler, thermal_storage - def hvac_simulation(self): + def dhw_sizing(self): + storage_factor = 3 + dhw_hp = self._dhw_system.generation_systems[0] + dhw_hp.nominal_heat_output = 0.7 * self._domestic_hot_water_peak_load + dhw_hp.source_temperature = self._t_out + dhw_tes = dhw_hp.energy_storage_systems[0] + dhw_tes.volume = round( + (self._domestic_hot_water_peak_load * storage_factor * 3600) / (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 10)) + return dhw_hp, dhw_tes + + def heating_system_simulation(self): hp, boiler, tes = self.hvac_sizing() - if hp.source_medium == cte.AIR: - hp.source_temperature = self._t_out[cte.HOUR] - # Heating System Simulation - variable_names = ["t_sup", "t_tank", "t_ret", "m_ch", "m_dis", "q_hp", "q_boiler", "hp_cop", - "hp_electricity", "boiler_gas", "boiler_consumption", "heating_consumption"] - num_hours = len(self._hourly_heating_demand) + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + demand = self._hourly_heating_demand + hp.source_temperature = self._t_out + variable_names = ["t_sup_hp", "t_tank", "t_ret", "m_ch", "m_dis", "q_hp", "q_boiler", "hp_cop", + "hp_electricity", "boiler_gas_consumption", "t_sup_boiler", "boiler_energy_consumption", + "heating_consumption"] + num_hours = len(demand) variables = {name: [0] * num_hours for name in variable_names} - (t_sup, t_tank, t_ret, m_ch, m_dis, q_hp, q_boiler, hp_cop, - hp_electricity, boiler_gas, boiler_consumption, heating_consumption) = [variables[name] for name in variable_names] - t_tank[0] = 30 + (t_sup_hp, t_tank, t_ret, m_ch, m_dis, q_hp, q_boiler, hp_cop, + hp_electricity, boiler_gas_consumption, t_sup_boiler, boiler_energy_consumption, heating_consumption) = \ + [variables[name] for name in variable_names] + t_tank[0] = 55 dt = 3600 hp_heating_cap = hp.nominal_heat_output - hp_efficiency = float(hp.heat_efficiency) + boiler_heating_cap = boiler.nominal_heat_output + hp_delta_t = 5 boiler_efficiency = float(boiler.heat_efficiency) v, h = float(tes.volume), float(tes.height) r_tot = sum(float(layer.thickness) / float(layer.material.conductivity) for layer in @@ -53,48 +71,269 @@ class Archetype13: a_side = math.pi * d * h a_top = math.pi * d ** 2 / 4 ua = u_tot * (2 * a_top + a_side) - for i in range(len(self._hourly_heating_demand) - 1): + # storage temperature prediction + for i in range(len(demand) - 1): t_tank[i + 1] = (t_tank[i] + - ((m_ch[i] * (t_sup[i] - t_tank[i])) + - (ua * (self._t_out[i] - t_tank[i] + 5)) / cte.WATER_HEAT_CAPACITY - + (m_ch[i] * (t_sup_boiler[i] - t_tank[i]) + + (ua * (self._t_out[i] - t_tank[i])) / cte.WATER_HEAT_CAPACITY - m_dis[i] * (t_tank[i] - t_ret[i])) * (dt / (cte.WATER_DENSITY * v))) + # hp operation if t_tank[i + 1] < 40: q_hp[i + 1] = hp_heating_cap - m_ch[i + 1] = q_hp[i + 1] / (cte.WATER_HEAT_CAPACITY * 7) - t_sup[i + 1] = (q_hp[i + 1] / (m_ch[i + 1] * cte.WATER_HEAT_CAPACITY)) + t_tank[i + 1] - elif 45 <= t_tank[i + 1] < 55 and q_hp[i] == 0: + m_ch[i + 1] = q_hp[i + 1] / (cte.WATER_HEAT_CAPACITY * hp_delta_t) + t_sup_hp[i + 1] = (q_hp[i + 1] / (m_ch[i + 1] * cte.WATER_HEAT_CAPACITY)) + t_tank[i + 1] + elif 40 <= t_tank[i + 1] < 55 and q_hp[i] == 0: q_hp[i + 1] = 0 m_ch[i + 1] = 0 - t_sup[i + 1] = t_tank[i + 1] - elif 45 <= t_tank[i + 1] < 55 and q_hp[i] > 0: + t_sup_hp[i + 1] = t_tank[i + 1] + elif 40 <= t_tank[i + 1] < 55 and q_hp[i] > 0: q_hp[i + 1] = hp_heating_cap - m_ch[i + 1] = q_hp[i + 1] / (cte.WATER_HEAT_CAPACITY * 3) - t_sup[i + 1] = (q_hp[i + 1] / (m_ch[i + 1] * cte.WATER_HEAT_CAPACITY)) + t_tank[i + 1] + m_ch[i + 1] = q_hp[i + 1] / (cte.WATER_HEAT_CAPACITY * hp_delta_t) + t_sup_hp[i + 1] = (q_hp[i + 1] / (m_ch[i + 1] * cte.WATER_HEAT_CAPACITY)) + t_tank[i + 1] else: - q_hp[i + 1], m_ch[i + 1], t_sup[i + 1] = 0, 0, t_tank[i + 1] - - hp_electricity[i + 1] = q_hp[i + 1] / hp_efficiency - if self._hourly_heating_demand[i + 1] == 0: - m_dis[i + 1], t_return, t_ret[i + 1] = 0, t_tank[i + 1], t_tank[i + 1] + q_hp[i + 1], m_ch[i + 1], t_sup_hp[i + 1] = 0, 0, t_tank[i + 1] + t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i + 1] + 32 + t_out_fahrenheit = 1.8 * self._t_out[i + 1] + 32 + if q_hp[i + 1] > 0: + hp_cop[i + 1] = (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_sup_hp_fahrenheit + + cop_curve_coefficients[2] * t_sup_hp_fahrenheit ** 2 + + cop_curve_coefficients[3] * t_out_fahrenheit + + cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + + cop_curve_coefficients[5] * t_sup_hp_fahrenheit * t_out_fahrenheit) + hp_electricity[i + 1] = q_hp[i + 1] / hp_cop[i + 1] else: - if self._hourly_heating_demand[i + 1] > 0.5 * self._heating_peak_load: + hp_cop[i + 1] = 0 + hp_electricity[i + 1] = 0 + # boiler operation + if q_hp[i + 1] > 0: + if t_sup_hp[i + 1] < 45: + q_boiler[i + 1] = boiler_heating_cap + elif demand[i + 1] > 0.5 * self._heating_peak_load / dt: + q_boiler[i + 1] = 0.5 * boiler_heating_cap + boiler_energy_consumption[i + 1] = q_boiler[i + 1] / boiler_efficiency + boiler_gas_consumption[i + 1] = (q_boiler[i + 1] * dt) / (boiler_efficiency * cte.NATURAL_GAS_LHV) + t_sup_boiler[i + 1] = t_sup_hp[i + 1] + (q_boiler[i + 1] / (m_ch[i + 1] * cte.WATER_HEAT_CAPACITY)) + # storage discharging + if demand[i + 1] == 0: + m_dis[i + 1] = 0 + t_ret[i + 1] = t_tank[i + 1] + else: + if demand[i + 1] > 0.5 * self._heating_peak_load / dt: factor = 8 else: factor = 4 - m_dis[i + 1] = self._heating_peak_load / (cte.WATER_HEAT_CAPACITY * factor * 3600) - t_return = t_tank[i + 1] - self._hourly_heating_demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY) - if m_dis[i + 1] == 0 or (m_dis[i + 1] > 0 and t_return < 25): - t_ret[i + 1] = max(25, t_tank[i + 1]) + m_dis[i + 1] = self._heating_peak_load / (cte.WATER_HEAT_CAPACITY * factor * dt) + t_ret[i + 1] = t_tank[i + 1] - demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY) + + hp.energy_consumption[cte.HEATING] = {} + hp.energy_consumption[cte.HEATING][cte.HOUR] = hp_electricity + hp.energy_consumption[cte.HEATING][cte.MONTH] = MonthlyValues.get_total_month( + hp.energy_consumption[cte.HEATING][cte.HOUR]) + hp.energy_consumption[cte.HEATING][cte.YEAR] = [ + sum(hp.energy_consumption[cte.HEATING][cte.MONTH])] + boiler.energy_consumption[cte.HEATING] = {} + boiler.energy_consumption[cte.HEATING][cte.HOUR] = boiler_energy_consumption + boiler.energy_consumption[cte.HEATING][cte.MONTH] = MonthlyValues.get_total_month( + boiler.energy_consumption[cte.HEATING][cte.HOUR]) + boiler.energy_consumption[cte.HEATING][cte.YEAR] = [ + sum(boiler.energy_consumption[cte.HEATING][cte.MONTH])] + tes.temperature = t_tank + self.results['Heating Demand (W)'] = demand + self.results['HP Heat Output (W)'] = q_hp + self.results['HP Source Temperature'] = self._t_out + self.results['HP Supply Temperature'] = t_sup_hp + self.results['HP COP'] = hp_cop + self.results['HP Electricity Consumption (W)'] = hp_electricity + self.results['Boiler Heat Output (W)'] = q_boiler + self.results['Boiler Supply Temperature'] = t_sup_boiler + self.results['Boiler Gas Consumption'] = boiler_gas_consumption + self.results['TES Temperature'] = t_tank + self.results['TES Charging Flow Rate (kg/s)'] = m_ch + self.results['TES Discharge Flow Rate (kg/s)'] = m_dis + self.results['Heating Loop Return Temperature'] = t_ret + return hp_electricity, boiler_energy_consumption + + def cooling_system_simulation(self): + hp = self.hvac_sizing()[0] + eer_curve_coefficients = [float(coefficient) for coefficient in hp.cooling_efficiency_curve.coefficients] + cooling_efficiency = float(hp.cooling_efficiency) + demand = self._hourly_cooling_demand + hp.source_temperature = self._t_out + variable_names = ["t_sup_hp", "t_ret", "m", "q_hp", "hp_electricity", "hp_eer"] + num_hours = len(demand) + variables = {name: [0] * num_hours for name in variable_names} + (t_sup_hp, t_ret, m, q_hp, hp_electricity, hp_eer) = [variables[name] for name in variable_names] + t_ret[0] = 13 + dt = 3600 + for i in range(len(demand) - 1): + if demand[i] > 0: + m[i] = self._cooling_peak_load / (cte.WATER_HEAT_CAPACITY * 5 * dt) + if t_ret[i] > 13: + if demand[i] < 0.25 * self._cooling_peak_load / dt: + q_hp[i] = 0.25 * hp.nominal_cooling_output + elif demand[i] < 0.5 * self._cooling_peak_load / dt: + q_hp[i] = 0.5 * hp.nominal_cooling_output + else: + q_hp[i] = hp.nominal_cooling_output + t_sup_hp[i] = t_ret[i] - q_hp[i] / (m[i] * cte.WATER_HEAT_CAPACITY) else: - t_ret[i + 1] = t_tank[i + 1] - self._hourly_heating_demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY * 3600) - tes_output = m_dis[i + 1] * cte.WATER_HEAT_CAPACITY * (t_tank[i + 1] - t_ret[i + 1]) - if tes_output < (self._hourly_heating_demand[i + 1] / 3600): - q_boiler[i + 1] = (self._hourly_heating_demand[i + 1] / 3600) - tes_output - boiler_gas[i + 1] = (q_boiler[i + 1] * dt) / 50e6 - boiler_consumption[i + 1] = q_boiler[i + 1] / boiler_efficiency - heating_consumption[i + 1] = boiler_consumption[i + 1] + hp_electricity[i + 1] - data = list(zip(t_tank, t_sup, t_ret, m_ch, m_dis, q_hp, hp_electricity, boiler_gas, q_boiler, - self._hourly_heating_demand)) + q_hp[i] = 0 + t_sup_hp[i] = t_ret[i] + t_ret[i + 1] = t_sup_hp[i] + demand[i] / (m[i] * cte.WATER_HEAT_CAPACITY) + else: + m[i] = 0 + q_hp[i] = 0 + t_sup_hp[i] = t_ret[i] + t_ret[i + 1] = t_ret[i] + t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 + t_out_fahrenheit = 1.8 * self._t_out[i] + 32 + if q_hp[i] > 0: + hp_eer[i] = (eer_curve_coefficients[0] + + eer_curve_coefficients[1] * t_sup_hp_fahrenheit + + eer_curve_coefficients[2] * t_sup_hp_fahrenheit ** 2 + + eer_curve_coefficients[3] * t_out_fahrenheit + + eer_curve_coefficients[4] * t_out_fahrenheit ** 2 + + eer_curve_coefficients[5] * t_sup_hp_fahrenheit * t_out_fahrenheit) + hp_electricity[i] = q_hp[i] / cooling_efficiency + else: + hp_eer[i] = 0 + hp_electricity[i] = 0 + hp.energy_consumption[cte.COOLING] = {} + hp.energy_consumption[cte.COOLING][cte.HOUR] = hp_electricity + hp.energy_consumption[cte.COOLING][cte.MONTH] = MonthlyValues.get_total_month( + hp.energy_consumption[cte.COOLING][cte.HOUR]) + hp.energy_consumption[cte.COOLING][cte.YEAR] = [ + sum(hp.energy_consumption[cte.COOLING][cte.MONTH])] + self.results['Cooling Demand (W)'] = demand + self.results['HP Cooling Output (W)'] = q_hp + self.results['HP Cooling Supply Temperature'] = t_sup_hp + self.results['HP Cooling COP'] = hp_eer + self.results['HP Electricity Consumption'] = hp_electricity + self.results['Cooling Loop Flow Rate (kg/s)'] = m + self.results['Cooling Loop Return Temperature'] = t_ret + return hp_electricity + + def dhw_system_simulation(self): + hp, tes = self.dhw_sizing() + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + demand = self._hourly_dhw_demand + variable_names = ["t_sup_hp", "t_tank", "m_ch", "m_dis", "q_hp", "q_coil", "hp_cop", + "hp_electricity", "available hot water (m3)", "refill flow rate (kg/s)"] + num_hours = len(demand) + variables = {name: [0] * num_hours for name in variable_names} + (t_sup_hp, t_tank, m_ch, m_dis, m_refill, q_hp, q_coil, hp_cop, hp_electricity, v_dhw) = \ + [variables[name] for name in variable_names] + t_tank[0] = 70 + v_dhw[0] = tes.volume + dt = 3600 + hp_heating_cap = hp.nominal_heat_output + hp_delta_t = 8 + v, h = float(tes.volume), float(tes.height) + r_tot = sum(float(layer.thickness) / float(layer.material.conductivity) for layer in + tes.layers) + u_tot = 1 / r_tot + d = math.sqrt((4 * v) / (math.pi * h)) + a_side = math.pi * d * h + a_top = math.pi * d ** 2 / 4 + ua = u_tot * (2 * a_top + a_side) + freshwater_temperature = 18 + for i in range(len(demand) - 1): + delta_t_demand = demand[i] * (dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v)) + if t_tank[i] < 65: + q_hp[i] = hp_heating_cap + delta_t_hp = q_hp[i] * (dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v)) + if demand[i] > 0: + dhw_needed = (demand[i] * cte.HOUR_TO_SECONDS) / (cte.WATER_HEAT_CAPACITY * t_tank[i] * cte.WATER_DENSITY) + m_dis[i] = dhw_needed * cte.WATER_DENSITY / cte.HOUR_TO_SECONDS + m_refill[i] = m_dis[i] + delta_t_freshwater = m_refill[i] * (t_tank[i] - freshwater_temperature) * (dt / (v * cte.WATER_DENSITY)) + diff = delta_t_freshwater + delta_t_demand - delta_t_hp + if diff > 0: + if diff > 0: + power = diff * (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v) / dt + if power <= float(tes.heating_coil_capacity): + q_coil[i] = power + else: + q_coil[i] = float(tes.heating_coil_capacity) + elif t_tank[i] < 65: + q_coil[i] = float(tes.heating_coil_capacity) + delta_t_coil = q_coil[i] * (dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v)) + + if q_hp[i] > 0: + m_ch[i] = q_hp[i] / (cte.WATER_HEAT_CAPACITY * hp_delta_t) + t_sup_hp[i] = (q_hp[i] / (m_ch[i] * cte.WATER_HEAT_CAPACITY)) + t_tank[i] + else: + m_ch[i] = 0 + t_sup_hp[i] = t_tank[i] + t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 + t_out_fahrenheit = 1.8 * self._t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_sup_hp_fahrenheit + + cop_curve_coefficients[2] * t_sup_hp_fahrenheit ** 2 + + cop_curve_coefficients[3] * t_out_fahrenheit + + cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + + cop_curve_coefficients[5] * t_sup_hp_fahrenheit * t_out_fahrenheit) + hp_electricity[i] = q_hp[i] / 3.5 + else: + hp_cop[i] = 0 + hp_electricity[i] = 0 + + t_tank[i + 1] = t_tank[i] + (delta_t_hp - delta_t_freshwater - delta_t_demand + delta_t_coil) + + hp.energy_consumption[cte.DOMESTIC_HOT_WATER] = {} + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR] = hp_electricity + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.MONTH] = MonthlyValues.get_total_month( + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR]) + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.YEAR] = [ + sum(hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.MONTH])] + tes.heating_coil_energy_consumption = {} + tes.heating_coil_energy_consumption[cte.HOUR] = q_coil + tes.heating_coil_energy_consumption[cte.MONTH] = MonthlyValues.get_total_month( + tes.heating_coil_energy_consumption[cte.HOUR]) + tes.heating_coil_energy_consumption[cte.YEAR] = [ + sum(tes.heating_coil_energy_consumption[cte.MONTH])] + tes.temperature = t_tank + + + self.results['DHW Demand (W)'] = demand + self.results['DHW HP Heat Output (W)'] = q_hp + self.results['DHW HP Electricity Consumption (W)'] = hp_electricity + self.results['DHW HP Source Temperature'] = self._t_out + self.results['DHW HP Supply Temperature'] = t_sup_hp + self.results['DHW HP COP'] = hp_cop + self.results['DHW TES Heating Coil Heat Output (W)'] = q_coil + self.results['DHW TES Temperature'] = t_tank + self.results['DHW TES Charging Flow Rate (kg/s)'] = m_ch + self.results['DHW Flow Rate (kg/s)'] = m_dis + self.results['DHW TES Refill Flow Rate (kg/s)'] = m_refill + self.results['Available Water in Tank (m3)'] = v_dhw + return hp_electricity, q_coil def enrich_buildings(self): - self.hvac_sizing() + hp_heating, boiler_consumption = self.heating_system_simulation() + hp_cooling = self.cooling_system_simulation() + hp_dhw, heating_coil = self.dhw_system_simulation() + heating_consumption = [hp_heating[i] + boiler_consumption[i] for i in range(len(hp_heating))] + dhw_consumption = [hp_dhw[i] + heating_coil[i] for i in range(len(hp_dhw))] + self._building.heating_consumption[cte.HOUR] = heating_consumption + self._building.heating_consumption[cte.MONTH] = ( + MonthlyValues.get_total_month(self._building.heating_consumption[cte.HOUR])) + self._building.heating_consumption[cte.YEAR] = sum(self._building.heating_consumption[cte.MONTH]) + self._building.cooling_consumption[cte.HOUR] = hp_cooling + self._building.cooling_consumption[cte.MONTH] = ( + MonthlyValues.get_total_month(self._building.cooling_consumption[cte.HOUR])) + self._building.cooling_consumption[cte.YEAR] = sum(self._building.cooling_consumption[cte.MONTH]) + self._building.domestic_hot_water_consumption[cte.HOUR] = dhw_consumption + self._building.domestic_hot_water_consumption[cte.MONTH] = ( + MonthlyValues.get_total_month(self._building.domestic_hot_water_consumption[cte.HOUR])) + self._building.domestic_hot_water_consumption[cte.YEAR] = ( + sum(self._building.domestic_hot_water_consumption[cte.MONTH])) + file_name = f'energy_system_simulation_results_{self._name}.csv' + with open(self._output_path / file_name, 'w', newline='') as csvfile: + output_file = csv.writer(csvfile) + # Write header + output_file.writerow(self.results.keys()) + # Write data + output_file.writerows(zip(*self.results.values()))