added lod to the city_objects

This commit is contained in:
Pilar Monsalvete 2023-05-12 09:27:29 -04:00
parent ef7addd5b5
commit e48dec81cf
22 changed files with 332 additions and 166 deletions

View File

@ -13,7 +13,7 @@ import pandas as pd
from hub.hub_logger import logger from hub.hub_logger import logger
import hub.helpers.constants as cte import hub.helpers.constants as cte
import hub.helpers.peak_loads as pl from hub.helpers.peak_loads import PeakLoads
from hub.city_model_structure.building_demand.surface import Surface from hub.city_model_structure.building_demand.surface import Surface
from hub.city_model_structure.city_object import CityObject from hub.city_model_structure.city_object import CityObject
from hub.city_model_structure.building_demand.household import Household from hub.city_model_structure.building_demand.household import Household
@ -50,8 +50,6 @@ class Building(CityObject):
self._domestic_hot_water_heat_demand = dict() self._domestic_hot_water_heat_demand = dict()
self._heating_consumption = dict() self._heating_consumption = dict()
self._cooling_consumption = dict() self._cooling_consumption = dict()
self._lighting_electrical_consumption = dict()
self._appliances_electrical_consumption = dict()
self._domestic_hot_water_consumption = dict() self._domestic_hot_water_consumption = dict()
self._onsite_electrical_production = dict() self._onsite_electrical_production = dict()
self._eave_height = None self._eave_height = None
@ -367,31 +365,40 @@ class Building(CityObject):
self._domestic_hot_water_heat_demand = value self._domestic_hot_water_heat_demand = value
@property @property
def heating_peak_load(self) -> dict: def heating_peak_load(self) -> Union[None, dict]:
""" """
Get heating peak load in W Get heating peak load in W
:return: dict{DataFrame(float)} :return: dict{DataFrame(float)}
""" """
results = {} results = {}
# todo: needed??
monthly_values = None
if cte.HOUR in self.heating: if cte.HOUR in self.heating:
monthly_values = pl.peak_loads_from_hourly(self.heating[cte.HOUR][next(iter(self.heating[cte.HOUR]))].values) monthly_values = PeakLoads().\
peak_loads_from_hourly(self.heating[cte.HOUR][next(iter(self.heating[cte.HOUR]))].values)
else: else:
monthly_values = pl.heating_peak_loads_from_methodology(self) monthly_values = PeakLoads(self).heating_peak_loads_from_methodology
if monthly_values is None:
return None
results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['heating peak loads']) results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['heating peak loads'])
results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['heating peak loads']) results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['heating peak loads'])
return results return results
@property @property
def cooling_peak_load(self) -> dict: def cooling_peak_load(self) -> Union[None, dict]:
""" """
Get cooling peak load in W Get cooling peak load in W
:return: dict{DataFrame(float)} :return: dict{DataFrame(float)}
""" """
results = {} results = {}
monthly_values = None
if cte.HOUR in self.cooling: if cte.HOUR in self.cooling:
monthly_values = pl.peak_loads_from_hourly(self.cooling[cte.HOUR][next(iter(self.cooling[cte.HOUR]))]) # todo: .values???????? Like heating
monthly_values = PeakLoads().peak_loads_from_hourly(self.cooling[cte.HOUR][next(iter(self.cooling[cte.HOUR]))])
else: else:
monthly_values = pl.cooling_peak_loads_from_methodology(self) monthly_values = PeakLoads(self).cooling_peak_loads_from_methodology
if monthly_values is None:
return None
results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['cooling peak loads']) results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['cooling peak loads'])
results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['cooling peak loads']) results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['cooling peak loads'])
return results return results
@ -532,7 +539,7 @@ class Building(CityObject):
return: dict return: dict
""" """
for heating_demand_key in self.heating: for heating_demand_key in self.heating:
demand = self.heating[heating_demand_key][0] demand = self.heating[heating_demand_key][cte.INSEL_MEB]
consumption_type = cte.HEATING consumption_type = cte.HEATING
final_energy_consumed = self._calculate_consumption(consumption_type, demand) final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._heating_consumption[heating_demand_key] = final_energy_consumed self._heating_consumption[heating_demand_key] = final_energy_consumed
@ -545,7 +552,7 @@ class Building(CityObject):
return: dict return: dict
""" """
for cooling_demand_key in self.cooling: for cooling_demand_key in self.cooling:
demand = self.cooling[cooling_demand_key][0] demand = self.cooling[cooling_demand_key][cte.INSEL_MEB]
consumption_type = cte.COOLING consumption_type = cte.COOLING
final_energy_consumed = self._calculate_consumption(consumption_type, demand) final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._cooling_consumption[cooling_demand_key] = final_energy_consumed self._cooling_consumption[cooling_demand_key] = final_energy_consumed
@ -558,44 +565,18 @@ class Building(CityObject):
return: dict return: dict
""" """
for domestic_hot_water_demand_key in self.domestic_hot_water_heat_demand: for domestic_hot_water_demand_key in self.domestic_hot_water_heat_demand:
demand = self.domestic_hot_water_heat_demand[domestic_hot_water_demand_key][0] demand = self.domestic_hot_water_heat_demand[domestic_hot_water_demand_key][cte.INSEL_MEB]
consumption_type = cte.DOMESTIC_HOT_WATER consumption_type = cte.DOMESTIC_HOT_WATER
final_energy_consumed = self._calculate_consumption(consumption_type, demand) final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._domestic_hot_water_consumption[domestic_hot_water_demand_key] = final_energy_consumed self._domestic_hot_water_consumption[domestic_hot_water_demand_key] = final_energy_consumed
return self._domestic_hot_water_consumption return self._domestic_hot_water_consumption
@property
def lighting_electrical_consumption(self):
"""
Get energy consumption for lighting according to the electricity system installed
return: dict
"""
for lighting_demand_key in self.lighting_electrical_demand:
demand = self.lighting_electrical_demand[lighting_demand_key][0]
consumption_type = cte.ELECTRICITY
final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._lighting_electrical_consumption[lighting_demand_key] = final_energy_consumed
return self._lighting_electrical_consumption
@property
def appliances_electrical_consumption(self):
"""
Get energy consumption for appliances according to the electricity system installed
return: dict
"""
for appliances_demand_key in self.appliances_electrical_demand:
demand = self.appliances_electrical_demand[appliances_demand_key][0]
consumption_type = cte.ELECTRICITY
final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._appliances_electrical_consumption[appliances_demand_key] = final_energy_consumed
return self._appliances_electrical_consumption
def _calculate_consumption(self, consumption_type, demand): def _calculate_consumption(self, consumption_type, demand):
# todo: modify when COP depends on the hour # todo: modify when COP depends on the hour
coefficient_of_performance = 0 coefficient_of_performance = 0
for energy_system in self.energy_systems: for energy_system in self.energy_systems:
for demand_type in energy_system.demand_types: for demand_type in energy_system.demand_types:
if demand_type == consumption_type: if demand_type.lower() == consumption_type.lower():
if consumption_type == cte.HEATING or consumption_type == cte.DOMESTIC_HOT_WATER: if consumption_type == cte.HEATING or consumption_type == cte.DOMESTIC_HOT_WATER:
coefficient_of_performance = energy_system.generation_system.heat_efficiency coefficient_of_performance = energy_system.generation_system.heat_efficiency
elif consumption_type == cte.COOLING: elif consumption_type == cte.COOLING:
@ -620,18 +601,11 @@ class Building(CityObject):
for energy_system in self.energy_systems: for energy_system in self.energy_systems:
if energy_system.generation_system.type == cte.PHOTOVOLTAIC: if energy_system.generation_system.type == cte.PHOTOVOLTAIC:
_efficiency = energy_system.generation_system.electricity_efficiency _efficiency = energy_system.generation_system.electricity_efficiency
_temporal_cases = self.roofs[0].global_irradiance.keys()
self._onsite_electrical_production = {} self._onsite_electrical_production = {}
for _case in _temporal_cases: for _key in self.roofs[0].global_irradiance.keys():
_results = [] _results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key]))]
for surface in self.surfaces: for surface in self.surfaces:
for i, value in enumerate(surface.global_irradiance[_case]): _results = [x + y * _efficiency * surface.perimeter_area * surface.solar_collectors_area_reduction_factor
if len(_results) == 0: for x, y in zip(_results, surface.global_irradiance[_key])]
_collector_production = value * _efficiency \ self._onsite_electrical_production[_key] = _results
* surface.perimeter_area * surface.solar_collectors_area_reduction_factor
else:
_collector_production = _results[i] * value * _efficiency \
* surface.perimeter_area * surface.solar_collectors_area_reduction_factor
_results.append(_collector_production)
self._onsite_electrical_production[_case] = _results
return self._onsite_electrical_production return self._onsite_electrical_production

