feat: the workflow is organized to separate system models
This commit is contained in:
parent
9af87fe482
commit
b0e6c7d9ef
@ -6,7 +6,7 @@ import csv
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
|
||||
sys.path.append('./')
|
||||
sys.path.append('../energy_system_modelling_package/')
|
||||
|
||||
|
||||
def energy_plus_workflow(city, output_path):
|
@ -11,10 +11,10 @@ import pandas as pd
|
||||
import numpy_financial as npf
|
||||
from hub.city_model_structure.building import Building
|
||||
import hub.helpers.constants as cte
|
||||
from scripts.costs.configuration import Configuration
|
||||
from scripts.costs.constants import (SKIN_RETROFIT, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV,
|
||||
SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS, PV, SYSTEM_RETROFIT)
|
||||
from scripts.costs.cost_base import CostBase
|
||||
from costing_package.configuration import Configuration
|
||||
from costing_package.constants import (SKIN_RETROFIT, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV,
|
||||
SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS, PV, SYSTEM_RETROFIT)
|
||||
from costing_package.cost_base import CostBase
|
||||
|
||||
|
||||
class CapitalCosts(CostBase):
|
@ -5,19 +5,18 @@ Copyright © 2023 Project Coder Guille Gutierrez guillermo.gutierrezmorote@conco
|
||||
Code contributor Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
Code contributor Oriol Gavalda Torrellas oriol.gavalda@concordia.ca
|
||||
"""
|
||||
import datetime
|
||||
|
||||
import pandas as pd
|
||||
import numpy_financial as npf
|
||||
from hub.city_model_structure.building import Building
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from scripts.costs.configuration import Configuration
|
||||
from scripts.costs.capital_costs import CapitalCosts
|
||||
from scripts.costs.end_of_life_costs import EndOfLifeCosts
|
||||
from scripts.costs.total_maintenance_costs import TotalMaintenanceCosts
|
||||
from scripts.costs.total_operational_costs import TotalOperationalCosts
|
||||
from scripts.costs.total_operational_incomes import TotalOperationalIncomes
|
||||
from scripts.costs.constants import CURRENT_STATUS, SKIN_RETROFIT, SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV
|
||||
from costing_package.configuration import Configuration
|
||||
from costing_package.capital_costs import CapitalCosts
|
||||
from costing_package.end_of_life_costs import EndOfLifeCosts
|
||||
from costing_package.total_maintenance_costs import TotalMaintenanceCosts
|
||||
from costing_package.total_operational_costs import TotalOperationalCosts
|
||||
from costing_package.total_operational_incomes import TotalOperationalIncomes
|
||||
from costing_package.constants import CURRENT_STATUS
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
@ -8,7 +8,7 @@ Code contributor Oriol Gavalda Torrellas oriol.gavalda@concordia.ca
|
||||
|
||||
from hub.city_model_structure.building import Building
|
||||
|
||||
from scripts.costs.configuration import Configuration
|
||||
from costing_package.configuration import Configuration
|
||||
|
||||
|
||||
class CostBase:
|
@ -9,8 +9,8 @@ import math
|
||||
import pandas as pd
|
||||
from hub.city_model_structure.building import Building
|
||||
|
||||
from scripts.costs.configuration import Configuration
|
||||
from scripts.costs.cost_base import CostBase
|
||||
from costing_package.configuration import Configuration
|
||||
from costing_package.cost_base import CostBase
|
||||
|
||||
|
||||
class EndOfLifeCosts(CostBase):
|
@ -10,8 +10,8 @@ import pandas as pd
|
||||
from hub.city_model_structure.building import Building
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
from scripts.costs.configuration import Configuration
|
||||
from scripts.costs.cost_base import CostBase
|
||||
from costing_package.configuration import Configuration
|
||||
from costing_package.cost_base import CostBase
|
||||
|
||||
|
||||
class TotalMaintenanceCosts(CostBase):
|
@ -10,9 +10,9 @@ import pandas as pd
|
||||
from hub.city_model_structure.building import Building
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
from scripts.costs.configuration import Configuration
|
||||
from scripts.costs.cost_base import CostBase
|
||||
from scripts.costs.peak_load import PeakLoad
|
||||
from costing_package.configuration import Configuration
|
||||
from costing_package.cost_base import CostBase
|
||||
from costing_package.peak_load import PeakLoad
|
||||
|
||||
|
||||
class TotalOperationalCosts(CostBase):
|
@ -10,8 +10,8 @@ import pandas as pd
|
||||
from hub.city_model_structure.building import Building
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
from scripts.costs.configuration import Configuration
|
||||
from scripts.costs.cost_base import CostBase
|
||||
from costing_package.configuration import Configuration
|
||||
from costing_package.cost_base import CostBase
|
||||
|
||||
|
||||
class TotalOperationalIncomes(CostBase):
|
@ -0,0 +1,147 @@
|
||||
import csv
|
||||
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.heat_pump_boiler_tes_heating import \
|
||||
HeatPumpBoilerTesHeating
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.heat_pump_cooling import \
|
||||
HeatPumpCooling
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.domestic_hot_water_heat_pump_with_tes import \
|
||||
DomesticHotWaterHeatPumpTes
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_model import PVModel
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.electricity_demand_calculator import HourlyElectricityDemand
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class ArchetypeCluster1:
|
||||
def __init__(self, building, dt, output_path, csv_output=True):
|
||||
self.building = building
|
||||
self.dt = dt
|
||||
self.output_path = output_path
|
||||
self.csv_output = csv_output
|
||||
self.heating_results, self.building_heating_hourly_consumption = self.heating_system_simulation()
|
||||
self.cooling_results, self.total_cooling_consumption_hourly = self.cooling_system_simulation()
|
||||
self.dhw_results, self.total_dhw_consumption_hourly = self.dhw_system_simulation()
|
||||
if 'PV' in self.building.energy_systems_archetype_name:
|
||||
self.pv_results = self.pv_system_simulation()
|
||||
else:
|
||||
self.pv_results = None
|
||||
|
||||
def heating_system_simulation(self):
|
||||
building_heating_hourly_consumption = []
|
||||
boiler = self.building.energy_systems[1].generation_systems[0]
|
||||
hp = self.building.energy_systems[1].generation_systems[1]
|
||||
tes = self.building.energy_systems[1].generation_systems[0].energy_storage_systems[0]
|
||||
heating_demand_joules = self.building.heating_demand[cte.HOUR]
|
||||
heating_peak_load_watts = self.building.heating_peak_load[cte.YEAR][0]
|
||||
upper_limit_tes_heating = 55
|
||||
outdoor_temperature = self.building.external_temperature[cte.HOUR]
|
||||
results = HeatPumpBoilerTesHeating(hp=hp,
|
||||
boiler=boiler,
|
||||
tes=tes,
|
||||
hourly_heating_demand_joules=heating_demand_joules,
|
||||
heating_peak_load_watts=heating_peak_load_watts,
|
||||
upper_limit_tes=upper_limit_tes_heating,
|
||||
outdoor_temperature=outdoor_temperature,
|
||||
dt=self.dt).simulation()
|
||||
number_of_ts = int(cte.HOUR_TO_SECONDS/self.dt)
|
||||
heating_consumption_joules = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in
|
||||
results['Total Heating Power Consumption (W)']]
|
||||
heating_consumption = 0
|
||||
for i in range(1, len(heating_consumption_joules)):
|
||||
heating_consumption += heating_consumption_joules[i]
|
||||
if (i - 1) % number_of_ts == 0:
|
||||
building_heating_hourly_consumption.append(heating_consumption)
|
||||
heating_consumption = 0
|
||||
return results, building_heating_hourly_consumption
|
||||
|
||||
def cooling_system_simulation(self):
|
||||
hp = self.building.energy_systems[1].generation_systems[1]
|
||||
cooling_demand_joules = self.building.cooling_demand[cte.HOUR]
|
||||
cooling_peak_load = self.building.cooling_peak_load[cte.YEAR][0]
|
||||
cutoff_temperature = 13
|
||||
outdoor_temperature = self.building.external_temperature[cte.HOUR]
|
||||
results = HeatPumpCooling(hp=hp,
|
||||
hourly_cooling_demand_joules=cooling_demand_joules,
|
||||
cooling_peak_load_watts=cooling_peak_load,
|
||||
cutoff_temperature=cutoff_temperature,
|
||||
outdoor_temperature=outdoor_temperature,
|
||||
dt=self.dt).simulation()
|
||||
building_cooling_hourly_consumption = hp.energy_consumption[cte.COOLING][cte.HOUR]
|
||||
return results, building_cooling_hourly_consumption
|
||||
|
||||
def dhw_system_simulation(self):
|
||||
building_dhw_hourly_consumption = []
|
||||
hp = self.building.energy_systems[2].generation_systems[0]
|
||||
tes = self.building.energy_systems[2].generation_systems[0].energy_storage_systems[0]
|
||||
dhw_demand_joules = self.building.domestic_hot_water_heat_demand[cte.HOUR]
|
||||
upper_limit_tes = 65
|
||||
outdoor_temperature = self.building.external_temperature[cte.HOUR]
|
||||
results = DomesticHotWaterHeatPumpTes(hp=hp,
|
||||
tes=tes,
|
||||
hourly_dhw_demand_joules=dhw_demand_joules,
|
||||
upper_limit_tes=upper_limit_tes,
|
||||
outdoor_temperature=outdoor_temperature,
|
||||
dt=self.dt).simulation()
|
||||
number_of_ts = int(cte.HOUR_TO_SECONDS/self.dt)
|
||||
dhw_consumption_joules = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in
|
||||
results['Total DHW Power Consumption (W)']]
|
||||
dhw_consumption = 0
|
||||
for i in range(1, len(dhw_consumption_joules)):
|
||||
dhw_consumption += dhw_consumption_joules[i]
|
||||
if (i - 1) % number_of_ts == 0:
|
||||
building_dhw_hourly_consumption.append(dhw_consumption)
|
||||
dhw_consumption = 0
|
||||
return results, building_dhw_hourly_consumption
|
||||
|
||||
def pv_system_simulation(self):
|
||||
results = None
|
||||
pv = self.building.energy_systems[0].generation_systems[0]
|
||||
hourly_electricity_demand = HourlyElectricityDemand(self.building).calculate()
|
||||
model_type = 'fixed_efficiency'
|
||||
if model_type == 'fixed_efficiency':
|
||||
results = PVModel(pv=pv,
|
||||
hourly_electricity_demand_joules=hourly_electricity_demand,
|
||||
solar_radiation=self.building.roofs[0].global_irradiance_tilted[cte.HOUR],
|
||||
installed_pv_area=self.building.roofs[0].installed_solar_collector_area,
|
||||
model_type='fixed_efficiency').fixed_efficiency()
|
||||
return results
|
||||
|
||||
def enrich_building(self):
|
||||
results = self.heating_results | self.cooling_results | self.dhw_results
|
||||
self.building.heating_consumption[cte.HOUR] = self.building_heating_hourly_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] = self.total_cooling_consumption_hourly
|
||||
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] = self.total_dhw_consumption_hourly
|
||||
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])]
|
||||
if self.pv_results is not None:
|
||||
self.building.onsite_electrical_production[cte.HOUR] = [x * cte.WATTS_HOUR_TO_JULES for x in
|
||||
self.pv_results['PV Output (W)']]
|
||||
self.building.onsite_electrical_production[cte.MONTH] = MonthlyValues.get_total_month(self.building.onsite_electrical_production[cte.HOUR])
|
||||
self.building.onsite_electrical_production[cte.YEAR] = [sum(self.building.onsite_electrical_production[cte.MONTH])]
|
||||
if self.csv_output:
|
||||
file_name = f'pv_system_simulation_results_{self.building.name}.csv'
|
||||
with open(self.output_path / file_name, 'w', newline='') as csvfile:
|
||||
output_file = csv.writer(csvfile)
|
||||
# Write header
|
||||
output_file.writerow(self.pv_results.keys())
|
||||
# Write data
|
||||
output_file.writerows(zip(*self.pv_results.values()))
|
||||
if self.csv_output:
|
||||
file_name = f'energy_system_simulation_results_{self.building.name}.csv'
|
||||
with open(self.output_path / file_name, 'w', newline='') as csvfile:
|
||||
output_file = csv.writer(csvfile)
|
||||
# Write header
|
||||
output_file.writerow(results.keys())
|
||||
# Write data
|
||||
output_file.writerows(zip(*results.values()))
|
||||
|
||||
|
||||
|
@ -0,0 +1,80 @@
|
||||
"""
|
||||
EnergySystemSizingSimulationFactory retrieve the energy system archetype sizing and simulation module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2024 Concordia CERC group
|
||||
Project Coder Saeed Ranjbar saeed.ranjbar@mail.concordia.ca
|
||||
"""
|
||||
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.system_sizing_methods.peak_load_sizing import \
|
||||
PeakLoadSizing
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.system_sizing_methods.heuristic_sizing import \
|
||||
HeuristicSizing
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_sizing import PVSizing
|
||||
|
||||
|
||||
class EnergySystemsSizingFactory:
|
||||
"""
|
||||
EnergySystemsFactory class
|
||||
"""
|
||||
|
||||
def __init__(self, handler, city):
|
||||
self._handler = '_' + handler.lower()
|
||||
self._city = city
|
||||
|
||||
def _peak_load_sizing(self):
|
||||
"""
|
||||
Size Energy Systems based on a Load Matching method using the heating, cooling, and dhw peak loads
|
||||
"""
|
||||
PeakLoadSizing(self._city).enrich_buildings()
|
||||
self._city.level_of_detail.energy_systems = 1
|
||||
for building in self._city.buildings:
|
||||
building.level_of_detail.energy_systems = 1
|
||||
|
||||
def _heurisitc_sizing(self):
|
||||
"""
|
||||
Size Energy Systems using a Single or Multi Objective GA
|
||||
"""
|
||||
HeuristicSizing(self._city).enrich_buildings()
|
||||
self._city.level_of_detail.energy_systems = 1
|
||||
for building in self._city.buildings:
|
||||
building.level_of_detail.energy_systems = 1
|
||||
|
||||
def _pv_sizing(self):
|
||||
"""
|
||||
Size rooftop, facade or mixture of them for buildings
|
||||
"""
|
||||
system_type = 'rooftop'
|
||||
results = {}
|
||||
if system_type == 'rooftop':
|
||||
surface_azimuth = 180
|
||||
maintenance_factor = 0.1
|
||||
mechanical_equipment_factor = 0.3
|
||||
orientation_factor = 0.1
|
||||
tilt_angle = self._city.latitude
|
||||
pv_sizing = PVSizing(self._city,
|
||||
tilt_angle=tilt_angle,
|
||||
surface_azimuth=surface_azimuth,
|
||||
mechanical_equipment_factor=mechanical_equipment_factor,
|
||||
maintenance_factor=maintenance_factor,
|
||||
orientation_factor=orientation_factor,
|
||||
system_type=system_type)
|
||||
results = pv_sizing.rooftop_sizing()
|
||||
pv_sizing.rooftop_tilted_radiation()
|
||||
|
||||
self._city.level_of_detail.energy_systems = 1
|
||||
for building in self._city.buildings:
|
||||
building.level_of_detail.energy_systems = 1
|
||||
return results
|
||||
|
||||
def _district_heating_cooling_sizing(self):
|
||||
"""
|
||||
Size District Heating and Cooling Network
|
||||
"""
|
||||
pass
|
||||
|
||||
def enrich(self):
|
||||
"""
|
||||
Enrich the city given to the class using the class given handler
|
||||
:return: None
|
||||
"""
|
||||
return getattr(self, self._handler, lambda: None)()
|
@ -0,0 +1,118 @@
|
||||
import hub.helpers.constants as cte
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.heat_pump_characteristics import HeatPump
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.thermal_storage_tank import StorageTank
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class DomesticHotWaterHeatPumpTes:
|
||||
def __init__(self, hp, tes, hourly_dhw_demand_joules, upper_limit_tes,
|
||||
outdoor_temperature, dt=900):
|
||||
self.hp = hp
|
||||
self.tes = tes
|
||||
self.dhw_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in hourly_dhw_demand_joules]
|
||||
self.upper_limit_tes = upper_limit_tes
|
||||
self.hp_characteristics = HeatPump(self.hp, outdoor_temperature)
|
||||
self.t_out = outdoor_temperature
|
||||
self.dt = dt
|
||||
self.results = {}
|
||||
|
||||
def simulation(self):
|
||||
hp = self.hp
|
||||
tes = self.tes
|
||||
heating_coil_nominal_output = 0
|
||||
if tes.heating_coil_capacity is not None:
|
||||
heating_coil_nominal_output = float(tes.heating_coil_capacity)
|
||||
storage_tank = StorageTank(volume=float(tes.volume),
|
||||
height=float(tes.height),
|
||||
material_layers=tes.layers,
|
||||
heating_coil_capacity=heating_coil_nominal_output)
|
||||
|
||||
hp_delta_t = 8
|
||||
number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt)
|
||||
source_temperature_hourly = self.hp_characteristics.hp_source_temperature()
|
||||
source_temperature = [x for x in source_temperature_hourly for _ in range(number_of_ts)]
|
||||
demand = [x for x in self.dhw_demand 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)", "total_consumption"]
|
||||
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, total_consumption) = \
|
||||
[variables[name] for name in variable_names]
|
||||
freshwater_temperature = 18
|
||||
t_tank[0] = 70
|
||||
for i in range(len(demand) - 1):
|
||||
delta_t_demand = demand[i] * (self.dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY *
|
||||
storage_tank.volume))
|
||||
if t_tank[i] < self.upper_limit_tes:
|
||||
q_hp[i] = hp.nominal_heat_output
|
||||
delta_t_hp = q_hp[i] * (self.dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * storage_tank.volume))
|
||||
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 / (storage_tank.volume *
|
||||
cte.WATER_DENSITY))
|
||||
if t_tank[i] < 60:
|
||||
q_coil[i] = float(storage_tank.heating_coil_capacity)
|
||||
delta_t_coil = q_coil[i] * (self.dt / (cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * storage_tank.volume))
|
||||
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]
|
||||
if q_hp[i] > 0:
|
||||
if hp.source_medium == cte.AIR and hp.supply_medium == cte.WATER:
|
||||
hp_cop[i] = self.hp_characteristics.air_to_water_cop(source_temperature[i], t_tank[i],
|
||||
mode=cte.DOMESTIC_HOT_WATER)
|
||||
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)
|
||||
total_consumption[i] = q_hp[i] + q_coil[i]
|
||||
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])]
|
||||
if self.tes.heating_coil_capacity is not None:
|
||||
tes.heating_coil_energy_consumption[cte.DOMESTIC_HOT_WATER] = {}
|
||||
tes.heating_coil_energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR] = coil_hourly
|
||||
tes.heating_coil_energy_consumption[cte.DOMESTIC_HOT_WATER][cte.MONTH] = MonthlyValues.get_total_month(
|
||||
tes.heating_coil_energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR])
|
||||
tes.heating_coil_energy_consumption[cte.DOMESTIC_HOT_WATER][cte.YEAR] = [
|
||||
sum(tes.heating_coil_energy_consumption[cte.DOMESTIC_HOT_WATER][cte.MONTH])]
|
||||
|
||||
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'] = source_temperature
|
||||
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
|
||||
self.results['Total DHW Power Consumption (W)'] = total_consumption
|
||||
return self.results
|
@ -0,0 +1,166 @@
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.heat_pump_characteristics import \
|
||||
HeatPump
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.thermal_storage_tank import \
|
||||
StorageTank
|
||||
|
||||
|
||||
class HeatPumpBoilerTesHeating:
|
||||
def __init__(self, hp, boiler, tes, hourly_heating_demand_joules, heating_peak_load_watts, upper_limit_tes,
|
||||
outdoor_temperature, dt=900):
|
||||
self.hp = hp
|
||||
self.boiler = boiler
|
||||
self.tes = tes
|
||||
self.heating_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in hourly_heating_demand_joules]
|
||||
self.heating_peak_load = heating_peak_load_watts
|
||||
self.upper_limit_tes = upper_limit_tes
|
||||
self.hp_characteristics = HeatPump(self.hp, outdoor_temperature)
|
||||
self.t_out = outdoor_temperature
|
||||
self.dt = dt
|
||||
self.results = {}
|
||||
|
||||
def simulation(self):
|
||||
hp, boiler, tes = self.hp, self.boiler, self.tes
|
||||
heating_coil_nominal_output = 0
|
||||
if tes.heating_coil_capacity is not None:
|
||||
heating_coil_nominal_output = float(tes.heating_coil_capacity)
|
||||
storage_tank = StorageTank(volume=float(tes.volume),
|
||||
height=float(tes.height),
|
||||
material_layers=tes.layers,
|
||||
heating_coil_capacity=heating_coil_nominal_output)
|
||||
number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt)
|
||||
demand = [0] + [x for x in self.heating_demand for _ in range(number_of_ts)]
|
||||
t_out = [0] + [x for x in self.t_out for _ in range(number_of_ts)]
|
||||
source_temperature_hourly = self.hp_characteristics.hp_source_temperature()
|
||||
source_temperature = [0] + [x for x in source_temperature_hourly for _ in range(number_of_ts)]
|
||||
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", "heating_coil_output", "total_heating_energy_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_fuel_consumption, t_sup_boiler, boiler_energy_consumption, heating_consumption, q_coil,
|
||||
total_consumption) = [variables[name] for name in variable_names]
|
||||
t_tank[0] = self.upper_limit_tes
|
||||
hp_delta_t = 5
|
||||
# storage temperature prediction
|
||||
for i in range(len(demand) - 1):
|
||||
t_tank[i + 1] = storage_tank.calculate_space_heating_fully_mixed(charging_flow_rate=m_ch[i],
|
||||
discharging_flow_rate=m_dis[i],
|
||||
supply_temperature=t_sup_boiler[i],
|
||||
return_temperature=t_ret[i],
|
||||
current_tank_temperature=t_tank[i],
|
||||
heat_generator_input=q_coil[i],
|
||||
ambient_temperature=t_out[i],
|
||||
dt=self.dt)
|
||||
# hp operation
|
||||
if t_tank[i + 1] < 40:
|
||||
q_hp[i + 1] = hp.nominal_heat_output
|
||||
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] < self.upper_limit_tes 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] < self.upper_limit_tes and q_hp[i] > 0:
|
||||
q_hp[i + 1] = hp.nominal_heat_output
|
||||
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]
|
||||
if q_hp[i + 1] > 0:
|
||||
if hp.source_medium == cte.AIR and self.hp.supply_medium == cte.WATER:
|
||||
hp_cop[i + 1] = self.hp_characteristics.air_to_water_cop(source_temperature[i + 1], t_tank[i + 1], mode=cte.HEATING)
|
||||
hp_electricity[i + 1] = q_hp[i + 1] / hp_cop[i + 1]
|
||||
else:
|
||||
hp_cop[i] = 0
|
||||
hp_electricity[i] = 0
|
||||
# boiler operation
|
||||
if q_hp[i + 1] > 0:
|
||||
if t_sup_hp[i + 1] < 45:
|
||||
q_boiler[i + 1] = boiler.nominal_heat_output
|
||||
elif demand[i + 1] > 0.5 * self.heating_peak_load / self.dt:
|
||||
q_boiler[i + 1] = 0.5 * boiler.nominal_heat_output
|
||||
boiler_energy_consumption[i + 1] = q_boiler[i + 1] / float(boiler.heat_efficiency)
|
||||
if boiler.fuel_type == cte.ELECTRICITY:
|
||||
boiler_fuel_consumption[i + 1] = boiler_energy_consumption[i + 1]
|
||||
else:
|
||||
# TODO: Other fuels should be considered
|
||||
boiler_fuel_consumption[i + 1] = (q_boiler[i + 1] * self.dt) / (
|
||||
float(boiler.heat_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))
|
||||
# heating coil operation
|
||||
if t_tank[i + 1] < 35:
|
||||
q_coil[i + 1] = heating_coil_nominal_output
|
||||
# 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)
|
||||
# total consumption
|
||||
total_consumption[i + 1] = q_hp[i + 1] + q_boiler[i + 1] + q_coil[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_energy_consumption]
|
||||
heating_coil_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in q_coil]
|
||||
hp_hourly = []
|
||||
boiler_hourly = []
|
||||
coil_hourly = []
|
||||
boiler_sum = 0
|
||||
hp_sum = 0
|
||||
coil_sum = 0
|
||||
for i in range(1, len(demand)):
|
||||
hp_sum += hp_electricity_j[i]
|
||||
boiler_sum += boiler_consumption_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)
|
||||
boiler_hourly.append(boiler_sum)
|
||||
coil_hourly.append(coil_sum)
|
||||
hp_sum = 0
|
||||
boiler_sum = 0
|
||||
coil_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])]
|
||||
if tes.heating_coil_capacity is not None:
|
||||
tes.heating_coil_energy_consumption[cte.HEATING] = {}
|
||||
tes.heating_coil_energy_consumption[cte.HEATING][cte.HOUR] = coil_hourly
|
||||
tes.heating_coil_energy_consumption[cte.HEATING][cte.MONTH] = MonthlyValues.get_total_month(
|
||||
tes.heating_coil_energy_consumption[cte.HEATING][cte.HOUR])
|
||||
tes.heating_coil_energy_consumption[cte.HEATING][cte.YEAR] = [
|
||||
sum(tes.heating_coil_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'] = source_temperature
|
||||
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 Power Consumption (W)'] = boiler_energy_consumption
|
||||
self.results['Boiler Supply Temperature'] = t_sup_boiler
|
||||
self.results['Boiler Fuel Consumption'] = boiler_fuel_consumption
|
||||
self.results['TES Temperature'] = t_tank
|
||||
self.results['Heating Coil heat input'] = q_coil
|
||||
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
|
||||
self.results['Total Heating Power Consumption (W)'] = total_consumption
|
||||
return self.results
|
@ -0,0 +1,54 @@
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HeatPump:
|
||||
def __init__(self, hp, t_out):
|
||||
self.hp = hp
|
||||
self.t_out = t_out
|
||||
|
||||
def hp_source_temperature(self):
|
||||
if self.hp.source_medium == cte.AIR:
|
||||
self.hp.source_temperature = self.t_out
|
||||
elif self.hp.source_medium == cte.GROUND:
|
||||
average_air_temperature = sum(self.t_out) / len(self.t_out)
|
||||
self.hp.source_temperature = [average_air_temperature + 10] * len(self.t_out)
|
||||
elif self.hp.source_medium == cte.WATER:
|
||||
self.hp.source_temperature = [15] * len(self.t_out)
|
||||
return self.hp.source_temperature
|
||||
|
||||
def air_to_water_cop(self, source_temperature, inlet_water_temperature, mode=cte.HEATING):
|
||||
cop_coefficient = 1
|
||||
t_inlet_water_fahrenheit = 1.8 * inlet_water_temperature + 32
|
||||
t_source_fahrenheit = 1.8 * source_temperature + 32
|
||||
if mode == cte.HEATING:
|
||||
if self.hp.heat_efficiency_curve is not None:
|
||||
cop_curve_coefficients = [float(coefficient) for coefficient in self.hp.heat_efficiency_curve.coefficients]
|
||||
cop_coefficient = (1 / (cop_curve_coefficients[0] +
|
||||
cop_curve_coefficients[1] * t_inlet_water_fahrenheit +
|
||||
cop_curve_coefficients[2] * t_inlet_water_fahrenheit ** 2 +
|
||||
cop_curve_coefficients[3] * t_source_fahrenheit +
|
||||
cop_curve_coefficients[4] * t_source_fahrenheit ** 2 +
|
||||
cop_curve_coefficients[5] * t_inlet_water_fahrenheit * t_source_fahrenheit))
|
||||
hp_efficiency = float(self.hp.heat_efficiency)
|
||||
elif mode == cte.COOLING:
|
||||
if self.hp.cooling_efficiency_curve is not None:
|
||||
cop_curve_coefficients = [float(coefficient) for coefficient in self.hp.cooling_efficiency_curve.coefficients]
|
||||
cop_coefficient = (1 / (cop_curve_coefficients[0] +
|
||||
cop_curve_coefficients[1] * t_inlet_water_fahrenheit +
|
||||
cop_curve_coefficients[2] * t_inlet_water_fahrenheit ** 2 +
|
||||
cop_curve_coefficients[3] * t_source_fahrenheit +
|
||||
cop_curve_coefficients[4] * t_source_fahrenheit ** 2 +
|
||||
cop_curve_coefficients[5] * t_inlet_water_fahrenheit * t_source_fahrenheit))
|
||||
hp_efficiency = float(self.hp.cooling_efficiency)
|
||||
else:
|
||||
if self.hp.heat_efficiency_curve is not None:
|
||||
cop_curve_coefficients = [float(coefficient) for coefficient in self.hp.heat_efficiency_curve.coefficients]
|
||||
cop_coefficient = (1 / (cop_curve_coefficients[0] +
|
||||
cop_curve_coefficients[1] * inlet_water_temperature +
|
||||
cop_curve_coefficients[2] * inlet_water_temperature ** 2 +
|
||||
cop_curve_coefficients[3] * source_temperature +
|
||||
cop_curve_coefficients[4] * source_temperature ** 2 +
|
||||
cop_curve_coefficients[5] * inlet_water_temperature * source_temperature))
|
||||
hp_efficiency = float(self.hp.heat_efficiency)
|
||||
hp_cop = cop_coefficient * hp_efficiency
|
||||
return hp_cop
|
@ -0,0 +1,86 @@
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.heat_pump_characteristics import HeatPump
|
||||
|
||||
|
||||
class HeatPumpCooling:
|
||||
def __init__(self, hp, hourly_cooling_demand_joules, cooling_peak_load_watts, cutoff_temperature, outdoor_temperature,
|
||||
dt=900):
|
||||
self.hp = hp
|
||||
self.cooling_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in hourly_cooling_demand_joules]
|
||||
self.cooling_peak_load = cooling_peak_load_watts
|
||||
self.cutoff_temperature = cutoff_temperature
|
||||
self.dt = dt
|
||||
self.results = {}
|
||||
self.heat_pump_characteristics = HeatPump(self.hp, outdoor_temperature)
|
||||
|
||||
def simulation(self):
|
||||
source_temperature_hourly = self.heat_pump_characteristics.hp_source_temperature()
|
||||
cooling_efficiency = float(self.hp.cooling_efficiency)
|
||||
number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt)
|
||||
demand = [0] + [x for x in self.cooling_demand for _ in range(number_of_ts)]
|
||||
source_temperature = [0] + [x for x in source_temperature_hourly for _ in range(number_of_ts)]
|
||||
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] = self.cutoff_temperature
|
||||
|
||||
for i in range(1, len(demand)):
|
||||
if demand[i] > 0.15 * self.cooling_peak_load:
|
||||
m[i] = self.hp.nominal_cooling_output / (cte.WATER_HEAT_CAPACITY * 5)
|
||||
if t_ret[i - 1] >= self.cutoff_temperature:
|
||||
if demand[i] < 0.25 * self.cooling_peak_load:
|
||||
q_hp[i] = 0.25 * self.hp.nominal_cooling_output
|
||||
elif demand[i] < 0.5 * self.cooling_peak_load:
|
||||
q_hp[i] = 0.5 * self.hp.nominal_cooling_output
|
||||
else:
|
||||
q_hp[i] = self.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]
|
||||
if q_hp[i] > 0:
|
||||
if self.hp.source_medium == cte.AIR and self.hp.supply_medium == cte.WATER:
|
||||
hp_cop[i] = self.heat_pump_characteristics.air_to_water_cop(source_temperature[i], t_ret[i],
|
||||
mode=cte.COOLING)
|
||||
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
|
||||
self.hp.energy_consumption[cte.COOLING] = {}
|
||||
self.hp.energy_consumption[cte.COOLING][cte.HOUR] = hp_hourly
|
||||
self.hp.energy_consumption[cte.COOLING][cte.MONTH] = MonthlyValues.get_total_month(
|
||||
self.hp.energy_consumption[cte.COOLING][cte.HOUR])
|
||||
self.hp.energy_consumption[cte.COOLING][cte.YEAR] = [
|
||||
sum(self.hp.energy_consumption[cte.COOLING][cte.MONTH])]
|
||||
self.results['Cooling Demand (W)'] = demand
|
||||
self.results['HP Cooling Output (W)'] = q_hp
|
||||
self.results['HP Source Temperature'] = source_temperature
|
||||
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 self.results
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,52 @@
|
||||
import math
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class StorageTank:
|
||||
"""
|
||||
Calculation of the temperature inside a hot water storage tank in the next time step
|
||||
"""
|
||||
|
||||
def __init__(self, volume, height, material_layers, heating_coil_capacity, stratification_layer=1):
|
||||
self.volume = volume
|
||||
self.height = height
|
||||
self.materials = material_layers
|
||||
self.number_of_vertical_layers = stratification_layer
|
||||
self.heating_coil_capacity = heating_coil_capacity
|
||||
|
||||
def heat_loss_coefficient(self):
|
||||
if self.number_of_vertical_layers == 1:
|
||||
r_tot = sum(float(layer.thickness) / float(layer.material.conductivity) for layer in
|
||||
self.materials)
|
||||
u_tot = 1 / r_tot
|
||||
d = math.sqrt((4 * self.volume) / (math.pi * self.height))
|
||||
a_side = math.pi * d * self.height
|
||||
a_top = math.pi * d ** 2 / 4
|
||||
ua = u_tot * (2 * a_top + a_side)
|
||||
return ua
|
||||
else:
|
||||
r_tot = sum(float(layer.thickness) / float(layer.material.conductivity) for layer in
|
||||
self.materials)
|
||||
u_tot = 1 / r_tot
|
||||
d = math.sqrt((4 * self.volume) / (math.pi * self.height))
|
||||
a_side = math.pi * d * self.height
|
||||
a_top = math.pi * d ** 2 / 4
|
||||
ua_side = u_tot * a_side
|
||||
ua_top_bottom = u_tot * (a_top + a_side)
|
||||
return ua_side, ua_top_bottom
|
||||
|
||||
def calculate_space_heating_fully_mixed(self, charging_flow_rate, discharging_flow_rate, supply_temperature, return_temperature,
|
||||
current_tank_temperature, heat_generator_input, ambient_temperature, dt):
|
||||
ua = self.heat_loss_coefficient()
|
||||
t_tank = (current_tank_temperature +
|
||||
(charging_flow_rate * (supply_temperature - current_tank_temperature) +
|
||||
(ua * (ambient_temperature - current_tank_temperature)) / cte.WATER_HEAT_CAPACITY -
|
||||
discharging_flow_rate * (current_tank_temperature - return_temperature) +
|
||||
heat_generator_input / cte.WATER_HEAT_CAPACITY) * (dt / (cte.WATER_DENSITY * self.volume)))
|
||||
return t_tank
|
||||
|
||||
def calculate_dhw_fully_mixed(self, charging_flow_rate, discharging_flow_rate, supply_temperature, return_temperature,
|
||||
current_tank_temperature, heat_generator_input, ambient_temperature, dt):
|
||||
pass
|
||||
|
@ -0,0 +1,35 @@
|
||||
"""
|
||||
EnergySystemSizingSimulationFactory retrieve the energy system archetype sizing and simulation module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2024 Concordia CERC group
|
||||
Project Coder Saeed Ranjbar saeed.ranjbar@mail.concordia.ca
|
||||
"""
|
||||
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.archetypes.montreal.archetype_cluster_1 import ArchetypeCluster1
|
||||
|
||||
|
||||
class MontrealEnergySystemArchetypesSimulationFactory:
|
||||
"""
|
||||
EnergySystemsFactory class
|
||||
"""
|
||||
|
||||
def __init__(self, handler, building, output_path):
|
||||
self._output_path = output_path
|
||||
self._handler = '_' + handler.lower()
|
||||
self._building = building
|
||||
|
||||
def _archetype_cluster_1(self):
|
||||
"""
|
||||
Enrich the city by using the sizing and simulation model developed for archetype13 of montreal_future_systems
|
||||
"""
|
||||
dt = 900
|
||||
ArchetypeCluster1(self._building, dt, self._output_path, csv_output=True).enrich_building()
|
||||
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)()
|
@ -0,0 +1,73 @@
|
||||
import hub.helpers.constants as cte
|
||||
class HourlyElectricityDemand:
|
||||
def __init__(self, building):
|
||||
self.building = building
|
||||
|
||||
def calculate(self):
|
||||
hourly_electricity_consumption = []
|
||||
energy_systems = self.building.energy_systems
|
||||
appliance = self.building.appliances_electrical_demand[cte.HOUR]
|
||||
lighting = self.building.lighting_electrical_demand[cte.HOUR]
|
||||
elec_heating = 0
|
||||
elec_cooling = 0
|
||||
elec_dhw = 0
|
||||
if cte.HEATING in self.building.energy_consumption_breakdown[cte.ELECTRICITY]:
|
||||
elec_heating = 1
|
||||
if cte.COOLING in self.building.energy_consumption_breakdown[cte.ELECTRICITY]:
|
||||
elec_cooling = 1
|
||||
if cte.DOMESTIC_HOT_WATER in self.building.energy_consumption_breakdown[cte.ELECTRICITY]:
|
||||
elec_dhw = 1
|
||||
heating = None
|
||||
cooling = None
|
||||
dhw = None
|
||||
|
||||
if elec_heating == 1:
|
||||
for energy_system in energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.fuel_type == cte.ELECTRICITY:
|
||||
if cte.HEATING in generation_system.energy_consumption:
|
||||
heating = generation_system.energy_consumption[cte.HEATING][cte.HOUR]
|
||||
else:
|
||||
if len(energy_system.generation_systems) > 1:
|
||||
heating = [x / 2 for x in self.building.heating_consumption[cte.HOUR]]
|
||||
else:
|
||||
heating = self.building.heating_consumption[cte.HOUR]
|
||||
|
||||
if elec_dhw == 1:
|
||||
for energy_system in energy_systems:
|
||||
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.fuel_type == cte.ELECTRICITY:
|
||||
if cte.DOMESTIC_HOT_WATER in generation_system.energy_consumption:
|
||||
dhw = generation_system.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR]
|
||||
else:
|
||||
if len(energy_system.generation_systems) > 1:
|
||||
dhw = [x / 2 for x in self.building.domestic_hot_water_consumption[cte.HOUR]]
|
||||
else:
|
||||
dhw = self.building.domestic_hot_water_consumption[cte.HOUR]
|
||||
|
||||
if elec_cooling == 1:
|
||||
for energy_system in energy_systems:
|
||||
if cte.COOLING in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if cte.COOLING in generation_system.energy_consumption:
|
||||
cooling = generation_system.energy_consumption[cte.COOLING][cte.HOUR]
|
||||
else:
|
||||
if len(energy_system.generation_systems) > 1:
|
||||
cooling = [x / 2 for x in self.building.cooling_consumption[cte.HOUR]]
|
||||
else:
|
||||
cooling = self.building.cooling_consumption[cte.HOUR]
|
||||
|
||||
for i in range(len(self.building.heating_demand[cte.HOUR])):
|
||||
hourly = 0
|
||||
hourly += appliance[i]
|
||||
hourly += lighting[i]
|
||||
if heating is not None:
|
||||
hourly += heating[i]
|
||||
if cooling is not None:
|
||||
hourly += cooling[i]
|
||||
if dhw is not None:
|
||||
hourly += dhw[i]
|
||||
hourly_electricity_consumption.append(hourly)
|
||||
return hourly_electricity_consumption
|
@ -1,7 +1,7 @@
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from scripts.geojson_creator import process_geojson
|
||||
from building_modelling.geojson_creator import process_geojson
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
@ -9,8 +9,8 @@ from hub.exports.exports_factory import ExportsFactory
|
||||
|
||||
|
||||
def pv_feasibility(current_x, current_y, current_diff, selected_buildings):
|
||||
input_files_path = (Path(__file__).parent.parent / 'input_files')
|
||||
output_path = (Path(__file__).parent.parent / 'out_files').resolve()
|
||||
input_files_path = (Path(__file__).parent.parent.parent.parent / 'input_files')
|
||||
output_path = (Path(__file__).parent.parent.parent.parent / 'out_files').resolve()
|
||||
sra_output_path = output_path / 'sra_outputs' / 'extended_city_sra_outputs'
|
||||
sra_output_path.mkdir(parents=True, exist_ok=True)
|
||||
new_diff = current_diff * 5
|
@ -0,0 +1,42 @@
|
||||
import math
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class PVModel:
|
||||
def __init__(self, pv, hourly_electricity_demand_joules, solar_radiation, installed_pv_area, model_type, ns=None,
|
||||
np=None):
|
||||
self.pv = pv
|
||||
self.hourly_electricity_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in hourly_electricity_demand_joules]
|
||||
self.solar_radiation = solar_radiation
|
||||
self.installed_pv_area = installed_pv_area
|
||||
self._model_type = '_' + model_type.lower()
|
||||
self.ns = ns
|
||||
self.np = np
|
||||
self.results = {}
|
||||
|
||||
def fixed_efficiency(self):
|
||||
module_efficiency = float(self.pv.electricity_efficiency)
|
||||
variable_names = ["pv_output", "import", "export", "self_sufficiency_ratio"]
|
||||
variables = {name: [0] * len(self.hourly_electricity_demand) for name in variable_names}
|
||||
(pv_out, grid_import, grid_export, self_sufficiency_ratio) = [variables[name] for name in variable_names]
|
||||
for i in range(len(self.hourly_electricity_demand)):
|
||||
pv_out[i] = module_efficiency * self.installed_pv_area * self.solar_radiation[i] / cte.WATTS_HOUR_TO_JULES
|
||||
if pv_out[i] < self.hourly_electricity_demand[i]:
|
||||
grid_import[i] = self.hourly_electricity_demand[i] - pv_out[i]
|
||||
else:
|
||||
grid_export[i] = pv_out[i] - self.hourly_electricity_demand[i]
|
||||
self_sufficiency_ratio[i] = pv_out[i] / self.hourly_electricity_demand[i]
|
||||
self.results['Electricity Demand (W)'] = self.hourly_electricity_demand
|
||||
self.results['PV Output (W)'] = pv_out
|
||||
self.results['Imported from Grid (W)'] = grid_import
|
||||
self.results['Exported to Grid (W)'] = grid_export
|
||||
self.results['Self Sufficiency Ratio'] = self_sufficiency_ratio
|
||||
return self.results
|
||||
|
||||
def enrich(self):
|
||||
"""
|
||||
Enrich the city given to the class using the class given handler
|
||||
:return: None
|
||||
"""
|
||||
return getattr(self, self._model_type, lambda: None)()
|
@ -0,0 +1,70 @@
|
||||
import math
|
||||
import hub.helpers.constants as cte
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.solar_angles import CitySolarAngles
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.radiation_tilted import RadiationTilted
|
||||
|
||||
|
||||
class PVSizing(CitySolarAngles):
|
||||
def __init__(self, city, tilt_angle, surface_azimuth=180, maintenance_factor=0.1, mechanical_equipment_factor=0.3,
|
||||
orientation_factor=0.1, system_type='rooftop'):
|
||||
super().__init__(location_latitude=city.latitude,
|
||||
location_longitude=city.longitude,
|
||||
tilt_angle=tilt_angle,
|
||||
surface_azimuth_angle=surface_azimuth)
|
||||
self.city = city
|
||||
self.maintenance_factor = maintenance_factor
|
||||
self.mechanical_equipment_factor = mechanical_equipment_factor
|
||||
self.orientation_factor = orientation_factor
|
||||
self.angles = self.calculate
|
||||
self.system_type = system_type
|
||||
|
||||
def rooftop_sizing(self):
|
||||
results = {}
|
||||
# Available Roof Area
|
||||
for building in self.city.buildings:
|
||||
for energy_system in building.energy_systems:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.system_type == cte.PHOTOVOLTAIC:
|
||||
module_width = float(generation_system.width)
|
||||
module_height = float(generation_system.height)
|
||||
roof_area = 0
|
||||
for roof in building.roofs:
|
||||
roof_area += roof.perimeter_area
|
||||
pv_module_area = module_width * module_height
|
||||
available_roof = ((self.maintenance_factor + self.orientation_factor + self.mechanical_equipment_factor) *
|
||||
roof_area)
|
||||
# Inter-Row Spacing
|
||||
winter_solstice = self.angles[(self.angles['AST'].dt.month == 12) &
|
||||
(self.angles['AST'].dt.day == 21) &
|
||||
(self.angles['AST'].dt.hour == 12)]
|
||||
solar_altitude = winter_solstice['solar altitude'].values[0]
|
||||
solar_azimuth = winter_solstice['solar azimuth'].values[0]
|
||||
distance = ((module_height * abs(math.cos(math.radians(solar_azimuth)))) /
|
||||
math.tan(math.radians(solar_altitude)))
|
||||
distance = float(format(distance, '.1f'))
|
||||
# Calculation of the number of panels
|
||||
space_dimension = math.sqrt(available_roof)
|
||||
space_dimension = float(format(space_dimension, '.2f'))
|
||||
panels_per_row = math.ceil(space_dimension / module_width)
|
||||
number_of_rows = math.ceil(space_dimension / distance)
|
||||
total_number_of_panels = panels_per_row * number_of_rows
|
||||
total_pv_area = panels_per_row * number_of_rows * pv_module_area
|
||||
building.roofs[0].installed_solar_collector_area = total_pv_area
|
||||
results[f'Building {building.name}'] = {'total_roof_area': roof_area,
|
||||
'PV dedicated area': available_roof,
|
||||
'total_pv_area': total_pv_area,
|
||||
'total_number_of_panels': total_number_of_panels,
|
||||
'number_of_rows': number_of_rows,
|
||||
'panels_per_row': panels_per_row}
|
||||
return results
|
||||
|
||||
def rooftop_tilted_radiation(self):
|
||||
for building in self.city.buildings:
|
||||
RadiationTilted(building=building,
|
||||
solar_angles=self.angles,
|
||||
tilt_angle=self.tilt_angle,
|
||||
ghi=building.roofs[0].global_irradiance[cte.HOUR],
|
||||
).enrich()
|
||||
|
||||
def facade_sizing(self):
|
||||
pass
|
@ -1,6 +1,6 @@
|
||||
import math
|
||||
|
||||
from scripts.radiation_tilted import RadiationTilted
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.radiation_tilted import RadiationTilted
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
@ -43,7 +43,7 @@ class PVSizingSimulation(RadiationTilted):
|
||||
self.total_number_of_panels = panels_per_row * number_of_rows
|
||||
return panels_per_row, number_of_rows
|
||||
|
||||
def pv_output(self):
|
||||
def pv_output_constant_efficiency(self):
|
||||
radiation = self.total_radiation_tilted
|
||||
pv_module_area = self.module_width * self.module_height
|
||||
available_roof = self.available_space()
|
@ -100,10 +100,7 @@ class RadiationTilted:
|
||||
|
||||
def enrich(self):
|
||||
tilted_radiation = self.total_radiation_tilted
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.HOUR] = [x * cte.WATTS_HOUR_TO_JULES for x in
|
||||
tilted_radiation]
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.HOUR] = [x * cte.WATTS_HOUR_TO_JULES for x in
|
||||
tilted_radiation]
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.HOUR] = tilted_radiation
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(self.building.roofs[0].global_irradiance_tilted[cte.HOUR]))
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.YEAR] = \
|
@ -5,9 +5,8 @@ from pathlib import Path
|
||||
|
||||
|
||||
class CitySolarAngles:
|
||||
def __init__(self, file_name, location_latitude, location_longitude, tilt_angle, surface_azimuth_angle,
|
||||
def __init__(self, location_latitude, location_longitude, tilt_angle, surface_azimuth_angle,
|
||||
standard_meridian=-75):
|
||||
self.file_name = file_name
|
||||
self.location_latitude = location_latitude
|
||||
self.location_longitude = location_longitude
|
||||
self.location_latitude_rad = math.radians(location_latitude)
|
||||
@ -29,7 +28,7 @@ class CitySolarAngles:
|
||||
self.incidents = []
|
||||
self.beam_tilted = []
|
||||
self.factor = []
|
||||
self.times = pd.date_range(start='2023-01-01', end='2024-01-01', freq='H', tz=self.timezone)
|
||||
self.times = pd.date_range(start='2023-01-01', end='2024-01-01', freq='h', tz=self.timezone)
|
||||
self.df = pd.DataFrame(index=self.times)
|
||||
self.day_of_year = self.df.index.dayofyear
|
||||
|
@ -0,0 +1,6 @@
|
||||
class HeuristicSizing:
|
||||
def __init__(self, city):
|
||||
pass
|
||||
|
||||
def enrich_buildings(self):
|
||||
pass
|
@ -0,0 +1,99 @@
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class PeakLoadSizing:
|
||||
def __init__(self, city, default_primary_unit_percentage=0.7, storage_peak_coverage=3):
|
||||
self.city = city
|
||||
self.default_primary_unit_percentage = default_primary_unit_percentage
|
||||
self.storage_peak_coverage = storage_peak_coverage
|
||||
|
||||
def enrich_buildings(self):
|
||||
total_demand = 0
|
||||
for building in self.city.buildings:
|
||||
energy_systems = building.energy_systems
|
||||
for energy_system in energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
total_demand = [(building.heating_demand[cte.HOUR][i] +
|
||||
building.domestic_hot_water_heat_demand[cte.HOUR][i]) / cte.WATTS_HOUR_TO_JULES
|
||||
for i in range(len(building.heating_demand[cte.HOUR]))]
|
||||
else:
|
||||
total_demand = building.heating_peak_load[cte.YEAR]
|
||||
design_load = max(total_demand)
|
||||
self.allocate_capacity(energy_system, design_load, cte.HEATING, self.default_primary_unit_percentage)
|
||||
if cte.COOLING in energy_system.demand_types:
|
||||
cooling_design_load = building.cooling_peak_load[cte.YEAR][0]
|
||||
self.allocate_capacity(energy_system, cooling_design_load, cte.COOLING,
|
||||
self.default_primary_unit_percentage)
|
||||
|
||||
elif cte.COOLING in energy_system.demand_types:
|
||||
design_load = building.cooling_peak_load[cte.YEAR][0]
|
||||
self.allocate_capacity(energy_system, design_load, cte.COOLING, self.default_primary_unit_percentage)
|
||||
elif cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
design_load = building.domestic_hot_water_peak_load[cte.YEAR][0]
|
||||
self.allocate_capacity(energy_system, design_load, cte.DOMESTIC_HOT_WATER,
|
||||
self.default_primary_unit_percentage)
|
||||
|
||||
for generation_system in energy_system.generation_systems:
|
||||
storage_systems = generation_system.energy_storage_systems
|
||||
if storage_systems is not None:
|
||||
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
operation_range = 10
|
||||
else:
|
||||
operation_range = 20
|
||||
for storage_system in storage_systems:
|
||||
if storage_system.type_energy_stored == cte.THERMAL:
|
||||
self.tes_sizing(storage_system, max(total_demand), self.storage_peak_coverage, operation_range)
|
||||
|
||||
def allocate_capacity(self, energy_system, design_load, demand_type, default_primary_unit_percentage):
|
||||
if len(energy_system.generation_systems) == 1:
|
||||
# If there's only one generation system, it gets the full design load.
|
||||
if demand_type == cte.HEATING or demand_type == cte.DOMESTIC_HOT_WATER:
|
||||
energy_system.generation_systems[0].nominal_heat_output = design_load
|
||||
elif demand_type == cte.COOLING:
|
||||
energy_system.generation_systems[0].nominal_cooling_output = design_load
|
||||
else:
|
||||
cooling_equipments_number = 0
|
||||
# Distribute the load among generation systems.
|
||||
max_efficiency = 0
|
||||
main_generation_unit = None
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if demand_type == cte.HEATING or demand_type == cte.DOMESTIC_HOT_WATER:
|
||||
if max_efficiency < float(generation_system.heat_efficiency):
|
||||
max_efficiency = float(generation_system.heat_efficiency)
|
||||
main_generation_unit = generation_system
|
||||
elif demand_type == cte.COOLING and generation_system.fuel_type == cte.ELECTRICITY:
|
||||
cooling_equipments_number += 1
|
||||
if max_efficiency < float(generation_system.cooling_efficiency):
|
||||
max_efficiency = float(generation_system.heat_efficiency)
|
||||
main_generation_unit = generation_system
|
||||
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.system_type == main_generation_unit.system_type:
|
||||
if demand_type == cte.HEATING or demand_type == cte.DOMESTIC_HOT_WATER:
|
||||
generation_system.nominal_heat_output = round(default_primary_unit_percentage * design_load)
|
||||
elif demand_type == cte.COOLING and cooling_equipments_number > 1:
|
||||
generation_system.nominal_cooling_output = round(default_primary_unit_percentage * design_load)
|
||||
else:
|
||||
generation_system.nominal_cooling_output = design_load
|
||||
else:
|
||||
if demand_type == cte.HEATING or demand_type == cte.DOMESTIC_HOT_WATER:
|
||||
generation_system.nominal_heat_output = round(((1 - default_primary_unit_percentage) * design_load /
|
||||
(len(energy_system.generation_systems) - 1)))
|
||||
elif demand_type == cte.COOLING and cooling_equipments_number > 1:
|
||||
generation_system.nominal_cooling_output = round(((1 - default_primary_unit_percentage) * design_load /
|
||||
(len(energy_system.generation_systems) - 1)))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def tes_sizing(storage, peak_load, coverage, operational_temperature_range):
|
||||
storage.volume = round((peak_load * coverage * cte.WATTS_HOUR_TO_JULES) /
|
||||
(cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * operational_temperature_range))
|
||||
|
||||
@staticmethod
|
||||
def cooling_equipments(energy_system):
|
||||
counter = 0
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.fuel_type == cte.ELECTRICITY:
|
||||
counter += 1
|
||||
return counter
|
@ -2,7 +2,7 @@ import os
|
||||
import hub.helpers.constants as cte
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import cm
|
||||
from scripts.report_creation import LatexReport
|
||||
from energy_system_modelling_package.report_creation import LatexReport
|
||||
from matplotlib.ticker import MaxNLocator
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
@ -565,7 +565,7 @@ class EnergySystemRetrofitReport:
|
||||
placement='H')
|
||||
self.report.add_section(f'{self.retrofit_scenario}')
|
||||
self.report.add_subsection('Proposed Systems')
|
||||
self.energy_system_archetype_schematic()
|
||||
# self.energy_system_archetype_schematic()
|
||||
if 'PV' in self.retrofit_scenario:
|
||||
self.report.add_subsection('Rooftop Photovoltaic System Implementation')
|
||||
self.pv_system()
|
@ -5,10 +5,10 @@ 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
|
||||
from energy_system_modelling_package.system_simulation_models.archetype13 import Archetype13
|
||||
from energy_system_modelling_package.system_simulation_models.archetype13_stratified_tes import Archetype13Stratified
|
||||
from energy_system_modelling_package.system_simulation_models.archetype1 import Archetype1
|
||||
from energy_system_modelling_package.system_simulation_models.archetypes14_15 import Archetype14_15
|
||||
|
||||
|
||||
class EnergySystemsSimulationFactory:
|
@ -28,13 +28,21 @@ residential_systems_percentage = {'system 1 gas': 15,
|
||||
'system 8 gas': 15,
|
||||
'system 8 electricity': 35}
|
||||
|
||||
residential_new_systems_percentage = {'PV+ASHP+GasBoiler+TES': 0,
|
||||
'PV+4Pipe+DHW': 100,
|
||||
'PV+ASHP+ElectricBoiler+TES': 0,
|
||||
'PV+GSHP+GasBoiler+TES': 0,
|
||||
'PV+GSHP+ElectricBoiler+TES': 0,
|
||||
'PV+WSHP+GasBoiler+TES': 0,
|
||||
'PV+WSHP+ElectricBoiler+TES': 0}
|
||||
residential_new_systems_percentage = {
|
||||
'Central 4 Pipes Air to Water Heat Pump and Gas Boiler with Independent Water Heating and PV': 100,
|
||||
'Central 4 Pipes Air to Water Heat Pump and electrical Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and Gas Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and electrical Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and Gas Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and electrical Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Air to Water Heat Pump and Gas Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Air to Water Heat Pump and electrical Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and Gas Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and electrical Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and Gas Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and electrical Boiler with Independent Water Heating': 0,
|
||||
'Rooftop PV System': 0
|
||||
}
|
||||
|
||||
non_residential_systems_percentage = {'system 1 gas': 0,
|
||||
'system 1 electricity': 0,
|
@ -1,26 +1,25 @@
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from scripts.ep_run_enrich import energy_plus_workflow
|
||||
from building_modelling.ep_run_enrich import energy_plus_workflow
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.montreal_energy_system_archetype_modelling_factory import \
|
||||
MontrealEnergySystemArchetypesSimulationFactory
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_feasibility import \
|
||||
pv_feasibility
|
||||
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 scripts.energy_system_retrofit_report import EnergySystemRetrofitReport
|
||||
from scripts.geojson_creator import process_geojson
|
||||
from scripts import random_assignation
|
||||
from energy_system_modelling_package.energy_system_retrofit.energy_system_retrofit_report import EnergySystemRetrofitReport
|
||||
from building_modelling.geojson_creator import process_geojson
|
||||
from energy_system_modelling_package import random_assignation
|
||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||
from scripts.energy_system_sizing import SystemSizing
|
||||
from scripts.solar_angles import CitySolarAngles
|
||||
from scripts.pv_sizing_and_simulation import PVSizingSimulation
|
||||
from scripts.energy_system_retrofit_results import consumption_data, cost_data
|
||||
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
|
||||
from scripts.costs.cost import Cost
|
||||
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
|
||||
import hub.helpers.constants as cte
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.energy_system_sizing_factory import EnergySystemsSizingFactory
|
||||
from energy_system_modelling_package.energy_system_retrofit.energy_system_retrofit_results import consumption_data, cost_data
|
||||
from costing_package.cost import Cost
|
||||
from costing_package.constants import SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from scripts.pv_feasibility import pv_feasibility
|
||||
|
||||
# Specify the GeoJSON file path
|
||||
input_files_path = (Path(__file__).parent / 'input_files')
|
||||
@ -52,14 +51,9 @@ subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', city, sra_output_path).enrich()
|
||||
pv_feasibility(-73.5681295982132, 45.49218262677643, 0.0001, selected_buildings=city.buildings)
|
||||
energy_plus_workflow(city, energy_plus_output_path)
|
||||
solar_angles = CitySolarAngles(city.name,
|
||||
city.latitude,
|
||||
city.longitude,
|
||||
tilt_angle=45,
|
||||
surface_azimuth_angle=180).calculate
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_systems_percentage)
|
||||
EnergySystemsFactory('montreal_custom', city).enrich()
|
||||
SystemSizing(city.buildings).montreal_custom()
|
||||
EnergySystemsSizingFactory('peak_load_sizing', city).enrich()
|
||||
current_status_energy_consumption = consumption_data(city)
|
||||
current_status_life_cycle_cost = {}
|
||||
for building in city.buildings:
|
||||
@ -71,18 +65,12 @@ for building in city.buildings:
|
||||
current_status_life_cycle_cost[f'{building.name}'] = cost_data(building, lcc_dataframe, cost_retrofit_scenario)
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
|
||||
EnergySystemsFactory('montreal_future', city).enrich()
|
||||
EnergySystemsSizingFactory('pv_sizing', city).enrich()
|
||||
EnergySystemsSizingFactory('peak_load_sizing', city).enrich()
|
||||
for building in city.buildings:
|
||||
if 'PV' in building.energy_systems_archetype_name:
|
||||
ghi = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]]
|
||||
pv_sizing_simulation = PVSizingSimulation(building,
|
||||
solar_angles,
|
||||
tilt_angle=45,
|
||||
module_height=1,
|
||||
module_width=2,
|
||||
ghi=ghi)
|
||||
pv_sizing_simulation.pv_output()
|
||||
if building.energy_systems_archetype_name == 'PV+4Pipe+DHW':
|
||||
EnergySystemsSimulationFactory('archetype13', building=building, output_path=simulation_results_path).enrich()
|
||||
MontrealEnergySystemArchetypesSimulationFactory(f'archetype_cluster_{building.energy_systems_archetype_cluster_id}',
|
||||
building,
|
||||
simulation_results_path).enrich()
|
||||
retrofitted_energy_consumption = consumption_data(city)
|
||||
retrofitted_life_cycle_cost = {}
|
||||
for building in city.buildings:
|
||||
|
@ -15,11 +15,20 @@ class Archetype:
|
||||
"""
|
||||
Archetype class
|
||||
"""
|
||||
def __init__(self, name, systems):
|
||||
|
||||
def __init__(self, name, systems, archetype_cluster_id=None):
|
||||
self._cluster_id = archetype_cluster_id
|
||||
self._name = name
|
||||
self._systems = systems
|
||||
|
||||
@property
|
||||
def cluster_id(self):
|
||||
"""
|
||||
Get id
|
||||
:return: string
|
||||
"""
|
||||
return self._cluster_id
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
@ -43,8 +52,9 @@ class Archetype:
|
||||
_systems.append(_system.to_dictionary())
|
||||
content = {
|
||||
'Archetype': {
|
||||
'cluster_id': self.cluster_id,
|
||||
'name': self.name,
|
||||
'systems': _systems
|
||||
}
|
||||
}
|
||||
}
|
||||
return content
|
||||
|
@ -17,8 +17,9 @@ class PvGenerationSystem(GenerationSystem):
|
||||
def __init__(self, system_id, name, system_type, model_name=None, manufacturer=None, electricity_efficiency=None,
|
||||
nominal_electricity_output=None, nominal_ambient_temperature=None, nominal_cell_temperature=None,
|
||||
nominal_radiation=None, standard_test_condition_cell_temperature=None,
|
||||
standard_test_condition_maximum_power=None, cell_temperature_coefficient=None, width=None, height=None,
|
||||
distribution_systems=None, energy_storage_systems=None):
|
||||
standard_test_condition_maximum_power=None, standard_test_condition_radiation=None,
|
||||
cell_temperature_coefficient=None, width=None, height=None, distribution_systems=None,
|
||||
energy_storage_systems=None):
|
||||
super().__init__(system_id=system_id, name=name, model_name=model_name,
|
||||
manufacturer=manufacturer, fuel_type='renewable', distribution_systems=distribution_systems,
|
||||
energy_storage_systems=energy_storage_systems)
|
||||
@ -30,6 +31,7 @@ class PvGenerationSystem(GenerationSystem):
|
||||
self._nominal_radiation = nominal_radiation
|
||||
self._standard_test_condition_cell_temperature = standard_test_condition_cell_temperature
|
||||
self._standard_test_condition_maximum_power = standard_test_condition_maximum_power
|
||||
self._standard_test_condition_radiation = standard_test_condition_radiation
|
||||
self._cell_temperature_coefficient = cell_temperature_coefficient
|
||||
self._width = width
|
||||
self._height = height
|
||||
@ -98,6 +100,15 @@ class PvGenerationSystem(GenerationSystem):
|
||||
"""
|
||||
return self._standard_test_condition_maximum_power
|
||||
|
||||
@property
|
||||
def standard_test_condition_radiation(self):
|
||||
"""
|
||||
Get standard test condition cell temperature of PV panels in W/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._standard_test_condition_radiation
|
||||
|
||||
|
||||
@property
|
||||
def cell_temperature_coefficient(self):
|
||||
"""
|
||||
@ -143,6 +154,7 @@ class PvGenerationSystem(GenerationSystem):
|
||||
'nominal radiation [W/m2]': self.nominal_radiation,
|
||||
'standard test condition cell temperature [Celsius]': self.standard_test_condition_cell_temperature,
|
||||
'standard test condition maximum power [W]': self.standard_test_condition_maximum_power,
|
||||
'standard test condition radiation [W/m2]': self.standard_test_condition_radiation,
|
||||
'cell temperature coefficient': self.cell_temperature_coefficient,
|
||||
'width': self.width,
|
||||
'height': self.height,
|
||||
|
@ -193,6 +193,7 @@ class MontrealFutureSystemCatalogue(Catalog):
|
||||
nominal_radiation = pv['nominal_radiation']
|
||||
standard_test_condition_cell_temperature = pv['standard_test_condition_cell_temperature']
|
||||
standard_test_condition_maximum_power = pv['standard_test_condition_maximum_power']
|
||||
standard_test_condition_radiation = pv['standard_test_condition_radiation']
|
||||
cell_temperature_coefficient = pv['cell_temperature_coefficient']
|
||||
width = pv['width']
|
||||
height = pv['height']
|
||||
@ -215,6 +216,7 @@ class MontrealFutureSystemCatalogue(Catalog):
|
||||
standard_test_condition_cell_temperature=
|
||||
standard_test_condition_cell_temperature,
|
||||
standard_test_condition_maximum_power=standard_test_condition_maximum_power,
|
||||
standard_test_condition_radiation=standard_test_condition_radiation,
|
||||
cell_temperature_coefficient=cell_temperature_coefficient,
|
||||
width=width,
|
||||
height=height,
|
||||
@ -379,6 +381,7 @@ class MontrealFutureSystemCatalogue(Catalog):
|
||||
_system_archetypes = []
|
||||
system_clusters = self._archetypes['EnergySystemCatalog']['system_archetypes']['system_archetype']
|
||||
for system_cluster in system_clusters:
|
||||
archetype_id = system_cluster['@cluster_id']
|
||||
name = system_cluster['name']
|
||||
systems = system_cluster['systems']['system_id']
|
||||
integer_system_ids = [int(item) for item in systems]
|
||||
@ -386,7 +389,7 @@ class MontrealFutureSystemCatalogue(Catalog):
|
||||
for system_archetype in self._systems:
|
||||
if int(system_archetype.id) in integer_system_ids:
|
||||
_systems.append(system_archetype)
|
||||
_system_archetypes.append(Archetype(name=name, systems=_systems))
|
||||
_system_archetypes.append(Archetype(archetype_cluster_id=archetype_id, name=name, systems=_systems))
|
||||
return _system_archetypes
|
||||
|
||||
def _load_materials(self):
|
||||
|
@ -92,7 +92,7 @@ class Building(CityObject):
|
||||
logging.error('Building %s [%s] has an unexpected surface type %s.', self.name, self.aliases, surface.type)
|
||||
self._domestic_hot_water_peak_load = None
|
||||
self._fuel_consumption_breakdown = {}
|
||||
self._pv_generation = {}
|
||||
self._systems_archetype_cluster_id = None
|
||||
|
||||
@property
|
||||
def shell(self) -> Polyhedron:
|
||||
@ -857,8 +857,8 @@ class Building(CityObject):
|
||||
storage_systems = generation_system.energy_storage_systems
|
||||
if storage_systems:
|
||||
for storage_system in storage_systems:
|
||||
if storage_system.type_energy_stored == 'thermal' and storage_system.heating_coil_energy_consumption:
|
||||
fuel_breakdown[cte.ELECTRICITY][f'{demand_type}'] += storage_system.heating_coil_energy_consumption[cte.YEAR][0]
|
||||
if storage_system.type_energy_stored == 'thermal' and storage_system.heating_coil_capacity is not None:
|
||||
fuel_breakdown[cte.ELECTRICITY][f'{demand_type}'] += storage_system.heating_coil_energy_consumption[f'{demand_type}'][cte.YEAR][0]
|
||||
#TODO: When simulation models of all energy system archetypes are created, this part can be removed
|
||||
heating_fuels = []
|
||||
dhw_fuels = []
|
||||
@ -890,3 +890,19 @@ class Building(CityObject):
|
||||
self._fuel_consumption_breakdown = fuel_breakdown
|
||||
return self._fuel_consumption_breakdown
|
||||
|
||||
@property
|
||||
def energy_systems_archetype_cluster_id(self):
|
||||
"""
|
||||
Get energy systems archetype id
|
||||
:return: str
|
||||
"""
|
||||
return self._systems_archetype_cluster_id
|
||||
|
||||
@energy_systems_archetype_cluster_id.setter
|
||||
def energy_systems_archetype_cluster_id(self, value):
|
||||
"""
|
||||
Set energy systems archetype id
|
||||
:param value: str
|
||||
"""
|
||||
self._systems_archetype_cluster_id = value
|
||||
|
||||
|
@ -18,7 +18,6 @@ from hub.city_model_structure.attributes.point import Point
|
||||
from hub.city_model_structure.greenery.vegetation import Vegetation
|
||||
from hub.city_model_structure.building_demand.thermal_boundary import ThermalBoundary
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.configuration_helper import ConfigurationHelper
|
||||
|
||||
|
||||
class Surface:
|
||||
@ -157,6 +156,7 @@ class Surface:
|
||||
if self._inclination is None:
|
||||
self._inclination = np.arccos(self.perimeter_polygon.normal[2])
|
||||
return self._inclination
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
"""
|
||||
@ -167,10 +167,10 @@ class Surface:
|
||||
"""
|
||||
if self._type is None:
|
||||
inclination_cos = math.cos(self.inclination)
|
||||
# 170 degrees
|
||||
# 170 degrees
|
||||
if inclination_cos <= -0.98:
|
||||
self._type = 'Ground'
|
||||
# between 80 and 100 degrees
|
||||
# between 80 and 100 degrees
|
||||
elif abs(inclination_cos) <= 0.17:
|
||||
self._type = 'Wall'
|
||||
else:
|
||||
@ -365,12 +365,12 @@ class Surface:
|
||||
_protected_building_restriction = 1
|
||||
# 10 degrees range
|
||||
if abs(math.sin(self.inclination)) < 0.17:
|
||||
# horizontal
|
||||
# horizontal
|
||||
_construction_restriction = 0.8
|
||||
_separation_of_panels = 0.46
|
||||
_shadow_between_panels = 0.7
|
||||
else:
|
||||
# tilted
|
||||
# tilted
|
||||
_construction_restriction = 0.9
|
||||
_separation_of_panels = 0.9
|
||||
_shadow_between_panels = 1
|
||||
@ -417,4 +417,4 @@ class Surface:
|
||||
Set installed solar collector area in m2
|
||||
:return: dict
|
||||
"""
|
||||
self._installed_solar_collector_area = value
|
||||
self._installed_solar_collector_area = value
|
||||
|
@ -24,7 +24,7 @@ class ThermalStorageSystem(EnergyStorageSystem):
|
||||
self._maximum_operating_temperature = None
|
||||
self._heating_coil_capacity = None
|
||||
self._temperature = None
|
||||
self._heating_coil_energy_consumption = None
|
||||
self._heating_coil_energy_consumption = {}
|
||||
|
||||
@property
|
||||
def volume(self):
|
||||
|
@ -457,6 +457,7 @@
|
||||
<nominal_cell_temperature/>
|
||||
<nominal_radiation/>
|
||||
<standard_test_condition_cell_temperature/>
|
||||
<standard_test_condition_radiation/>
|
||||
<standard_test_condition_maximum_power/>
|
||||
<cell_temperature_coefficient/>
|
||||
<width>2.01</width>
|
||||
@ -911,7 +912,7 @@
|
||||
<nominal_cooling_output/>
|
||||
<minimum_cooling_output/>
|
||||
<maximum_cooling_output/>
|
||||
<cooling_efficiency>4.5</cooling_efficiency>
|
||||
<cooling_efficiency>4</cooling_efficiency>
|
||||
<electricity_efficiency/>
|
||||
<source_temperature/>
|
||||
<source_mass_flow/>
|
||||
@ -962,7 +963,7 @@
|
||||
<nominal_cooling_output/>
|
||||
<minimum_cooling_output/>
|
||||
<maximum_cooling_output/>
|
||||
<cooling_efficiency/>
|
||||
<cooling_efficiency>5</cooling_efficiency>
|
||||
<electricity_efficiency/>
|
||||
<source_temperature/>
|
||||
<source_mass_flow/>
|
||||
@ -993,7 +994,7 @@
|
||||
<nominal_heat_output/>
|
||||
<minimum_heat_output/>
|
||||
<maximum_heat_output/>
|
||||
<heat_efficiency>3.5</heat_efficiency>
|
||||
<heat_efficiency>4</heat_efficiency>
|
||||
<reversible>True</reversible>
|
||||
<fuel_type>electricity</fuel_type>
|
||||
<source_medium>Water</source_medium>
|
||||
@ -1001,7 +1002,7 @@
|
||||
<nominal_cooling_output/>
|
||||
<minimum_cooling_output/>
|
||||
<maximum_cooling_output/>
|
||||
<cooling_efficiency/>
|
||||
<cooling_efficiency>6</cooling_efficiency>
|
||||
<electricity_efficiency/>
|
||||
<source_temperature/>
|
||||
<source_mass_flow/>
|
||||
@ -1035,9 +1036,10 @@
|
||||
<nominal_cell_temperature/>
|
||||
<nominal_radiation/>
|
||||
<standard_test_condition_cell_temperature/>
|
||||
<standard_test_condition_radiation/>
|
||||
<standard_test_condition_maximum_power/>
|
||||
<cell_temperature_coefficient/>
|
||||
<width>1.0</width>
|
||||
<width>2.0</width>
|
||||
<height>1.0</height>
|
||||
<distribution_systems/>
|
||||
<energy_storage_systems/>
|
||||
@ -1180,7 +1182,8 @@
|
||||
<insulation>
|
||||
<material_id>1</material_id>
|
||||
<insulationThickness>90.0</insulationThickness>
|
||||
</insulation> <physical_characteristics>
|
||||
</insulation>
|
||||
<physical_characteristics>
|
||||
<material_id>2</material_id>
|
||||
<tankThickness>0</tankThickness>
|
||||
<height>1.5</height>
|
||||
@ -1309,89 +1312,6 @@
|
||||
<systems>
|
||||
<system>
|
||||
<id>1</id>
|
||||
<name>4 pipe storage equipped air source heat pump and gas boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>21</generation_id>
|
||||
<generation_id>18</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>2</id>
|
||||
<name>4 pipe storage equipped air source heat pump and electrical boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
<demand>domestic_hot_water</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>22</generation_id>
|
||||
<generation_id>18</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>3</id>
|
||||
<name>4 pipe storage equipped ground source heat pump and gas boiler</name>
|
||||
<schema>schemas/GSHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
<demand>domestic_hot_water</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>21</generation_id>
|
||||
<generation_id>19</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>4</id>
|
||||
<name>4 pipe storage equipped ground source heat pump and electrical boiler</name>
|
||||
<schema>schemas/GSHP+TES+ElectricBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
<demand>domestic_hot_water</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>22</generation_id>
|
||||
<generation_id>19</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>5</id>
|
||||
<name>4 pipe storage equipped ground source heat pump and gas boiler</name>
|
||||
<schema>schemas/WSHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
<demand>domestic_hot_water</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>21</generation_id>
|
||||
<generation_id>20</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>6</id>
|
||||
<name>4 pipe storage equipped ground source heat pump and electrical boiler</name>
|
||||
<schema>schemas/WSHP+TES+ElectricBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
<demand>domestic_hot_water</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>22</generation_id>
|
||||
<generation_id>20</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>7</id>
|
||||
<name>Photovoltaic System</name>
|
||||
<schema>schemas/PV.jpg</schema>
|
||||
<demands>
|
||||
@ -1402,8 +1322,8 @@
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>8</id>
|
||||
<name>4 pipe system with air source heat pump storage and gas boiler</name>
|
||||
<id>2</id>
|
||||
<name>4 pipe central air to water heat pump with storage tank and gas boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
@ -1415,20 +1335,177 @@
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>9</id>
|
||||
<name>4 pipe system with air source heat pump storage and electric boiler</name>
|
||||
<id>3</id>
|
||||
<name>4 pipe central air to water heat pump with storage tank and electric boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>22</generation_id>
|
||||
<generation_id>18</generation_id>
|
||||
<generation_id>23</generation_id>
|
||||
<generation_id>17</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>4</id>
|
||||
<name>4 pipe central ground to water heat pump with storage tank and gas boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>24</generation_id>
|
||||
<generation_id>16</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>5</id>
|
||||
<name>4 pipe central ground to water heat pump with storage tank and electric boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>24</generation_id>
|
||||
<generation_id>17</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>6</id>
|
||||
<name>4 pipe central water to water heat pump with storage tank and gas boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>25</generation_id>
|
||||
<generation_id>16</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>7</id>
|
||||
<name>4 pipe central water to water heat pump with storage tank and electric boiler</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>25</generation_id>
|
||||
<generation_id>17</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>8</id>
|
||||
<name>district heating network with air to water heat pump gas boiler thermal storage tank</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>23</generation_id>
|
||||
<generation_id>16</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>9</id>
|
||||
<name>district heating network with air to water heat pump electrical boiler thermal storage tank</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>23</generation_id>
|
||||
<generation_id>17</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>10</id>
|
||||
<name>district heating network with ground to water heat pump gas boiler thermal storage tank</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>24</generation_id>
|
||||
<generation_id>16</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>11</id>
|
||||
<name>district heating network with ground to water heat pump electrical boiler thermal storage tank</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>24</generation_id>
|
||||
<generation_id>17</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>12</id>
|
||||
<name>district heating network with water to water heat pump gas boiler thermal storage tank</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>25</generation_id>
|
||||
<generation_id>16</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>13</id>
|
||||
<name>district heating network with water to water heat pump electrical boiler thermal storage tank</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>25</generation_id>
|
||||
<generation_id>17</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>14</id>
|
||||
<name>Unitary air to water heat pump cooling system</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>23</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>15</id>
|
||||
<name>Unitary ground to water heat pump cooling system</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>24</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>16</id>
|
||||
<name>unitary water to water heat pump cooling system</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>25</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>17</id>
|
||||
<name>Domestic Hot Water Heat Pump with Coiled Storage</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
@ -1438,134 +1515,103 @@
|
||||
<generation_id>27</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>11</id>
|
||||
<name>Central Heating System َASHP Gas-Boiler TES</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>heating</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>23</generation_id>
|
||||
<generation_id>16</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
<system>
|
||||
<id>12</id>
|
||||
<name>Unitary ASHP Cooling System</name>
|
||||
<schema>schemas/ASHP+TES+GasBoiler.jpg</schema>
|
||||
<demands>
|
||||
<demand>cooling</demand>
|
||||
</demands>
|
||||
<components>
|
||||
<generation_id>23</generation_id>
|
||||
</components>
|
||||
</system>
|
||||
</systems>
|
||||
|
||||
<system_archetypes>
|
||||
<system_archetype id="1">
|
||||
<name>PV+ASHP+GasBoiler+TES</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>1</system_id>
|
||||
<system_id>10</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="2">
|
||||
<name>PV+ASHP+ElectricBoiler+TES</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>2</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="3">
|
||||
<name>PV+GSHP+GasBoiler+TES</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>3</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="4">
|
||||
<name>PV+GSHP+ElectricBoiler+TES</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>4</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="5">
|
||||
<name>PV+WSHP+GasBoiler+TES</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>5</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="6">
|
||||
<name>PV+WSHP+ElectricBoiler+TES</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>6</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="7">
|
||||
<name>ASHP+GasBoiler+TES</name>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Air to Water Heat Pump and Gas Boiler with Independent Water Heating and PV</name>
|
||||
<systems>
|
||||
<system_id>1</system_id>
|
||||
<system_id>2</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="8">
|
||||
<name>ASHP+ElectricBoiler+TES</name>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Air to Water Heat Pump and electrical Boiler with Independent Water Heating and PV</name>
|
||||
<systems>
|
||||
<system_id>1</system_id>
|
||||
<system_id>3</system_id>
|
||||
<system_id>8</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Ground to Water Heat Pump and Gas Boiler with Independent Water Heating and PV</name>
|
||||
<systems>
|
||||
<system_id>1</system_id>
|
||||
<system_id>4</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Ground to Water Heat Pump and electrical Boiler with Independent Water Heating and PV</name>
|
||||
<systems>
|
||||
<system_id>1</system_id>
|
||||
<system_id>5</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Water to Water Heat Pump and Gas Boiler with Independent Water Heating and PV</name>
|
||||
<systems>
|
||||
<system_id>1</system_id>
|
||||
<system_id>6</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Water to Water Heat Pump and electrical Boiler with Independent Water Heating and PV</name>
|
||||
<systems>
|
||||
<system_id>1</system_id>
|
||||
<system_id>7</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Air to Water Heat Pump and Gas Boiler with Independent Water Heating</name>
|
||||
<systems>
|
||||
<system_id>2</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="9">
|
||||
<name>GSHP+GasBoiler+TES</name>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Air to Water Heat Pump and electrical Boiler with Independent Water Heating</name>
|
||||
<systems>
|
||||
<system_id>3</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="10">
|
||||
<name>GSHP+ElectricBoiler+TES</name>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Ground to Water Heat Pump and Gas Boiler with Independent Water Heating</name>
|
||||
<systems>
|
||||
<system_id>4</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="11">
|
||||
<name>WSHP+GasBoiler+TES</name>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Ground to Water Heat Pump and electrical Boiler with Independent Water Heating</name>
|
||||
<systems>
|
||||
<system_id>5</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="12">
|
||||
<name>WSHP+ElectricBoiler+TES</name>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Water to Water Heat Pump and Gas Boiler with Independent Water Heating</name>
|
||||
<systems>
|
||||
<system_id>6</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="13">
|
||||
<name>PV+4Pipe+DHW</name>
|
||||
<system_archetype cluster_id="1">
|
||||
<name>Central 4 Pipes Water to Water Heat Pump and electrical Boiler with Independent Water Heating</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>8</system_id>
|
||||
<system_id>10</system_id>
|
||||
<system_id>17</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="14">
|
||||
<name>Central Heating+Unitary Cooling+Unitary DHW</name>
|
||||
<system_archetype cluster_id="2">
|
||||
<name>Rooftop PV System</name>
|
||||
<systems>
|
||||
<system_id>10</system_id>
|
||||
<system_id>11</system_id>
|
||||
<system_id>12</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
<system_archetype id="15">
|
||||
<name>Central Heating+Unitary Cooling+Unitary DHW+PV</name>
|
||||
<systems>
|
||||
<system_id>7</system_id>
|
||||
<system_id>10</system_id>
|
||||
<system_id>11</system_id>
|
||||
<system_id>12</system_id>
|
||||
<system_id>1</system_id>
|
||||
</systems>
|
||||
</system_archetype>
|
||||
</system_archetypes>
|
||||
|
@ -7,6 +7,9 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
||||
Oriol Gavalda Torrellas oriol.gavalda@concordia.ca
|
||||
"""
|
||||
import copy
|
||||
import datetime
|
||||
import glob
|
||||
import os
|
||||
from pathlib import Path
|
||||
from geomeppy import IDF
|
||||
import hub.helpers.constants as cte
|
||||
@ -275,11 +278,12 @@ class Idf:
|
||||
_kwargs[f'Field_{counter + 2}'] = 'Until: 24:00,0.0'
|
||||
self._idf.newidfobject(self._COMPACT_SCHEDULE, **_kwargs)
|
||||
|
||||
def _write_schedules_file(self, usage, schedule):
|
||||
file_name = str((Path(self._output_path) / f'{schedule.type} schedules {usage}.csv').resolve())
|
||||
with open(file_name, 'w', encoding='utf8') as file:
|
||||
for value in schedule.values:
|
||||
file.write(f'{str(value)},\n')
|
||||
def _write_schedules_file(self, schedule, usage):
|
||||
file_name = str((Path(self._output_path) / f'{schedule.type} schedules {usage.replace("/","_")}.csv').resolve())
|
||||
if not Path(file_name).exists():
|
||||
with open(file_name, 'w', encoding='utf8') as file:
|
||||
for value in schedule.values:
|
||||
file.write(f'{str(value)},\n')
|
||||
return Path(file_name).name
|
||||
|
||||
def _add_file_schedule(self, usage, schedule, file_name):
|
||||
@ -304,7 +308,7 @@ class Idf:
|
||||
for schedule in self._idf.idfobjects[self._FILE_SCHEDULE]:
|
||||
if schedule.Name == f'{schedule_type} schedules {usage}':
|
||||
return
|
||||
file_name = self._write_schedules_file(usage, new_schedules[0])
|
||||
file_name = self._write_schedules_file(new_schedules[0], usage)
|
||||
self._add_file_schedule(usage, new_schedules[0], file_name)
|
||||
return
|
||||
|
||||
@ -321,7 +325,7 @@ class Idf:
|
||||
if construction.Name == vegetation_name:
|
||||
return
|
||||
else:
|
||||
if construction.Name == thermal_boundary.construction_name:
|
||||
if construction.Name == f'{thermal_boundary.construction_name} {thermal_boundary.parent_surface.type}':
|
||||
return
|
||||
if thermal_boundary.layers is None:
|
||||
for material in self._idf.idfobjects[self._MATERIAL]:
|
||||
@ -340,7 +344,8 @@ class Idf:
|
||||
for i in range(0, len(layers) - 1):
|
||||
_kwargs[f'Layer_{i + 2}'] = layers[i].material_name
|
||||
else:
|
||||
_kwargs = {'Name': thermal_boundary.construction_name, 'Outside_Layer': layers[0].material_name}
|
||||
_kwargs = {'Name': f'{thermal_boundary.construction_name} {thermal_boundary.parent_surface.type}',
|
||||
'Outside_Layer': layers[0].material_name}
|
||||
for i in range(1, len(layers) - 1):
|
||||
_kwargs[f'Layer_{i + 1}'] = layers[i].material_name
|
||||
self._idf.newidfobject(self._CONSTRUCTION, **_kwargs)
|
||||
@ -470,7 +475,7 @@ class Idf:
|
||||
Air_Changes_per_Hour=_air_change
|
||||
)
|
||||
|
||||
def _add_dhw(self, thermal_zone, zone_name):
|
||||
def _add_dhw(self, thermal_zone, zone_name, usage):
|
||||
peak_flow_rate = thermal_zone.domestic_hot_water.peak_flow * thermal_zone.total_floor_area
|
||||
self._idf.newidfobject(self._DHW,
|
||||
Name=f'DHW {zone_name}',
|
||||
@ -478,7 +483,7 @@ class Idf:
|
||||
Flow_Rate_Fraction_Schedule_Name=f'DHW_prof schedules {thermal_zone.usage_name}',
|
||||
Target_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
||||
Hot_Water_Supply_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
||||
Cold_Water_Supply_Temperature_Schedule_Name=f'cold_temp schedules {zone_name}',
|
||||
Cold_Water_Supply_Temperature_Schedule_Name=f'cold_temp schedules {usage}',
|
||||
EndUse_Subcategory=f'DHW {zone_name}',
|
||||
Zone_Name=zone_name
|
||||
)
|
||||
@ -512,19 +517,25 @@ class Idf:
|
||||
self._rename_building(self._city.name)
|
||||
self._lod = self._city.level_of_detail.geometry
|
||||
for building in self._city.buildings:
|
||||
is_target = building.name in self._target_buildings or building.name in self._adjacent_buildings
|
||||
for internal_zone in building.internal_zones:
|
||||
if internal_zone.thermal_zones_from_internal_zones is None:
|
||||
self._target_buildings.remoidf_surface_typeve(building.name)
|
||||
is_target = False
|
||||
continue
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self._add_construction(thermal_boundary)
|
||||
if thermal_boundary.parent_surface.vegetation is not None:
|
||||
self._add_vegetation_material(thermal_boundary.parent_surface.vegetation)
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
self._add_window_construction_and_material(thermal_opening)
|
||||
usage = thermal_zone.usage_name
|
||||
if building.name in self._target_buildings or building.name in self._adjacent_buildings:
|
||||
|
||||
if is_target:
|
||||
start = datetime.datetime.now()
|
||||
service_temperature = thermal_zone.domestic_hot_water.service_temperature
|
||||
usage = thermal_zone.usage_name
|
||||
_new_schedules = self._create_infiltration_schedules(thermal_zone)
|
||||
self._add_schedules(usage, 'Infiltration', _new_schedules)
|
||||
_new_schedules = self._create_ventilation_schedules(thermal_zone)
|
||||
@ -536,11 +547,10 @@ class Idf:
|
||||
self._add_schedules(usage, 'Lighting', thermal_zone.lighting.schedules)
|
||||
self._add_schedules(usage, 'Appliance', thermal_zone.appliances.schedules)
|
||||
self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules)
|
||||
_new_schedules = self._create_yearly_values_schedules('cold_temp',
|
||||
building.cold_water_temperature[cte.HOUR])
|
||||
self._add_schedules(building.name, 'cold_temp', _new_schedules)
|
||||
value = thermal_zone.domestic_hot_water.service_temperature
|
||||
_new_schedules = self._create_constant_value_schedules('DHW_temp', value)
|
||||
_new_schedules = self._create_yearly_values_schedules('cold_temp', building.cold_water_temperature[cte.HOUR])
|
||||
self._add_schedules(usage, 'cold_temp', _new_schedules)
|
||||
|
||||
_new_schedules = self._create_constant_value_schedules('DHW_temp', service_temperature)
|
||||
self._add_schedules(usage, 'DHW_temp', _new_schedules)
|
||||
_occ = thermal_zone.occupancy
|
||||
if _occ.occupancy_density == 0:
|
||||
@ -557,11 +567,13 @@ class Idf:
|
||||
self._add_occupancy(thermal_zone, building.name)
|
||||
self._add_lighting(thermal_zone, building.name)
|
||||
self._add_appliances(thermal_zone, building.name)
|
||||
self._add_dhw(thermal_zone, building.name)
|
||||
self._add_dhw(thermal_zone, building.name, usage)
|
||||
if self._export_type == "Surfaces":
|
||||
if building.name in self._target_buildings or building.name in self._adjacent_buildings:
|
||||
if is_target:
|
||||
if building.thermal_zones_from_internal_zones is not None:
|
||||
start = datetime.datetime.now()
|
||||
self._add_surfaces(building, building.name)
|
||||
print(f'add surfaces {datetime.datetime.now() - start}')
|
||||
else:
|
||||
self._add_pure_geometry(building, building.name)
|
||||
else:
|
||||
@ -717,7 +729,7 @@ class Idf:
|
||||
if boundary.parent_surface.vegetation is not None:
|
||||
construction_name = f'{boundary.construction_name}_{boundary.parent_surface.vegetation.name}'
|
||||
else:
|
||||
construction_name = boundary.construction_name
|
||||
construction_name = f'{boundary.construction_name} {boundary.parent_surface.type}'
|
||||
_kwargs['Construction_Name'] = construction_name
|
||||
|
||||
surface = self._idf.newidfobject(self._SURFACE, **_kwargs)
|
||||
|
@ -270,7 +270,7 @@ class InselMonthlyEnergyBalance:
|
||||
global_irradiance = surface.global_irradiance[cte.MONTH]
|
||||
for j in range(0, len(global_irradiance)):
|
||||
parameters.append(f'{j + 1} '
|
||||
f'{global_irradiance[j] * cte.WATTS_HOUR_TO_JULES / 24 / _NUMBER_DAYS_PER_MONTH[j]}')
|
||||
f'{global_irradiance[j] / 24 / _NUMBER_DAYS_PER_MONTH[j]}')
|
||||
else:
|
||||
for j in range(0, 12):
|
||||
parameters.append(f'{j + 1} 0.0')
|
||||
|
@ -310,7 +310,8 @@ LATENT = 'Latent'
|
||||
LITHIUMION = 'Lithium Ion'
|
||||
NICD = 'NiCd'
|
||||
LEADACID = 'Lead Acid'
|
||||
|
||||
THERMAL = 'thermal'
|
||||
ELECTRICAL = 'electrical'
|
||||
# Geometry
|
||||
EPSILON = 0.0000001
|
||||
|
||||
|
@ -43,6 +43,7 @@ class MontrealFutureEnergySystemParameters:
|
||||
archetype_name = building.energy_systems_archetype_name
|
||||
try:
|
||||
archetype = self._search_archetypes(montreal_custom_catalog, archetype_name)
|
||||
building.energy_systems_archetype_cluster_id = archetype.cluster_id
|
||||
except KeyError:
|
||||
logging.error('Building %s has unknown energy system archetype for system name %s', building.name,
|
||||
archetype_name)
|
||||
@ -103,15 +104,21 @@ class MontrealFutureEnergySystemParameters:
|
||||
_generation_system.nominal_radiation = archetype_generation_system.nominal_radiation
|
||||
_generation_system.standard_test_condition_cell_temperature = archetype_generation_system.standard_test_condition_cell_temperature
|
||||
_generation_system.standard_test_condition_maximum_power = archetype_generation_system.standard_test_condition_maximum_power
|
||||
_generation_system.standard_test_condition_radiation = archetype_generation_system.standard_test_condition_radiation
|
||||
_generation_system.cell_temperature_coefficient = archetype_generation_system.cell_temperature_coefficient
|
||||
_generation_system.width = archetype_generation_system.width
|
||||
_generation_system.height = archetype_generation_system.height
|
||||
_generation_system.tilt_angle = self._city.latitude
|
||||
_generic_storage_system = None
|
||||
if archetype_generation_system.energy_storage_systems is not None:
|
||||
_generic_storage_system = ElectricalStorageSystem()
|
||||
_generic_storage_system.type_energy_stored = 'electrical'
|
||||
_generation_system.energy_storage_systems = [_generic_storage_system]
|
||||
_storage_systems = []
|
||||
for storage_system in archetype_generation_system.energy_storage_systems:
|
||||
if storage_system.type_energy_stored == 'electrical':
|
||||
_generic_storage_system = ElectricalStorageSystem()
|
||||
_generic_storage_system.type_energy_stored = 'electrical'
|
||||
_storage_systems.append(_generic_storage_system)
|
||||
_generation_system.energy_storage_systems = _storage_systems
|
||||
|
||||
else:
|
||||
_generation_system = NonPvGenerationSystem()
|
||||
_generation_system.name = archetype_generation_system.name
|
||||
|
@ -1,157 +0,0 @@
|
||||
"""
|
||||
Energy System catalog heat generation system
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2023 Concordia CERC group
|
||||
Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import logging
|
||||
import copy
|
||||
|
||||
from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory
|
||||
from hub.city_model_structure.energy_systems.energy_system import EnergySystem
|
||||
from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem
|
||||
from hub.city_model_structure.energy_systems.non_pv_generation_system import NonPvGenerationSystem
|
||||
from hub.city_model_structure.energy_systems.pv_generation_system import PvGenerationSystem
|
||||
from hub.city_model_structure.energy_systems.electrical_storage_system import ElectricalStorageSystem
|
||||
from hub.city_model_structure.energy_systems.thermal_storage_system import ThermalStorageSystem
|
||||
from hub.city_model_structure.energy_systems.emission_system import EmissionSystem
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
|
||||
|
||||
class NorthAmericaCustomEnergySystemParameters:
|
||||
"""
|
||||
MontrealCustomEnergySystemParameters class
|
||||
"""
|
||||
|
||||
def __init__(self, city):
|
||||
self._city = city
|
||||
|
||||
def enrich_buildings(self):
|
||||
"""
|
||||
Returns the city with the system parameters assigned to the buildings
|
||||
:return:
|
||||
"""
|
||||
city = self._city
|
||||
montreal_custom_catalog = EnergySystemsCatalogFactory('north_america').catalog
|
||||
if city.generic_energy_systems is None:
|
||||
_generic_energy_systems = {}
|
||||
else:
|
||||
_generic_energy_systems = city.generic_energy_systems
|
||||
for building in city.buildings:
|
||||
archetype_name = building.energy_systems_archetype_name
|
||||
try:
|
||||
archetype = self._search_archetypes(montreal_custom_catalog, archetype_name)
|
||||
except KeyError:
|
||||
logging.error('Building %s has unknown energy system archetype for system name %s', building.name,
|
||||
archetype_name)
|
||||
continue
|
||||
|
||||
if archetype.name not in _generic_energy_systems:
|
||||
_generic_energy_systems = self._create_generic_systems_list(archetype, _generic_energy_systems)
|
||||
|
||||
city.generic_energy_systems = _generic_energy_systems
|
||||
|
||||
self._assign_energy_systems_to_buildings(city)
|
||||
|
||||
@staticmethod
|
||||
def _search_archetypes(catalog, name):
|
||||
archetypes = catalog.entries('archetypes')
|
||||
for building_archetype in archetypes:
|
||||
if str(name) == str(building_archetype.name):
|
||||
return building_archetype
|
||||
raise KeyError('archetype not found')
|
||||
|
||||
def _create_generic_systems_list(self, archetype, _generic_energy_systems):
|
||||
building_systems = []
|
||||
for archetype_system in archetype.systems:
|
||||
energy_system = EnergySystem()
|
||||
_hub_demand_types = []
|
||||
for demand_type in archetype_system.demand_types:
|
||||
_hub_demand_types.append(Dictionaries().montreal_demand_type_to_hub_energy_demand_type[demand_type])
|
||||
energy_system.name = archetype_system.name
|
||||
energy_system.demand_types = _hub_demand_types
|
||||
energy_system.configuration_schema = archetype_system.configuration_schema
|
||||
energy_system.generation_systems = self._create_generation_systems(archetype_system)
|
||||
if energy_system.distribution_systems is not None:
|
||||
energy_system.distribution_systems = self._create_distribution_systems(archetype_system)
|
||||
building_systems.append(energy_system)
|
||||
|
||||
_generic_energy_systems[archetype.name] = building_systems
|
||||
|
||||
return _generic_energy_systems
|
||||
|
||||
@staticmethod
|
||||
def _create_generation_systems(archetype_system):
|
||||
_generation_systems = []
|
||||
for archetype_generation_system in archetype_system.generation_systems:
|
||||
if archetype_generation_system.system_type == 'PV system':
|
||||
_generation_system = PvGenerationSystem()
|
||||
_type = 'PV system'
|
||||
_generation_system.system_type = Dictionaries().montreal_generation_system_to_hub_energy_generation_system[_type]
|
||||
_fuel_type = Dictionaries().montreal_custom_fuel_to_hub_fuel[archetype_generation_system.fuel_type]
|
||||
_generation_system.fuel_type = _fuel_type
|
||||
_generation_system.electricity_efficiency = archetype_generation_system.electricity_efficiency
|
||||
_generic_storage_system = None
|
||||
if archetype_generation_system.energy_storage_systems is not None:
|
||||
_generic_storage_system = ElectricalStorageSystem()
|
||||
_generic_storage_system.type_energy_stored = 'electrical'
|
||||
_generation_system.energy_storage_systems = [_generic_storage_system]
|
||||
else:
|
||||
_generation_system = NonPvGenerationSystem()
|
||||
_type = archetype_generation_system.system_type
|
||||
_generation_system.system_type = Dictionaries().montreal_generation_system_to_hub_energy_generation_system[_type]
|
||||
_fuel_type = Dictionaries().north_america_custom_fuel_to_hub_fuel[archetype_generation_system.fuel_type]
|
||||
_generation_system.fuel_type = _fuel_type
|
||||
_generation_system.source_types = archetype_generation_system.source_medium
|
||||
_generation_system.heat_efficiency = archetype_generation_system.heat_efficiency
|
||||
_generation_system.cooling_efficiency = archetype_generation_system.cooling_efficiency
|
||||
_generation_system.electricity_efficiency = archetype_generation_system.electricity_efficiency
|
||||
_generic_storage_system = None
|
||||
if archetype_generation_system.energy_storage_systems is not None:
|
||||
_storage_systems = []
|
||||
for storage_system in archetype_generation_system.energy_storage_systems:
|
||||
if storage_system.type_energy_stored == 'electrical':
|
||||
_generic_storage_system = ElectricalStorageSystem()
|
||||
_generic_storage_system.type_energy_stored = 'electrical'
|
||||
else:
|
||||
_generic_storage_system = ThermalStorageSystem()
|
||||
_generic_storage_system.type_energy_stored = 'thermal'
|
||||
_storage_systems.append(_generic_storage_system)
|
||||
_generation_system.energy_storage_systems = [_storage_systems]
|
||||
if archetype_generation_system.dual_supply_capability:
|
||||
_generation_system.dual_supply_capability = True
|
||||
_generation_systems.append(_generation_system)
|
||||
return _generation_systems
|
||||
|
||||
@staticmethod
|
||||
def _create_distribution_systems(archetype_system):
|
||||
_distribution_systems = []
|
||||
for archetype_distribution_system in archetype_system.distribution_systems:
|
||||
_distribution_system = DistributionSystem()
|
||||
_distribution_system.type = archetype_distribution_system.type
|
||||
_distribution_system.distribution_consumption_fix_flow = \
|
||||
archetype_distribution_system.distribution_consumption_fix_flow
|
||||
_distribution_system.distribution_consumption_variable_flow = \
|
||||
archetype_distribution_system.distribution_consumption_variable_flow
|
||||
_distribution_system.heat_losses = archetype_distribution_system.heat_losses
|
||||
_emission_system = None
|
||||
if archetype_distribution_system.emission_systems is not None:
|
||||
_emission_system = EmissionSystem()
|
||||
_distribution_system.emission_systems = [_emission_system]
|
||||
_distribution_systems.append(_distribution_system)
|
||||
return _distribution_systems
|
||||
|
||||
@staticmethod
|
||||
def _assign_energy_systems_to_buildings(city):
|
||||
for building in city.buildings:
|
||||
_building_energy_systems = []
|
||||
energy_systems_cluster_name = building.energy_systems_archetype_name
|
||||
if str(energy_systems_cluster_name) == 'nan':
|
||||
break
|
||||
_generic_building_energy_systems = city.generic_energy_systems[energy_systems_cluster_name]
|
||||
for _generic_building_energy_system in _generic_building_energy_systems:
|
||||
_building_energy_systems.append(copy.deepcopy(_generic_building_energy_system))
|
||||
|
||||
building.energy_systems = _building_energy_systems
|
@ -6,17 +6,15 @@ Project Coder Pilar Monsalvete pilar.monsalvete@concordi.
|
||||
Code contributors: Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
from hub.imports.energy_systems.montreal_custom_energy_system_parameters import MontrealCustomEnergySystemParameters
|
||||
from hub.imports.energy_systems.north_america_custom_energy_system_parameters import NorthAmericaCustomEnergySystemParameters
|
||||
from hub.imports.energy_systems.montreal_future_energy_systems_parameters import MontrealFutureEnergySystemParameters
|
||||
|
||||
|
||||
class EnergySystemsFactory:
|
||||
"""
|
||||
EnergySystemsFactory class
|
||||
"""
|
||||
|
||||
def __init__(self, handler, city, base_path=None):
|
||||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/energy_systems')
|
||||
@ -34,15 +32,6 @@ class EnergySystemsFactory:
|
||||
for building in self._city.buildings:
|
||||
building.level_of_detail.energy_systems = 1
|
||||
|
||||
def _north_america(self):
|
||||
"""
|
||||
Enrich the city by using north america custom energy systems catalog information
|
||||
"""
|
||||
NorthAmericaCustomEnergySystemParameters(self._city).enrich_buildings()
|
||||
self._city.level_of_detail.energy_systems = 2
|
||||
for building in self._city.buildings:
|
||||
building.level_of_detail.energy_systems = 2
|
||||
|
||||
def _montreal_future(self):
|
||||
"""
|
||||
Enrich the city by using north america custom energy systems catalog information
|
||||
|
@ -156,6 +156,8 @@ class Geojson:
|
||||
building_aliases = []
|
||||
if 'id' in feature:
|
||||
building_name = feature['id']
|
||||
elif 'id' in feature['properties']:
|
||||
building_name = feature['properties']['id']
|
||||
else:
|
||||
building_name = uuid.uuid4()
|
||||
if self._aliases_field is not None:
|
||||
|
95
main.py
95
main.py
@ -1,95 +0,0 @@
|
||||
from pathlib import Path
|
||||
from scripts.district_heating_network.directory_manager import DirectoryManager
|
||||
import subprocess
|
||||
from scripts.ep_run_enrich 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 scripts.energy_system_retrofit_report import EnergySystemRetrofitReport
|
||||
from scripts.geojson_creator import process_geojson
|
||||
from scripts import random_assignation
|
||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||
from scripts.energy_system_sizing import SystemSizing
|
||||
from scripts.solar_angles import CitySolarAngles
|
||||
from scripts.pv_sizing_and_simulation import PVSizingSimulation
|
||||
from scripts.energy_system_retrofit_results import consumption_data, cost_data
|
||||
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
|
||||
from scripts.costs.cost import Cost
|
||||
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from scripts.pv_feasibility import pv_feasibility
|
||||
import matplotlib.pyplot as plt
|
||||
from scripts.district_heating_network.district_heating_network_creator import DistrictHeatingNetworkCreator
|
||||
from scripts.district_heating_network.road_processor import road_processor
|
||||
from scripts.district_heating_network.district_heating_factory import DistrictHeatingFactory
|
||||
|
||||
base_path = Path(__file__).parent
|
||||
dir_manager = DirectoryManager(base_path)
|
||||
|
||||
# Input files directory
|
||||
input_files_path = dir_manager.create_directory('input_files')
|
||||
geojson_file_path = input_files_path / 'output_buildings.geojson'
|
||||
|
||||
# Output files directory
|
||||
output_path = dir_manager.create_directory('out_files')
|
||||
|
||||
# Subdirectories for output files
|
||||
energy_plus_output_path = dir_manager.create_directory('out_files/energy_plus_outputs')
|
||||
simulation_results_path = dir_manager.create_directory('out_files/simulation_results')
|
||||
sra_output_path = dir_manager.create_directory('out_files/sra_outputs')
|
||||
cost_analysis_output_path = dir_manager.create_directory('out_files/cost_analysis')
|
||||
|
||||
# Select city area
|
||||
location = [45.53067276979674, -73.70234652694087]
|
||||
process_geojson(x=location[1], y=location[0], diff=0.001)
|
||||
|
||||
# Create city object
|
||||
city = GeometryFactory(file_type='geojson',
|
||||
path=geojson_file_path,
|
||||
height_field='height',
|
||||
year_of_construction_field='year_of_construction',
|
||||
function_field='function',
|
||||
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)
|
||||
# data[f'{city.buildings[0].function}'] = city.buildings[0].heating_demand[cte.YEAR][0] / 3.6e9
|
||||
# city.buildings[0].function = cte.COMMERCIAL
|
||||
# ConstructionFactory('nrcan', city).enrich()
|
||||
# UsageFactory('nrcan', city).enrich()
|
||||
# energy_plus_workflow(city, energy_plus_output_path)
|
||||
# data[f'{city.buildings[0].function}'] = city.buildings[0].heating_demand[cte.YEAR][0] / 3.6e9
|
||||
# city.buildings[0].function = cte.MEDIUM_OFFICE
|
||||
# ConstructionFactory('nrcan', city).enrich()
|
||||
# UsageFactory('nrcan', city).enrich()
|
||||
# energy_plus_workflow(city, energy_plus_output_path)
|
||||
# data[f'{city.buildings[0].function}'] = city.buildings[0].heating_demand[cte.YEAR][0] / 3.6e9
|
||||
# categories = list(data.keys())
|
||||
# values = list(data.values())
|
||||
# # Plotting
|
||||
# fig, ax = plt.subplots(figsize=(10, 6), dpi=96)
|
||||
# fig.suptitle('Impact of different usages on yearly heating demand', fontsize=16, weight='bold', alpha=.8)
|
||||
# ax.bar(categories, values, color=['#2196f3', '#ff5a5f', '#4caf50'], width=0.6, zorder=2)
|
||||
# ax.grid(which="major", axis='x', color='#DAD8D7', alpha=0.5, zorder=1)
|
||||
# ax.grid(which="major", axis='y', color='#DAD8D7', alpha=0.5, zorder=1)
|
||||
# ax.set_xlabel('Building Type', fontsize=12, labelpad=10)
|
||||
# ax.set_ylabel('Energy Consumption (MWh)', fontsize=14, labelpad=10)
|
||||
# ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
|
||||
# ax.set_xticks(np.arange(len(categories)))
|
||||
# ax.set_xticklabels(categories, rotation=45, ha='right')
|
||||
# ax.bar_label(ax.containers[0], padding=3, color='black', fontsize=12, rotation=0)
|
||||
# ax.spines[['top', 'left', 'bottom']].set_visible(False)
|
||||
# ax.spines['right'].set_linewidth(1.1)
|
||||
# # Set a white background
|
||||
# fig.patch.set_facecolor('white')
|
||||
# # Adjust the margins around the plot area
|
||||
# plt.subplots_adjust(left=0.1, right=0.9, top=0.85, bottom=0.25)
|
||||
# # Save the plot
|
||||
# plt.savefig('plot_nrcan.png', bbox_inches='tight')
|
||||
# plt.close()
|
||||
print('test')
|
BIN
plot_nrcan.png
BIN
plot_nrcan.png
Binary file not shown.
Before Width: | Height: | Size: 46 KiB |
@ -1,73 +0,0 @@
|
||||
import pandas as pd
|
||||
from scripts.geojson_creator import process_geojson
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
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 scripts.solar_angles import CitySolarAngles
|
||||
from scripts.ep_run_enrich import energy_plus_workflow
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from scripts.pv_sizing_and_simulation import PVSizingSimulation
|
||||
# Specify the GeoJSON file path
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
|
||||
file_path = (Path(__file__).parent / 'input_files' / 'output_buildings.geojson')
|
||||
# Specify the output path for the PDF file
|
||||
output_path = (Path(__file__).parent / 'out_files').resolve()
|
||||
# Create city object from GeoJSON file
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='height',
|
||||
year_of_construction_field='year_of_construction',
|
||||
function_field='function',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
# Enrich city data
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
ExportsFactory('sra', city, output_path).export()
|
||||
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', city, output_path).enrich()
|
||||
energy_plus_workflow(city, output_path=output_path)
|
||||
solar_angles = CitySolarAngles(city.name,
|
||||
city.latitude,
|
||||
city.longitude,
|
||||
tilt_angle=45,
|
||||
surface_azimuth_angle=180).calculate
|
||||
df = pd.DataFrame()
|
||||
df.index = ['yearly lighting (kWh)', 'yearly appliance (kWh)', 'yearly heating (kWh)', 'yearly cooling (kWh)',
|
||||
'yearly dhw (kWh)', 'roof area (m2)', 'used area for pv (m2)', 'number of panels', 'pv production (kWh)']
|
||||
for building in city.buildings:
|
||||
ghi = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]]
|
||||
pv_sizing_simulation = PVSizingSimulation(building,
|
||||
solar_angles,
|
||||
tilt_angle=45,
|
||||
module_height=1,
|
||||
module_width=2,
|
||||
ghi=ghi)
|
||||
pv_sizing_simulation.pv_output()
|
||||
yearly_lighting = building.lighting_electrical_demand[cte.YEAR][0] / 1000
|
||||
yearly_appliance = building.appliances_electrical_demand[cte.YEAR][0] / 1000
|
||||
yearly_heating = building.heating_demand[cte.YEAR][0] / (3.6e6 * 3)
|
||||
yearly_cooling = building.cooling_demand[cte.YEAR][0] / (3.6e6 * 4.5)
|
||||
yearly_dhw = building.domestic_hot_water_heat_demand[cte.YEAR][0] / 1000
|
||||
roof_area = building.roofs[0].perimeter_area
|
||||
used_roof = pv_sizing_simulation.available_space()
|
||||
number_of_pv_panels = pv_sizing_simulation.total_number_of_panels
|
||||
yearly_pv = building.onsite_electrical_production[cte.YEAR][0] / 1000
|
||||
df[f'{building.name}'] = [yearly_lighting, yearly_appliance, yearly_heating, yearly_cooling, yearly_dhw, roof_area,
|
||||
used_roof, number_of_pv_panels, yearly_pv]
|
||||
|
||||
df.to_csv(output_path / 'pv.csv')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,63 +0,0 @@
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import csv
|
||||
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
|
||||
sys.path.append('./')
|
||||
|
||||
try:
|
||||
file_path = (Path(__file__).parent.parent / 'input_files' / 'eilat.geojson')
|
||||
out_path = (Path(__file__).parent.parent / 'out_files')
|
||||
files = glob.glob(f'{out_path}/*')
|
||||
|
||||
for file in files:
|
||||
if file != '.gitignore':
|
||||
os.remove(file)
|
||||
|
||||
print('[simulation start]')
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='heightmax',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().eilat_function_to_hub_function).city
|
||||
print(f'city created from {file_path}')
|
||||
ConstructionFactory('eilat', city).enrich()
|
||||
print('enrich constructions... done')
|
||||
UsageFactory('eilat', city).enrich()
|
||||
print('enrich usage... done')
|
||||
WeatherFactory('epw', city).enrich()
|
||||
print('enrich weather... done')
|
||||
|
||||
area = 0
|
||||
volume = 0
|
||||
for building in city.buildings:
|
||||
volume = building.volume
|
||||
for ground in building.grounds:
|
||||
area += ground.perimeter_polygon.area
|
||||
|
||||
print('exporting:')
|
||||
_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)
|
||||
print('[simulation abort]')
|
||||
sys.stdout.flush()
|
@ -1,26 +0,0 @@
|
||||
import random
|
||||
import numpy as np
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
class EnergySystemOptimizer:
|
||||
def __init__(self, building, objectives, population_size=20, number_of_generations=100, crossover_rate=0.8,
|
||||
mutation_rate=0.1):
|
||||
self.building = building
|
||||
self.objectives = objectives
|
||||
self.population_size = population_size
|
||||
self.num_gen = number_of_generations
|
||||
self.crossover_rate = crossover_rate
|
||||
self.mutation_rate = mutation_rate
|
||||
|
||||
# Initialize population
|
||||
def initialize_population(self):
|
||||
population = []
|
||||
for _ in range(self.population_size):
|
||||
individual = [
|
||||
random.uniform(0.1, 10.0), # hp_size
|
||||
random.uniform(0.1, 10.0), # boiler_size
|
||||
random.uniform(0.1, 10.0), # tes_size
|
||||
random.uniform(40, 60) # cutoff_temp
|
||||
]
|
||||
population.append(individual)
|
||||
return population
|
@ -1,16 +0,0 @@
|
||||
# Objective functions
|
||||
MINIMUM_LCC = 1
|
||||
MINIMUM_EC = 2
|
||||
MINIMUM_EMISSIONS = 3
|
||||
MINIMUM_LCC_MINIMUM_EC = 4
|
||||
MINIMUM_LCC_MINIMUM_EMISSIONS = 5
|
||||
MINIMUM_EC_MINIMUM_EMISSIONS = 6
|
||||
MINIMUM_LCC_MINIMUM_EC_MINIMUM_EMISSIONS = 7
|
||||
OBJECTIVE_FUNCTIONS = [MINIMUM_LCC,
|
||||
MINIMUM_EC,
|
||||
MINIMUM_EMISSIONS,
|
||||
MINIMUM_LCC_MINIMUM_EC,
|
||||
MINIMUM_LCC_MINIMUM_EMISSIONS,
|
||||
MINIMUM_EC_MINIMUM_EMISSIONS,
|
||||
MINIMUM_LCC_MINIMUM_EC_MINIMUM_EMISSIONS]
|
||||
|
@ -1,378 +0,0 @@
|
||||
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 = [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 = [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)
|
||||
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
|
||||
# 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] = 30
|
||||
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()))
|
||||
|
@ -1,385 +0,0 @@
|
||||
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, csv_output=True,):
|
||||
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
|
||||
self.csv_output = csv_output
|
||||
|
||||
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])]
|
||||
if self.csv_output:
|
||||
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()))
|
@ -1,416 +0,0 @@
|
||||
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()))
|
@ -1,398 +0,0 @@
|
||||
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()))
|
@ -39,9 +39,9 @@ class TestSystemsCatalog(TestCase):
|
||||
|
||||
catalog_categories = catalog.names()
|
||||
archetypes = catalog.names()
|
||||
self.assertEqual(15, len(archetypes['archetypes']))
|
||||
self.assertEqual(13, len(archetypes['archetypes']))
|
||||
systems = catalog.names('systems')
|
||||
self.assertEqual(12, len(systems['systems']))
|
||||
self.assertEqual(17, len(systems['systems']))
|
||||
generation_equipments = catalog.names('generation_equipments')
|
||||
self.assertEqual(27, len(generation_equipments['generation_equipments']))
|
||||
with self.assertRaises(ValueError):
|
||||
|
@ -114,7 +114,8 @@ class TestSystemsFactory(TestCase):
|
||||
ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich()
|
||||
|
||||
for building in self._city.buildings:
|
||||
building.energy_systems_archetype_name = 'PV+4Pipe+DHW'
|
||||
building.energy_systems_archetype_name = ('Central 4 Pipes Air to Water Heat Pump and Gas Boiler with '
|
||||
'Independent Water Heating and PV')
|
||||
EnergySystemsFactory('montreal_future', self._city).enrich()
|
||||
# Need to assign energy systems to buildings:
|
||||
for building in self._city.buildings:
|
||||
@ -131,5 +132,4 @@ class TestSystemsFactory(TestCase):
|
||||
self.assertLess(0, building.heating_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.cooling_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.domestic_hot_water_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.onsite_electrical_production[cte.YEAR][0])
|
||||
print('test')
|
||||
self.assertLess(0, building.onsite_electrical_production[cte.YEAR][0])
|
Loading…
Reference in New Issue
Block a user