From aee505aab629c0ad785b53599bd070f4c3315e9a Mon Sep 17 00:00:00 2001 From: s_ranjbar Date: Thu, 1 Aug 2024 11:59:21 -0400 Subject: [PATCH] added system simulation --- .../montreal_future_systems.xml | 4 +- ...gy_system_sizing_and_simulation_factory.py | 54 +++ scripts/ep_workflow.py | 17 +- .../system_simulation_models/archetype1.py | 377 ++++++++++++++++ .../system_simulation_models/archetype13.py | 383 ++++++++++++++++ .../archetype13_stratified_tes.py | 416 ++++++++++++++++++ .../archetypes14_15.py | 398 +++++++++++++++++ simulation_test.py | 44 ++ 8 files changed, 1689 insertions(+), 4 deletions(-) create mode 100644 scripts/energy_system_sizing_and_simulation_factory.py create mode 100644 scripts/system_simulation_models/archetype1.py create mode 100644 scripts/system_simulation_models/archetype13.py create mode 100644 scripts/system_simulation_models/archetype13_stratified_tes.py create mode 100644 scripts/system_simulation_models/archetypes14_15.py create mode 100644 simulation_test.py diff --git a/hub/data/energy_systems/montreal_future_systems.xml b/hub/data/energy_systems/montreal_future_systems.xml index b51c9488..64f26baa 100644 --- a/hub/data/energy_systems/montreal_future_systems.xml +++ b/hub/data/energy_systems/montreal_future_systems.xml @@ -714,7 +714,7 @@ COP source_temperature supply_temperature - + @@ -1001,7 +1001,7 @@ - + 5 diff --git a/scripts/energy_system_sizing_and_simulation_factory.py b/scripts/energy_system_sizing_and_simulation_factory.py new file mode 100644 index 00000000..9a0e14bb --- /dev/null +++ b/scripts/energy_system_sizing_and_simulation_factory.py @@ -0,0 +1,54 @@ +""" +EnergySystemSizingSimulationFactory retrieve the energy system archetype sizing and simulation module +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Saeed Ranjbar saeed.ranjbar@mail.concordia.ca +""" + +from scripts.system_simulation_models.archetype13 import Archetype13 +from scripts.system_simulation_models.archetype13_stratified_tes import Archetype13Stratified +from scripts.system_simulation_models.archetype1 import Archetype1 +from scripts.system_simulation_models.archetypes14_15 import Archetype14_15 + + +class EnergySystemsSimulationFactory: + """ + EnergySystemsFactory class + """ + + def __init__(self, handler, building, output_path): + self._output_path = output_path + self._handler = '_' + handler.lower() + self._building = building + + def _archetype1(self): + """ + Enrich the city by using the sizing and simulation model developed for archetype13 of montreal_future_systems + """ + Archetype1(self._building, self._output_path).enrich_buildings() + self._building.level_of_detail.energy_systems = 2 + self._building.level_of_detail.energy_systems = 2 + + def _archetype13(self): + """ + Enrich the city by using the sizing and simulation model developed for archetype13 of montreal_future_systems + """ + Archetype13(self._building, self._output_path).enrich_buildings() + self._building.level_of_detail.energy_systems = 2 + self._building.level_of_detail.energy_systems = 2 + + def _archetype14_15(self): + """ + Enrich the city by using the sizing and simulation model developed for archetype14 and archetype15 of + montreal_future_systems + """ + Archetype14_15(self._building, self._output_path).enrich_buildings() + self._building.level_of_detail.energy_systems = 2 + self._building.level_of_detail.energy_systems = 2 + + def enrich(self): + """ + Enrich the city given to the class using the class given handler + :return: None + """ + getattr(self, self._handler, lambda: None)() diff --git a/scripts/ep_workflow.py b/scripts/ep_workflow.py index 0373bd33..68c24c8c 100644 --- a/scripts/ep_workflow.py +++ b/scripts/ep_workflow.py @@ -1,17 +1,27 @@ import glob +import os import sys from pathlib import Path +import csv from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory from hub.imports.results_factory import ResultFactory sys.path.append('./') -def energy_plus_workflow(city): +def energy_plus_workflow(city, output_path): try: - out_path = (Path(__file__).parent.parent / 'out_files') + # city = city + out_path = output_path + files = glob.glob(f'{out_path}/*') + + # for file in files: + # if file != '.gitignore': + # os.remove(file) area = 0 + volume = 0 for building in city.buildings: + volume = building.volume for ground in building.grounds: area += ground.perimeter_polygon.area @@ -19,12 +29,15 @@ def energy_plus_workflow(city): _idf = EnergyBuildingsExportsFactory('idf', city, out_path).export() print(' idf exported...') _idf.run() + csv_file = str((out_path / f'{city.name}_out.csv').resolve()) eso_file = str((out_path / f'{city.name}_out.eso').resolve()) idf_file = str((out_path / f'{city.name}.idf').resolve()) obj_file = str((out_path / f'{city.name}.obj').resolve()) ResultFactory('energy_plus_multiple_buildings', city, out_path).enrich() + + except Exception as ex: print(ex) print('error: ', ex) diff --git a/scripts/system_simulation_models/archetype1.py b/scripts/system_simulation_models/archetype1.py new file mode 100644 index 00000000..bd17efd4 --- /dev/null +++ b/scripts/system_simulation_models/archetype1.py @@ -0,0 +1,377 @@ +import math +import csv +import hub.helpers.constants as cte +from hub.helpers.monthly_values import MonthlyValues + + +class Archetype1: + def __init__(self, building, output_path): + self._building = building + self._name = building.name + self._pv_system = building.energy_systems[1] + self._hvac_system = building.energy_systems[0] + self._dhw_system = building.energy_systems[-1] + 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._output_path = output_path + self._t_out = [0] + building.external_temperature[cte.HOUR] + self.results = {} + self.dt = 900 + + 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.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.WATTS_HOUR_TO_JULES) / + (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 25)) + return heat_pump, boiler, thermal_storage + + 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() + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_heating_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + hp.source_temperature = self._t_out + # Heating System Simulation + variable_names = ["t_sup_hp", "t_tank", "t_ret", "m_ch", "m_dis", "q_hp", "q_boiler", "hp_cop", + "hp_electricity", "boiler_gas", "boiler_consumption", "t_sup_boiler", "heating_consumption"] + num_hours = len(demand) + variables = {name: [0] * num_hours for name in variable_names} + (t_sup_hp, t_tank, t_ret, m_ch, m_dis, q_hp, q_boiler, hp_cop, + hp_electricity, boiler_gas, boiler_consumption, t_sup_boiler, 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_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 + 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) + for i in range(len(demand) - 1): + t_tank[i + 1] = (t_tank[i] + + ((m_ch[i] * (t_sup_hp[i] - t_tank[i])) + + (ua * (t_out[i] - t_tank[i])) / cte.WATER_HEAT_CAPACITY - + m_dis[i] * (t_tank[i] - t_ret[i])) * (dt / (cte.WATER_DENSITY * v))) + 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 * 5) + 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_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_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_hp[i + 1] = 0, 0, t_tank[i + 1] + t_tank_fahrenheit = 1.8 * t_tank[i + 1] + 32 + t_out_fahrenheit = 1.8 * t_out[i + 1] + 32 + if q_hp[i + 1] > 0: + hp_cop[i + 1] = (1 / (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_tank_fahrenheit + + cop_curve_coefficients[2] * t_tank_fahrenheit ** 2 + + cop_curve_coefficients[3] * t_out_fahrenheit + + cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + + cop_curve_coefficients[5] * t_tank_fahrenheit * t_out_fahrenheit)) * hp_efficiency + hp_electricity[i + 1] = q_hp[i + 1] / hp_cop[i + 1] + else: + hp_cop[i + 1] = 0 + hp_electricity[i + 1] = 0 + if demand[i + 1] == 0: + m_dis[i + 1], t_return, t_ret[i + 1] = 0, t_tank[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 * dt) + t_return = t_tank[i + 1] - demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY) + if t_return >= 25: + t_ret[i + 1] = t_tank[i + 1] - demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY) + q_boiler[i + 1] = 0 + t_sup_boiler[i + 1] = t_tank[i + 1] + else: + t_ret[i + 1] = 25 + t_sup_boiler[i + 1] = t_ret[i + 1] + (demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY)) + q_boiler[i + 1] = m_dis[i + 1] * cte.WATER_HEAT_CAPACITY * (t_sup_boiler[i + 1] - t_tank[i + 1]) + boiler_gas[i + 1] = (q_boiler[i + 1] * dt) / cte.NATURAL_GAS_LHV + boiler_consumption[i + 1] = q_boiler[i + 1] / boiler_efficiency + heating_consumption[i + 1] = boiler_consumption[i + 1] + hp_electricity[i + 1] + tes.temperature = [] + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + boiler_consumption_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in boiler_consumption] + hp_hourly = [] + boiler_hourly = [] + boiler_sum = 0 + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + boiler_sum += boiler_consumption_j[i] + if (i - 1) % number_of_ts == 0: + tes.temperature.append(t_tank[i]) + hp_hourly.append(hp_sum) + boiler_hourly.append(boiler_sum) + hp_sum = 0 + boiler_sum = 0 + hp.energy_consumption[cte.HEATING] = {} + hp.energy_consumption[cte.HEATING][cte.HOUR] = hp_hourly + 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_hourly + 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])] + self.results['Heating Demand (W)'] = demand + self.results['HP Heat Output (W)'] = q_hp + self.results['HP Source Temperature'] = 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_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_hourly, boiler_hourly + + 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) + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_cooling_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + hp.source_temperature = self._t_out + variable_names = ["t_sup_hp", "t_ret", "m", "q_hp", "hp_electricity", "hp_cop"] + 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_cop) = [variables[name] for name in variable_names] + t_ret[0] = 13 + + for i in range(1, len(demand)): + if demand[i] > 0.15 * self._cooling_peak_load: + m[i] = hp.nominal_cooling_output / (cte.WATER_HEAT_CAPACITY * 5) + if t_ret[i - 1] >= 13: + if demand[i] < 0.25 * self._cooling_peak_load: + q_hp[i] = 0.25 * hp.nominal_cooling_output + elif demand[i] < 0.5 * self._cooling_peak_load: + q_hp[i] = 0.5 * hp.nominal_cooling_output + else: + q_hp[i] = hp.nominal_cooling_output + t_sup_hp[i] = t_ret[i - 1] - q_hp[i] / (m[i] * cte.WATER_HEAT_CAPACITY) + else: + q_hp[i] = 0 + t_sup_hp[i] = t_ret[i - 1] + if m[i] == 0: + t_ret[i] = t_sup_hp[i] + else: + t_ret[i] = 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 - 1] + t_ret[i] = t_ret[i - 1] + t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 + t_out_fahrenheit = 1.8 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (1 / (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)) * cooling_efficiency / 3.41 + hp_electricity[i] = q_hp[i] / cooling_efficiency + else: + hp_cop[i] = 0 + hp_electricity[i] = 0 + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + hp_hourly = [] + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + if (i - 1) % number_of_ts == 0: + hp_hourly.append(hp_sum) + hp_sum = 0 + hp.energy_consumption[cte.COOLING] = {} + hp.energy_consumption[cte.COOLING][cte.HOUR] = hp_hourly + 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_cop + 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_hourly + + def dhw_system_simulation(self): + hp, tes = self.dhw_sizing() + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_dhw_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + 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 + + 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] * (self.dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v)) + if t_tank[i] < 62: + q_hp[i] = hp_heating_cap + delta_t_hp = q_hp[i] * (self.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) * (self.dt / (v * cte.WATER_DENSITY)) + if t_tank[i] < 60: + q_coil[i] = float(tes.heating_coil_capacity) + delta_t_coil = q_coil[i] * (self.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 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_out[i] + + cop_curve_coefficients[2] * t_out[i] ** 2 + + cop_curve_coefficients[3] * t_tank[i] + + cop_curve_coefficients[4] * t_tank[i] ** 2 + + cop_curve_coefficients[5] * t_tank[i] * t_out[i]) * float(hp.heat_efficiency) + hp_electricity[i] = q_hp[i] / hp_cop[i] + 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) + tes.temperature = [] + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + heating_coil_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in q_coil] + hp_hourly = [] + coil_hourly = [] + coil_sum = 0 + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + coil_sum += heating_coil_j[i] + if (i - 1) % number_of_ts == 0: + tes.temperature.append(t_tank[i]) + hp_hourly.append(hp_sum) + coil_hourly.append(coil_sum) + hp_sum = 0 + coil_sum = 0 + + hp.energy_consumption[cte.DOMESTIC_HOT_WATER] = {} + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR] = hp_hourly + 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] = coil_hourly + 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'] = 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_hourly, coil_hourly + + def enrich_buildings(self): + 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())) + diff --git a/scripts/system_simulation_models/archetype13.py b/scripts/system_simulation_models/archetype13.py new file mode 100644 index 00000000..642bfca4 --- /dev/null +++ b/scripts/system_simulation_models/archetype13.py @@ -0,0 +1,383 @@ +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 = [demand / cte.WATTS_HOUR_TO_JULES for demand in building.heating_demand[cte.HOUR]] + self._hourly_cooling_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in building.cooling_demand[cte.HOUR]] + self._hourly_dhw_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in + building.domestic_hot_water_heat_demand[cte.HOUR]] + self._output_path = output_path + self._t_out = building.external_temperature[cte.HOUR] + self.results = {} + self.dt = 900 + + def hvac_sizing(self): + storage_factor = 3 + 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) + heat_pump.nominal_cooling_output = round(self._cooling_peak_load) + boiler.nominal_heat_output = round(0.5 * self._heating_peak_load) + thermal_storage.volume = round( + (self._heating_peak_load * storage_factor * cte.WATTS_HOUR_TO_JULES) / + (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 25)) + return heat_pump, boiler, thermal_storage + + 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() + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_heating_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + 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_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 + 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 + 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) + # storage temperature prediction + for i in range(len(demand) - 1): + t_tank[i + 1] = (t_tank[i] + + (m_ch[i] * (t_sup_boiler[i] - t_tank[i]) + + (ua * (t_out[i] - t_tank[i])) / cte.WATER_HEAT_CAPACITY - + m_dis[i] * (t_tank[i] - t_ret[i])) * (self.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 * 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_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 * 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_hp[i + 1] = 0, 0, t_tank[i + 1] + t_tank_fahrenheit = 1.8 * t_tank[i + 1] + 32 + t_out_fahrenheit = 1.8 * t_out[i + 1] + 32 + if q_hp[i + 1] > 0: + hp_cop[i + 1] = (1 / (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_tank_fahrenheit + + cop_curve_coefficients[2] * t_tank_fahrenheit ** 2 + + cop_curve_coefficients[3] * t_out_fahrenheit + + cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + + cop_curve_coefficients[5] * t_tank_fahrenheit * t_out_fahrenheit)) * hp_efficiency + hp_electricity[i + 1] = q_hp[i + 1] / hp_cop[i + 1] + else: + 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 / self.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] * self.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: + factor = 8 + else: + factor = 4 + m_dis[i + 1] = self._heating_peak_load / (cte.WATER_HEAT_CAPACITY * factor) + t_ret[i + 1] = t_tank[i + 1] - demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY) + tes.temperature = [] + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + boiler_consumption_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in boiler_energy_consumption] + hp_hourly = [] + boiler_hourly = [] + boiler_sum = 0 + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + boiler_sum += boiler_consumption_j[i] + if (i - 1) % number_of_ts == 0: + tes.temperature.append(t_tank[i]) + hp_hourly.append(hp_sum) + boiler_hourly.append(boiler_sum) + hp_sum = 0 + boiler_sum = 0 + hp.energy_consumption[cte.HEATING] = {} + hp.energy_consumption[cte.HEATING][cte.HOUR] = hp_hourly + 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_hourly + 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])] + + self.results['Heating Demand (W)'] = demand + self.results['HP Heat Output (W)'] = q_hp + self.results['HP Source Temperature'] = 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_hourly, boiler_hourly + + 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) + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_cooling_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + hp.source_temperature = self._t_out + variable_names = ["t_sup_hp", "t_ret", "m", "q_hp", "hp_electricity", "hp_cop"] + 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_cop) = [variables[name] for name in variable_names] + t_ret[0] = 13 + + for i in range(1, len(demand)): + if demand[i] > 0.15 * self._cooling_peak_load: + m[i] = hp.nominal_cooling_output / (cte.WATER_HEAT_CAPACITY * 5) + if t_ret[i - 1] >= 13: + if demand[i] < 0.25 * self._cooling_peak_load: + q_hp[i] = 0.25 * hp.nominal_cooling_output + elif demand[i] < 0.5 * self._cooling_peak_load: + q_hp[i] = 0.5 * hp.nominal_cooling_output + else: + q_hp[i] = hp.nominal_cooling_output + t_sup_hp[i] = t_ret[i - 1] - q_hp[i] / (m[i] * cte.WATER_HEAT_CAPACITY) + else: + q_hp[i] = 0 + t_sup_hp[i] = t_ret[i - 1] + if m[i] == 0: + t_ret[i] = t_sup_hp[i] + else: + t_ret[i] = 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 - 1] + t_ret[i] = t_ret[i - 1] + t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 + t_out_fahrenheit = 1.8 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (1 / (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)) * cooling_efficiency / 3.41 + hp_electricity[i] = q_hp[i] / cooling_efficiency + else: + hp_cop[i] = 0 + hp_electricity[i] = 0 + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + hp_hourly = [] + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + if (i - 1) % number_of_ts == 0: + hp_hourly.append(hp_sum) + hp_sum = 0 + hp.energy_consumption[cte.COOLING] = {} + hp.energy_consumption[cte.COOLING][cte.HOUR] = hp_hourly + 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_cop + 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_hourly + + def dhw_system_simulation(self): + hp, tes = self.dhw_sizing() + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_dhw_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + 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 + + 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] * (self.dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v)) + if t_tank[i] < 62: + q_hp[i] = hp_heating_cap + delta_t_hp = q_hp[i] * (self.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) * (self.dt / (v * cte.WATER_DENSITY)) + if t_tank[i] < 60: + q_coil[i] = float(tes.heating_coil_capacity) + delta_t_coil = q_coil[i] * (self.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 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_out[i] + + cop_curve_coefficients[2] * t_out[i] ** 2 + + cop_curve_coefficients[3] * t_tank[i] + + cop_curve_coefficients[4] * t_tank[i] ** 2 + + cop_curve_coefficients[5] * t_tank[i] * t_out[i]) * float(hp.heat_efficiency) + hp_electricity[i] = q_hp[i] / hp_cop[i] + 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) + tes.temperature = [] + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + heating_coil_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in q_coil] + hp_hourly = [] + coil_hourly = [] + coil_sum = 0 + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + coil_sum += heating_coil_j[i] + if (i - 1) % number_of_ts == 0: + tes.temperature.append(t_tank[i]) + hp_hourly.append(hp_sum) + coil_hourly.append(coil_sum) + hp_sum = 0 + coil_sum = 0 + + hp.energy_consumption[cte.DOMESTIC_HOT_WATER] = {} + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR] = hp_hourly + 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] = coil_hourly + 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'] = 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_hourly, coil_hourly + + def enrich_buildings(self): + 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())) diff --git a/scripts/system_simulation_models/archetype13_stratified_tes.py b/scripts/system_simulation_models/archetype13_stratified_tes.py new file mode 100644 index 00000000..632ed304 --- /dev/null +++ b/scripts/system_simulation_models/archetype13_stratified_tes.py @@ -0,0 +1,416 @@ +import math +import hub.helpers.constants as cte +import csv +from hub.helpers.monthly_values import MonthlyValues +import numpy as np + + +class Archetype13Stratified: + 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 = [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 = [0] + building.domestic_hot_water_heat_demand[cte.HOUR] + self._output_path = output_path + self._t_out = building.external_temperature[cte.HOUR] + self.results = {} + self.dt = 300 + + def hvac_sizing(self): + storage_factor = 3 + 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 * 25)) + return heat_pump, boiler, thermal_storage + + 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_stratified(self): + hp, boiler, tes = self.hvac_sizing() + hp_efficiency = float(hp.heat_efficiency) + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + demand = [0] + [x for x in self._hourly_heating_demand for _ in range(12)] + hp.source_temperature = self._t_out + t_out = [0] + [x for x in self._t_out for _ in range(12)] + variable_names = ["t_sup_hp", "t1", "t2", "t3", "t4", "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_hp, t1, t2, t3, t4, 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 + t1[0] = 55 + t2[0] = 55 + t3[0] = 55 + t4[0] = 55 + dt = 300 + hp_heating_cap = hp.nominal_heat_output + boiler_heating_cap = boiler.nominal_heat_output + hp_delta_t = 5 + boiler_efficiency = float(boiler.heat_efficiency) + v, h = float(tes.volume) / 4, float(tes.height) / 4 + 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_side = u_tot * a_side + ua_top_bottom = u_tot * (a_top + a_side) + # storage temperature prediction + for i in range(len(demand) - 1): + t1[i + 1] = t1[i] + ((m_ch[i] * (t_sup_boiler[i] - t1[i])) + ( + np.heaviside((m_dis[i] - m_ch[i]), 0) * (m_ch[i] - m_dis[i]) * (t1[i] - t2[i])) + ( + ua_top_bottom * (t_out[i] - t1[i])) / cte.WATER_HEAT_CAPACITY - cte.WATER_THERMAL_CONDUCTIVITY * (a_top * (t1[i] - t2[i])) / ( + cte.WATER_HEAT_CAPACITY * h)) * (dt / (cte.WATER_DENSITY * v)) + t2[i + 1] = t2[i] + ((np.heaviside((m_dis[i] - m_ch[i]), 0) * (m_ch[i] - m_dis[i]) * (t2[i] - t3[i])) + ( + ua_side * (t_out[i] - t2[i])) / cte.WATER_HEAT_CAPACITY - (cte.WATER_THERMAL_CONDUCTIVITY * (a_top * (t2[i] - t1[i])) / (cte.WATER_HEAT_CAPACITY * h)) - ( + cte.WATER_THERMAL_CONDUCTIVITY * (a_top * (t2[i] - t3[i])) / (cte.WATER_HEAT_CAPACITY * h)) + ( + np.heaviside((m_ch[i] - m_dis[i]), 0) * (m_ch[i] - m_dis[i]) * ( + t1[i] - t2[i]))) * (dt / (cte.WATER_DENSITY * v)) + t3[i + 1] = t3[i] + ((np.heaviside((m_dis[i] - m_ch[i]), 0) * (m_ch[i] - m_dis[i]) * (t3[i] - t4[i])) + ( + ua_side * (t_out[i] - t3[i])) / cte.WATER_HEAT_CAPACITY - (cte.WATER_THERMAL_CONDUCTIVITY * (a_top * (t3[i] - t2[i])) / (cte.WATER_HEAT_CAPACITY * h)) - ( + cte.WATER_THERMAL_CONDUCTIVITY * (a_top * (t3[i] - t4[i])) / (cte.WATER_HEAT_CAPACITY * h)) + ( + np.heaviside((m_ch[i] - m_dis[i]), 0) * (m_ch[i] - m_dis[i]) * ( + t2[i] - t3[i]))) * (dt / (cte.WATER_DENSITY * v)) + t4[i + 1] = t4[i] + (np.heaviside((m_ch[i] - m_dis[i]), 0) * ((m_ch[i] - m_dis[i]) * (t3[i] - t4[i])) + ( + ua_top_bottom * (t_out[i] - t4[-1])) / cte.WATER_HEAT_CAPACITY - m_dis[i] * ((t4[i] - t_ret[i])) - ( + cte.WATER_THERMAL_CONDUCTIVITY * (a_top * (t4[i] - t3[i])) / (cte.WATER_HEAT_CAPACITY * h))) * (dt / (cte.WATER_DENSITY * v)) + # hp operation + if t1[i + 1] < 40: + q_hp[i + 1] = hp_heating_cap + 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)) + t4[i + 1] + elif 40 <= t1[i + 1] < 55 and q_hp[i] == 0: + q_hp[i + 1] = 0 + m_ch[i + 1] = 0 + t_sup_hp[i + 1] = t4[i + 1] + elif 40 <= t1[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 * hp_delta_t) + t_sup_hp[i + 1] = (q_hp[i + 1] / (m_ch[i + 1] * cte.WATER_HEAT_CAPACITY)) + t4[i + 1] + else: + q_hp[i + 1], m_ch[i + 1], t_sup_hp[i + 1] = 0, 0, t4[i + 1] + t_tank_fahrenheit = 1.8 * t4[i + 1] + 32 + t_out_fahrenheit = 1.8 * t_out[i + 1] + 32 + if q_hp[i + 1] > 0: + hp_cop[i + 1] = (1 / (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_tank_fahrenheit + + cop_curve_coefficients[2] * t_tank_fahrenheit ** 2 + + cop_curve_coefficients[3] * t_out_fahrenheit + + cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + + cop_curve_coefficients[5] * t_tank_fahrenheit * t_out_fahrenheit)) * hp_efficiency + hp_electricity[i + 1] = q_hp[i + 1] / hp_cop[i + 1] + else: + 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] = t1[i + 1] + else: + if demand[i + 1] > 0.5 * self._heating_peak_load / cte.HOUR_TO_SECONDS: + factor = 8 + else: + factor = 4 + m_dis[i + 1] = self._heating_peak_load / (cte.WATER_HEAT_CAPACITY * factor * cte.HOUR_TO_SECONDS) + t_ret[i + 1] = t1[i + 1] - demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY) + + hp_electricity_wh = [x / 12 for x in hp_electricity] + boiler_consumption_wh = [x / 12 for x in boiler_energy_consumption] + hp_hourly = [] + boiler_hourly = [] + tes.temperature = {} + tes.temperature['layer_1'] = [] + tes.temperature['layer_2'] = [] + tes.temperature['layer_3'] = [] + tes.temperature['layer_4'] = [] + for i in range(1, len(demand), 12): + tes.temperature['layer_1'].append(t1[i]) + tes.temperature['layer_2'].append(t2[i]) + tes.temperature['layer_3'].append(t3[i]) + tes.temperature['layer_4'].append(t4[i]) + demand_modified = demand[1:] + hp_hourly.append(hp_electricity[1]) + boiler_hourly.append(boiler_energy_consumption[1]) + boiler_sum = 0 + hp_sum = 0 + for i in range(1, len(demand_modified) + 1): + hp_sum += hp_electricity_wh[i] + boiler_sum += boiler_consumption_wh[i] + if i % 12 == 0: + hp_hourly.append(hp_sum) + boiler_hourly.append(boiler_sum) + hp_sum = 0 + boiler_sum = 0 + + hp.energy_consumption[cte.HEATING] = {} + hp.energy_consumption[cte.HEATING][cte.HOUR] = hp_hourly + 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_hourly + 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])] + + self.results['Heating Demand (W)'] = demand + self.results['HP Heat Output (W)'] = q_hp + self.results['HP Source Temperature'] = 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 Layer 1 Temperature'] = t1 + self.results['TES Layer 2 Temperature'] = t2 + self.results['TES Layer 3 Temperature'] = t3 + self.results['TES Layer 4 Temperature'] = t4 + 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) + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_cooling_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + hp.source_temperature = self._t_out + variable_names = ["t_sup_hp", "t_ret", "m", "q_hp", "hp_electricity", "hp_cop"] + 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_cop) = [variables[name] for name in variable_names] + t_ret[0] = 13 + + for i in range(1, len(demand)): + if demand[i] > 0.15 * self._cooling_peak_load: + m[i] = hp.nominal_cooling_output / (cte.WATER_HEAT_CAPACITY * 5) + if t_ret[i - 1] >= 13: + if demand[i] < 0.25 * self._cooling_peak_load: + q_hp[i] = 0.25 * hp.nominal_cooling_output + elif demand[i] < 0.5 * self._cooling_peak_load: + q_hp[i] = 0.5 * hp.nominal_cooling_output + else: + q_hp[i] = hp.nominal_cooling_output + t_sup_hp[i] = t_ret[i - 1] - q_hp[i] / (m[i] * cte.WATER_HEAT_CAPACITY) + else: + q_hp[i] = 0 + t_sup_hp[i] = t_ret[i - 1] + if m[i] == 0: + t_ret[i] = t_sup_hp[i] + else: + t_ret[i] = 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 - 1] + t_ret[i] = t_ret[i - 1] + t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 + t_out_fahrenheit = 1.8 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (1 / (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)) * cooling_efficiency / 3.41 + hp_electricity[i] = q_hp[i] / cooling_efficiency + else: + hp_cop[i] = 0 + hp_electricity[i] = 0 + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + hp_hourly = [] + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + if (i - 1) % number_of_ts == 0: + hp_hourly.append(hp_sum) + hp_sum = 0 + hp.energy_consumption[cte.COOLING] = {} + hp.energy_consumption[cte.COOLING][cte.HOUR] = hp_hourly + 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_cop + 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_hourly + + def dhw_system_simulation(self): + hp, tes = self.dhw_sizing() + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_dhw_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + 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 + + 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] * (self.dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v)) + if t_tank[i] < 62: + q_hp[i] = hp_heating_cap + delta_t_hp = q_hp[i] * (self.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) * (self.dt / (v * cte.WATER_DENSITY)) + if t_tank[i] < 60: + q_coil[i] = float(tes.heating_coil_capacity) + delta_t_coil = q_coil[i] * (self.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 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_out[i] + + cop_curve_coefficients[2] * t_out[i] ** 2 + + cop_curve_coefficients[3] * t_tank[i] + + cop_curve_coefficients[4] * t_tank[i] ** 2 + + cop_curve_coefficients[5] * t_tank[i] * t_out[i]) * float(hp.heat_efficiency) + hp_electricity[i] = q_hp[i] / hp_cop[i] + 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) + tes.temperature = [] + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + heating_coil_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in q_coil] + hp_hourly = [] + coil_hourly = [] + coil_sum = 0 + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + coil_sum += heating_coil_j[i] + if (i - 1) % number_of_ts == 0: + tes.temperature.append(t_tank[i]) + hp_hourly.append(hp_sum) + coil_hourly.append(coil_sum) + hp_sum = 0 + coil_sum = 0 + + hp.energy_consumption[cte.DOMESTIC_HOT_WATER] = {} + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR] = hp_hourly + 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] = coil_hourly + 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'] = 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_hourly, coil_hourly + + def enrich_buildings(self): + hp_heating, boiler_consumption = self.heating_system_simulation_stratified() + 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())) diff --git a/scripts/system_simulation_models/archetypes14_15.py b/scripts/system_simulation_models/archetypes14_15.py new file mode 100644 index 00000000..cc5f8d6a --- /dev/null +++ b/scripts/system_simulation_models/archetypes14_15.py @@ -0,0 +1,398 @@ +import math +import hub.helpers.constants as cte +import csv +from hub.helpers.monthly_values import MonthlyValues + + +class Archetype14_15: + def __init__(self, building, output_path): + self._building = building + self._name = building.name + if 'PV' in building.energy_systems_archetype_name: + i = 1 + self._pv_system = building.energy_systems[0] + else: + i = 0 + self._dhw_system = building.energy_systems[i] + self._heating_system = building.energy_systems[i + 1] + self._cooling_system = building.energy_systems[i + 2] + 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 = [demand / cte.WATTS_HOUR_TO_JULES for demand in building.heating_demand[cte.HOUR]] + self._hourly_cooling_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in building.cooling_demand[cte.HOUR]] + self._hourly_dhw_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in + building.domestic_hot_water_heat_demand[cte.HOUR]] + self._output_path = output_path + self._t_out = building.external_temperature[cte.HOUR] + self.results = {} + self.dt = 900 + + def heating_system_sizing(self): + storage_factor = 3 + heat_pump = self._heating_system.generation_systems[1] + heat_pump.source_temperature = self._t_out + boiler = self._heating_system.generation_systems[0] + thermal_storage = boiler.energy_storage_systems[0] + heat_pump.nominal_heat_output = round(0.5 * self._heating_peak_load) + boiler.nominal_heat_output = round(0.5 * self._heating_peak_load) + thermal_storage.volume = round( + (self._heating_peak_load * storage_factor * cte.WATTS_HOUR_TO_JULES) / + (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 25)) + return heat_pump, boiler, thermal_storage + + def cooling_system_sizing(self): + heat_pump = self._cooling_system.generation_systems[0] + heat_pump.nominal_cooling_output = heat_pump.nominal_cooling_output = round(self._cooling_peak_load) + heat_pump.source_temperature = self._t_out + return heat_pump + + + def dhw_system_sizing(self): + storage_factor = 3 + dhw_hp = self._dhw_system.generation_systems[0] + dhw_hp.nominal_heat_output = round(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 * cte.WATTS_HOUR_TO_JULES) / + (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 10)) + return dhw_hp, dhw_tes + + def heating_system_simulation(self): + hp, boiler, tes = self.heating_system_sizing() + hp_efficiency = float(hp.heat_efficiency) + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_heating_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + 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_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 + hp_heating_cap = hp.nominal_heat_output + 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 + 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) + # storage temperature prediction + for i in range(len(demand) - 1): + t_tank[i + 1] = (t_tank[i] + + (m_ch[i] * (t_sup_boiler[i] - t_tank[i]) + + (ua * (t_out[i] - t_tank[i])) / cte.WATER_HEAT_CAPACITY - + m_dis[i] * (t_tank[i] - t_ret[i])) * (self.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 * 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_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 * 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_hp[i + 1] = 0, 0, t_tank[i + 1] + t_tank_fahrenheit = 1.8 * t_tank[i + 1] + 32 + t_out_fahrenheit = 1.8 * t_out[i + 1] + 32 + if q_hp[i + 1] > 0: + hp_cop[i + 1] = (1 / (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_tank_fahrenheit + + cop_curve_coefficients[2] * t_tank_fahrenheit ** 2 + + cop_curve_coefficients[3] * t_out_fahrenheit + + cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + + cop_curve_coefficients[5] * t_tank_fahrenheit * t_out_fahrenheit)) * hp_efficiency + hp_electricity[i + 1] = q_hp[i + 1] / hp_cop[i + 1] + else: + 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 / self.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] * self.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 / cte.HOUR_TO_SECONDS: + factor = 8 + else: + factor = 4 + m_dis[i + 1] = self._heating_peak_load / (cte.WATER_HEAT_CAPACITY * factor * cte.HOUR_TO_SECONDS) + t_ret[i + 1] = t_tank[i + 1] - demand[i + 1] / (m_dis[i + 1] * cte.WATER_HEAT_CAPACITY) + tes.temperature = [] + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + boiler_consumption_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in boiler_energy_consumption] + hp_hourly = [] + boiler_hourly = [] + boiler_sum = 0 + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + boiler_sum += boiler_consumption_j[i] + if (i - 1) % number_of_ts == 0: + tes.temperature.append(t_tank[i]) + hp_hourly.append(hp_sum) + boiler_hourly.append(boiler_sum) + hp_sum = 0 + boiler_sum = 0 + hp.energy_consumption[cte.HEATING] = {} + hp.energy_consumption[cte.HEATING][cte.HOUR] = hp_hourly + 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_hourly + 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])] + + self.results['Heating Demand (W)'] = demand + self.results['HP Heat Output (W)'] = q_hp + self.results['HP Source Temperature'] = 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_hourly, boiler_hourly + + def cooling_system_simulation(self): + hp = self.cooling_system_sizing()[0] + eer_curve_coefficients = [float(coefficient) for coefficient in hp.cooling_efficiency_curve.coefficients] + cooling_efficiency = float(hp.cooling_efficiency) + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_cooling_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + hp.source_temperature = self._t_out + variable_names = ["t_sup_hp", "t_ret", "m", "q_hp", "hp_electricity", "hp_cop"] + 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_cop) = [variables[name] for name in variable_names] + t_ret[0] = 13 + + for i in range(1, len(demand)): + if demand[i] > 0.15 * self._cooling_peak_load: + m[i] = hp.nominal_cooling_output / (cte.WATER_HEAT_CAPACITY * 5) + if t_ret[i - 1] >= 13: + if demand[i] < 0.25 * self._cooling_peak_load: + q_hp[i] = 0.25 * hp.nominal_cooling_output + elif demand[i] < 0.5 * self._cooling_peak_load: + q_hp[i] = 0.5 * hp.nominal_cooling_output + else: + q_hp[i] = hp.nominal_cooling_output + t_sup_hp[i] = t_ret[i - 1] - q_hp[i] / (m[i] * cte.WATER_HEAT_CAPACITY) + else: + q_hp[i] = 0 + t_sup_hp[i] = t_ret[i - 1] + if m[i] == 0: + t_ret[i] = t_sup_hp[i] + else: + t_ret[i] = 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 - 1] + t_ret[i] = t_ret[i - 1] + t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 + t_out_fahrenheit = 1.8 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (1 / (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)) * cooling_efficiency / 3.41 + hp_electricity[i] = q_hp[i] / cooling_efficiency + else: + hp_cop[i] = 0 + hp_electricity[i] = 0 + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + hp_hourly = [] + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + if (i - 1) % number_of_ts == 0: + hp_hourly.append(hp_sum) + hp_sum = 0 + hp.energy_consumption[cte.COOLING] = {} + hp.energy_consumption[cte.COOLING][cte.HOUR] = hp_hourly + 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_cop + 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_hourly + + def dhw_system_simulation(self): + hp, tes = self.dhw_system_sizing() + cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) + demand = [0] + [x for x in self._hourly_dhw_demand for _ in range(number_of_ts)] + t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] + 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 + + 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] * (self.dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * v)) + if t_tank[i] < 62: + q_hp[i] = hp_heating_cap + delta_t_hp = q_hp[i] * (self.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) * (self.dt / (v * cte.WATER_DENSITY)) + if t_tank[i] < 60: + q_coil[i] = float(tes.heating_coil_capacity) + delta_t_coil = q_coil[i] * (self.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 * t_out[i] + 32 + if q_hp[i] > 0: + hp_cop[i] = (cop_curve_coefficients[0] + + cop_curve_coefficients[1] * t_out[i] + + cop_curve_coefficients[2] * t_out[i] ** 2 + + cop_curve_coefficients[3] * t_tank[i] + + cop_curve_coefficients[4] * t_tank[i] ** 2 + + cop_curve_coefficients[5] * t_tank[i] * t_out[i]) * float(hp.heat_efficiency) + hp_electricity[i] = q_hp[i] / hp_cop[i] + 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) + tes.temperature = [] + hp_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity] + heating_coil_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in q_coil] + hp_hourly = [] + coil_hourly = [] + coil_sum = 0 + hp_sum = 0 + for i in range(1, len(demand)): + hp_sum += hp_electricity_j[i] + coil_sum += heating_coil_j[i] + if (i - 1) % number_of_ts == 0: + tes.temperature.append(t_tank[i]) + hp_hourly.append(hp_sum) + coil_hourly.append(coil_sum) + hp_sum = 0 + coil_sum = 0 + + hp.energy_consumption[cte.DOMESTIC_HOT_WATER] = {} + hp.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR] = hp_hourly + 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] = coil_hourly + 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'] = 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_hourly, coil_hourly + + + + def enrich_buildings(self): + 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())) diff --git a/simulation_test.py b/simulation_test.py new file mode 100644 index 00000000..8eb057e2 --- /dev/null +++ b/simulation_test.py @@ -0,0 +1,44 @@ +from pathlib import Path +import subprocess +from scripts.ep_workflow import energy_plus_workflow +from hub.imports.geometry_factory import GeometryFactory +from hub.helpers.dictionaries import Dictionaries +from hub.imports.construction_factory import ConstructionFactory +from hub.imports.usage_factory import UsageFactory +from hub.imports.weather_factory import WeatherFactory +from hub.imports.results_factory import ResultFactory +from hub.imports.energy_systems_factory import EnergySystemsFactory +from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory +import hub.helpers.constants as cte +from hub.exports.exports_factory import ExportsFactory + + +# Specify the GeoJSON file path +input_files_path = (Path(__file__).parent / 'input_files') +input_files_path.mkdir(parents=True, exist_ok=True) +geojson_file_path = input_files_path / 'test.geojson' +output_path = (Path(__file__).parent / 'out_files').resolve() +output_path.mkdir(parents=True, exist_ok=True) +energy_plus_output_path = output_path / 'energy_plus_outputs' +energy_plus_output_path.mkdir(parents=True, exist_ok=True) +simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve() +simulation_results_path.mkdir(parents=True, exist_ok=True) +sra_output_path = output_path / 'sra_outputs' +sra_output_path.mkdir(parents=True, exist_ok=True) +cost_analysis_output_path = output_path / 'cost_analysis' +cost_analysis_output_path.mkdir(parents=True, exist_ok=True) +city = GeometryFactory(file_type='geojson', + path=geojson_file_path, + height_field='maximum_roof_height', + year_of_construction_field='year_built', + function_field='building_type', + function_to_hub=Dictionaries().montreal_function_to_hub_function).city +ConstructionFactory('nrcan', city).enrich() +UsageFactory('nrcan', city).enrich() +WeatherFactory('epw', city).enrich() +energy_plus_workflow(city, energy_plus_output_path) +for building in city.buildings: + building.energy_systems_archetype_name = 'PV+4Pipe+DHW' +EnergySystemsFactory('montreal_future', city).enrich() +for building in city.buildings: + EnergySystemsSimulationFactory('archetype13', building=building, output_path=simulation_results_path).enrich() \ No newline at end of file