all tests passed

This commit is contained in:
Pilar Monsalvete 2023-08-07 12:32:33 -04:00
parent e138a24555
commit 67cd435fd5
41 changed files with 252 additions and 1533 deletions

View File

@ -296,7 +296,7 @@ class Building(CityObject):
def cold_water_temperature(self) -> {float}: def cold_water_temperature(self) -> {float}:
""" """
Get cold water temperature in degrees Celsius Get cold water temperature in degrees Celsius
:return: dict{DataFrame(float)} :return: dict{[float]}
""" """
return self._cold_water_temperature return self._cold_water_temperature
@ -304,7 +304,7 @@ class Building(CityObject):
def cold_water_temperature(self, value): def cold_water_temperature(self, value):
""" """
Set cold water temperature in degrees Celsius Set cold water temperature in degrees Celsius
:param value: dict{DataFrame(float)} :param value: dict{[float]}
""" """
self._cold_water_temperature = value self._cold_water_temperature = value
@ -312,7 +312,7 @@ class Building(CityObject):
def heating_demand(self) -> dict: def heating_demand(self) -> dict:
""" """
Get heating demand in Wh Get heating demand in Wh
:return: dict{DataFrame(float)} :return: dict{[float]}
""" """
return self._heating_demand return self._heating_demand
@ -320,7 +320,7 @@ class Building(CityObject):
def heating_demand(self, value): def heating_demand(self, value):
""" """
Set heating demand in Wh Set heating demand in Wh
:param value: dict{DataFrame(float)} :param value: dict{[float]}
""" """
self._heating_demand = value self._heating_demand = value
@ -328,7 +328,7 @@ class Building(CityObject):
def cooling_demand(self) -> dict: def cooling_demand(self) -> dict:
""" """
Get cooling demand in Wh Get cooling demand in Wh
:return: dict{DataFrame(float)} :return: dict{[float]}
""" """
return self._cooling_demand return self._cooling_demand
@ -336,7 +336,7 @@ class Building(CityObject):
def cooling_demand(self, value): def cooling_demand(self, value):
""" """
Set cooling demand in Wh Set cooling demand in Wh
:param value: dict{DataFrame(float)} :param value: dict{[float]}
""" """
self._cooling_demand = value self._cooling_demand = value
@ -344,7 +344,7 @@ class Building(CityObject):
def lighting_electrical_demand(self) -> dict: def lighting_electrical_demand(self) -> dict:
""" """
Get lighting electrical demand in Wh Get lighting electrical demand in Wh
:return: dict{DataFrame(float)} :return: dict{[float]}
""" """
return self._lighting_electrical_demand return self._lighting_electrical_demand
@ -352,7 +352,7 @@ class Building(CityObject):
def lighting_electrical_demand(self, value): def lighting_electrical_demand(self, value):
""" """
Set lighting electrical demand in Wh Set lighting electrical demand in Wh
:param value: dict{DataFrame(float)} :param value: dict{[float]}
""" """
self._lighting_electrical_demand = value self._lighting_electrical_demand = value
@ -360,7 +360,7 @@ class Building(CityObject):
def appliances_electrical_demand(self) -> dict: def appliances_electrical_demand(self) -> dict:
""" """
Get appliances electrical demand in Wh Get appliances electrical demand in Wh
:return: dict{DataFrame(float)} :return: dict{[float]}
""" """
return self._appliances_electrical_demand return self._appliances_electrical_demand
@ -368,7 +368,7 @@ class Building(CityObject):
def appliances_electrical_demand(self, value): def appliances_electrical_demand(self, value):
""" """
Set appliances electrical demand in Wh Set appliances electrical demand in Wh
:param value: dict{DataFrame(float)} :param value: dict{[float]}
""" """
self._appliances_electrical_demand = value self._appliances_electrical_demand = value
@ -376,7 +376,7 @@ class Building(CityObject):
def domestic_hot_water_heat_demand(self) -> dict: def domestic_hot_water_heat_demand(self) -> dict:
""" """
Get domestic hot water heat demand in Wh Get domestic hot water heat demand in Wh
:return: dict{DataFrame(float)} :return: dict{[float]}
""" """
return self._domestic_hot_water_heat_demand return self._domestic_hot_water_heat_demand
@ -384,7 +384,7 @@ class Building(CityObject):
def domestic_hot_water_heat_demand(self, value): def domestic_hot_water_heat_demand(self, value):
""" """
Set domestic hot water heat demand in Wh Set domestic hot water heat demand in Wh
:param value: dict{DataFrame(float)} :param value: dict{[float]}
""" """
self._domestic_hot_water_heat_demand = value self._domestic_hot_water_heat_demand = value
@ -428,12 +428,12 @@ class Building(CityObject):
def heating_peak_load(self) -> Union[None, 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{[float]}
""" """
results = {} results = {}
if cte.HOUR in self.heating_demand: if cte.HOUR in self.heating_demand:
monthly_values = PeakLoads().\ monthly_values = PeakLoads().\
peak_loads_from_hourly(self.heating_demand[cte.HOUR][next(iter(self.heating_demand[cte.HOUR]))]) peak_loads_from_hourly(self.heating_demand[cte.HOUR])
else: else:
monthly_values = PeakLoads(self).heating_peak_loads_from_methodology monthly_values = PeakLoads(self).heating_peak_loads_from_methodology
if monthly_values is None: if monthly_values is None:
@ -446,11 +446,11 @@ class Building(CityObject):
def cooling_peak_load(self) -> Union[None, 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{[float]}
""" """
results = {} results = {}
if cte.HOUR in self.cooling_demand: if cte.HOUR in self.cooling_demand:
monthly_values = PeakLoads().peak_loads_from_hourly(self.cooling_demand[cte.HOUR][next(iter(self.cooling_demand[cte.HOUR]))]) monthly_values = PeakLoads().peak_loads_from_hourly(self.cooling_demand[cte.HOUR])
else: else:
monthly_values = PeakLoads(self).cooling_peak_loads_from_methodology monthly_values = PeakLoads(self).cooling_peak_loads_from_methodology
if monthly_values is None: if monthly_values is None:
@ -614,7 +614,8 @@ class Building(CityObject):
""" """
if len(self._heating_consumption) == 0: if len(self._heating_consumption) == 0:
for heating_demand_key in self.heating_demand: for heating_demand_key in self.heating_demand:
demand = self.heating_demand[heating_demand_key][cte.INSEL_MEB] demand = self.heating_demand[heating_demand_key]
print('AAAAAAAAAA', heating_demand_key, demand)
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)
if final_energy_consumed is None: if final_energy_consumed is None:
@ -630,7 +631,7 @@ class Building(CityObject):
""" """
if len(self._cooling_consumption) == 0: if len(self._cooling_consumption) == 0:
for cooling_demand_key in self.cooling_demand: for cooling_demand_key in self.cooling_demand:
demand = self.cooling_demand[cooling_demand_key][cte.INSEL_MEB] demand = self.cooling_demand[cooling_demand_key]
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)
if final_energy_consumed is None: if final_energy_consumed is None:
@ -646,7 +647,7 @@ class Building(CityObject):
""" """
if len(self._domestic_hot_water_consumption) == 0: if len(self._domestic_hot_water_consumption) == 0:
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][cte.INSEL_MEB] demand = self.domestic_hot_water_heat_demand[domestic_hot_water_demand_key]
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)
if final_energy_consumed is None: if final_energy_consumed is None:
@ -677,7 +678,7 @@ class Building(CityObject):
_total_hours = 0 _total_hours = 0
for key in _working_hours: for key in _working_hours:
hours = sum(_working_hours[key]) hours = sum(_working_hours[key])
_total_hours += hours * cte.DAYS_A_YEAR[key] _total_hours += hours * cte.WEEK_DAYS_A_YEAR[key]
return _total_hours return _total_hours
@property @property
@ -710,8 +711,8 @@ class Building(CityObject):
if _peak_load_type == cte.HEATING.lower(): if _peak_load_type == cte.HEATING.lower():
_consumption_fix_flow = distribution_system.distribution_consumption_fix_flow _consumption_fix_flow = distribution_system.distribution_consumption_fix_flow
for heating_demand_key in self.heating_demand: for heating_demand_key in self.heating_demand:
_consumption = [0]*len(self.heating_demand[heating_demand_key][cte.INSEL_MEB]) _consumption = [0]*len(self.heating_demand[heating_demand_key])
_demand = self.heating_demand[heating_demand_key][cte.INSEL_MEB] _demand = self.heating_demand[heating_demand_key]
for i, _ in enumerate(_consumption): for i, _ in enumerate(_consumption):
_consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i] _consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i]
self._distribution_systems_electrical_consumption[heating_demand_key] = _consumption self._distribution_systems_electrical_consumption[heating_demand_key] = _consumption
@ -720,7 +721,7 @@ class Building(CityObject):
_consumption_fix_flow = distribution_system.distribution_consumption_fix_flow _consumption_fix_flow = distribution_system.distribution_consumption_fix_flow
for demand_key in self.cooling_demand: for demand_key in self.cooling_demand:
_consumption = self._distribution_systems_electrical_consumption[demand_key] _consumption = self._distribution_systems_electrical_consumption[demand_key]
_demand = self.cooling_demand[demand_key][cte.INSEL_MEB] _demand = self.cooling_demand[demand_key]
for i, _ in enumerate(_consumption): for i, _ in enumerate(_consumption):
_consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i] _consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i]
self._distribution_systems_electrical_consumption[demand_key] = _consumption self._distribution_systems_electrical_consumption[demand_key] = _consumption
@ -780,12 +781,12 @@ class Building(CityObject):
_efficiency = energy_system.generation_system.generic_generation_system.electricity_efficiency _efficiency = energy_system.generation_system.generic_generation_system.electricity_efficiency
self._onsite_electrical_production = {} self._onsite_electrical_production = {}
for _key in self.roofs[0].global_irradiance.keys(): for _key in self.roofs[0].global_irradiance.keys():
_results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key][cte.SRA]))] _results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key]))]
for surface in self.roofs: for surface in self.roofs:
if _key in orientation_losses_factor: if _key in orientation_losses_factor:
_results = [x + y * _efficiency * surface.perimeter_area _results = [x + y * _efficiency * surface.perimeter_area
* surface.solar_collectors_area_reduction_factor * z * surface.solar_collectors_area_reduction_factor * z
for x, y, z in zip(_results, surface.global_irradiance[_key][cte.SRA], for x, y, z in zip(_results, surface.global_irradiance[_key],
orientation_losses_factor[_key]['south'])] orientation_losses_factor[_key]['south'])]
self._onsite_electrical_production[_key] = _results self._onsite_electrical_production[_key] = _results
return self._onsite_electrical_production return self._onsite_electrical_production

View File

@ -179,7 +179,7 @@ class Surface:
def global_irradiance(self) -> dict: def global_irradiance(self) -> dict:
""" """
Get global irradiance on surface in Wh/m2 Get global irradiance on surface in Wh/m2
:return: dict{DataFrame(float)} :return: dict
""" """
return self._global_irradiance return self._global_irradiance
@ -187,7 +187,7 @@ class Surface:
def global_irradiance(self, value): def global_irradiance(self, value):
""" """
Set global irradiance on surface in Wh/m2 Set global irradiance on surface in Wh/m2
:param value: dict{DataFrame(float)} :param value: dict
""" """
self._global_irradiance = value self._global_irradiance = value

View File

@ -25,7 +25,6 @@ from hub.city_model_structure.building import Building
from hub.city_model_structure.buildings_cluster import BuildingsCluster from hub.city_model_structure.buildings_cluster import BuildingsCluster
from hub.city_model_structure.city_object import CityObject from hub.city_model_structure.city_object import CityObject
from hub.city_model_structure.city_objects_cluster import CityObjectsCluster from hub.city_model_structure.city_objects_cluster import CityObjectsCluster
from hub.city_model_structure.energy_system import EnergySystem
from hub.city_model_structure.iot.station import Station from hub.city_model_structure.iot.station import Station
from hub.city_model_structure.level_of_detail import LevelOfDetail from hub.city_model_structure.level_of_detail import LevelOfDetail
from hub.city_model_structure.parts_consisting_building import PartsConsistingBuilding from hub.city_model_structure.parts_consisting_building import PartsConsistingBuilding
@ -163,9 +162,6 @@ class City:
if self.buildings is not None: if self.buildings is not None:
for building in self.buildings: for building in self.buildings:
self._city_objects.append(building) self._city_objects.append(building)
if self.energy_systems is not None:
for energy_system in self.energy_systems:
self._city_objects.append(energy_system)
return self._city_objects return self._city_objects
@property @property
@ -409,14 +405,6 @@ class City:
""" """
return self._parts_consisting_buildings return self._parts_consisting_buildings
@property
def energy_systems(self) -> Union[List[EnergySystem], None]:
"""
Get energy systems belonging to the city
:return: None or [EnergySystem]
"""
return self._energy_systems
@property @property
def stations(self) -> [Station]: def stations(self) -> [Station]:
""" """
@ -478,12 +466,12 @@ class City:
parameter_city_building_total_radiation = 0 parameter_city_building_total_radiation = 0
for surface in building.surfaces: for surface in building.surfaces:
if surface.global_irradiance: if surface.global_irradiance:
parameter_city_building_total_radiation += surface.global_irradiance[cte.YEAR].iloc[0, 0] parameter_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
merged_city_building_total_radiation = 0 merged_city_building_total_radiation = 0
for surface in merged_city.city_object(building.name).surfaces: for surface in merged_city.city_object(building.name).surfaces:
if surface.global_irradiance: if surface.global_irradiance:
merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR].iloc[0, 0] merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
if merged_city_building_total_radiation == 0: if merged_city_building_total_radiation == 0:
merged_city.remove_city_object(merged_city.city_object(building.name)) merged_city.remove_city_object(merged_city.city_object(building.name))