View File

@ -8,6 +8,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
from __future__ import annotations from __future__ import annotations
from typing import List, Union from typing import List, Union
from hub.city_model_structure.level_of_detail import LevelOfDetail
from hub.city_model_structure.iot.sensor import Sensor from hub.city_model_structure.iot.sensor import Sensor
from hub.city_model_structure.building_demand.surface import Surface from hub.city_model_structure.building_demand.surface import Surface
from hub.city_model_structure.attributes.polyhedron import Polyhedron from hub.city_model_structure.attributes.polyhedron import Polyhedron
@ -21,6 +22,7 @@ class CityObject:
""" """
def __init__(self, name, surfaces): def __init__(self, name, surfaces):
self._name = name self._name = name
self._level_of_detail = LevelOfDetail()
self._surfaces = surfaces self._surfaces = surfaces
self._type = None self._type = None
self._city_object_lower_corner = None self._city_object_lower_corner = None
@ -43,6 +45,14 @@ class CityObject:
self._sensors = [] self._sensors = []
self._neighbours = None self._neighbours = None
@property
def level_of_detail(self) -> LevelOfDetail:
"""
Get level of detail of different aspects of the city: geometry, construction and usage
:return: LevelOfDetail
"""
return self._level_of_detail
@property @property
def name(self): def name(self):
""" """

View File

