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
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.city_object import CityObject
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._heating_consumption = dict()
self._cooling_consumption = dict()
self._lighting_electrical_consumption = dict()
self._appliances_electrical_consumption = dict()
self._domestic_hot_water_consumption = dict()
self._onsite_electrical_production = dict()
self._eave_height = None
@ -367,31 +365,40 @@ class Building(CityObject):
self._domestic_hot_water_heat_demand = value
@property
def heating_peak_load(self) -> dict:
def heating_peak_load(self) -> Union[None, dict]:
"""
Get heating peak load in W
:return: dict{DataFrame(float)}
"""
results = {}
# todo: needed??
monthly_values = None
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:
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.YEAR] = pd.DataFrame([max(monthly_values)], columns=['heating peak loads'])
return results
@property
def cooling_peak_load(self) -> dict:
def cooling_peak_load(self) -> Union[None, dict]:
"""
Get cooling peak load in W
:return: dict{DataFrame(float)}
"""
results = {}
monthly_values = None
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:
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.YEAR] = pd.DataFrame([max(monthly_values)], columns=['cooling peak loads'])
return results
@ -532,7 +539,7 @@ class Building(CityObject):
return: dict
"""
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
final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._heating_consumption[heating_demand_key] = final_energy_consumed
@ -545,7 +552,7 @@ class Building(CityObject):
return: dict
"""
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
final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._cooling_consumption[cooling_demand_key] = final_energy_consumed
@ -558,44 +565,18 @@ class Building(CityObject):
return: dict
"""
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
final_energy_consumed = self._calculate_consumption(consumption_type, demand)
self._domestic_hot_water_consumption[domestic_hot_water_demand_key] = final_energy_consumed
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):
# todo: modify when COP depends on the hour
coefficient_of_performance = 0
for energy_system in self.energy_systems:
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:
coefficient_of_performance = energy_system.generation_system.heat_efficiency
elif consumption_type == cte.COOLING:
@ -620,18 +601,11 @@ class Building(CityObject):
for energy_system in self.energy_systems:
if energy_system.generation_system.type == cte.PHOTOVOLTAIC:
_efficiency = energy_system.generation_system.electricity_efficiency
_temporal_cases = self.roofs[0].global_irradiance.keys()
self._onsite_electrical_production = {}
for _case in _temporal_cases:
_results = []
for _key in self.roofs[0].global_irradiance.keys():
_results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key]))]
for surface in self.surfaces:
for i, value in enumerate(surface.global_irradiance[_case]):
if len(_results) == 0:
_collector_production = value * _efficiency \
* 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
_results = [x + y * _efficiency * surface.perimeter_area * surface.solar_collectors_area_reduction_factor
for x, y in zip(_results, surface.global_irradiance[_key])]
self._onsite_electrical_production[_key] = _results
return self._onsite_electrical_production

View File

@ -8,6 +8,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
from __future__ import annotations
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.building_demand.surface import Surface
from hub.city_model_structure.attributes.polyhedron import Polyhedron
@ -21,6 +22,7 @@ class CityObject:
"""
def __init__(self, name, surfaces):
self._name = name
self._level_of_detail = LevelOfDetail()
self._surfaces = surfaces
self._type = None
self._city_object_lower_corner = None
@ -43,6 +45,14 @@ class CityObject:
self._sensors = []
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
def name(self):
"""

View File

@ -26,7 +26,9 @@ class GenericGenerationSystem:
self._source_temperature = None
self._source_mass_flow = None
self._storage_capacity = None
self._storage = None
self._auxiliary_equipment = None
self._peak_coverages = None
@property
def type(self):
@ -82,6 +84,15 @@ class GenericGenerationSystem:
Get heat_power in W
: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
@heat_power.setter
@ -220,6 +231,22 @@ class GenericGenerationSystem:
"""
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
def auxiliary_equipment(self) -> Union[None, GenericGenerationSystem]:
"""
@ -235,3 +262,19 @@ class GenericGenerationSystem:
:param value: GenerationSystem
"""
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()
def _export(self):
for i_file, content in enumerate(self._contents):
file_name = self._insel_files_paths[i_file]
@ -63,7 +62,7 @@ class InselMonthlyEnergyBalance(Insel):
levels_of_detail = self._city.level_of_detail
if levels_of_detail.geometry is None:
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')
if levels_of_detail.construction is None:
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')
if levels_of_detail.usage < 1:
raise Exception(f'Level of detail of usage = {levels_of_detail.usage}. Required minimum level 1')
for building in self._city.buildings:
if cte.MONTH not in building.external_temperature:
raise Exception(f'Building {building.name} does not have external temperature assigned')
for surface in building.surfaces:
if surface.type != cte.GROUND:
if cte.MONTH not in surface.global_irradiance:
raise Exception(f'Building {building.name} does not have global irradiance on surfaces assigned')
if levels_of_detail.weather is None:
raise Exception(f'Level of detail of usage not assigned')
if levels_of_detail.weather < 1:
raise Exception(f'Level of detail of weather = {levels_of_detail.weather}. Required minimum level 1')
if levels_of_detail.surface_radiation is None:
raise Exception(f'Level of detail of usage not 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
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_nrcan_usage import HubUsageToNrcanUsage
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
@ -99,6 +100,14 @@ class Dictionaries:
Get montreal custom system names to hub energy system names, transformation 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
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
from hub.hub_logger import logger
import hub.helpers.constants as cte
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]
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):
monthly_heating_loads = []
ambient_temperature = building.external_temperature[cte.HOUR]['epw']
for month in range(0, 12):
ground_temperature = 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(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
class PeakLoads:
"""
PeakLoads class
"""
def __init__(self, building=None):
self._building = building
def cooling_peak_loads_from_methodology(building):
monthly_cooling_loads = []
ambient_temperature = building.external_temperature[cte.HOUR]['epw']
for month in range(0, 12):
ground_temperature = 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(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
def _can_be_calculated(self):
levels_of_detail = self._building.level_of_detail
can_be_calculated = True
if levels_of_detail.geometry is None:
can_be_calculated = False
if levels_of_detail.geometry < 1:
can_be_calculated = False
if levels_of_detail.construction is None:
can_be_calculated = False
if levels_of_detail.construction < 1:
can_be_calculated = False
if levels_of_detail.usage is None:
can_be_calculated = False
if levels_of_detail.usage < 1:
can_be_calculated = False
if levels_of_detail.weather is None:
can_be_calculated = False
if levels_of_detail.weather < 2:
can_be_calculated = False
if levels_of_detail.surface_radiation is None:
can_be_calculated = False
if levels_of_detail.surface_radiation < 2:
can_be_calculated = False
return can_be_calculated
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
@staticmethod
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
@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()
self._city.level_of_detail.construction = 2
for building in self._city.buildings:
building.level_of_detail.construction = 2
def _nrcan(self):
"""
@ -40,6 +42,8 @@ class ConstructionFactory:
"""
NrcanPhysicsParameters(self._city).enrich_buildings()
self._city.level_of_detail.construction = 2
for building in self._city.buildings:
building.level_of_detail.construction = 2
def enrich(self):
"""

View File

@ -7,14 +7,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
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.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_distribution_system import GenericDistributionSystem
from hub.helpers.dictionaries import Dictionaries
logger = get_logger()
import hub.helpers.constants as cte
class MontrealCustomEnergySystemParameters:
@ -48,17 +47,15 @@ class MontrealCustomEnergySystemParameters:
building_systems = []
for equipment in archetype.equipments:
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()
archetype_generation_equipment = equipment.generation_system
_type = str(equipment.name).split('_')[0]
_generation_system.type = Dictionaries().montreal_system_to_hub_energy_generation_system[
_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.source_types = archetype_generation_equipment.source_types
_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.source_temperature = archetype_generation_equipment.source_temperature
_generation_system.source_mass_flow = archetype_generation_equipment.source_mass_flow
if archetype_generation_equipment.storage:
# todo: calculate storage capacity in J
_generation_system.storage_capacity = 0
# dhw peak does not add anything to the total heat peak
_generation_system.peak_coverages = {cte.HEATING: 1,
cte.COOLING: 1,
cte.DOMESTIC_HOT_WATER: 0,
cte.ELECTRICITY: 0}
_generation_system.storage = archetype_generation_equipment.storage
_generation_system.auxiliary_equipment = None
energy_system.generation_system = _generation_system
@ -84,6 +83,7 @@ class MontrealCustomEnergySystemParameters:
energy_system.distribution_system = _distribution_system
building_systems.append(energy_system)
building.energy_systems = building_systems
@staticmethod
def _search_archetypes(catalog, name):

View File

@ -37,19 +37,27 @@ class EnergySystemsFactory:
Enrich the city by using xlsx heat pump information
"""
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):
"""
Enrich the city by using water to water heat pump information
"""
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):
"""
Enrich the city by using montreal custom energy systems catalog information
"""
self._city.level_of_detail.energy_systems = 1
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):
"""

View File

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

View File

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

View File

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

View File

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

View File

@ -87,9 +87,20 @@ class InselMonthlyEnergyBalance:
total_dhw_demand += total_day * cte.DAYS_A_MONTH[day_type][month] * demand
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])
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])
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):
for building in self._city.buildings:

View File

@ -95,3 +95,6 @@ class SimplifiedRadiosityAlgorithm:
if cte.YEAR not in surface.global_irradiance:
surface.global_irradiance[cte.YEAR] = self._get_yearly_mean_values(new_value)
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
"""
self._city.level_of_detail.usage = 2
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):
"""
Enrich the city with NRCAN usage library
"""
self._city.level_of_detail.usage = 2
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):
"""

View File

@ -160,3 +160,6 @@ class EpwWeatherParameters:
usage.domestic_hot_water.density = density
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
import hub.exports.exports_factory
from hub.imports.usage_factory import UsageFactory
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
from hub.helpers.dictionaries import MontrealFunctionToHubFunction, Dictionaries
from hub.helpers.dictionaries import MontrealFunctionToHubFunction
from hub.helpers.geometry_helper import GeometryHelper
from hub.imports.construction_factory import ConstructionFactory
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
"""
import subprocess
from pathlib import Path
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.geometry_factory import GeometryFactory
from hub.imports.results_factory import ResultFactory
from hub.imports.usage_factory import UsageFactory
from hub.imports.energy_systems_factory import EnergySystemsFactory
@ -20,39 +26,50 @@ class TestSystemsFactory(TestCase):
"""
def setUp(self) -> None:
"""
Configure test environment
:return:
Test setup
:return: None
"""
self._city = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def _get_citygml(self, file):
file_path = (self._example_path / file).resolve()
self._city = GeometryFactory('citygml', path=file_path).city
self.assertIsNotNone(self._city, 'city is none')
self.assertIsNotNone(self._city.level_of_detail.geometry, 'wrong construction level of detail')
return self._city
self._gml_path = (self._example_path / 'FZK_Haus_LoD_2.gml').resolve()
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
self._city = GeometryFactory('citygml',
self._gml_path,
function_to_hub=Dictionaries().alkis_function_to_hub_function).city
def test_montreal_custom_system_factory(self):
"""
Enrich the city with the construction information and verify it
"""
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
for building in self._city.buildings:
building.energy_systems_archetype_name = 'system 1 gas'
EnergySystemsFactory('montreal_custom', city).enrich()
for building in city.buildings:
print(building.energy_systems)
EnergySystemsFactory('montreal_custom', self._city).enrich()
for building in self._city.buildings:
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):
"""
Enrich the city with the construction information and verify it
"""
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.year_of_construction = 1980
ConstructionFactory('nrcan', city).enrich()
UsageFactory('nrcan', city).enrich()
ConstructionFactory('nrcan', self._city).enrich()
UsageFactory('nrcan', self._city).enrich()
weather_file = (self._example_path / 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
ExportsFactory('sra', self._city, self._output_path, weather_file=weather_file, weather_format='epw').export()
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
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])