View File

@ -172,7 +172,7 @@ class CityObject:
def external_temperature(self) -> {float}: def external_temperature(self) -> {float}:
""" """
Get external temperature surrounding the city object in Celsius Get external temperature surrounding the city object in Celsius
:return: dict{DataFrame(float)} :return: dict{dict{[float]}}
""" """
return self._external_temperature return self._external_temperature
@ -180,11 +180,10 @@ class CityObject:
def external_temperature(self, value): def external_temperature(self, value):
""" """
Set external temperature surrounding the city object in Celsius Set external temperature surrounding the city object in Celsius
:param value: dict{DataFrame(float)} :param value: dict{dict{[float]}}
""" """
self._external_temperature = value self._external_temperature = value
# todo: this is the new format we will use to get rid of the data frames
@property @property
def ground_temperature(self) -> dict: def ground_temperature(self) -> dict:
""" """
@ -206,7 +205,7 @@ class CityObject:
def global_horizontal(self) -> dict: def global_horizontal(self) -> dict:
""" """
Get global horizontal radiation surrounding the city object in W/m2 Get global horizontal radiation surrounding the city object in W/m2
:return: dict{DataFrame(float)} :return: dict{dict{[float]}}
""" """
return self._global_horizontal return self._global_horizontal
@ -214,7 +213,7 @@ class CityObject:
def global_horizontal(self, value): def global_horizontal(self, value):
""" """
Set global horizontal radiation surrounding the city object in W/m2 Set global horizontal radiation surrounding the city object in W/m2
:param value: dict{DataFrame(float)} :param value: dict{dict{[float]}}
""" """
self._global_horizontal = value self._global_horizontal = value
@ -222,7 +221,7 @@ class CityObject:
def diffuse(self) -> dict: def diffuse(self) -> dict:
""" """
Get diffuse radiation surrounding the city object in W/m2 Get diffuse radiation surrounding the city object in W/m2
:return: dict{DataFrame(float)} :return: dict{dict{[float]}}
""" """
return self._diffuse return self._diffuse
@ -230,7 +229,7 @@ class CityObject:
def diffuse(self, value): def diffuse(self, value):
""" """
Set diffuse radiation surrounding the city object in W/m2 Set diffuse radiation surrounding the city object in W/m2
:param value: dict{DataFrame(float)} :param value: dict{dict{[float]}}
""" """
self._diffuse = value self._diffuse = value
@ -238,7 +237,7 @@ class CityObject:
def beam(self) -> dict: def beam(self) -> dict:
""" """
Get beam radiation surrounding the city object in W/m2 Get beam radiation surrounding the city object in W/m2
:return: dict{DataFrame(float)} :return: dict{dict{[float]}}
""" """
return self._beam return self._beam
@ -246,7 +245,7 @@ class CityObject:
def beam(self, value): def beam(self, value):
""" """
Set beam radiation surrounding the city object in W/m2 Set beam radiation surrounding the city object in W/m2
:param value: dict{DataFrame(float)} :param value: dict{dict{[float]}}
""" """
self._beam = value self._beam = value

View File

@ -1,65 +0,0 @@
"""
EnergySystem module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Peter Yefi peteryefi@gmail.com
"""
from hub.city_model_structure.city_object import CityObject
from hub.city_model_structure.energy_systems.air_source_hp import AirSourceHP
from hub.city_model_structure.energy_systems.water_to_water_hp import WaterToWaterHP
class EnergySystem(CityObject):
"""
EnergySystem(CityObject) class
"""
def __init__(self, name, surfaces):
super().__init__(name, surfaces)
self._air_source_hp = None
self._water_to_water_hp = None
self._type = 'energy_system'
@property
def air_source_hp(self) -> AirSourceHP:
"""
Heat pump energy system
:return:
"""
return self._air_source_hp
@air_source_hp.setter
def air_source_hp(self, value):
"""
Set heat pump for energy system
:param value: AirSourceHP
"""
if self._air_source_hp is None:
self._air_source_hp = value
@property
def water_to_water_hp(self) -> WaterToWaterHP:
"""
Water to water heat pump energy system
:return:
"""
return self._water_to_water_hp
@water_to_water_hp.setter
def water_to_water_hp(self, value):
"""
Set water to water heat pump for energy system
:param value: WaterToWaterHP
"""
if self._water_to_water_hp is None:
self._water_to_water_hp = value
@property
def type(self) -> str:
"""
Type of city object
:return: str
"""
return self._type

View File

@ -1,132 +0,0 @@
"""
air_source_hp module defines an air source heat pump
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Peter Yefi peteryefi@gmail.com
"""
from typing import List
from hub.city_model_structure.energy_systems.heat_pump import HeatPump
class AirSourceHP(HeatPump):
"""
AirSourceHP class
"""
def __init__(self):
super().__init__()
self._cooling_capacity = None
self._cooling_comp_power = None
self._cooling_capacity_coff = None # a coefficients for insel
self._heating_capacity = None
self._heating_comp_power = None
self._heating_capacity_coff = None
@property
def cooling_capacity(self) -> List[float]:
"""
Get cooling capacity in kW
:return: [[float]]
"""
return self._cooling_capacity
@cooling_capacity.setter
def cooling_capacity(self, value):
"""
Set cooling capacity in kW
:param value: [[float]]
"""
if self._cooling_capacity is None:
self._cooling_capacity = value
@property
def cooling_comp_power(self) -> List[float]:
"""
Get cooling compressor power input in kW
:return: [[float]]
"""
return self._cooling_comp_power
@cooling_comp_power.setter
def cooling_comp_power(self, value):
"""
Set the cooling compressor in kW
:param value: [[float]]
:return:
"""
if self._cooling_comp_power is None:
self._cooling_comp_power = value
@property
def cooling_capacity_coff(self) -> List[float]:
"""
Get cooling capacity coefficients
:return: [float]
"""
return self._cooling_capacity_coff
@cooling_capacity_coff.setter
def cooling_capacity_coff(self, value):
"""
Set the value for cooling capacity coefficients
:param value: [float]
:return:
"""
if self._cooling_capacity_coff is None:
self._cooling_capacity_coff = value
@property
def heating_capacity(self) -> List[float]:
"""
Get heating capacity kW
:return: [[float]]
"""
return self._heating_capacity
@heating_capacity.setter
def heating_capacity(self, value):
"""
Set the heating capacity in kW
:param value: [[float]]
:return:
"""
if self._heating_capacity is None:
self._heating_capacity = value
@property
def heating_comp_power(self) -> List[float]:
"""
Get heating compressor power kW
:return: [[float]]
"""
return self._heating_comp_power
@heating_comp_power.setter
def heating_comp_power(self, value):
"""
Set the heating compressor power in kW
:param value: [[float]]
:return:
"""
if self._heating_comp_power is None:
self._heating_comp_power = value
@property
def heating_capacity_coff(self) -> List[float]:
"""
Get heating capacity coefficients
:return: [float]
"""
return self._heating_capacity_coff
@heating_capacity_coff.setter
def heating_capacity_coff(self, value):
"""
Set the value for heating capacity coefficients
:param value: [float]
:return:
"""
if self._heating_capacity_coff is None:
self._heating_capacity_coff = value

View File

@ -1,131 +0,0 @@
"""
water_to_water_hp module defines a water to water heat pump heat pump
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com
"""
from typing import List
from hub.city_model_structure.energy_systems.heat_pump import HeatPump
class WaterToWaterHP(HeatPump):
"""
WaterToWaterHP class
"""
def __init__(self):
super().__init__()
self._entering_water_temp = None
self._leaving_water_temp = None
self._total_cooling_capacity = None
self._power_demand = None
self._flow_rate = None
self._power_demand_coff = None # a coefficients
@property
def entering_water_temp(self) -> List[float]:
"""
Get entering water temperature in degree celsius
:return: [[float]]
"""
return self._entering_water_temp
@entering_water_temp.setter
def entering_water_temp(self, value):
"""
Set entering water temperature in degree celsius
:param value: [[float]]
"""
if self._entering_water_temp is None:
self._entering_water_temp = value
@property
def leaving_water_temp(self) -> List[float]:
"""
Get leaving water temperature in degree celsius
:return: [[float]]
"""
return self._leaving_water_temp
@leaving_water_temp.setter
def leaving_water_temp(self, value):
"""
Set the leaving water temperature in degree celsius
:param value: [[float]]
:return:
"""
if self._leaving_water_temp is None:
self._leaving_water_temp = value
@property
def total_cooling_capacity(self) -> List[float]:
"""
Get total cooling capacity
:return: [float]
"""
return self._total_cooling_capacity
@total_cooling_capacity.setter
def total_cooling_capacity(self, value):
"""
Set the value for total cooling capacity
:param value: [float]
:return:
"""
if self._total_cooling_capacity is None:
self._total_cooling_capacity = value
@property
def power_demand(self) -> List[float]:
"""
Get power demand in kW
:return: [float]
"""
return self._power_demand
@power_demand.setter
def power_demand(self, value):
"""
Set the value for power demand in kW
:param value: [float]
:return:
"""
if self._power_demand is None:
self._power_demand = value
@property
def flow_rate(self) -> List[float]:
"""
Get flow rate in kg/s
:return: [[float]]
"""
return self._flow_rate
@flow_rate.setter
def flow_rate(self, value):
"""
Set flow rate in kW
:param value: [[float]]
:return:
"""
if self._flow_rate is None:
self._flow_rate = value
@property
def power_demand_coff(self) -> List[float]:
"""
Get power demand coefficients
:return: [float]
"""
return self._power_demand_coff
@power_demand_coff.setter
def power_demand_coff(self, value):
"""
Set the value for power demand coefficients
:param value: [float]
:return:
"""
if self._power_demand_coff is None:
self._power_demand_coff = value

View File

@ -533,7 +533,7 @@ class Idf:
self._add_schedules(usage, 'Appliance', thermal_zone.appliances.schedules) self._add_schedules(usage, 'Appliance', thermal_zone.appliances.schedules)
self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules) self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules)
_new_schedules = self._create_yearly_values_schedules('cold_temp', _new_schedules = self._create_yearly_values_schedules('cold_temp',
building.cold_water_temperature[cte.HOUR]['epw']) building.cold_water_temperature[cte.HOUR])
self._add_schedules(building.name, 'cold_temp', _new_schedules) self._add_schedules(building.name, 'cold_temp', _new_schedules)
value = thermal_zone.domestic_hot_water.service_temperature value = thermal_zone.domestic_hot_water.service_temperature
_new_schedules = self._create_constant_value_schedules('DHW_temp', value) _new_schedules = self._create_constant_value_schedules('DHW_temp', value)

View File

