fix: simulation models fixed for hourly consumption calculation, optimization process improved

This commit is contained in:
Saeed Ranjbar 2024-11-25 21:12:42 +01:00
parent 09d1d08ed7
commit a143100b39
13 changed files with 25899 additions and 162 deletions

View File

@ -73,16 +73,16 @@ class DomesticHotWaterHeatPumpTes:
t_tank[i + 1] = t_tank[i] + (delta_t_hp - delta_t_freshwater - delta_t_demand + delta_t_coil)
total_consumption[i] = hp_electricity[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_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity[1:]]
heating_coil_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in q_coil[1:]]
hp_hourly = []
coil_hourly = []
coil_sum = 0
hp_sum = 0
for i in range(1, len(demand)):
for i in range(len(demand) - 1):
hp_sum += hp_electricity_j[i]
coil_sum += heating_coil_j[i]
if (i - 1) % number_of_ts == 0:
if i % number_of_ts == 0 or i == len(demand) - 1:
tes.temperature.append(t_tank[i])
hp_hourly.append(hp_sum)
coil_hourly.append(coil_sum)
@ -104,17 +104,17 @@ class DomesticHotWaterHeatPumpTes:
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
self.results['DHW Demand (W)'] = demand[1:]
self.results['DHW HP Heat Output (W)'] = q_hp[1:]
self.results['DHW HP Electricity Consumption (W)'] = hp_electricity[1:]
self.results['DHW HP Source Temperature'] = source_temperature[1:]
self.results['DHW HP Supply Temperature'] = t_sup_hp[1:]
self.results['DHW HP COP'] = hp_cop[1:]
self.results['DHW TES Heating Coil Heat Output (W)'] = q_coil[1:]
self.results['DHW TES Temperature'] = t_tank[1:]
self.results['DHW TES Charging Flow Rate (kg/s)'] = m_ch[1:]
self.results['DHW Flow Rate (kg/s)'] = m_dis[1:]
self.results['DHW TES Refill Flow Rate (kg/s)'] = m_refill[1:]
self.results['Available Water in Tank (m3)'] = v_dhw[1:]
self.results['Total DHW Power Consumption (W)'] = total_consumption[1:]
return self.results

View File

@ -25,8 +25,9 @@ class HeatPumpBoilerTesHeating:
def simulation(self):
hp, boiler, tes = self.hp, self.boiler, self.tes
if hp.nominal_heat_output < 0 or boiler.nominal_heat_output < 0:
raise ValueError("Heat output values must be non-negative. Check the nominal_heat_output for hp and boiler.")
if boiler is not None:
if hp.nominal_heat_output < 0 or boiler.nominal_heat_output < 0:
raise ValueError("Heat output values must be non-negative. Check the nominal_heat_output for hp and boiler.")
heating_coil_nominal_output = 0
if tes.heating_coil_capacity is not None:
@ -113,20 +114,20 @@ class HeatPumpBoilerTesHeating:
# total consumption
total_consumption[i + 1] = hp_electricity[i + 1] + boiler_energy_consumption[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_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity[1:]]
boiler_consumption_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in boiler_energy_consumption[1:]]
heating_coil_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in q_coil[1:]]
hp_hourly = []
boiler_hourly = []
coil_hourly = []
boiler_sum = 0
hp_sum = 0
coil_sum = 0
for i in range(1, len(demand)):
for i in range(len(demand) - 1):
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:
if i % number_of_ts == 0 or i == len(demand) - 1:
tes.temperature.append(t_tank[i])
hp_hourly.append(hp_sum)
boiler_hourly.append(boiler_sum)
@ -136,17 +137,19 @@ class HeatPumpBoilerTesHeating:
coil_sum = 0
hp.energy_consumption[cte.HEATING] = {}
hp.energy_consumption[cte.HEATING][cte.HOUR] = hp_hourly
boiler.energy_consumption[cte.HEATING] = {}
boiler.energy_consumption[cte.HEATING][cte.HOUR] = boiler_hourly
if boiler is not None:
boiler.energy_consumption[cte.HEATING] = {}
boiler.energy_consumption[cte.HEATING][cte.HOUR] = boiler_hourly
if len(self.heating_demand) == 8760:
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][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 boiler is not None:
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] = {}
if len(self.heating_demand) == 8760:
@ -155,20 +158,20 @@ class HeatPumpBoilerTesHeating:
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
self.results['Heating Demand (W)'] = demand[1:]
self.results['HP Heat Output (W)'] = q_hp[1:]
self.results['HP Source Temperature'] = source_temperature[1:]
self.results['HP Supply Temperature'] = t_sup_hp[1:]
self.results['HP COP'] = hp_cop[1:]
self.results['HP Electricity Consumption (W)'] = hp_electricity[1:]
self.results['Boiler Heat Output (W)'] = q_boiler[1:]
self.results['Boiler Power Consumption (W)'] = boiler_energy_consumption[1:]
self.results['Boiler Supply Temperature'] = t_sup_boiler[1:]
self.results['Boiler Fuel Consumption'] = boiler_fuel_consumption[1:]
self.results['TES Temperature'] = t_tank[1:]
self.results['Heating Coil heat input'] = q_coil[1:]
self.results['TES Charging Flow Rate (kg/s)'] = m_ch[1:]
self.results['TES Discharge Flow Rate (kg/s)'] = m_dis[1:]
self.results['Heating Loop Return Temperature'] = t_ret[1:]
self.results['Total Heating Power Consumption (W)'] = total_consumption[1:]
return self.results