@ -26,7 +26,9 @@ class GenericGenerationSystem:
self._source_temperature = None self._source_temperature = None
self._source_mass_flow = None self._source_mass_flow = None
self._storage_capacity = None self._storage_capacity = None
self._storage = None
self._auxiliary_equipment = None self._auxiliary_equipment = None
self._peak_coverages = None
@property @property
def type(self): def type(self):
@ -82,6 +84,15 @@ class GenericGenerationSystem:
Get heat_power in W Get heat_power in W
:return: float :return: float
""" """
if building.heating_peak_load is not None:
_generation_system.heat_power = building.heating_peak_load
if building.cooling_peak_load is not None:
_generation_system.cooling_power = building.cooling_peak_load
# the only system that generates electricity in the montreal custom catalog is PV systems
_generation_system.electricity_power = 0
if archetype_generation_equipment.storage:
# todo: calculate storage capacity in J
_generation_system.storage_capacity = 0
return self._heat_power return self._heat_power
@heat_power.setter @heat_power.setter
@ -220,6 +231,22 @@ class GenericGenerationSystem:
""" """
self._storage_capacity = value self._storage_capacity = value
@property
def storage(self):
"""
Get boolean storage exists
:return: bool
"""
return self._storage
@storage.setter
def storage(self, value):
"""
Set boolean storage exists
:return: bool
"""
self._storage = value
@property @property
def auxiliary_equipment(self) -> Union[None, GenericGenerationSystem]: def auxiliary_equipment(self) -> Union[None, GenericGenerationSystem]:
""" """
@ -235,3 +262,19 @@ class GenericGenerationSystem:
:param value: GenerationSystem :param value: GenerationSystem
""" """
self._auxiliary_equipment = value self._auxiliary_equipment = value
@property
def peak_coverages(self) -> dict:
"""
Get ratio of each energy type power peak covered by the system
:return: dict {Heating: value, Cooling: value, Domestic Hot Water: value, Electricity: value}
"""
return self._peak_coverages
@peak_coverages.setter
def peak_coverages(self, value):
"""
Set ratio of each energy type power peak covered by the system
:param value: dict
"""
self._peak_coverages = value

View File

@ -51,7 +51,6 @@ class InselMonthlyEnergyBalance(Insel):
) )
self._export() self._export()
def _export(self): def _export(self):
for i_file, content in enumerate(self._contents): for i_file, content in enumerate(self._contents):
file_name = self._insel_files_paths[i_file] file_name = self._insel_files_paths[i_file]
@ -63,7 +62,7 @@ class InselMonthlyEnergyBalance(Insel):
levels_of_detail = self._city.level_of_detail levels_of_detail = self._city.level_of_detail
if levels_of_detail.geometry is None: if levels_of_detail.geometry is None:
raise Exception(f'Level of detail of geometry not assigned') raise Exception(f'Level of detail of geometry not assigned')
if levels_of_detail.geometry < 0.5: if levels_of_detail.geometry < 1:
raise Exception(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 0.5') raise Exception(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 0.5')
if levels_of_detail.construction is None: if levels_of_detail.construction is None:
raise Exception(f'Level of detail of construction not assigned') raise Exception(f'Level of detail of construction not assigned')
@ -73,13 +72,15 @@ class InselMonthlyEnergyBalance(Insel):
raise Exception(f'Level of detail of usage not assigned') raise Exception(f'Level of detail of usage not assigned')
if levels_of_detail.usage < 1: if levels_of_detail.usage < 1:
raise Exception(f'Level of detail of usage = {levels_of_detail.usage}. Required minimum level 1') raise Exception(f'Level of detail of usage = {levels_of_detail.usage}. Required minimum level 1')
for building in self._city.buildings: if levels_of_detail.weather is None:
if cte.MONTH not in building.external_temperature: raise Exception(f'Level of detail of usage not assigned')
raise Exception(f'Building {building.name} does not have external temperature assigned') if levels_of_detail.weather < 1:
for surface in building.surfaces: raise Exception(f'Level of detail of weather = {levels_of_detail.weather}. Required minimum level 1')
if surface.type != cte.GROUND: if levels_of_detail.surface_radiation is None:
if cte.MONTH not in surface.global_irradiance: raise Exception(f'Level of detail of usage not assigned')
raise Exception(f'Building {building.name} does not have global irradiance on surfaces assigned') if levels_of_detail.surface_radiation < 1:
raise Exception(f'Level of detail of surface radiation = {levels_of_detail.surface_radiation}. '
f'Required minimum level 1')
@staticmethod @staticmethod
def _generate_meb_template(building, insel_outputs_path, radiation_calculation_method, weather_format): def _generate_meb_template(building, insel_outputs_path, radiation_calculation_method, weather_format):

View File