@ -30,13 +30,11 @@ class InselMonthlyEnergyBalance:
""" """
Insel monthly energy balance class Insel monthly energy balance class
""" """
def __init__(self, city, path, custom_insel_block, radiation_calculation_method='sra', weather_format='epw'): def __init__(self, city, path, custom_insel_block):
self._city = city self._city = city
self._path = path self._path = path
self._custom_insel_block = custom_insel_block self._custom_insel_block = custom_insel_block
self._results = None self._results = None
self._radiation_calculation_method = radiation_calculation_method
self._weather_format = weather_format
self._contents = [] self._contents = []
self._insel_files_paths = [] self._insel_files_paths = []
self._sanity_check() self._sanity_check()
@ -48,7 +46,7 @@ class InselMonthlyEnergyBalance:
logging.warning('Building %s has missing values. Monthly Energy Balance cannot be processed', building.name) logging.warning('Building %s has missing values. Monthly Energy Balance cannot be processed', building.name)
self._contents.append( self._contents.append(
self._generate_meb_template(building, output_path, self._radiation_calculation_method, self._weather_format, self._custom_insel_block) self._generate_meb_template(building, output_path, self._custom_insel_block)
) )
self._export() self._export()
@ -96,7 +94,7 @@ class InselMonthlyEnergyBalance:
f'Required minimum level 1') f'Required minimum level 1')
@staticmethod @staticmethod
def _generate_meb_template(building, insel_outputs_path, radiation_calculation_method, weather_format, custom_insel_block): def _generate_meb_template(building, insel_outputs_path, custom_insel_block):
file = "" file = ""
i_block = 1 i_block = 1
parameters = ["1", "12", "1"] parameters = ["1", "12", "1"]
@ -148,7 +146,7 @@ class InselMonthlyEnergyBalance:
total_values = sum(schedule.values) total_values = sum(schedule.values)
total_hours = 0 total_hours = 0
for day_type in schedule.day_types: for day_type in schedule.day_types:
total_hours += cte.DAYS_A_YEAR[day_type] / 365 / 24 total_hours += cte.WEEK_DAYS_A_YEAR[day_type] / 365 / 24
total_values *= total_hours total_values *= total_hours
total_internal_gain += internal_gain * total_values total_internal_gain += internal_gain * total_values
@ -181,8 +179,8 @@ class InselMonthlyEnergyBalance:
ventilation_day += 0 ventilation_day += 0
infiltration_day += infiltration_value / 24 infiltration_day += infiltration_value / 24
for day_type in schedule.day_types: for day_type in schedule.day_types:
infiltration += infiltration_day * cte.DAYS_A_YEAR[day_type] / 365 infiltration += infiltration_day * cte.WEEK_DAYS_A_YEAR[day_type] / 365
ventilation += ventilation_day * cte.DAYS_A_YEAR[day_type] / 365 ventilation += ventilation_day * cte.WEEK_DAYS_A_YEAR[day_type] / 365
ventilation_infiltration = ventilation + infiltration ventilation_infiltration = ventilation + infiltration
parameters.append(f'{ventilation_infiltration} % BP(18) #8 Minimum air change rate zone {i + 1} (ACH)') parameters.append(f'{ventilation_infiltration} % BP(18) #8 Minimum air change rate zone {i + 1} (ACH)')
@ -230,7 +228,6 @@ class InselMonthlyEnergyBalance:
parameters.append(thermal_boundary.parent_surface.short_wave_reflectance) parameters.append(thermal_boundary.parent_surface.short_wave_reflectance)
else: else:
parameters.append(0.0) parameters.append(0.0)
file = InselMonthlyEnergyBalance._add_block(file, i_block, custom_insel_block, inputs=inputs, parameters=parameters) file = InselMonthlyEnergyBalance._add_block(file, i_block, custom_insel_block, inputs=inputs, parameters=parameters)
i_block = 20 i_block = 20
@ -238,9 +235,8 @@ class InselMonthlyEnergyBalance:
parameters = ['12 % Monthly ambient temperature (degree Celsius)'] parameters = ['12 % Monthly ambient temperature (degree Celsius)']
external_temperature = building.external_temperature[cte.MONTH] external_temperature = building.external_temperature[cte.MONTH]
for i in range(0, len(external_temperature)): for i in range(0, len(external_temperature)):
parameters.append(f'{i + 1} {external_temperature.at[i, weather_format]}') parameters.append(f'{i + 1} {external_temperature[i]}')
file = InselMonthlyEnergyBalance._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters) file = InselMonthlyEnergyBalance._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters)
@ -248,12 +244,11 @@ class InselMonthlyEnergyBalance:
inputs = ['1'] inputs = ['1']
parameters = ['12 % Monthly sky temperature'] parameters = ['12 % Monthly sky temperature']
sky_temperature = Weather.sky_temperature(external_temperature[[weather_format]].to_numpy().T[0]) sky_temperature = Weather.sky_temperature(external_temperature)
for i, temperature in enumerate(sky_temperature): for i, temperature in enumerate(sky_temperature):
parameters.append(f'{i + 1} {temperature}') parameters.append(f'{i + 1} {temperature}')
file = InselMonthlyEnergyBalance._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters) file = InselMonthlyEnergyBalance._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters)
for i, surface in enumerate(surfaces): for i, surface in enumerate(surfaces):
i_block = 101 + i i_block = 101 + i
inputs = ['1 % Monthly surface radiation (W/m2)'] inputs = ['1 % Monthly surface radiation (W/m2)']
@ -266,7 +261,7 @@ class InselMonthlyEnergyBalance:
global_irradiance = surface.global_irradiance[cte.MONTH] global_irradiance = surface.global_irradiance[cte.MONTH]
for j in range(0, len(global_irradiance)): for j in range(0, len(global_irradiance)):
parameters.append(f'{j + 1} ' parameters.append(f'{j + 1} '
f'{global_irradiance.at[j, radiation_calculation_method] / 24 / _NUMBER_DAYS_PER_MONTH[j]}') f'{global_irradiance[j] / 24 / _NUMBER_DAYS_PER_MONTH[j]}')
else: else:
for j in range(0, 12): for j in range(0, 12):
parameters.append(f'{j + 1} 0.0') parameters.append(f'{j + 1} 0.0')
@ -290,5 +285,4 @@ class InselMonthlyEnergyBalance:
f"'{str(insel_outputs_path)}' % File name", f"'{str(insel_outputs_path)}' % File name",
"'*' % Fortran format"] "'*' % Fortran format"]
file = InselMonthlyEnergyBalance._add_block(file, i_block, 'WRITE', inputs=inputs, parameters=parameters) file = InselMonthlyEnergyBalance._add_block(file, i_block, 'WRITE', inputs=inputs, parameters=parameters)
return file return file

View File

@ -66,8 +66,8 @@ class SimplifiedRadiosityAlgorithm:
else: else:
i = (total_days + day - 1) * 24 + hour - 1 i = (total_days + day - 1) * 24 + hour - 1
representative_building = self._city.buildings[0] representative_building = self._city.buildings[0]
content += f'{day} {month} {hour} {representative_building.global_horizontal[cte.HOUR].epw[i]} ' \ content += f'{day} {month} {hour} {representative_building.global_horizontal[cte.HOUR][i]} ' \
f'{representative_building.beam[cte.HOUR].epw[i]}\n' f'{representative_building.beam[cte.HOUR][i]}\n'
with open(file, 'w', encoding='utf-8') as file: with open(file, 'w', encoding='utf-8') as file:
file.write(content) file.write(content)

View File

