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