@ -0,0 +1,22 @@
"""
Dictionaries module for Montreal system catalog demand types to hub energy demand types
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import hub.helpers.constants as cte
class MontrealDemandTypeToHubEnergyDemandType:
def __init__(self):
self._dictionary = {'heating': cte.HEATING,
'cooling': cte.COOLING,
'domestic_hot_water': cte.DOMESTIC_HOT_WATER,
'electricity': cte.ELECTRICITY,
}
@property
def dictionary(self) -> dict:
return self._dictionary

View File

@ -15,6 +15,7 @@ from hub.helpers.data.hub_usage_to_comnet_usage import HubUsageToComnetUsage
from hub.helpers.data.hub_usage_to_hft_usage import HubUsageToHftUsage from hub.helpers.data.hub_usage_to_hft_usage import HubUsageToHftUsage
from hub.helpers.data.hub_usage_to_nrcan_usage import HubUsageToNrcanUsage from hub.helpers.data.hub_usage_to_nrcan_usage import HubUsageToNrcanUsage
from hub.helpers.data.montreal_system_to_hub_energy_generation_system import MontrealSystemToHubEnergyGenerationSystem from hub.helpers.data.montreal_system_to_hub_energy_generation_system import MontrealSystemToHubEnergyGenerationSystem
from hub.helpers.data.montreal_demand_type_to_hub_energy_demand_type import MontrealDemandTypeToHubEnergyDemandType
from hub.helpers.data.hub_function_to_montreal_custom_costs_function import HubFunctionToMontrealCustomCostsFunction from hub.helpers.data.hub_function_to_montreal_custom_costs_function import HubFunctionToMontrealCustomCostsFunction
@ -99,6 +100,14 @@ class Dictionaries:
Get montreal custom system names to hub energy system names, transformation dictionary Get montreal custom system names to hub energy system names, transformation dictionary
""" """
return MontrealSystemToHubEnergyGenerationSystem().dictionary return MontrealSystemToHubEnergyGenerationSystem().dictionary
@property
def montreal_demand_type_to_hub_energy_demand_type(self):
"""
Get montreal custom system demand type to hub energy demand type, transformation dictionary
"""
return MontrealDemandTypeToHubEnergyDemandType().dictionary
@property @property
def hub_function_to_montreal_custom_costs_function(self) -> dict: def hub_function_to_montreal_custom_costs_function(self) -> dict:
""" """

View File

@ -1,71 +1,121 @@
"""
Cooling and Heating peak loads module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import sys
import math import math
from hub.hub_logger import logger
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.helpers.peak_calculation.loads_calculation import LoadsCalculation from hub.helpers.peak_calculation.loads_calculation import LoadsCalculation
_MONTH_STARTING_HOUR = [0, 744, 1416, 2160, 2880, 3624, 4344, 5088, 5832, 6552, 7296, 8016, math.inf] _MONTH_STARTING_HOUR = [0, 744, 1416, 2160, 2880, 3624, 4344, 5088, 5832, 6552, 7296, 8016, math.inf]
def peak_loads_from_hourly(hourly_values):
month = 1
peaks = [0 for _ in range(12)]
for i, value in enumerate(hourly_values):
if _MONTH_STARTING_HOUR[month] <= i:
month += 1
if value > peaks[month-1]:
peaks[month-1] = value
return peaks
def heating_peak_loads_from_methodology(building): class PeakLoads:
monthly_heating_loads = [] """
ambient_temperature = building.external_temperature[cte.HOUR]['epw'] PeakLoads class
for month in range(0, 12): """
ground_temperature = building.ground_temperature[cte.MONTH]['2'][month] def __init__(self, building=None):
heating_ambient_temperature = 100 self._building = building
start_hour = _MONTH_STARTING_HOUR[month]
end_hour = 8760
if month < 11:
end_hour = _MONTH_STARTING_HOUR[month + 1]
for hour in range(start_hour, end_hour):
temperature = ambient_temperature[hour]
if temperature < heating_ambient_temperature:
heating_ambient_temperature = temperature
loads = LoadsCalculation(building)
heating_load_transmitted = loads.get_heating_transmitted_load(heating_ambient_temperature, ground_temperature)
heating_load_ventilation_sensible = loads.get_heating_ventilation_load_sensible(heating_ambient_temperature)
heating_load_ventilation_latent = 0
heating_load = heating_load_transmitted + heating_load_ventilation_sensible + heating_load_ventilation_latent
if heating_load < 0:
heating_load = 0
monthly_heating_loads.append(heating_load)
return monthly_heating_loads
def cooling_peak_loads_from_methodology(building): def _can_be_calculated(self):
monthly_cooling_loads = [] levels_of_detail = self._building.level_of_detail
ambient_temperature = building.external_temperature[cte.HOUR]['epw'] can_be_calculated = True
for month in range(0, 12): if levels_of_detail.geometry is None:
ground_temperature = building.ground_temperature[cte.MONTH]['2'][month] can_be_calculated = False
cooling_ambient_temperature = -100 if levels_of_detail.geometry < 1:
cooling_calculation_hour = -1 can_be_calculated = False
start_hour = _MONTH_STARTING_HOUR[month] if levels_of_detail.construction is None:
end_hour = 8760 can_be_calculated = False
if month < 11: if levels_of_detail.construction < 1:
end_hour = _MONTH_STARTING_HOUR[month + 1] can_be_calculated = False
for hour in range(start_hour, end_hour): if levels_of_detail.usage is None:
temperature = ambient_temperature[hour] can_be_calculated = False
if temperature > cooling_ambient_temperature: if levels_of_detail.usage < 1:
cooling_ambient_temperature = temperature can_be_calculated = False
cooling_calculation_hour = hour if levels_of_detail.weather is None:
loads = LoadsCalculation(building) can_be_calculated = False
cooling_load_transmitted = loads.get_cooling_transmitted_load(cooling_ambient_temperature, ground_temperature) if levels_of_detail.weather < 2:
cooling_load_renovation_sensible = loads.get_cooling_ventilation_load_sensible(cooling_ambient_temperature) can_be_calculated = False
cooling_load_internal_gains_sensible = loads.get_internal_load_sensible() if levels_of_detail.surface_radiation is None:
cooling_load_radiation = loads.get_radiation_load('sra', cooling_calculation_hour) can_be_calculated = False
cooling_load_sensible = cooling_load_transmitted + cooling_load_renovation_sensible - cooling_load_radiation \ if levels_of_detail.surface_radiation < 2:
- cooling_load_internal_gains_sensible can_be_calculated = False
return can_be_calculated
cooling_load_latent = 0 @staticmethod
cooling_load = cooling_load_sensible + cooling_load_latent def peak_loads_from_hourly(hourly_values):
if cooling_load > 0: month = 1
cooling_load = 0 peaks = [0 for _ in range(12)]
monthly_cooling_loads.append(abs(cooling_load)) for i, value in enumerate(hourly_values):
return monthly_cooling_loads if _MONTH_STARTING_HOUR[month] <= i:
month += 1
if value > peaks[month-1]:
peaks[month-1] = value
return peaks
@property
def heating_peak_loads_from_methodology(self):
if self._can_be_calculated():
return None
monthly_heating_loads = []
ambient_temperature = self._building.external_temperature[cte.HOUR]['epw']
for month in range(0, 12):
ground_temperature = self._building.ground_temperature[cte.MONTH]['2'][month]
heating_ambient_temperature = 100
start_hour = _MONTH_STARTING_HOUR[month]
end_hour = 8760
if month < 11:
end_hour = _MONTH_STARTING_HOUR[month + 1]
for hour in range(start_hour, end_hour):
temperature = ambient_temperature[hour]
if temperature < heating_ambient_temperature:
heating_ambient_temperature = temperature
loads = LoadsCalculation(self._building)
heating_load_transmitted = loads.get_heating_transmitted_load(heating_ambient_temperature, ground_temperature)
heating_load_ventilation_sensible = loads.get_heating_ventilation_load_sensible(heating_ambient_temperature)
heating_load_ventilation_latent = 0
heating_load = heating_load_transmitted + heating_load_ventilation_sensible + heating_load_ventilation_latent
if heating_load < 0:
heating_load = 0
monthly_heating_loads.append(heating_load)
return monthly_heating_loads
@property
def cooling_peak_loads_from_methodology(self):
if self._can_be_calculated():
return None
monthly_cooling_loads = []
ambient_temperature = self._building.external_temperature[cte.HOUR]['epw']
for month in range(0, 12):
ground_temperature = self._building.ground_temperature[cte.MONTH]['2'][month]
cooling_ambient_temperature = -100
cooling_calculation_hour = -1
start_hour = _MONTH_STARTING_HOUR[month]
end_hour = 8760
if month < 11:
end_hour = _MONTH_STARTING_HOUR[month + 1]
for hour in range(start_hour, end_hour):
temperature = ambient_temperature[hour]
if temperature > cooling_ambient_temperature:
cooling_ambient_temperature = temperature
cooling_calculation_hour = hour
loads = LoadsCalculation(self._building)
cooling_load_transmitted = loads.get_cooling_transmitted_load(cooling_ambient_temperature, ground_temperature)
cooling_load_renovation_sensible = loads.get_cooling_ventilation_load_sensible(cooling_ambient_temperature)
cooling_load_internal_gains_sensible = loads.get_internal_load_sensible()
cooling_load_radiation = loads.get_radiation_load('sra', cooling_calculation_hour)
cooling_load_sensible = cooling_load_transmitted + cooling_load_renovation_sensible - cooling_load_radiation \
- cooling_load_internal_gains_sensible
cooling_load_latent = 0
cooling_load = cooling_load_sensible + cooling_load_latent
if cooling_load > 0:
cooling_load = 0
monthly_cooling_loads.append(abs(cooling_load))
return monthly_cooling_loads