@ -48,23 +48,36 @@ WEEK_DAYS = 'Weekdays'
WEEK_ENDS = 'Weekends' WEEK_ENDS = 'Weekends'
ALL_DAYS = 'Alldays' ALL_DAYS = 'Alldays'
DAYS_A_MONTH = {'monday': [5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 5], WEEK_DAYS_A_MONTH = {'monday': [5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 5],
'tuesday': [5, 4, 4, 4, 5, 4, 5, 4, 4, 5, 4, 4], 'tuesday': [5, 4, 4, 4, 5, 4, 5, 4, 4, 5, 4, 4],
'wednesday': [5, 4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4], 'wednesday': [5, 4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4],
'thursday': [4, 4, 5, 4, 5, 4, 4, 5, 4, 4, 5, 4], 'thursday': [4, 4, 5, 4, 5, 4, 4, 5, 4, 4, 5, 4],
'friday': [4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5, 4], 'friday': [4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5, 4],
'saturday': [4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5], 'saturday': [4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5],
'sunday': [4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5], 'sunday': [4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5],
'holiday': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} 'holiday': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
DAYS_A_YEAR = {'monday': 51, WEEK_DAYS_A_YEAR = {'monday': 51,
'tuesday': 50, 'tuesday': 50,
'wednesday': 50, 'wednesday': 50,
'thursday': 50, 'thursday': 50,
'friday': 50, 'friday': 50,
'saturday': 52, 'saturday': 52,
'sunday': 52, 'sunday': 52,
'holiday': 10} 'holiday': 10}
DAYS_A_MONTH = {'January': 31,
'February': 28,
'March': 31,
'April': 30,
'May': 31,
'June': 30,
'July': 31,
'August': 31,
'September': 30,
'October': 31,
'November': 30,
'December': 31}
# data types # data types
ANY_NUMBER = 'any_number' ANY_NUMBER = 'any_number'

View File

@ -3,55 +3,46 @@ Monthly values module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
import calendar as cal
import pandas as pd import hub.helpers.constants as cte
import numpy as np
class MonthlyValues: class MonthlyValues:
""" """
Monthly values class Monthly values class
""" """
def __init__(self): @staticmethod
self._month_hour = None def get_mean_values(values):
def get_mean_values(self, values):
""" """
Calculates the mean values for each month Calculates the mean values for each month from a list with hourly values
:return: DataFrame(float) :return: [float] x 12
:param values: [float] x 8760
""" """
out = None out = []
if values is not None: if values is not None:
if 'month' not in values.columns: for month in cte.DAYS_A_MONTH:
values = pd.concat([self.month_hour, pd.DataFrame(values)], axis=1) total = 0
out = values.groupby('month', as_index=False).mean() for j in range(0, cte.DAYS_A_MONTH[month]):
del out['month'] for k in range(0, 24):
hour = k + 24 * j + cte.DAYS_A_MONTH[month] - 31
total += values[hour] / 24 / cte.DAYS_A_MONTH[month]
out.append(total)
return out return out
def get_total_month(self, values): @staticmethod
def get_total_month(values):
""" """
Calculates the total value for each month Calculates the total value for each month
:return: DataFrame(int) :return: [float] x 12
:param values: [float] x 8760
""" """
out = None out = []
if values is not None: if values is not None:
if 'month' not in values.columns: for month in cte.DAYS_A_MONTH:
values = pd.concat([self.month_hour, pd.DataFrame(values)], axis=1) total = 0
out = pd.DataFrame(values).groupby('month', as_index=False).sum() for j in range(0, cte.DAYS_A_MONTH[month]):
del out['month'] for k in range(0, 24):
hour = k + 24 * j + cte.DAYS_A_MONTH[month] - 31
total += values[hour]
out.append(total)
return out return out
@property
def month_hour(self):
"""
returns a DataFrame that has x values of the month number (January = 1, February = 2...),
being x the number of hours of the corresponding month
:return: DataFrame(int)
"""
array = []
for i in range(0, 12):
days_of_month = cal.monthrange(2015, i+1)[1]
total_hours = days_of_month * 24
array = np.concatenate((array, np.full(total_hours, i + 1)))
self._month_hour = pd.DataFrame(array, columns=['month'])
return self._month_hour

View File

@ -132,7 +132,7 @@ class LoadsCalculation:
internal_load = cooling_load_occupancy_sensible + cooling_load_lighting + cooling_load_equipment_sensible internal_load = cooling_load_occupancy_sensible + cooling_load_lighting + cooling_load_equipment_sensible
return internal_load return internal_load
def get_radiation_load(self, irradiance_format, hour): def get_radiation_load(self, hour):
""" """
Calculates the radiation load Calculates the radiation load
:return: int :return: int
@ -142,7 +142,7 @@ class LoadsCalculation:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones:
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening in thermal_boundary.thermal_openings: for thermal_opening in thermal_boundary.thermal_openings:
radiation = thermal_boundary.parent_surface.global_irradiance[cte.HOUR][irradiance_format][hour] radiation = thermal_boundary.parent_surface.global_irradiance[cte.HOUR][hour]
cooling_load_radiation += ( cooling_load_radiation += (
thermal_opening.area * (1 - thermal_opening.frame_ratio) * thermal_opening.g_value * radiation thermal_opening.area * (1 - thermal_opening.frame_ratio) * thermal_opening.g_value * radiation
) )

View File

@ -54,11 +54,13 @@ class PeakLoads:
""" """
month = 1 month = 1
peaks = [0 for _ in range(12)] peaks = [0 for _ in range(12)]
for i, value in enumerate(hourly_values): print('hv', hourly_values)
for i in range(0, len(hourly_values)):
if _MONTH_STARTING_HOUR[month] <= i: if _MONTH_STARTING_HOUR[month] <= i:
month += 1 month += 1
if value > peaks[month-1]: if hourly_values[i] > peaks[month-1]:
peaks[month-1] = value peaks[month-1] = hourly_values[i]
print('peak', peaks)
return peaks return peaks
@property @property
@ -70,7 +72,7 @@ class PeakLoads:
if not self._can_be_calculated(): if not self._can_be_calculated():
return None return None
monthly_heating_loads = [] monthly_heating_loads = []
ambient_temperature = self._building.external_temperature[cte.HOUR]['epw'] ambient_temperature = self._building.external_temperature[cte.HOUR]
for month in range(0, 12): for month in range(0, 12):
ground_temperature = self._building.ground_temperature[cte.MONTH]['2'][month] ground_temperature = self._building.ground_temperature[cte.MONTH]['2'][month]
heating_ambient_temperature = 100 heating_ambient_temperature = 100
@ -100,7 +102,7 @@ class PeakLoads:
if not self._can_be_calculated(): if not self._can_be_calculated():
return None return None
monthly_cooling_loads = [] monthly_cooling_loads = []
ambient_temperature = self._building.external_temperature[cte.HOUR]['epw'] ambient_temperature = self._building.external_temperature[cte.HOUR]
for month in range(0, 12): for month in range(0, 12):
ground_temperature = self._building.ground_temperature[cte.MONTH]['2'][month] ground_temperature = self._building.ground_temperature[cte.MONTH]['2'][month]
cooling_ambient_temperature = -100 cooling_ambient_temperature = -100
@ -118,7 +120,7 @@ class PeakLoads:
cooling_load_transmitted = loads.get_cooling_transmitted_load(cooling_ambient_temperature, ground_temperature) 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_renovation_sensible = loads.get_cooling_ventilation_load_sensible(cooling_ambient_temperature)
cooling_load_internal_gains_sensible = loads.get_internal_load_sensible() cooling_load_internal_gains_sensible = loads.get_internal_load_sensible()
cooling_load_radiation = loads.get_radiation_load('sra', cooling_calculation_hour) cooling_load_radiation = loads.get_radiation_load(cooling_calculation_hour)
cooling_load_sensible = cooling_load_transmitted + cooling_load_renovation_sensible - cooling_load_radiation \ cooling_load_sensible = cooling_load_transmitted + cooling_load_renovation_sensible - cooling_load_radiation \
- cooling_load_internal_gains_sensible - cooling_load_internal_gains_sensible

View File

@ -1,147 +0,0 @@
"""
AirSourceHeatPumpParameters import the heat pump information
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.comCode
contributor Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import io
import itertools
from typing import List
from typing import Dict
import pandas as pd
import numpy as np
from scipy.optimize import curve_fit
from hub.city_model_structure.energy_systems.air_source_hp import AirSourceHP
from hub.city_model_structure.energy_system import EnergySystem
class AirSourceHeatPumpParameters:
"""
AirSourceHeatPumpParameters class
"""
def __init__(self, city, base_path):
self._city = city
self._base_path = (base_path / 'heat_pumps/air_source.xlsx').resolve()
def _read_file(self) -> Dict:
"""
reads xlsx file containing the heat pump information
into a dictionary
:return : Dict
"""
with open(self._base_path, 'rb') as xls:
xl_file = pd.read_excel(io.BytesIO(xls.read()), sheet_name=None)
cooling_data = {}
heating_data = {}
for sheet, _ in xl_file.items():
if 'Summary' in sheet:
continue
# Remove nan rows and columns and extract cooling and heating data
# for each sheet
df = xl_file[sheet].dropna(axis=1, how='all')
cooling_df = df.iloc[4:34, 0:8]
heating_df = df.iloc[4:29, 8:20]
# extract the data into dictionaries each sheet is a key entry in the
# dictionary
cooling_data[sheet] = {}
heating_data[sheet] = {}
i = 0
# for each sheet extract data for twout/Ta.RU temperatures. Thus, the twout
# temp is the key for the values of pf,pa,qw data
while i < 25:
cooling_data[sheet][cooling_df.iloc[i][0]] = cooling_df.iloc[i + 1:i + 4, 2:8].values.tolist()
heating_data[sheet][heating_df.iloc[i][0]] = heating_df.iloc[i + 1:i + 4, 2:8].values.tolist()
i = i + 5
# extract the last cooling data
cooling_data[sheet][cooling_df.iloc[i][0]] = cooling_df.iloc[i + 1:i + 4, 2:8].values.tolist()
return {"cooling": cooling_data, "heating": heating_data}
def enrich_city(self):
"""
Enriches the city with information from file
"""
heat_pump_data = self._read_file()
for (k_cool, v_cool), (_, v_heat) in zip(heat_pump_data["cooling"].items(), heat_pump_data["heating"].items()):
heat_pump = AirSourceHP()
heat_pump.model = k_cool
h_data = self._extract_heat_pump_data(v_heat)
c_data = self._extract_heat_pump_data(v_cool)
heat_pump.cooling_capacity = c_data[0]
heat_pump.cooling_comp_power = c_data[1]
heat_pump.cooling_capacity_coff = self._compute_coefficients(c_data, "cool")
heat_pump.heating_capacity = h_data[0]
heat_pump.heating_comp_power = h_data[1]
heat_pump.heating_capacity_coff = self._compute_coefficients(h_data)
energy_system = EnergySystem(f'{heat_pump.model} capacity heat pump', [])
energy_system.air_source_hp = heat_pump
self._city.add_city_object(energy_system)
return self._city
@staticmethod
def _extract_heat_pump_data(heat_pump_capacity_data: Dict) -> [List, List]:
"""
Fetches a list of metric based data for heat pump for various temperature,
e.g. cooling capacity data for 12 capacity heat pump
for 6,7,8,9,10 and 11 degree Celsius
:param heat_pump_capacity_data: the heat pump capacity data from the
which the metric specific data is fetched: {List}
:return: List
"""
cooling_heating_capacity_data = []
compressor_power_data = []
for _, metric_data in heat_pump_capacity_data.items():
cooling_heating_capacity_data.append(metric_data[0])
compressor_power_data.append(metric_data[1])
return [cooling_heating_capacity_data, compressor_power_data]
def _compute_coefficients(self, heat_pump_data: List, data_type="heat") -> List[float]:
"""
Compute heat output and electrical demand coefficients
from heating and cooling performance data
:param heat_pump_data: a list of heat pump data. e.g. cooling capacity
:param data_type: string to indicate if data is cooling performance data
or heating performance data
:return: Tuple[Dict, Dict]
"""
# Determine the recurrence of temperature values. 6 repetitions for
# cooling performance and 5 repetition for heating performance
temp_multiplier = 5 if data_type == "heat" else 6
out_temp = [25, 30, 32, 35, 40, 45] * temp_multiplier
heat_x_values = np.repeat([-5, 0, 7, 10, 15], 6)
cool_x_values = np.repeat([6, 7, 8, 9, 10, 11], 6)
x_values = heat_x_values if data_type == "heat" else cool_x_values
x_values = x_values.tolist()
# convert list of lists to one list
hp_data = [i / j for i, j in
zip(list(itertools.chain.from_iterable(heat_pump_data[0])),
list(itertools.chain.from_iterable(heat_pump_data[1])))]
# Compute heat output coefficients
popt, _ = curve_fit(self._objective_function, [x_values, out_temp], hp_data)
return popt.tolist()
@staticmethod
def _objective_function(xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float) -> float:
"""
Objective function for computing coefficients
:param xdata:
:param a1: float
:param a2: float
:param a3: float
:param a4: float
:param a5: float
:param a6: float
:return:
"""
x, y = xdata
return (a1 * x ** 2) + (a2 * x) + (a3 * x * y) + (a4 * y) + (a5 * y ** 2) + a6

View File

@ -1,29 +0,0 @@
"""
Energy systems helper
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from hub.helpers import constants as cte
class EnergySystemsHelper:
"""
EnergySystems helper
"""
_montreal_custom_fuel_to_hub_fuel = {
'gas': cte.GAS,
'electricity': cte.ELECTRICITY,
'renewable': cte.RENEWABLE
}
@staticmethod
def montreal_custom_fuel_to_hub_fuel(fuel):
"""
Get hub fuel from montreal_custom catalog fuel
:param fuel: str
:return: str
"""
return EnergySystemsHelper._montreal_custom_fuel_to_hub_fuel[fuel]

View File

@ -19,7 +19,6 @@ from hub.city_model_structure.energy_systems.generation_system import Generation
from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem
from hub.city_model_structure.energy_systems.emission_system import EmissionSystem from hub.city_model_structure.energy_systems.emission_system import EmissionSystem
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
from hub.imports.energy_systems.helpers.energy_systems_helper import EnergySystemsHelper
class MontrealCustomEnergySystemParameters: class MontrealCustomEnergySystemParameters:

View File

@ -1,173 +0,0 @@
"""
WaterToWaterHPParameters import the heat pump information
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com
"""
from typing import Dict
from typing import List
import numpy as np
import pandas as pd
from scipy.optimize import curve_fit
from hub.city_model_structure.energy_system import EnergySystem
from hub.city_model_structure.energy_systems.water_to_water_hp import WaterToWaterHP
class WaterToWaterHPParameters:
"""
WaterToWaterHPParameters class
"""
def __init__(self, city, base_path):
self._city = city
self._base_path = (base_path / 'heat_pumps/water_to_water.xlsx').resolve()
def _read_file(self) -> Dict:
# todo: this method is keeping the excel file open and should be either corrected or removed
xl_file = pd.ExcelFile(self._base_path)
heat_pump_dfs = {sheet_name: xl_file.parse(sheet_name)
for sheet_name in xl_file.sheet_names}
hp_data = {}
flow_rates = {
'156': [2.84, 4.23, 5.68],
'256': [4.73, 7.13, 9.446],
'335': [6.62, 9.97, 12.93],
}
for sheet, _ in heat_pump_dfs.items():
df = heat_pump_dfs[sheet].dropna(axis=1, how='all')
df = df.iloc[3:, 6:35]
if '156' in sheet:
hp_data[sheet] = self._extract_required_hp_data(df, [0, 10, 25, 40, 55, 67], flow_rates['156'])
elif '256' in sheet:
hp_data[sheet] = self._extract_required_hp_data(df, [0, 9, 24, 39, 54, 66], flow_rates['256'])
elif '335' in sheet:
hp_data[sheet] = self._extract_required_hp_data(df, [0, 11, 26, 41, 56, 69], flow_rates['335'])
return hp_data
def _extract_required_hp_data(self, dataframe, ranges, flow_rates):
"""
Extracts 156 Kw water to water heat pump data
:param dataframe: dataframe containing all data
:param ranges: the range of values to extract
:param flow_rates: the flow rates of water through pump
:return: Dict
"""
# extract data rows and columns
data = {'tc': self._extract_hp_data(dataframe, [1, 11, 21], ranges),
'pd': self._extract_hp_data(dataframe, [2, 12, 22], ranges),
'lwt': self._extract_hp_data(dataframe, [5, 15, 25], ranges),
'fr': (self._extract_flow_and_ewt(dataframe, ranges, [1, 11, 21], flow_rates))[0],
'ewt': (self._extract_flow_and_ewt(dataframe, ranges, [1, 11, 21], flow_rates))[1]}
# range values for extracting data
return data
@staticmethod
def _extract_hp_data(df, columns, ranges):
"""
Extract variable specific (LWT, PD or TC) data from water to water hp
:param df: the dataframe
:param columns: the columns to extract data from
:param ranges: the range of values to extract
:return: List
"""
data = pd.concat([df.iloc[ranges[0]:ranges[1], columns[0]], df.iloc[ranges[0]:ranges[1], columns[1]]])
data = pd.concat([df.iloc[ranges[0]:ranges[1], columns[2]], data])
for i in range(1, 5):
data = pd.concat([df.iloc[ranges[i]:ranges[i + 1], columns[0]], data])
data = pd.concat([df.iloc[ranges[i]:ranges[i + 1], columns[1]], data])
data = pd.concat([df.iloc[ranges[i]:ranges[i + 1], columns[2]], data])
return data.dropna().values.tolist()
@staticmethod
def _extract_flow_and_ewt(df, ranges, columns, flow_rates):
"""
Create the flow and ewt data based on the length of the various
columns for the variables being extracted
:param df: the dataframe
:param ranges: the range of values to extract
:param columns: the columns to extract data from
:param flow_rates: flow rate values
:return:
"""
ewt_values = [-1.111111111, 4.444444444, 10, 15.55555556, 21.11111111]
length = [len(df.iloc[ranges[0]:ranges[1], columns[0]].dropna()),
len(df.iloc[ranges[0]:ranges[1], columns[1]].dropna()),
len(df.iloc[ranges[0]:ranges[1], columns[2]].dropna())]
ewt_data = np.repeat(ewt_values[0], sum(length))
flow_rates_data = np.repeat(flow_rates, length)
for i in range(1, 5):
length = [len(df.iloc[ranges[i]:ranges[i + 1], columns[0]].dropna()),
len(df.iloc[ranges[i]:ranges[i + 1], columns[1]].dropna()),
len(df.iloc[ranges[i]:ranges[i + 1], columns[2]].dropna())]
flow_rates_data = np.append(flow_rates_data, np.repeat(flow_rates, length))
ewt_data = np.append(ewt_data, np.repeat(ewt_values[i], sum(length)))
return flow_rates_data.tolist(), ewt_data.tolist()
def enrich_city(self):
"""
Enriches the city with information from file
"""
heap_pump_data = self._read_file()
for model, data in heap_pump_data.items():
heat_pump = WaterToWaterHP()
heat_pump.model = model.strip()
heat_pump.total_cooling_capacity = data['tc']
heat_pump.power_demand = data['pd']
heat_pump.flow_rate = data['fr']
heat_pump.entering_water_temp = data['ewt']
heat_pump.leaving_water_temp = data['lwt']
heat_pump.power_demand_coff = self._compute_coefficients(data)
energy_system = EnergySystem(heat_pump.model, [])
energy_system.water_to_water_hp = heat_pump
self._city.add_city_object(energy_system)
return self._city
def _compute_coefficients(self, heat_pump_data: Dict) -> List[float]:
"""
Compute heat output and electrical demand coefficients
from heating performance data
:param heat_pump_data: a dictionary of heat pump data.
:return: Tuple[Dict, Dict]
"""
demand = [i / j for i, j in zip(heat_pump_data['tc'], heat_pump_data['pd'])]
# Compute heat output coefficients
popt, _ = curve_fit(
self._objective_function, [heat_pump_data['ewt'], heat_pump_data['lwt'], heat_pump_data['fr']], demand
)
return popt.tolist()
@staticmethod
def _objective_function(xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float,
a7: float, a8: float, a9: float, a10: float, a11: float) -> float:
"""
Objective function for computing coefficients
:param xdata:
:param a1: float
:param a2: float
:param a3: float
:param a4: float
:param a5: float
:param a6: float
:param a7: float
:param a8: float
:param a9: float
:param a10: float
:param a11: float
:return:
"""
x, y, t = xdata
return (a1 * x ** 2) + (a2 * x) + (a3 * y ** 2) + (a4 * y) + (a5 * t ** 2) + (a6 * t) + (a7 * x * y) + (
a8 * x * t) + (a9 * y * t) + (a10 * x * y * t) + a11

View File

@ -8,9 +8,7 @@ Code contributors: Peter Yefi peteryefi@gmail.com
from pathlib import Path from pathlib import Path
from hub.helpers.utils import validate_import_export_type from hub.helpers.utils import validate_import_export_type
from hub.imports.energy_systems.air_source_hp_parameters import AirSourceHeatPumpParameters
from hub.imports.energy_systems.montreal_custom_energy_system_parameters import MontrealCustomEnergySystemParameters from hub.imports.energy_systems.montreal_custom_energy_system_parameters import MontrealCustomEnergySystemParameters
from hub.imports.energy_systems.water_to_water_hp_parameters import WaterToWaterHPParameters
class EnergySystemsFactory: class EnergySystemsFactory:
@ -26,24 +24,6 @@ class EnergySystemsFactory:
self._city = city self._city = city
self._base_path = base_path self._base_path = base_path
def _air_source_hp(self):
"""
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): 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

View File

@ -1,116 +0,0 @@
"""
gpandas module parses geopandas input table and import the geometry into the city model structure
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder: Milad Aghamohamadnia --- milad.aghamohamadnia@concordia.ca
"""
import trimesh
import trimesh.exchange.load
import trimesh.geometry
import trimesh.creation
import trimesh.repair
from shapely.geometry import Point
from shapely.geometry import Polygon as ShapelyPoly
from trimesh import Scene
from hub.city_model_structure.attributes.polygon import Polygon
from hub.city_model_structure.building import Building
from hub.city_model_structure.building_demand.surface import Surface
from hub.city_model_structure.city import City
import hub.helpers.constants as cte
class GPandas:
"""
GeoPandas class
"""
def __init__(self, dataframe, srs_name='EPSG:26911'):
"""_summary_
Arguments:
dataframe {Geopandas.Dataframe} -- input geometry data in geopandas table
Keyword Arguments:
srs_name {str} -- coordinate system of coordinate system (default: {'EPSG:26911'})
"""
self._srs_name = srs_name
self._city = None
self._scene = dataframe
self._scene = self._scene.to_crs(self._srs_name)
min_x, min_y, max_x, max_y = self._scene.total_bounds
self._lower_corner = [min_x, min_y, 0]
self._upper_corner = [max_x, max_y, 0]
@property
def scene(self) -> Scene:
"""
Get GeoPandas scene
"""
return self._scene
@property
def city(self) -> City:
"""
Get city out of a GeoPandas Table
"""
if self._city is None:
self._city = City(self._lower_corner, self._upper_corner, self._srs_name)
lod = 0
for _, bldg in self._scene.iterrows():
polygon = bldg.geometry
height = float(bldg['height'])
building_mesh = trimesh.creation.extrude_polygon(polygon, height)
trimesh.repair.fill_holes(building_mesh)
trimesh.repair.fix_winding(building_mesh)
year_of_construction = int(bldg['year_built'])
name = bldg['name']
lod = 1
if year_of_construction > 2000:
function = cte.RESIDENTIAL
else:
function = cte.INDUSTRY
surfaces = []
for _, face in enumerate(building_mesh.faces):
points = []
for vertex_index in face:
points.append(building_mesh.vertices[vertex_index])
solid_polygon = Polygon(points)
perimeter_polygon = solid_polygon
surface = Surface(solid_polygon, perimeter_polygon)
surfaces.append(surface)
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
def resize_polygon(poly, factor=0.10, expand=False) -> ShapelyPoly:
"""
returns the shapely polygon which is smaller or bigger by passed factor.
Arguments:
poly {shapely.geometry.Polygon} -- an input geometry in shapely polygon format
Keyword Arguments:
factor {float} -- factor of expansion (default: {0.10})
expand {bool} -- If expand = True , then it returns bigger polygon, else smaller (default: {False})
Returns:
{shapely.geometry.Polygon} -- output geometry in shapely polygon format
"""
xs = list(poly.exterior.coords.xy[0])
ys = list(poly.exterior.coords.xy[1])
x_center = 0.5 * min(xs) + 0.5 * max(xs)
y_center = 0.5 * min(ys) + 0.5 * max(ys)
min_corner = Point(min(xs), min(ys))
center = Point(x_center, y_center)
shrink_distance = center.distance(min_corner) * factor
if expand:
poly_resized = poly.buffer(shrink_distance) # expand
else:
poly_resized = poly.buffer(-shrink_distance) # shrink
return poly_resized

View File

@ -4,13 +4,11 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import geopandas
from hub.city_model_structure.city import City from hub.city_model_structure.city import City
from hub.helpers.utils import validate_import_export_type from hub.helpers.utils import validate_import_export_type
from hub.imports.geometry.citygml import CityGml from hub.imports.geometry.citygml import CityGml
from hub.imports.geometry.geojson import Geojson from hub.imports.geometry.geojson import Geojson
from hub.imports.geometry.gpandas import GPandas
from hub.imports.geometry.obj import Obj from hub.imports.geometry.obj import Obj
@ -56,16 +54,6 @@ class GeometryFactory:
""" """
return Obj(self._path).city return Obj(self._path).city
@property
def _gpandas(self) -> City:
"""
Enrich the city by using GeoPandas information as data source
:return: City
"""
if self._data_frame is None:
self._data_frame = geopandas.read_file(self._path)
return GPandas(self._data_frame).city
@property @property
def _geojson(self) -> City: def _geojson(self) -> City:
""" """

View File

@ -1,40 +0,0 @@
"""
Insel Heap pump energy demand and fossil fuel consumption
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder peter.yefi@gmail.cm
"""
from pathlib import Path
import pandas as pd
class InselHeatPumpEnergyDemand:
"""
Import Energy demand and fossil fuel consumption results
"""
def __init__(self, city, base_path, hp_model):
"""
:param city: the city
:param base_path: the insel simulation output file
:param hp_model: the heatpump model for both air source and water to water
"""
self._city = city
self._hp_model = hp_model
with open(Path(base_path).resolve(), 'r', encoding='utf8') as csv_file:
df = pd.read_csv(csv_file)
self._monthly_electricity_demand = df.iloc[:, 1]
self._monthly_fossil_fuel_consumption = df.iloc[:, 2]
def enrich(self):
"""
Enrich the city with the heat pump information
"""
for energy_system in self._city.energy_systems:
if energy_system.air_source_hp is not None:
if energy_system.air_source_hp.model == self._hp_model:
energy_system.air_source_hp.hp_monthly_fossil_consumption = self._monthly_fossil_fuel_consumption
if energy_system.water_to_water_hp is not None:
if energy_system.water_to_water_hp.model == self._hp_model:
energy_system.water_to_water_hp.hp_monthly_electricity_demand = self._monthly_electricity_demand

View File

@ -4,9 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Guillermo.GutierrezMorote@concordia.ca Project Coder Guillermo.GutierrezMorote@concordia.ca
""" """
from pathlib import Path from pathlib import Path
import csv import csv
import pandas as pd
import hub.helpers.constants as cte import hub.helpers.constants as cte
@ -34,11 +34,9 @@ class InselMonthlyEnergyBalance:
demand[i] = str(aux) demand[i] = str(aux)
else: else:
demand[i] = '0' demand[i] = '0'
heating.append(demand[0]) heating.append(float(demand[0]))
cooling.append(demand[1]) cooling.append(float(demand[1]))
monthly_heating = pd.DataFrame(heating, columns=[cte.INSEL_MEB]).astype(float) return heating, cooling
monthly_cooling = pd.DataFrame(cooling, columns=[cte.INSEL_MEB]).astype(float)
return monthly_heating, monthly_cooling
def _dhw_and_electric_demand(self): def _dhw_and_electric_demand(self):
for building in self._city.buildings: for building in self._city.buildings:
@ -52,7 +50,7 @@ class InselMonthlyEnergyBalance:
else: else:
thermal_zone = building.internal_zones[0].thermal_zones[0] thermal_zone = building.internal_zones[0].thermal_zones[0]
area = thermal_zone.total_floor_area area = thermal_zone.total_floor_area
cold_water = building.cold_water_temperature[cte.MONTH]['epw'] cold_water = building.cold_water_temperature[cte.MONTH]
peak_flow = thermal_zone.domestic_hot_water.peak_flow peak_flow = thermal_zone.domestic_hot_water.peak_flow
service_temperature = thermal_zone.domestic_hot_water.service_temperature service_temperature = thermal_zone.domestic_hot_water.service_temperature
lighting_density = thermal_zone.lighting.density lighting_density = thermal_zone.lighting.density
@ -68,7 +66,7 @@ class InselMonthlyEnergyBalance:
for value in schedule.values: for value in schedule.values:
total_day += value total_day += value
for day_type in schedule.day_types: for day_type in schedule.day_types:
total_lighting += total_day * cte.DAYS_A_MONTH[day_type][month] * lighting_density total_lighting += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] * lighting_density
lighting_demand.append(total_lighting * area) lighting_demand.append(total_lighting * area)
for schedule in thermal_zone.appliances.schedules: for schedule in thermal_zone.appliances.schedules:
@ -76,7 +74,7 @@ class InselMonthlyEnergyBalance:
for value in schedule.values: for value in schedule.values:
total_day += value total_day += value
for day_type in schedule.day_types: for day_type in schedule.day_types:
total_appliances += total_day * cte.DAYS_A_MONTH[day_type][month] * appliances_density total_appliances += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] * appliances_density
appliances_demand.append(total_appliances * area) appliances_demand.append(total_appliances * area)
for schedule in thermal_zone.domestic_hot_water.schedules: for schedule in thermal_zone.domestic_hot_water.schedules:
@ -87,26 +85,15 @@ class InselMonthlyEnergyBalance:
demand = ( demand = (
peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * (service_temperature - cold_water[month]) peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * (service_temperature - cold_water[month])
) )
total_dhw_demand += total_day * cte.DAYS_A_MONTH[day_type][month] * demand total_dhw_demand += total_day * cte.WEEK_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, building.domestic_hot_water_heat_demand[cte.MONTH] = domestic_hot_water_demand
columns=[cte.INSEL_MEB]) building.domestic_hot_water_heat_demand[cte.YEAR] = [sum(domestic_hot_water_demand)]
yearly_domestic_hot_water_demand = [sum(domestic_hot_water_demand)] building.lighting_electrical_demand[cte.MONTH] = lighting_demand
building.domestic_hot_water_heat_demand[cte.YEAR] = pd.DataFrame(yearly_domestic_hot_water_demand, building.lighting_electrical_demand[cte.YEAR] = [sum(lighting_demand)]
columns=[cte.INSEL_MEB]) building.appliances_electrical_demand[cte.MONTH] = appliances_demand
building.lighting_electrical_demand[cte.MONTH] = pd.DataFrame(lighting_demand, columns=[cte.INSEL_MEB]) building.appliances_electrical_demand[cte.YEAR] = [sum(appliances_demand)]
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): def enrich(self):
""" """
@ -118,10 +105,6 @@ class InselMonthlyEnergyBalance:
insel_output_file_path = Path(self._base_path / file_name).resolve() insel_output_file_path = Path(self._base_path / file_name).resolve()
if insel_output_file_path.is_file(): if insel_output_file_path.is_file():
building.heating_demand[cte.MONTH], building.cooling_demand[cte.MONTH] = self._conditioning_demand(insel_output_file_path) building.heating_demand[cte.MONTH], building.cooling_demand[cte.MONTH] = self._conditioning_demand(insel_output_file_path)
building.heating_demand[cte.YEAR] = pd.DataFrame( building.heating_demand[cte.YEAR] = [sum(building.heating_demand[cte.MONTH])]
[building.heating_demand[cte.MONTH][cte.INSEL_MEB].astype(float).sum()], columns=[cte.INSEL_MEB] building.cooling_demand[cte.YEAR] = [sum(building.cooling_demand[cte.MONTH])]
)
building.cooling_demand[cte.YEAR] = pd.DataFrame(
[building.cooling_demand[cte.MONTH][cte.INSEL_MEB].astype(float).sum()], columns=[cte.INSEL_MEB]
)
self._dhw_and_electric_demand() self._dhw_and_electric_demand()

View File

@ -4,10 +4,10 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Guillermo.GutierrezMorote@concordia.ca Project Coder Guillermo.GutierrezMorote@concordia.ca
""" """
import calendar as cal
import pandas as pd import pandas as pd
import numpy as np
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.helpers.monthly_values import MonthlyValues
class SimplifiedRadiosityAlgorithm: class SimplifiedRadiosityAlgorithm:
@ -19,54 +19,11 @@ class SimplifiedRadiosityAlgorithm:
self._city = city self._city = city
self._base_path = base_path self._base_path = base_path
self._input_file_path = (self._base_path / f'{self._city.name}_sra_SW.out').resolve() self._input_file_path = (self._base_path / f'{self._city.name}_sra_SW.out').resolve()
self._month_hour = self._month_hour_data_frame
self._results = self._read_results()
self._radiation_list = []
@property
def _month_hour_data_frame(self):
array = []
for i in range(0, 12):
days_of_month = cal.monthrange(2015, i+1)[1]
total_hours = days_of_month * 24
array = np.concatenate((array, np.full(total_hours, i + 1)))
return pd.DataFrame(array, columns=[cte.MONTH])
def _get_monthly_values(self, values):
out = None
if values is not None:
if cte.MONTH not in values.columns:
values = pd.concat([self._month_hour, pd.DataFrame(values)], axis=1)
out = values.groupby(cte.MONTH, as_index=False).sum()
del out[cte.MONTH]
return out
@staticmethod
def _get_yearly_values(values):
return [values.sum()]
def _read_results(self):
try: try:
return pd.read_csv(self._input_file_path, sep='\s+', header=0) self._results = pd.read_csv(self._input_file_path, sep='\s+', header=0).to_dict(orient='list')
except FileNotFoundError as err: except FileNotFoundError as err:
raise FileNotFoundError('No SRA output file found') from err raise FileNotFoundError('No SRA output file found') from err
@property
def _radiation(self) -> []:
if len(self._radiation_list) == 0:
id_building = ''
header_building = []
for column in self._results.columns.values:
if id_building != column.split(':')[1]:
id_building = column.split(':')[1]
if len(header_building) > 0:
self._radiation_list.append(pd.concat([self._month_hour, self._results[header_building]], axis=1))
header_building = [column]
else:
header_building.append(column)
self._radiation_list.append(pd.concat([self._month_hour, self._results[header_building]], axis=1))
return self._radiation_list
def enrich(self): def enrich(self):
""" """
saves in building surfaces the correspondent irradiance at different time-scales depending on the mode saves in building surfaces the correspondent irradiance at different time-scales depending on the mode
@ -74,28 +31,21 @@ class SimplifiedRadiosityAlgorithm:
specific building values specific building values
:return: none :return: none
""" """
for radiation in self._radiation: _irradiance = {}
city_object_name = radiation.columns.values.tolist()[1].split(':')[1] for key in self._results:
header_name = key.split(':')
result = self._results[key]
city_object_name = header_name[1]
building = self._city.city_object(city_object_name) building = self._city.city_object(city_object_name)
for column in radiation.columns.values: surface_id = header_name[2]
if column == cte.MONTH: surface = building.surface_by_id(surface_id)
continue monthly_result = MonthlyValues.get_total_month(result)
header_id = column yearly_result = [sum(result)]
surface_id = header_id.split(':')[2] _irradiance[cte.YEAR] = yearly_result
surface = building.surface_by_id(surface_id) _irradiance[cte.MONTH] = monthly_result
new_value = pd.DataFrame(radiation[[header_id]].to_numpy(), columns=[cte.SRA]) _irradiance[cte.HOUR] = result
month_new_value = self._get_monthly_values(new_value) surface.global_irradiance = _irradiance
if cte.MONTH not in surface.global_irradiance:
surface.global_irradiance[cte.MONTH] = month_new_value
else:
pd.concat([surface.global_irradiance[cte.MONTH], month_new_value], axis=1)
if cte.HOUR not in surface.global_irradiance:
surface.global_irradiance[cte.HOUR] = new_value
else:
pd.concat([surface.global_irradiance[cte.HOUR], new_value], axis=1)
if cte.YEAR not in surface.global_irradiance:
surface.global_irradiance[cte.YEAR] = pd.DataFrame(SimplifiedRadiosityAlgorithm._get_yearly_values(new_value),
columns=[cte.SRA])
self._city.level_of_detail.surface_radiation = 2 self._city.level_of_detail.surface_radiation = 2
for building in self._city.buildings: for building in self._city.buildings:
building.level_of_detail.surface_radiation = 2 building.level_of_detail.surface_radiation = 2

View File

@ -8,7 +8,6 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
from pathlib import Path from pathlib import Path
from hub.helpers.utils import validate_import_export_type from hub.helpers.utils import validate_import_export_type
from hub.imports.results.insel_heatpump_energy_demand import InselHeatPumpEnergyDemand
from hub.imports.results.insel_monthly_energry_balance import InselMonthlyEnergyBalance from hub.imports.results.insel_monthly_energry_balance import InselMonthlyEnergyBalance
from hub.imports.results.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm from hub.imports.results.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
@ -41,13 +40,6 @@ class ResultFactory:
""" """
SimplifiedRadiosityAlgorithm(self._city, self._base_path).enrich() SimplifiedRadiosityAlgorithm(self._city, self._base_path).enrich()
def _heat_pump(self):
"""
Enrich the city (energy system specifically) with heat pump insel simulation
results
"""
InselHeatPumpEnergyDemand(self._city, self._base_path, self._hp_model).enrich()
def _insel_monthly_energy_balance(self): def _insel_monthly_energy_balance(self):
""" """
Enrich the city with insel monthly energy balance results Enrich the city with insel monthly energy balance results

View File

@ -104,7 +104,7 @@ class ComnetUsageParameters:
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature _domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
peak_flow = None peak_flow = None
if len(cold_water_temperature) > 0: if len(cold_water_temperature) > 0:
cold_temperature = cold_water_temperature[cte.YEAR]['epw'] cold_temperature = cold_water_temperature[cte.YEAR][0]
peak_flow = 0 peak_flow = 0
if (archetype.domestic_hot_water.service_temperature - cold_temperature) > 0: if (archetype.domestic_hot_water.service_temperature - cold_temperature) > 0:
peak_flow = archetype.domestic_hot_water.density / cte.WATER_DENSITY / cte.WATER_HEAT_CAPACITY \ peak_flow = archetype.domestic_hot_water.density / cte.WATER_DENSITY / cte.WATER_HEAT_CAPACITY \

View File

@ -104,7 +104,7 @@ class EilatUsageParameters:
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature _domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
peak_flow = None peak_flow = None
if len(cold_water_temperature) > 0: if len(cold_water_temperature) > 0:
cold_temperature = cold_water_temperature[cte.YEAR]['epw'] cold_temperature = cold_water_temperature[cte.YEAR][0]
peak_flow = 0 peak_flow = 0
if (archetype.domestic_hot_water.service_temperature - cold_temperature) > 0: if (archetype.domestic_hot_water.service_temperature - cold_temperature) > 0:
peak_flow = archetype.domestic_hot_water.density / cte.WATER_DENSITY / cte.WATER_HEAT_CAPACITY \ peak_flow = archetype.domestic_hot_water.density / cte.WATER_DENSITY / cte.WATER_HEAT_CAPACITY \

View File

@ -130,7 +130,7 @@ class NrcanUsageParameters:
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature _domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
density = None density = None
if len(cold_water_temperature) > 0: if len(cold_water_temperature) > 0:
cold_temperature = cold_water_temperature[cte.YEAR]['epw'] cold_temperature = cold_water_temperature[cte.YEAR][0]
density = ( density = (
archetype.domestic_hot_water.peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * archetype.domestic_hot_water.peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY *
(archetype.domestic_hot_water.service_temperature - cold_temperature) (archetype.domestic_hot_water.service_temperature - cold_temperature)

View File

@ -4,14 +4,15 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 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 logging import logging
import sys import sys
from pathlib import Path from pathlib import Path
import pandas as pd
import requests import requests
import pandas as pd
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.helpers.monthly_values import MonthlyValues
from hub.city_model_structure.city import City from hub.city_model_structure.city import City
from hub.imports.weather.helpers.weather import Weather as wh from hub.imports.weather.helpers.weather import Weather as wh
@ -75,6 +76,25 @@ class EpwWeatherParameters:
'snow_depth_cm', 'snow_depth_cm',
'days_since_last_snowfall', 'albedo', 'liquid_precipitation_depth_mm', 'days_since_last_snowfall', 'albedo', 'liquid_precipitation_depth_mm',
'liquid_precipitation_quality_hr']) 'liquid_precipitation_quality_hr'])
number_invalid_records = self._weather_values[
self._weather_values.dry_bulb_temperature_c == 99.9].count().dry_bulb_temperature_c
if number_invalid_records > 0:
sys.stderr.write(f'Warning: {self._path} invalid records (value of 99.9) in dry bulb temperature\n')
number_invalid_records = self._weather_values[
self._weather_values.global_horizontal_radiation_wh_m2 == 9999].count().global_horizontal_radiation_wh_m2
if number_invalid_records > 0:
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in global horizontal radiation\n')
number_invalid_records = self._weather_values[
self._weather_values.diffuse_horizontal_radiation_wh_m2 == 9999].count().diffuse_horizontal_radiation_wh_m2
if number_invalid_records > 0:
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in diffuse horizontal radiation\n')
number_invalid_records = self._weather_values[
self._weather_values.direct_normal_radiation_wh_m2 == 9999].count().direct_normal_radiation_wh_m2
if number_invalid_records > 0:
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in direct horizontal radiation\n')
self._weather_values = self._weather_values.to_dict(orient='list')
except SystemExit: except SystemExit:
sys.stderr.write(f'Error: wrong formatting of weather file {self._path}\n') sys.stderr.write(f'Error: wrong formatting of weather file {self._path}\n')
sys.exit() sys.exit()
@ -82,72 +102,29 @@ class EpwWeatherParameters:
building.ground_temperature[cte.MONTH] = ground_temperature_from_file building.ground_temperature[cte.MONTH] = ground_temperature_from_file
ground_temperature = {} ground_temperature = {}
for ground_temperature_set in building.ground_temperature[cte.MONTH]: for ground_temperature_set in building.ground_temperature[cte.MONTH]:
temperature = 0 temperature = sum(building.ground_temperature[cte.MONTH][ground_temperature_set]) / 12
for value in building.ground_temperature[cte.MONTH][ground_temperature_set]:
temperature += value / 12
ground_temperature[ground_temperature_set] = [temperature] ground_temperature[ground_temperature_set] = [temperature]
building.ground_temperature[cte.YEAR] = ground_temperature building.ground_temperature[cte.YEAR] = ground_temperature
if cte.HOUR in building.external_temperature: if cte.HOUR in building.external_temperature:
del building.external_temperature[cte.HOUR] del building.external_temperature[cte.HOUR]
new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw']) # new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
number_invalid_records = new_value[new_value.epw == 99.9].count().epw # number_invalid_records = new_value[new_value.epw == 99.9].count().epw
if number_invalid_records > 0: building.external_temperature[cte.HOUR] = self._weather_values['dry_bulb_temperature_c']
sys.stderr.write(f'Warning: {self._path} invalid records (value of 99.9) in dry bulb temperature\n') building.global_horizontal[cte.HOUR] = self._weather_values['global_horizontal_radiation_wh_m2']
if cte.HOUR not in building.external_temperature: building.diffuse[cte.HOUR] = self._weather_values['diffuse_horizontal_radiation_wh_m2']
building.external_temperature[cte.HOUR] = new_value building.beam[cte.HOUR] = self._weather_values['direct_normal_radiation_wh_m2']
else: building.cold_water_temperature[cte.HOUR] = wh().cold_water_temperature(building.external_temperature[cte.HOUR])
pd.concat([building.external_temperature[cte.HOUR], new_value], axis=1)
new_value = pd.DataFrame(self._weather_values[['global_horizontal_radiation_wh_m2']].to_numpy(), columns=['epw'])
number_invalid_records = new_value[new_value.epw == 9999].count().epw
if number_invalid_records > 0:
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in global horizontal radiation\n')
if cte.HOUR not in building.global_horizontal:
building.global_horizontal[cte.HOUR] = new_value
else:
pd.concat([building.global_horizontal[cte.HOUR], new_value], axis=1)
new_value = pd.DataFrame(self._weather_values[['diffuse_horizontal_radiation_wh_m2']].to_numpy(), columns=['epw'])
number_invalid_records = new_value[new_value.epw == 9999].count().epw
if number_invalid_records > 0:
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in diffuse horizontal radiation\n')
if cte.HOUR not in building.diffuse:
building.diffuse[cte.HOUR] = new_value
else:
pd.concat([building.diffuse[cte.HOUR], new_value], axis=1)
new_value = pd.DataFrame(self._weather_values[['direct_normal_radiation_wh_m2']].to_numpy(), columns=['epw'])
number_invalid_records = new_value[new_value.epw == 9999].count().epw
if number_invalid_records > 0:
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in direct horizontal radiation\n')
if cte.HOUR not in building.beam:
building.beam[cte.HOUR] = new_value
else:
pd.concat([building.beam[cte.HOUR], new_value], axis=1)
new_value = wh().cold_water_temperature(building.external_temperature[cte.HOUR]['epw'])
if cte.HOUR not in building.cold_water_temperature:
building.cold_water_temperature[cte.HOUR] = new_value
else:
pd.concat([building.cold_water_temperature[cte.HOUR], new_value], axis=1)
# create the monthly and yearly values out of the hourly # create the monthly and yearly values out of the hourly
for building in self._city.buildings: for building in self._city.buildings:
if cte.MONTH not in building.external_temperature: building.external_temperature[cte.MONTH] = MonthlyValues().get_mean_values(building.external_temperature[cte.HOUR])
building.external_temperature[cte.MONTH] = \ building.external_temperature[cte.YEAR] = [sum(building.external_temperature[cte.HOUR]) / 9870]
wh().get_monthly_mean_values(building.external_temperature[cte.HOUR][['epw']]) building.cold_water_temperature[cte.MONTH] = MonthlyValues().get_mean_values(building.cold_water_temperature[cte.HOUR])
if cte.YEAR not in building.external_temperature: building.cold_water_temperature[cte.YEAR] = [sum(building.cold_water_temperature[cte.HOUR]) / 9870]
building.external_temperature[cte.YEAR] = \
wh(). get_yearly_mean_values(building.external_temperature[cte.HOUR][['epw']])
if cte.MONTH not in building.cold_water_temperature:
building.cold_water_temperature[cte.MONTH] = wh().get_monthly_mean_values(
building.cold_water_temperature[cte.HOUR][['epw']])
if cte.YEAR not in building.cold_water_temperature:
building.cold_water_temperature[cte.YEAR] = wh().get_yearly_mean_values(
building.cold_water_temperature[cte.HOUR][['epw']])
# If the usage has already being imported, the domestic hot water missing values must be calculated here that # If the usage has already being imported, the domestic hot water missing values must be calculated here that
# the cold water temperature is finally known # the cold water temperature is finally known
cold_temperature = building.cold_water_temperature[cte.YEAR]['epw'] cold_temperature = building.cold_water_temperature[cte.YEAR][0]
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
if internal_zone.usages is not None: if internal_zone.usages is not None:
for usage in internal_zone.usages: for usage in internal_zone.usages:

View File

@ -4,11 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 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 logging import logging
import math import math
import calendar as cal
import pandas as pd
import numpy as np
import hub.helpers.constants as cte import hub.helpers.constants as cte
@ -75,55 +73,7 @@ class Weather:
for temperature in ambient_temperature_fahrenheit: for temperature in ambient_temperature_fahrenheit:
radians = (0.986 * (temperature-15-lag) - 90) * math.pi / 180 radians = (0.986 * (temperature-15-lag) - 90) * math.pi / 180
cold_temperature.append((average_temperature + 6 + ratio * (delta_temperature/2) * math.sin(radians) - 32) * 5/9) cold_temperature.append((average_temperature + 6 + ratio * (delta_temperature/2) * math.sin(radians) - 32) * 5/9)
return pd.DataFrame(cold_temperature, columns=['epw']) return cold_temperature
def get_monthly_mean_values(self, values):
"""
Get the monthly mean for the given values
:return: float
"""
out = None
if values is not None:
if 'month' not in values.columns:
values = pd.concat([self.month_hour, pd.DataFrame(values)], axis=1)
out = values.groupby('month', as_index=False).mean()
del out['month']
return out
@staticmethod
def get_yearly_mean_values(values):
"""
Get the yearly mean for the given values
:return: float
"""
return values.mean()
def get_total_month(self, values):
"""
Get the total value the given values
:return: float
"""
out = None
if values is not None:
if 'month' not in values.columns:
values = pd.concat([self.month_hour, pd.DataFrame(values)], axis=1)
out = pd.DataFrame(values).groupby('month', as_index=False).sum()
del out['month']
return out
@property
def month_hour(self):
"""
returns a DataFrame that has x values of the month number (January = 1, February = 2...),
being x the number of hours of the corresponding month
:return: DataFrame(int)
"""
array = []
for i in range(0, 12):
days_of_month = cal.monthrange(2015, i+1)[1]
total_hours = days_of_month * 24
array = np.concatenate((array, np.full(total_hours, i + 1)))
return pd.DataFrame(array, columns=['month'])
def epw_file(self, region_code): def epw_file(self, region_code):
""" """

View File

@ -4,7 +4,6 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 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
""" """
from pathlib import Path
from hub.city_model_structure.city import City from hub.city_model_structure.city import City
from hub.helpers.utils import validate_import_export_type from hub.helpers.utils import validate_import_export_type

View File

@ -4,14 +4,13 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
""" """
import copy import copy
import distutils.spawn import distutils.spawn
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
import pandas as pd
from hub.city_model_structure.city import City from hub.city_model_structure.city import City
from hub.imports.geometry_factory import GeometryFactory from hub.imports.geometry_factory import GeometryFactory
from hub.imports.results_factory import ResultFactory from hub.imports.results_factory import ResultFactory
@ -72,13 +71,13 @@ class TestCityMerge(TestCase):
for building in merged_city.buildings: for building in merged_city.buildings:
for surface in building.surfaces: for surface in building.surfaces:
if surface.global_irradiance: if surface.global_irradiance:
full_city_building_total_radiation += surface.global_irradiance[cte.YEAR].iloc[0, 0] full_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
merged_city_building_total_radiation = 0 merged_city_building_total_radiation = 0
for building in merged_city.buildings: for building in merged_city.buildings:
for surface in building.surfaces: for surface in building.surfaces:
if surface.global_irradiance: if surface.global_irradiance:
merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR].iloc[0, 0] merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation) self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation)
merged_city = even_city.merge(full_city) merged_city = even_city.merge(full_city)
@ -86,24 +85,24 @@ class TestCityMerge(TestCase):
for building in merged_city.buildings: for building in merged_city.buildings:
for surface in building.surfaces: for surface in building.surfaces:
if surface.global_irradiance: if surface.global_irradiance:
merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR].iloc[0, 0] merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation) self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation)
for building in even_city.buildings: for building in even_city.buildings:
for surface in building.surfaces: for surface in building.surfaces:
surface.global_irradiance[cte.YEAR] = pd.DataFrame([3], columns=['sra_mockup_value']) surface.global_irradiance[cte.YEAR] = [3]
merged_city = full_city.merge(even_city) merged_city = full_city.merge(even_city)
first_merged_city_building_total_radiation = 0 first_merged_city_building_total_radiation = 0
for building in merged_city.buildings: for building in merged_city.buildings:
for surface in building.surfaces: for surface in building.surfaces:
if surface.global_irradiance: if surface.global_irradiance:
first_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR].iloc[0, 0] first_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
merged_city = even_city.merge(full_city) merged_city = even_city.merge(full_city)
second_merged_city_building_total_radiation = 0 second_merged_city_building_total_radiation = 0
for building in merged_city.buildings: for building in merged_city.buildings:
for surface in building.surfaces: for surface in building.surfaces:
if surface.global_irradiance: if surface.global_irradiance:
second_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR].iloc[0, 0] second_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
self.assertEqual(first_merged_city_building_total_radiation, second_merged_city_building_total_radiation) self.assertEqual(first_merged_city_building_total_radiation, second_merged_city_building_total_radiation)

View File

@ -37,24 +37,6 @@ class TestExports(TestCase):
self.assertIsNotNone(self._city, 'city is none') self.assertIsNotNone(self._city, 'city is none')
return self._city return self._city
@property
def _read_sra_file(self) -> []:
path = (self._example_path / "one_building_in_kelowna_sra_SW.out").resolve()
_results = pd.read_csv(path, sep='\s+', header=0)
id_building = ''
header_building = []
_radiation = []
for column in _results.columns.values:
if id_building != column.split(':')[1]:
id_building = column.split(':')[1]
if len(header_building) > 0:
_radiation.append(pd.concat([MonthlyValues().month_hour, _results[header_building]], axis=1))
header_building = [column]
else:
header_building.append(column)
_radiation.append(pd.concat([MonthlyValues().month_hour, _results[header_building]], axis=1))
return _radiation
def _set_irradiance_surfaces(self, city): def _set_irradiance_surfaces(self, city):
""" """
saves in building surfaces the correspondent irradiance at different time-scales depending on the mode saves in building surfaces the correspondent irradiance at different time-scales depending on the mode
@ -64,19 +46,22 @@ class TestExports(TestCase):
:return: none :return: none
""" """
city.level_of_detail.surface_radiation = 2 city.level_of_detail.surface_radiation = 2
for radiation in self._read_sra_file: path = (self._example_path / "one_building_in_kelowna_sra_SW.out").resolve()
city_object_name = radiation.columns.values.tolist()[1].split(':')[1] self._results = pd.read_csv(path, sep='\s+', header=0).to_dict(orient='list')
building = city.city_object(city_object_name) _irradiance = {}
for column in radiation.columns.values: for key in self._results:
if column == cte.MONTH: header_name = key.split(':')
continue result = self._results[key]
header_id = column city_object_name = header_name[1]
surface_id = header_id.split(':')[2] building = self._city.city_object(city_object_name)
surface = building.surface_by_id(surface_id) surface_id = header_name[2]
new_value = pd.DataFrame(radiation[[header_id]].to_numpy(), columns=['sra']) surface = building.surface_by_id(surface_id)
surface.global_irradiance[cte.HOUR] = new_value monthly_result = MonthlyValues.get_total_month(result)
month_new_value = MonthlyValues().get_mean_values(new_value) yearly_result = [sum(result)]
surface.global_irradiance[cte.MONTH] = month_new_value _irradiance[cte.YEAR] = yearly_result
_irradiance[cte.MONTH] = monthly_result
_irradiance[cte.HOUR] = result
surface.global_irradiance = _irradiance
def test_insel_monthly_energy_balance_export(self): def test_insel_monthly_energy_balance_export(self):
""" """
@ -86,7 +71,7 @@ class TestExports(TestCase):
WeatherFactory('epw', city).enrich() WeatherFactory('epw', city).enrich()
for building in city.buildings: for building in city.buildings:
building.external_temperature[cte.MONTH] = MonthlyValues().\ building.external_temperature[cte.MONTH] = MonthlyValues().\
get_mean_values(building.external_temperature[cte.HOUR][['epw']]) get_mean_values(building.external_temperature[cte.HOUR])
self._set_irradiance_surfaces(city) self._set_irradiance_surfaces(city)
for building in city.buildings: for building in city.buildings:

View File

@ -225,16 +225,16 @@ TestDBFactory
yearly_lighting_peak_load = building.lighting_peak_load[cte.YEAR] yearly_lighting_peak_load = building.lighting_peak_load[cte.YEAR]
monthly_appliances_peak_load = building.appliances_peak_load[cte.MONTH] monthly_appliances_peak_load = building.appliances_peak_load[cte.MONTH]
yearly_appliances_peak_load = building.appliances_peak_load[cte.YEAR] yearly_appliances_peak_load = building.appliances_peak_load[cte.YEAR]
monthly_cooling_demand = building.cooling_demand[cte.MONTH][cte.INSEL_MEB] monthly_cooling_demand = building.cooling_demand[cte.MONTH]
yearly_cooling_demand = building.cooling_demand[cte.YEAR][cte.INSEL_MEB] yearly_cooling_demand = building.cooling_demand[cte.YEAR]
monthly_heating_demand = building.heating_demand[cte.MONTH][cte.INSEL_MEB] monthly_heating_demand = building.heating_demand[cte.MONTH]
yearly_heating_demand = building.heating_demand[cte.YEAR][cte.INSEL_MEB] yearly_heating_demand = building.heating_demand[cte.YEAR]
monthly_lighting_electrical_demand = building.lighting_electrical_demand[cte.MONTH][cte.INSEL_MEB] monthly_lighting_electrical_demand = building.lighting_electrical_demand[cte.MONTH]
yearly_lighting_electrical_demand = building.lighting_electrical_demand[cte.YEAR][cte.INSEL_MEB] yearly_lighting_electrical_demand = building.lighting_electrical_demand[cte.YEAR]
monthly_appliances_electrical_demand = building.appliances_electrical_demand[cte.MONTH][cte.INSEL_MEB] monthly_appliances_electrical_demand = building.appliances_electrical_demand[cte.MONTH]
yearly_appliances_electrical_demand = building.appliances_electrical_demand[cte.YEAR][cte.INSEL_MEB] yearly_appliances_electrical_demand = building.appliances_electrical_demand[cte.YEAR]
monthly_domestic_hot_water_heat_demand = building.domestic_hot_water_heat_demand[cte.MONTH][cte.INSEL_MEB] monthly_domestic_hot_water_heat_demand = building.domestic_hot_water_heat_demand[cte.MONTH]
yearly_domestic_hot_water_heat_demand = building.domestic_hot_water_heat_demand[cte.YEAR][cte.INSEL_MEB] yearly_domestic_hot_water_heat_demand = building.domestic_hot_water_heat_demand[cte.YEAR]
monthly_heating_consumption = building.heating_consumption[cte.MONTH] monthly_heating_consumption = building.heating_consumption[cte.MONTH]
yearly_heating_consumption = building.heating_consumption[cte.YEAR] yearly_heating_consumption = building.heating_consumption[cte.YEAR]
monthly_cooling_consumption = building.cooling_consumption[cte.MONTH] monthly_cooling_consumption = building.cooling_consumption[cte.MONTH]

View File

@ -1,74 +0,0 @@
"""
Test EnergySystemsFactory and various heatpump models
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com
"""
from pathlib import Path
import pandas as pd
from unittest import TestCase
from hub.imports.geometry_factory import GeometryFactory
from hub.imports.energy_systems_factory import EnergySystemsFactory
from hub.city_model_structure.energy_systems.air_source_hp import AirSourceHP
from hub.exports.energy_systems_factory import EnergySystemsExportFactory
import os
# User defined parameters
user_input = {
'StartYear': 2020,
'EndYear': 2021,
'MaximumHPEnergyInput': 8000,
'HoursOfStorageAtMaxDemand': 1,
'BuildingSuppTemp': 40,
'TemperatureDifference': 15,
'FuelLHV': 47100,
'FuelPrice': 0.12,
'FuelEF': 1887,
'FuelDensity': 0.717,
'HPSupTemp': 60
}
class TestEnergySystemsFactory(TestCase):
"""
TestBuilding TestCase 1
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
city_file = (self._example_path/"C40_Final.gml").resolve()
self._output_path = (self._output_path/"as_user_output.csv").resolve()
self._city = GeometryFactory('citygml', path=city_file).city
EnergySystemsFactory('air_source_hp', self._city).enrich()
def test_air_source_heat_pump_import(self):
self.assertIsNotNone(self._city.energy_systems, 'City has energy systems')
self.assertIsInstance(self._city.energy_systems[0].air_source_hp, AirSourceHP)
self.assertEqual(self._city.energy_systems[0].air_source_hp.model, '012')
self.assertEqual(self._city.energy_systems[16].air_source_hp.model, '140')
def test_air_source_series_heat_pump_export(self):
EnergySystemsExportFactory(city=self._city, handler=user_input, hp_model='012',
output_path=self._output_path).export()
df = pd.read_csv(self._output_path)
self.assertEqual(df.shape, (13, 3))
self.assertEqual(df.iloc[0, 1], 1867715.88)
def test_air_source_parallel_heat_pump_export(self):
output = EnergySystemsExportFactory(city=self._city, handler=user_input, hp_model='018',
output_path=None, sim_type=1).export()
self.assertEqual(output["hourly_electricity_demand"][0], 38748.5625)
self.assertIsNotNone(output["daily_fossil_consumption"])
self.assertEqual(len(output["hourly_electricity_demand"]), 8760)
def tearDown(self) -> None:
try:
os.remove(self._output_path)
except OSError:
pass

View File

@ -1,72 +0,0 @@
"""
Test EnergySystemsFactory and various heatpump models
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com
"""
from pathlib import Path
from unittest import TestCase
import pandas as pd
from hub.city_model_structure.energy_systems.water_to_water_hp import WaterToWaterHP
from hub.exports.energy_systems_factory import EnergySystemsExportFactory
from hub.imports.energy_systems_factory import EnergySystemsFactory
from hub.imports.geometry_factory import GeometryFactory
class TestEnergySystemsFactory(TestCase):
"""
TestEnergySystemsFactory for Water to Water HP
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
city_file = (self._example_path / "C40_Final.gml").resolve()
self._output_path = (self._example_path / "w2w_user_output.csv").resolve()
self._city = GeometryFactory('citygml', path=city_file).city
EnergySystemsFactory('water_to_water_hp', self._city).enrich()
def test_water_to_water_heat_pump_import(self):
self.assertIsNotNone(self._city.energy_systems, 'City has energy systems')
self.assertIsInstance(self._city.energy_systems[0].water_to_water_hp, WaterToWaterHP)
self.assertEqual(self._city.energy_systems[0].water_to_water_hp.model, 'ClimateMaster 156 kW')
self.assertEqual(self._city.energy_systems[2].water_to_water_hp.model, 'ClimateMaster 335 kW')
def test_water_to_water_heat_pump_export(self):
# User defined parameters
user_input = {
'StartYear': 2020,
'EndYear': 2021,
'MaximumHPEnergyInput': 8000,
'HoursOfStorageAtMaxDemand': 1,
'BuildingSuppTemp': 40,
'TemperatureDifference': 15,
'FuelLHV': 47100,
'FuelPrice': 0.12,
'FuelEF': 1887,
'FuelDensity': 0.717,
'HPSupTemp': 60,
'b1': 10,
'b2': 10,
'b3': 10,
'b4': 10,
'b5': 10,
'b6': 10,
'b7': 10,
'b8': 10,
'b9': 10,
'b10': 10,
'b11': 10
}
EnergySystemsExportFactory(city=self._city, handler=user_input, hp_model='ClimateMaster 256 kW',
output_path=self._output_path, sim_type=1).export('water')
df = pd.read_csv(self._output_path)
self.assertEqual(df.shape, (13, 3))
self.assertEqual(df.iloc[0, 1], 1031544.62)

View File

@ -5,10 +5,10 @@ Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import logging.handlers import logging.handlers
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
import pandas as pd
from hub.imports.geometry_factory import GeometryFactory from hub.imports.geometry_factory import GeometryFactory
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction_factory import ConstructionFactory from hub.imports.construction_factory import ConstructionFactory
@ -58,10 +58,10 @@ class TestExports(TestCase):
self._complete_city.climate_reference_city = 'Summerland' self._complete_city.climate_reference_city = 'Summerland'
dummy_measures = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] dummy_measures = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
for building in self._complete_city.buildings: for building in self._complete_city.buildings:
building.heating_demand[cte.MONTH] = pd.DataFrame({'INSEL': dummy_measures}) building.heating_demand[cte.MONTH] = dummy_measures
building.cooling_demand[cte.MONTH] = pd.DataFrame({'INSEL': dummy_measures}) building.cooling_demand[cte.MONTH] = dummy_measures
building.heating_demand[cte.YEAR] = pd.DataFrame({'INSEL': [0.0]}) building.heating_demand[cte.YEAR] = [0.0]
building.cooling_demand[cte.YEAR] = pd.DataFrame({'INSEL': [0.0]}) building.cooling_demand[cte.YEAR] = [0.0]
return self._complete_city return self._complete_city
def _export(self, export_type, from_pickle=False): def _export(self, export_type, from_pickle=False):

View File

@ -1,76 +0,0 @@
"""
Test EnergySystemsFactory and various heatpump models
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com
"""
from pathlib import Path
from unittest import TestCase
from hub.imports.geometry_factory import GeometryFactory
from hub.imports.energy_systems_factory import EnergySystemsFactory
from hub.exports.energy_systems_factory import EnergySystemsExportFactory
from hub.imports.results_factory import ResultFactory
import os
from pandas.core.series import Series
# User defined parameters
user_input = {
'StartYear': 2020,
'EndYear': 2021,
'MaximumHPEnergyInput': 8000,
'HoursOfStorageAtMaxDemand': 1,
'BuildingSuppTemp': 40,
'TemperatureDifference': 15,
'FuelLHV': 47100,
'FuelPrice': 0.12,
'FuelEF': 1887,
'FuelDensity': 0.717,
'HPSupTemp': 60
}
class TestHeatPumpResults(TestCase):
"""
TestHeatPumpResults
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
self._output_path = (Path(__file__).parent / 'tests_outputs/as_user_output.csv').resolve()
city_file = (self._example_path / "C40_Final.gml").resolve()
self._city = GeometryFactory('citygml', path=city_file).city
EnergySystemsFactory('air_source_hp', self._city).enrich()
def test_air_source_series_heat_pump_012_results(self):
EnergySystemsExportFactory(city=self._city, handler=user_input, hp_model='012',
output_path=self._output_path).export()
ResultFactory('heat_pump', self._city, self._output_path, '012').enrich()
for energy_system in self._city.energy_systems:
self.assertIsNone(energy_system.water_to_water_hp)
if energy_system.air_source_hp.model == '012':
self.assertIsInstance(energy_system.air_source_hp.hp_monthly_fossil_consumption, Series)
self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[5], 1.51325583)
self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[12], 35.853598782915)
def test_air_source_series_heat_pump_015_results(self):
EnergySystemsExportFactory(city=self._city, handler=user_input, hp_model='140',
output_path=self._output_path).export()
ResultFactory('heat_pump', self._city, self._output_path, '140').enrich()
for energy_system in self._city.energy_systems:
self.assertIsNone(energy_system.water_to_water_hp)
if energy_system.air_source_hp.model == '140':
self.assertIsInstance(energy_system.air_source_hp.hp_monthly_fossil_consumption, Series)
self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[0], 7.91282225)
self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[2], 0.068873927)
def tearDown(self) -> None:
try:
os.remove(self._output_path)
except OSError:
pass