View File

@ -57,11 +57,11 @@ class HeatPumpCooling:
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_electricity_j = [(x * cte.WATTS_HOUR_TO_JULES) / number_of_ts for x in hp_electricity[1:]]
hp_hourly = []
hp_supply_temperature_hourly = []
hp_sum = 0
for i in range(1, len(demand)):
for i in range(len(demand) - 1):
hp_sum += hp_electricity_j[i]
if (i - 1) % number_of_ts == 0:
hp_hourly.append(hp_sum)
@ -74,14 +74,14 @@ class HeatPumpCooling:
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 Cooling 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
self.results['Cooling Demand (W)'] = demand[1:]
self.results['HP Cooling Output (W)'] = q_hp[1:]
self.results['HP Cooling Source Temperature'] = source_temperature[1:]
self.results['HP Cooling Supply Temperature'] = t_sup_hp[1:]
self.results['HP Cooling COP'] = hp_cop[1:]
self.results['HP Electricity Consumption'] = hp_electricity[1:]
self.results['Cooling Loop Flow Rate (kg/s)'] = m[1:]
self.results['Cooling Loop Return Temperature'] = t_ret[1:]
return self.results

View File

@ -134,36 +134,40 @@ class Individual:
generation_component['heating_capacity'] = random.uniform(0, self.heating_design_load)
else:
if cte.HEATING in self.demand_types:
generation_component['heating_capacity'] = random.uniform(0, max(
self.design_period_energy_demands[cte.HEATING]['demands']) / cte.WATTS_HOUR_TO_JULES)
generation_component['heating_capacity'] = random.uniform(0,
self.building.heating_peak_load[cte.YEAR][0])
else:
generation_component['heating_capacity'] = random.uniform(0, max(
self.design_period_energy_demands[cte.DOMESTIC_HOT_WATER]['demands']) / cte.WATTS_HOUR_TO_JULES)
generation_component['heating_capacity'] = random.uniform(0,
self.building.domestic_hot_water_peak_load[cte.YEAR][0])
else:
generation_component['heating_capacity'] = None
if generation_component['nominal_cooling_efficiency'] is not None and cte.COOLING in self.demand_types:
if self.cooling_design_load is not None:
generation_component['cooling_capacity'] = random.uniform(0, self.cooling_design_load)
else:
generation_component['cooling_capacity'] = random.uniform(0, max(
self.design_period_energy_demands[cte.COOLING]['demands']) / cte.WATTS_HOUR_TO_JULES)
generation_component['cooling_capacity'] = random.uniform(0,
self.building.cooling_peak_load[cte.YEAR][0])
else:
generation_component['cooling_capacity'] = None
if generation_component['nominal_electricity_efficiency'] is None:
generation_component['electricity_capacity'] = None
for storage_component in storage_components:
if storage_component['type'] == f'{cte.THERMAL}_storage':
storage_component['volume'] = random.uniform(0, 0.01 * self.available_space)
storage_operation_range = 10 if cte.DOMESTIC_HOT_WATER in self.demand_types else 20
storage_energy_capacity = random.uniform(0, 6)
volume = (storage_energy_capacity * self.building.heating_peak_load[cte.YEAR][0] * 3600) / (cte.WATER_HEAT_CAPACITY * 1000 * storage_operation_range)
max_available_space = min(0.01 * self.available_space, volume)
storage_component['volume'] = random.uniform(0, max_available_space)
if storage_component['heating_coil_capacity'] is not None:
if self.heating_design_load is not None:
storage_component['heating_coil_capacity'] = random.uniform(0, self.heating_design_load)
else:
if cte.HEATING in self.demand_types:
storage_component['heating_coil_capacity'] = random.uniform(0, max(
self.design_period_energy_demands[cte.HEATING]['demands']) / cte.WATTS_HOUR_TO_JULES)
storage_component['heating_coil_capacity'] = random.uniform(0,
self.building.heating_peak_load[cte.YEAR][0])
else:
storage_component['heating_coil_capacity'] = random.uniform(0, max(
self.design_period_energy_demands[cte.DOMESTIC_HOT_WATER]['demands']) / cte.WATTS_HOUR_TO_JULES)
storage_component['heating_coil_capacity'] = random.uniform(0,
self.building.domestic_hot_water_peak_load[cte.YEAR][0])
def score_evaluation(self):
self.system_simulation()
@ -284,27 +288,55 @@ class Individual:
dt=self.dt).simulation()
if min(results['DHW TES Temperature']) < 55:
self.feasibility = False
if self.feasibility:
generation_system_types = [generation_system.system_type for generation_system in
self.energy_system.generation_systems]
for generation_component in self.individual['Generation Components']:
if generation_component['type'] in generation_system_types:
index = generation_system_types.index(generation_component['type'])
for demand_type in self.demand_types:
if demand_type in self.energy_system.generation_systems[index].energy_consumption:
generation_component['total_energy_consumption(kWh)'] = (sum(
self.energy_system.generation_systems[index].energy_consumption[demand_type][cte.HOUR]) / 3.6e6)
for storage_component in self.individual['Energy Storage Components']:
if storage_component['type'] == f'{cte.THERMAL}_storage' and storage_component[
'heating_coil_capacity'] is not None:
for generation_system in self.energy_system.generation_systems:
if generation_system.energy_storage_systems is not None:
for storage_system in generation_system.energy_storage_systems:
if storage_system.type_energy_stored == cte.THERMAL:
for demand_type in self.demand_types:
if demand_type in storage_system.heating_coil_energy_consumption:
storage_component['total_energy_consumption(kWh)'] = (sum(
storage_system.heating_coil_energy_consumption[demand_type][cte.HOUR]) / 3.6e6)
elif self.building.energy_systems_archetype_cluster_id == '3':
if cte.HEATING in self.demand_types:
hp = self.energy_system.generation_systems[0]
hp.nominal_heat_output = self.individual['Generation Components'][0]['heating_capacity']
tes = self.energy_system.generation_systems[0].energy_storage_systems[0]
tes.volume = self.individual['Energy Storage Components'][0]['volume']
tes.height = self.building.average_storey_height - 1
tes.heating_coil_capacity = self.individual['Energy Storage Components'][0]['heating_coil_capacity'] \
if self.individual['Energy Storage Components'][0]['heating_coil_capacity'] is not None else None
heating_demand_joules = self.design_period_energy_demands[cte.HEATING]['demands']
heating_peak_load_watts = max(self.design_period_energy_demands[cte.HEATING]) if \
(self.heating_design_load is not None) else self.building.heating_peak_load[cte.YEAR][0]
upper_limit_tes_heating = 55
design_period_start_index = self.design_period_energy_demands[cte.HEATING]['start_index']
design_period_end_index = self.design_period_energy_demands[cte.HEATING]['end_index']
outdoor_temperature = self.building.external_temperature[cte.HOUR][
design_period_start_index:design_period_end_index]
results = HeatPumpBoilerTesHeating(hp=hp,
boiler=None,
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()
if min(results['TES Temperature']) < 35:
self.feasibility = False
if self.feasibility:
generation_system_types = [generation_system.system_type for generation_system in
self.energy_system.generation_systems]
for generation_component in self.individual['Generation Components']:
if generation_component['type'] in generation_system_types:
index = generation_system_types.index(generation_component['type'])
for demand_type in self.demand_types:
if demand_type in self.energy_system.generation_systems[index].energy_consumption:
generation_component['total_energy_consumption(kWh)'] = (sum(
self.energy_system.generation_systems[index].energy_consumption[demand_type][cte.HOUR]) / 3.6e6)
for storage_component in self.individual['Energy Storage Components']:
if storage_component['type'] == f'{cte.THERMAL}_storage' and storage_component[
'heating_coil_capacity'] is not None:
for generation_system in self.energy_system.generation_systems:
if generation_system.energy_storage_systems is not None:
for storage_system in generation_system.energy_storage_systems:
if storage_system.type_energy_stored == cte.THERMAL:
for demand_type in self.demand_types:
if demand_type in storage_system.heating_coil_energy_consumption:
storage_component['total_energy_consumption(kWh)'] = (sum(
storage_system.heating_coil_energy_consumption[demand_type][cte.HOUR]) / 3.6e6)
def life_cycle_cost_calculation(self, investment_cost, operation_cost_year_0, maintenance_cost_year_0,
life_cycle_duration=41):

View File

@ -38,12 +38,14 @@ class MultiObjectiveGeneticAlgorithm:
operators such as crossover and mutation rates.
"""
def __init__(self, population_size=100, generations=100, crossover_rate=0.9, mutation_rate=0.1,
number_of_selected_solutions=None, optimization_scenario=None):
def __init__(self, population_size=100, generations=50, initial_crossover_rate=0.9, final_crossover_rate=0.5,
mutation_rate=0.1, number_of_selected_solutions=None, optimization_scenario=None):
self.population_size = population_size
self.population = []
self.generations = generations
self.crossover_rate = crossover_rate
self.initial_crossover_rate = initial_crossover_rate
self.final_crossover_rate = final_crossover_rate
self.crossover_rate = initial_crossover_rate # Initial value
self.mutation_rate = mutation_rate
self.optimization_scenario = optimization_scenario
self.number_of_selected_solutions = number_of_selected_solutions
@ -95,8 +97,9 @@ class MultiObjectiveGeneticAlgorithm:
individual.initialization()
individual.score_evaluation()
attempts += 1
if individual.feasibility:
self.population.append(individual)
self.population.append(individual)
# if individual.feasibility:
# self.population.append(individual)
if len(self.population) < self.population_size:
raise RuntimeError(f"Could not generate a feasible population of size {self.population_size}. "
f"Only {len(self.population)} feasible individuals were generated.")
@ -259,7 +262,11 @@ class MultiObjectiveGeneticAlgorithm:
for storage_component in individual['Energy Storage Components']:
if random.random() < self.mutation_rate:
if storage_component['type'] == f'{cte.THERMAL}_storage':
max_available_space = 0.01 * building.volume / building.storeys_above_ground
storage_operation_range = 10 if cte.DOMESTIC_HOT_WATER in energy_system.demand_types else 20
storage_energy_capacity = random.uniform(0, 6)
volume = (storage_energy_capacity * max(design_period_energy_demands[cte.HEATING]['demands'])) / (
cte.WATER_HEAT_CAPACITY * 1000 * storage_operation_range)
max_available_space = min(0.01 * building.volume / building.storeys_above_ground, volume)
storage_component['volume'] = abs(polynomial_mutation_operator(storage_component['volume'], 0,
max_available_space))
if storage_component['heating_coil_capacity'] is not None:
@ -442,7 +449,11 @@ class MultiObjectiveGeneticAlgorithm:
def solve_ga(self, building, energy_system):
self.initialize_population(building, energy_system)
solutions = {}
for n in range(self.generations + 1):
# self.crossover_rate = self.initial_crossover_rate + \
# (self.final_crossover_rate - self.initial_crossover_rate) * (n / self.generations)
solutions[f'generation_{n}'] = [individual.fitness_score for individual in self.population]
print(n)
progeny_population = []
while len(progeny_population) < self.population_size:
@ -591,13 +602,13 @@ class MultiObjectiveGeneticAlgorithm:
def get_start_end_indices(max_day_index, total_days):
if 0 < max_day_index < total_days - 1:
start_index = (max_day_index - 1) * 24
end_index = (max_day_index + 2) * 24
start_index = (max_day_index - 5) * 24
end_index = (max_day_index + 5) * 24
elif max_day_index == 0:
start_index = 0
end_index = (max_day_index + 2) * 24
end_index = (max_day_index + 10) * 24
else:
start_index = (max_day_index - 2) * 24
start_index = (max_day_index - 10) * 24
end_index = total_days * 24
return start_index, end_index

View File

@ -49,7 +49,7 @@ class PeakLoadSizing:
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
energy_system.generation_systems[0].nominal_heat_output = 0.7 * design_load
elif demand_type == cte.COOLING:
energy_system.generation_systems[0].nominal_cooling_output = design_load
else:

View File

@ -85,8 +85,8 @@
</D3050_other_hvac_ahu>
<D3060_storage_systems>
<D306010_storage_tank>
<investment_cost cost_unit="currency/kW">50</investment_cost>
<reposition cost_unit="currency/kW">50</reposition>
<investment_cost cost_unit="currency/kW">2000</investment_cost>
<reposition cost_unit="currency/kW">2000</reposition>
<lifetime_equipment lifetime="years">15</lifetime_equipment>
</D306010_storage_tank>
<D306020_storage_tank_with_coil>

View File

@ -715,7 +715,7 @@
<dependant_variable>COP</dependant_variable>
<parameters>source_temperature</parameters>
<parameters>supply_temperature</parameters>
<coefficients a="0.132733" b="0.012322" c="0.000032" d="-0.011109" e="-0.000125" f="-0.000123"/>
<coefficients a="1.039924" b="0.014600" c="0.000006" d="-0.05026" e="0.000635" f="-0.000154"/>
</heat_efficiency_curve>
<cooling_output_curve/>
<cooling_fuel_consumption_curve/>
@ -2145,6 +2145,12 @@
<system_id>1</system_id>
</systems>
</system_archetype>
<system_archetype cluster_id="3">
<name>Central Hydronic Air Source Heat Pump System with Storage</name>
<systems>
<system_id>8</system_id>
</systems>
</system_archetype>
</system_archetypes>
</EnergySystemCatalog>

View File

@ -4,8 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import glob
import logging
import subprocess
from pathlib import Path
import numpy as np
@ -57,6 +58,7 @@ class InselMonthlyEnergyBalance:
self._generate_meb_template(building, output_path, self._custom_insel_block)
)
self._export()
self._run()
@staticmethod
def _add_block(file, block_number, block_type, inputs=None, parameters=None):
@ -77,6 +79,17 @@ class InselMonthlyEnergyBalance:
with open(Path(self._path / file_name).resolve(), 'w', encoding='utf8') as insel_file:
insel_file.write(content)
def _run(self):
"""
Calls the software
"""
try:
_insel_files = glob.glob(f'{self._path}/*.insel')
for insel_file in _insel_files:
subprocess.run(['insel', str(insel_file)], stdout=subprocess.DEVNULL)
except (subprocess.SubprocessError, subprocess.TimeoutExpired, subprocess.CalledProcessError) as error:
raise Exception(error)
def _sanity_check(self):
levels_of_detail = self._city.level_of_detail
if levels_of_detail.geometry is None:
@ -115,6 +128,8 @@ class InselMonthlyEnergyBalance:
inputs.append(f"{str(100 + i)}.1 % Radiation surface {str(i)}")
number_of_storeys = int(building.eave_height / building.average_storey_height)
if number_of_storeys == 0:
number_of_storeys = 1
attic_heated = building.attic_heated
basement_heated = building.basement_heated
if building.attic_heated is None:
@ -189,6 +204,34 @@ class InselMonthlyEnergyBalance:
for day_type in schedule.day_types:
infiltration += infiltration_day * cte.WEEK_DAYS_A_YEAR[day_type] / 365
ventilation += ventilation_day * cte.WEEK_DAYS_A_YEAR[day_type] / 365
# total_exclusive_wall_area = 0
# for thermal_boundary in thermal_zone.thermal_boundaries:
# wall_area = 0
# if thermal_boundary.type == cte.WALL:
# wall_area = thermal_boundary.opaque_area * (1 + thermal_boundary.window_ratio)
# if thermal_boundary.parent_surface.percentage_shared is not None:
# wall_area = wall_area * (1 - thermal_boundary.parent_surface.percentage_shared)
# total_exclusive_wall_area += wall_area
# for schedule in usage.thermal_control.hvac_availability_schedules:
# ventilation_day = 0
# infiltration_day = 0
# for value in schedule.values:
# if value == 0:
# infiltration_day += internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_area_system_off * total_exclusive_wall_area / 24 * cte.INFILTRATION_75PA_TO_4PA * cte.HOUR_TO_SECONDS / building.volume
# ventilation_day += 0
# else:
# ventilation_value = usage.mechanical_air_change * value * cte.HOUR_TO_SECONDS
# infiltration_value = internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_area_system_off * value * total_exclusive_wall_area * cte.INFILTRATION_75PA_TO_4PA * cte.HOUR_TO_SECONDS / building.volume
# if ventilation_value >= infiltration_value:
# ventilation_day += ventilation_value / 24
# infiltration_day += 0
# else:
# ventilation_day += 0
# infiltration_day += infiltration_value / 24
# for day_type in schedule.day_types:
# infiltration += infiltration_day * cte.WEEK_DAYS_A_YEAR[day_type] / 365
# ventilation += ventilation_day * cte.WEEK_DAYS_A_YEAR[day_type] / 365
ventilation_infiltration = ventilation + infiltration
parameters.append(f'{ventilation_infiltration} % BP(18) #8 Minimum air change rate zone {i + 1} (ACH)')

10393
input_files/anjou.geojson Normal file

File diff suppressed because it is too large Load Diff

15305
input_files/pointe.geojson Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
from pathlib import Path
import subprocess
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.system_sizing_methods.genetic_algorithm.multi_objective_genetic_algorithm import MultiObjectiveGeneticAlgorithm
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
import hub.helpers.constants as cte
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 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 *
from hub.exports.exports_factory import ExportsFactory
# Specify the GeoJSON file path
input_files_path = (Path(__file__).parent / 'input_files')
input_files_path.mkdir(parents=True, exist_ok=True)
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.00006)
geojson_file_path = input_files_path / 'output_buildings.geojson'
output_path = (Path(__file__).parent / 'out_files').resolve()
output_path.mkdir(parents=True, exist_ok=True)
energy_plus_output_path = output_path / 'energy_plus_outputs'
energy_plus_output_path.mkdir(parents=True, exist_ok=True)
simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve()
simulation_results_path.mkdir(parents=True, exist_ok=True)
sra_output_path = output_path / 'sra_outputs'
sra_output_path.mkdir(parents=True, exist_ok=True)
cost_analysis_output_path = output_path / 'cost_analysis'
cost_analysis_output_path.mkdir(parents=True, exist_ok=True)
city = GeometryFactory(file_type='geojson',
path=geojson_file_path,
height_field='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()
ExportsFactory('sra', city, sra_output_path).export()
sra_path = (sra_output_path / f'{city.name}_sra.xml').resolve()
subprocess.run(['sra', str(sra_path)])
ResultFactory('sra', city, sra_output_path).enrich()
energy_plus_workflow(city, energy_plus_output_path)
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
EnergySystemsFactory('montreal_future', city).enrich()
for building in city.buildings:
design_period_demands = MultiObjectiveGeneticAlgorithm(optimization_scenario='energy-consumption_cost').design_period_identification(city.buildings[0])
heating_demand = design_period_demands[cte.HEATING]['demands']

View File

@ -55,4 +55,6 @@ random_assignation.call_random(city.buildings, random_assignation.residential_ne
EnergySystemsFactory('montreal_future', city).enrich()
for building in city.buildings:
energy_system = building.energy_systems[1]
MultiObjectiveGeneticAlgorithm(optimization_scenario='energy-consumption_cost').solve_ga(building, energy_system)
solutions = MultiObjectiveGeneticAlgorithm(optimization_scenario='energy-consumption_cost').solve_ga(building,
energy_system)