View File

@ -33,6 +33,8 @@ class ConstructionFactory:
""" """
NrelPhysicsParameters(self._city).enrich_buildings() NrelPhysicsParameters(self._city).enrich_buildings()
self._city.level_of_detail.construction = 2 self._city.level_of_detail.construction = 2
for building in self._city.buildings:
building.level_of_detail.construction = 2
def _nrcan(self): def _nrcan(self):
""" """
@ -40,6 +42,8 @@ class ConstructionFactory:
""" """
NrcanPhysicsParameters(self._city).enrich_buildings() NrcanPhysicsParameters(self._city).enrich_buildings()
self._city.level_of_detail.construction = 2 self._city.level_of_detail.construction = 2
for building in self._city.buildings:
building.level_of_detail.construction = 2
def enrich(self): def enrich(self):
""" """

View File

@ -7,14 +7,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
import sys import sys
from hub.hub_logger import get_logger from hub.hub_logger import logger
from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory
from hub.city_model_structure.energy_systems.generic_energy_system import GenericEnergySystem from hub.city_model_structure.energy_systems.generic_energy_system import GenericEnergySystem
from hub.city_model_structure.energy_systems.generic_generation_system import GenericGenerationSystem from hub.city_model_structure.energy_systems.generic_generation_system import GenericGenerationSystem
from hub.city_model_structure.energy_systems.generic_distribution_system import GenericDistributionSystem from hub.city_model_structure.energy_systems.generic_distribution_system import GenericDistributionSystem
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
import hub.helpers.constants as cte
logger = get_logger()
class MontrealCustomEnergySystemParameters: class MontrealCustomEnergySystemParameters:
@ -48,17 +47,15 @@ class MontrealCustomEnergySystemParameters:
building_systems = [] building_systems = []
for equipment in archetype.equipments: for equipment in archetype.equipments:
energy_system = GenericEnergySystem() energy_system = GenericEnergySystem()
energy_system.demand_types = equipment.demand_types _hub_demand_types = []
for demand_type in equipment.demand_types:
_hub_demand_types.append(Dictionaries().montreal_demand_type_to_hub_energy_demand_type[demand_type])
energy_system.demand_types = _hub_demand_types
_generation_system = GenericGenerationSystem() _generation_system = GenericGenerationSystem()
archetype_generation_equipment = equipment.generation_system archetype_generation_equipment = equipment.generation_system
_type = str(equipment.name).split('_')[0] _type = str(equipment.name).split('_')[0]
_generation_system.type = Dictionaries().montreal_system_to_hub_energy_generation_system[ _generation_system.type = Dictionaries().montreal_system_to_hub_energy_generation_system[
_type] _type]
# dhw peak does not add anything to the total heat peak
_generation_system.heat_power = building.heating_peak_load
_generation_system.cooling_power = building.cooling_peak_load
# the only system that generates electricity in the montreal custom catalog is PV systems
_generation_system.electricity_power = 0
_generation_system.fuel_type = archetype_generation_equipment.fuel_type _generation_system.fuel_type = archetype_generation_equipment.fuel_type
_generation_system.source_types = archetype_generation_equipment.source_types _generation_system.source_types = archetype_generation_equipment.source_types
_generation_system.heat_efficiency = archetype_generation_equipment.heat_efficiency _generation_system.heat_efficiency = archetype_generation_equipment.heat_efficiency
@ -66,10 +63,12 @@ class MontrealCustomEnergySystemParameters:
_generation_system.electricity_efficiency = archetype_generation_equipment.electricity_efficiency _generation_system.electricity_efficiency = archetype_generation_equipment.electricity_efficiency
_generation_system.source_temperature = archetype_generation_equipment.source_temperature _generation_system.source_temperature = archetype_generation_equipment.source_temperature
_generation_system.source_mass_flow = archetype_generation_equipment.source_mass_flow _generation_system.source_mass_flow = archetype_generation_equipment.source_mass_flow
if archetype_generation_equipment.storage: # dhw peak does not add anything to the total heat peak
# todo: calculate storage capacity in J _generation_system.peak_coverages = {cte.HEATING: 1,
_generation_system.storage_capacity = 0 cte.COOLING: 1,
cte.DOMESTIC_HOT_WATER: 0,
cte.ELECTRICITY: 0}
_generation_system.storage = archetype_generation_equipment.storage
_generation_system.auxiliary_equipment = None _generation_system.auxiliary_equipment = None
energy_system.generation_system = _generation_system energy_system.generation_system = _generation_system
@ -84,6 +83,7 @@ class MontrealCustomEnergySystemParameters:
energy_system.distribution_system = _distribution_system energy_system.distribution_system = _distribution_system
building_systems.append(energy_system) building_systems.append(energy_system)
building.energy_systems = building_systems
@staticmethod @staticmethod
def _search_archetypes(catalog, name): def _search_archetypes(catalog, name):