View File

@ -37,24 +37,6 @@ class TestExports(TestCase):
self.assertIsNotNone(self._city, 'city is none') self.assertIsNotNone(self._city, 'city is none')
return self._city return self._city
@property
def _read_sra_file(self) -> []:
path = (self._example_path / "one_building_in_kelowna_sra_SW.out").resolve()
_results = pd.read_csv(path, sep='\s+', header=0)
id_building = ''
header_building = []
_radiation = []
for column in _results.columns.values:
if id_building != column.split(':')[1]:
id_building = column.split(':')[1]
if len(header_building) > 0:
_radiation.append(pd.concat([MonthlyValues().month_hour, _results[header_building]], axis=1))
header_building = [column]
else:
header_building.append(column)
_radiation.append(pd.concat([MonthlyValues().month_hour, _results[header_building]], axis=1))
return _radiation
def _set_irradiance_surfaces(self, city): def _set_irradiance_surfaces(self, city):
""" """
saves in building surfaces the correspondent irradiance at different time-scales depending on the mode saves in building surfaces the correspondent irradiance at different time-scales depending on the mode
@ -64,19 +46,22 @@ class TestExports(TestCase):
:return: none :return: none
""" """
city.level_of_detail.surface_radiation = 2 city.level_of_detail.surface_radiation = 2
for radiation in self._read_sra_file: path = (self._example_path / "one_building_in_kelowna_sra_SW.out").resolve()
city_object_name = radiation.columns.values.tolist()[1].split(':')[1] self._results = pd.read_csv(path, sep='\s+', header=0).to_dict(orient='list')
building = city.city_object(city_object_name) _irradiance = {}
for column in radiation.columns.values: for key in self._results:
if column == cte.MONTH: header_name = key.split(':')
continue result = self._results[key]
header_id = column city_object_name = header_name[1]
surface_id = header_id.split(':')[2] building = self._city.city_object(city_object_name)
surface = building.surface_by_id(surface_id) surface_id = header_name[2]
new_value = pd.DataFrame(radiation[[header_id]].to_numpy(), columns=['sra']) surface = building.surface_by_id(surface_id)
surface.global_irradiance[cte.HOUR] = new_value monthly_result = MonthlyValues.get_total_month(result)
month_new_value = MonthlyValues().get_mean_values(new_value) yearly_result = [sum(result)]
surface.global_irradiance[cte.MONTH] = month_new_value _irradiance[cte.YEAR] = yearly_result
_irradiance[cte.MONTH] = monthly_result
_irradiance[cte.HOUR] = result
surface.global_irradiance = _irradiance
def test_insel_monthly_energy_balance_export(self): def test_insel_monthly_energy_balance_export(self):
""" """
@ -86,7 +71,7 @@ class TestExports(TestCase):
WeatherFactory('epw', city).enrich() WeatherFactory('epw', city).enrich()
for building in city.buildings: for building in city.buildings:
building.external_temperature[cte.MONTH] = MonthlyValues().\ building.external_temperature[cte.MONTH] = MonthlyValues().\
get_mean_values(building.external_temperature[cte.HOUR][['epw']]) get_mean_values(building.external_temperature[cte.HOUR])
self._set_irradiance_surfaces(city) self._set_irradiance_surfaces(city)
for building in city.buildings: for building in city.buildings:

View File

@ -4,12 +4,11 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
import pandas as pd
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
from hub.exports.exports_factory import ExportsFactory from hub.exports.exports_factory import ExportsFactory
@ -65,10 +64,10 @@ class TestResultsImport(TestCase):
ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich() ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich()
# Check that all the buildings have heating and cooling values # Check that all the buildings have heating and cooling values
for building in self._city.buildings: for building in self._city.buildings:
self.assertIsNotNone(building.heating_demand[cte.MONTH][cte.INSEL_MEB]) self.assertIsNotNone(building.heating_demand[cte.MONTH])
self.assertIsNotNone(building.cooling_demand[cte.MONTH][cte.INSEL_MEB]) self.assertIsNotNone(building.cooling_demand[cte.MONTH])
self.assertIsNotNone(building.heating_demand[cte.YEAR][cte.INSEL_MEB]) self.assertIsNotNone(building.heating_demand[cte.YEAR])
self.assertIsNotNone(building.cooling_demand[cte.YEAR][cte.INSEL_MEB]) self.assertIsNotNone(building.cooling_demand[cte.YEAR])
self.assertIsNotNone(building.lighting_peak_load[cte.MONTH]) self.assertIsNotNone(building.lighting_peak_load[cte.MONTH])
self.assertIsNotNone(building.lighting_peak_load[cte.YEAR]) self.assertIsNotNone(building.lighting_peak_load[cte.YEAR])
self.assertIsNotNone(building.appliances_peak_load[cte.MONTH]) self.assertIsNotNone(building.appliances_peak_load[cte.MONTH])
@ -89,7 +88,7 @@ class TestResultsImport(TestCase):
expected_monthly_list = [0 for _ in range(12)] expected_monthly_list = [0 for _ in range(12)]
expected_monthly_list[0] = 1000 expected_monthly_list[0] = 1000
for building in self._city.buildings: for building in self._city.buildings:
building.heating_demand[cte.HOUR] = pd.DataFrame(values, columns=['dummy']) building.heating_demand[cte.HOUR] = values
building.cooling_demand[cte.HOUR] = pd.DataFrame(values, columns=['dummy']) building.cooling_demand[cte.HOUR] = values
self.assertIsNotNone(building.heating_peak_load) self.assertIsNotNone(building.heating_peak_load)
self.assertIsNotNone(building.cooling_peak_load) self.assertIsNotNone(building.cooling_peak_load)