fix: simulation models fixed for hourly consumption calculation, optimization process improved
This commit is contained in:
parent
09d1d08ed7
commit
a143100b39
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
10393
input_files/anjou.geojson
Normal file
File diff suppressed because it is too large
Load Diff
15305
input_files/pointe.geojson
Normal file
15305
input_files/pointe.geojson
Normal file
File diff suppressed because it is too large
Load Diff
@ -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']
|
4
test.py
4
test.py
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user