View File

@ -37,19 +37,27 @@ class EnergySystemsFactory:
Enrich the city by using xlsx heat pump information Enrich the city by using xlsx heat pump information
""" """
AirSourceHeatPumpParameters(self._city, self._base_path).enrich_city() AirSourceHeatPumpParameters(self._city, self._base_path).enrich_city()
self._city.level_of_detail.energy_systems = 0
for building in self._city.buildings:
building.level_of_detail.energy_systems = 0
def _water_to_water_hp(self): def _water_to_water_hp(self):
""" """
Enrich the city by using water to water heat pump information Enrich the city by using water to water heat pump information
""" """
WaterToWaterHPParameters(self._city, self._base_path).enrich_city() WaterToWaterHPParameters(self._city, self._base_path).enrich_city()
self._city.level_of_detail.energy_systems = 0
for building in self._city.buildings:
building.level_of_detail.energy_systems = 0
def _montreal_custom(self): def _montreal_custom(self):
""" """
Enrich the city by using montreal custom energy systems catalog information Enrich the city by using montreal custom energy systems catalog information
""" """
self._city.level_of_detail.energy_systems = 1
MontrealCustomEnergySystemParameters(self._city).enrich_buildings() MontrealCustomEnergySystemParameters(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 enrich(self): def enrich(self):
""" """

View File

@ -166,4 +166,6 @@ class CityGml:
else: else:
self._city.add_city_object(self._create_building(city_object)) self._city.add_city_object(self._create_building(city_object))
self._city.level_of_detail.geometry = self._lod self._city.level_of_detail.geometry = self._lod
for building in self._city.buildings:
building.level_of_detail.geometry = self._lod
return self._city return self._city

View File

@ -177,7 +177,7 @@ class Geojson:
extrusion_height = 0 extrusion_height = 0
if self._extrusion_height_field is not None: if self._extrusion_height_field is not None:
extrusion_height = float(feature['properties'][self._extrusion_height_field]) extrusion_height = float(feature['properties'][self._extrusion_height_field])
lod = 0.5 lod = 1
year_of_construction = None year_of_construction = None
if self._year_of_construction_field is not None: if self._year_of_construction_field is not None:
year_of_construction = int(feature['properties'][self._year_of_construction_field]) year_of_construction = int(feature['properties'][self._year_of_construction_field])
@ -215,6 +215,8 @@ class Geojson:
if building.floor_area >= 25: if building.floor_area >= 25:
self._city.add_city_object(building) self._city.add_city_object(building)
self._city.level_of_detail.geometry = lod self._city.level_of_detail.geometry = lod
for building in self._city.buildings:
building.level_of_detail.geometry = lod
if lod > 0: if lod > 0:
lines_information = GeometryHelper.city_mapping(self._city, plot=False) lines_information = GeometryHelper.city_mapping(self._city, plot=False)
self._store_shared_percentage_to_walls(self._city, lines_information) self._store_shared_percentage_to_walls(self._city, lines_information)

View File

@ -83,6 +83,8 @@ class GPandas:
building = Building(name, surfaces, year_of_construction, function, terrains=None) building = Building(name, surfaces, year_of_construction, function, terrains=None)
self._city.add_city_object(building) self._city.add_city_object(building)
self._city.level_of_detail.geometry = lod self._city.level_of_detail.geometry = lod
for building in self._city.buildings:
building.level_of_detail.geometry = lod
return self._city return self._city
@staticmethod @staticmethod

View File

@ -81,4 +81,7 @@ class Obj:
building = Building(name, surfaces, year_of_construction, function, terrains=None) building = Building(name, surfaces, year_of_construction, function, terrains=None)
self._city.add_city_object(building) self._city.add_city_object(building)
self._city.level_of_detail.geometry = lod self._city.level_of_detail.geometry = lod
for building in self._city.buildings:
building.level_of_detail.geometry = lod
return self._city return self._city

View File

@ -133,5 +133,6 @@ class Rhino:
for building in buildings: for building in buildings:
city.add_city_object(building) city.add_city_object(building)
building.level_of_detail.geometry = 3
city.level_of_detail.geometry = 3 city.level_of_detail.geometry = 3
return city return city

View File

@ -87,9 +87,20 @@ class InselMonthlyEnergyBalance:
total_dhw_demand += total_day * cte.DAYS_A_MONTH[day_type][month] * demand total_dhw_demand += total_day * cte.DAYS_A_MONTH[day_type][month] * demand
domestic_hot_water_demand.append(total_dhw_demand * area) domestic_hot_water_demand.append(total_dhw_demand * area)
building.domestic_hot_water_heat_demand[cte.MONTH] = pd.DataFrame(domestic_hot_water_demand, columns=[cte.INSEL_MEB]) building.domestic_hot_water_heat_demand[cte.MONTH] = pd.DataFrame(domestic_hot_water_demand,
columns=[cte.INSEL_MEB])
yearly_domestic_hot_water_demand = [sum(domestic_hot_water_demand)]
building.domestic_hot_water_heat_demand[cte.YEAR] = pd.DataFrame(yearly_domestic_hot_water_demand,
columns=[cte.INSEL_MEB])
building.lighting_electrical_demand[cte.MONTH] = pd.DataFrame(lighting_demand, columns=[cte.INSEL_MEB]) building.lighting_electrical_demand[cte.MONTH] = pd.DataFrame(lighting_demand, columns=[cte.INSEL_MEB])
yearly_lighting_electrical_demand = [sum(lighting_demand)]
building.lighting_electrical_demand[cte.YEAR] = pd.DataFrame(yearly_lighting_electrical_demand,
columns=[cte.INSEL_MEB])
building.appliances_electrical_demand[cte.MONTH] = pd.DataFrame(appliances_demand, columns=[cte.INSEL_MEB]) building.appliances_electrical_demand[cte.MONTH] = pd.DataFrame(appliances_demand, columns=[cte.INSEL_MEB])
yearly_appliances_electrical_demand = [sum(appliances_demand)]
building.appliances_electrical_demand[cte.YEAR] = pd.DataFrame(yearly_appliances_electrical_demand,
columns=[cte.INSEL_MEB])
def enrich(self): def enrich(self):
for building in self._city.buildings: for building in self._city.buildings:

View File

@ -95,3 +95,6 @@ class SimplifiedRadiosityAlgorithm:
if cte.YEAR not in surface.global_irradiance: if cte.YEAR not in surface.global_irradiance:
surface.global_irradiance[cte.YEAR] = self._get_yearly_mean_values(new_value) surface.global_irradiance[cte.YEAR] = self._get_yearly_mean_values(new_value)
self._city.level_of_detail.surface_radiation = 2 self._city.level_of_detail.surface_radiation = 2
for building in self._city.buildings:
building.level_of_detail.surface_radiation = 2

View File

@ -32,15 +32,19 @@ class UsageFactory:
""" """
Enrich the city with COMNET usage library Enrich the city with COMNET usage library
""" """
self._city.level_of_detail.usage = 2
ComnetUsageParameters(self._city).enrich_buildings() ComnetUsageParameters(self._city).enrich_buildings()
self._city.level_of_detail.usage = 2
for building in self._city.buildings:
building.level_of_detail.usage = 2
def _nrcan(self): def _nrcan(self):
""" """
Enrich the city with NRCAN usage library Enrich the city with NRCAN usage library
""" """
self._city.level_of_detail.usage = 2
NrcanUsageParameters(self._city).enrich_buildings() NrcanUsageParameters(self._city).enrich_buildings()
self._city.level_of_detail.usage = 2
for building in self._city.buildings:
building.level_of_detail.usage = 2
def enrich(self): def enrich(self):
""" """

View File

@ -160,3 +160,6 @@ class EpwWeatherParameters:
usage.domestic_hot_water.density = density usage.domestic_hot_water.density = density
self._city.level_of_detail.weather = 2 self._city.level_of_detail.weather = 2
for building in self._city.buildings:
building.level_of_detail.weather = 2

View File

@ -8,10 +8,7 @@ from pathlib import Path
from unittest import TestCase from unittest import TestCase
import hub.exports.exports_factory import hub.exports.exports_factory
from hub.imports.usage_factory import UsageFactory from hub.helpers.dictionaries import MontrealFunctionToHubFunction
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
from hub.helpers.dictionaries import MontrealFunctionToHubFunction, Dictionaries
from hub.helpers.geometry_helper import GeometryHelper from hub.helpers.geometry_helper import GeometryHelper
from hub.imports.construction_factory import ConstructionFactory from hub.imports.construction_factory import ConstructionFactory
from hub.imports.geometry_factory import GeometryFactory from hub.imports.geometry_factory import GeometryFactory

View File

@ -5,11 +5,17 @@ Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import subprocess
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
from hub.imports.geometry_factory import GeometryFactory import hub.helpers.constants as cte
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
from hub.exports.exports_factory import ExportsFactory
from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction_factory import ConstructionFactory from hub.imports.construction_factory import ConstructionFactory
from hub.imports.geometry_factory import GeometryFactory
from hub.imports.results_factory import ResultFactory
from hub.imports.usage_factory import UsageFactory from hub.imports.usage_factory import UsageFactory
from hub.imports.energy_systems_factory import EnergySystemsFactory from hub.imports.energy_systems_factory import EnergySystemsFactory
@ -20,39 +26,50 @@ class TestSystemsFactory(TestCase):
""" """
def setUp(self) -> None: def setUp(self) -> None:
""" """
Configure test environment Test setup
:return: :return: None
""" """
self._city = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve() self._example_path = (Path(__file__).parent / 'tests_data').resolve()
self._gml_path = (self._example_path / 'FZK_Haus_LoD_2.gml').resolve()
def _get_citygml(self, file): self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
file_path = (self._example_path / file).resolve() self._city = GeometryFactory('citygml',
self._city = GeometryFactory('citygml', path=file_path).city self._gml_path,
self.assertIsNotNone(self._city, 'city is none') function_to_hub=Dictionaries().alkis_function_to_hub_function).city
self.assertIsNotNone(self._city.level_of_detail.geometry, 'wrong construction level of detail')
return self._city
def test_montreal_custom_system_factory(self): def test_montreal_custom_system_factory(self):
""" """
Enrich the city with the construction information and verify it Enrich the city with the construction information and verify it
""" """
file = 'one_building_in_kelowna.gml' for building in self._city.buildings:
city = self._get_citygml(file)
for building in city.buildings:
building.energy_systems_archetype_name = 'system 1 gas' building.energy_systems_archetype_name = 'system 1 gas'
EnergySystemsFactory('montreal_custom', city).enrich() EnergySystemsFactory('montreal_custom', self._city).enrich()
for building in city.buildings: for building in self._city.buildings:
print(building.energy_systems) self.assertEqual(2, len(building.energy_systems[0].demand_types))
self.assertEqual(1, len(building.energy_systems[1].demand_types))
def test_montreal_custom_system_results(self): def test_montreal_custom_system_results(self):
""" """
Enrich the city with the construction information and verify it Enrich the city with the construction information and verify it
""" """
file = 'one_building_in_kelowna.gml' ConstructionFactory('nrcan', self._city).enrich()
city = self._get_citygml(file) UsageFactory('nrcan', self._city).enrich()
for building in city.buildings: weather_file = (self._example_path / 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
building.year_of_construction = 1980 ExportsFactory('sra', self._city, self._output_path, weather_file=weather_file, weather_format='epw').export()
ConstructionFactory('nrcan', city).enrich() sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
UsageFactory('nrcan', city).enrich() subprocess.run(['sra', str(sra_path)])
ResultFactory('sra', self._city, self._output_path).enrich()
EnergyBuildingsExportsFactory('insel_monthly_energy_balance', self._city, self._output_path).export()
for building in self._city.buildings:
insel_path = (self._output_path / f'{building.name}.insel')
subprocess.run(['insel', str(insel_path)])
ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich()
for building in self._city.buildings:
building.energy_systems_archetype_name = 'system 1 gas'
EnergySystemsFactory('montreal_custom', self._city).enrich()
for building in self._city.buildings:
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])