added lod to the city_objects
This commit is contained in:
parent
ef7addd5b5
commit
e48dec81cf
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
|
@ -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:
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Reference in New Issue
Block a user