Merge branch 'main' into reviewing_units

# Conflicts:
#	hub/city_model_structure/building_demand/internal_zone.py
#	hub/city_model_structure/building_demand/thermal_zone.py
#	hub/exports/building_energy/insel/insel_monthly_energy_balance.py
This commit is contained in:
Pilar Monsalvete 2023-08-07 17:01:55 -04:00
commit 04ef636423
25 changed files with 855 additions and 840 deletions

View File

@ -41,7 +41,7 @@ class Building(CityObject):
self._floor_area = None self._floor_area = None
self._roof_type = None self._roof_type = None
self._internal_zones = None self._internal_zones = None
self._thermal_zones = None self._thermal_zones_from_internal_zones = None
self._shell = None self._shell = None
self._aliases = [] self._aliases = []
self._type = 'building' self._type = 'building'
@ -114,26 +114,24 @@ class Building(CityObject):
:return: [InternalZone] :return: [InternalZone]
""" """
if self._internal_zones is None: if self._internal_zones is None:
self._internal_zones = [InternalZone(self.surfaces, self.floor_area)] _number_of_storeys = self.eave_height * self.volume / self.floor_area
self._internal_zones = [InternalZone(self.surfaces, self.floor_area, self.volume, _number_of_storeys)]
return self._internal_zones return self._internal_zones
@property @property
def thermal_zones(self) -> Union[None, List[ThermalZone]]: def thermal_zones_from_internal_zones(self) -> Union[None, List[ThermalZone]]:
""" """
Get building thermal zones Get building thermal zones
For Lod up to 3, there can be more than one thermal zone per internal zone.
In LoD 4, there can be more than one internal zone, and therefore, only one thermal zone per internal zone
:return: [ThermalZone] :return: [ThermalZone]
""" """
if self._thermal_zones is None: if self._thermal_zones_from_internal_zones is None:
self._thermal_zones = [] self._thermal_zones_from_internal_zones = []
for internal_zone in self.internal_zones: for internal_zone in self.internal_zones:
if internal_zone.thermal_zones is None: if internal_zone.thermal_zones_from_internal_zones is None:
self._thermal_zones = None self._thermal_zones_from_internal_zones = None
return self._thermal_zones return self._thermal_zones_from_internal_zones
for thermal_zone in internal_zone.thermal_zones: self._thermal_zones_from_internal_zones.append(internal_zone.thermal_zones_from_internal_zones[0])
self._thermal_zones.append(thermal_zone) return self._thermal_zones_from_internal_zones
return self._thermal_zones
@property @property
def grounds(self) -> List[Surface]: def grounds(self) -> List[Surface]:
@ -261,6 +259,15 @@ class Building(CityObject):
Get building average storey height in meters Get building average storey height in meters
:return: None or float :return: None or float
""" """
if len(self.internal_zones) > 1:
self._average_storey_height = 0
for internal_zone in self.internal_zones:
self._average_storey_height += internal_zone.mean_height / len(self.internal_zones)
else:
if self.internal_zones[0].thermal_archetype is None:
self._average_storey_height = None
else:
self._average_storey_height = self.internal_zones[0].thermal_archetype.average_storey_height
return self._average_storey_height return self._average_storey_height
@average_storey_height.setter @average_storey_height.setter
@ -396,7 +403,8 @@ class Building(CityObject):
""" """
results = {} results = {}
peak_lighting = 0 peak_lighting = 0
for thermal_zone in self.thermal_zones: peak = 0
for thermal_zone in self.thermal_zones_from_internal_zones:
lighting = thermal_zone.lighting lighting = thermal_zone.lighting
for schedule in lighting.schedules: for schedule in lighting.schedules:
peak = max(schedule.values) * lighting.density * thermal_zone.total_floor_area peak = max(schedule.values) * lighting.density * thermal_zone.total_floor_area
@ -414,7 +422,8 @@ class Building(CityObject):
""" """
results = {} results = {}
peak_appliances = 0 peak_appliances = 0
for thermal_zone in self.thermal_zones: peak = 0
for thermal_zone in self.thermal_zones_from_internal_zones:
appliances = thermal_zone.appliances appliances = thermal_zone.appliances
for schedule in appliances.schedules: for schedule in appliances.schedules:
peak = max(schedule.values) * appliances.density * thermal_zone.total_floor_area peak = max(schedule.values) * appliances.density * thermal_zone.total_floor_area
@ -657,7 +666,7 @@ class Building(CityObject):
def _calculate_working_hours(self): def _calculate_working_hours(self):
_working_hours = {} _working_hours = {}
for internal_zone in self.internal_zones: for internal_zone in self.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
_working_hours_per_thermal_zone = {} _working_hours_per_thermal_zone = {}
for schedule in thermal_zone.thermal_control.hvac_availability_schedules: for schedule in thermal_zone.thermal_control.hvac_availability_schedules:
_working_hours_per_schedule = [0] * len(schedule.values) _working_hours_per_schedule = [0] * len(schedule.values)

View File

@ -0,0 +1,134 @@
"""
Construction thermal parameters
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from hub.city_model_structure.building_demand.layer import Layer
class Construction:
"""
Construction class
"""
def __init__(self):
self._type = None
self._layers = None
self._window_ratio = None
self._window_frame_ratio = None
self._window_g_value = None
self._window_overall_u_value = None
self._window_type = None
@property
def type(self):
"""
Get construction type
:return: str
"""
return self._type
@type.setter
def type(self, value):
"""
Set construction type
:param value: str
"""
self._type = value
@property
def layers(self) -> [Layer]:
"""
Get layers
:return: [layer]
"""
return self._layers
@layers.setter
def layers(self, value):
"""
Set layers
:param value: [layer]
"""
self._layers = value
@property
def window_ratio(self):
"""
Get window ratio
:return: dict
"""
return self._window_ratio
@window_ratio.setter
def window_ratio(self, value):
"""
Set window ratio
:param value: dict
"""
self._window_ratio = value
@property
def window_frame_ratio(self):
"""
Get window frame ratio
:return: float
"""
return self._window_frame_ratio
@window_frame_ratio.setter
def window_frame_ratio(self, value):
"""
Set window frame ratio
:param value: float
"""
self._window_frame_ratio = value
@property
def window_g_value(self):
"""
Get transparent surface g-value
:return: float
"""
return self._window_g_value
@window_g_value.setter
def window_g_value(self, value):
"""
Set transparent surface g-value
:param value: float
"""
self._window_g_value = value
@property
def window_overall_u_value(self):
"""
Get transparent surface overall U-value in W/m2K
:return: float
"""
return self._window_overall_u_value
@window_overall_u_value.setter
def window_overall_u_value(self, value):
"""
Set transparent surface overall U-value in W/m2K
:param value: float
"""
self._window_overall_u_value = value
@property
def window_type(self):
"""
Get transparent surface type, 'window' or 'skylight'
:return: str
"""
return self._window_type
@window_type.setter
def window_type(self, value):
"""
Set transparent surface type, 'window' or 'skylight'
:return: str
"""
self._window_type = value

View File

@ -8,7 +8,9 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
import uuid import uuid
from typing import Union, List from typing import Union, List
from hub.city_model_structure.building_demand.usage import Usage from hub.city_model_structure.building_demand.usage import Usage
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
from hub.city_model_structure.building_demand.thermal_boundary import ThermalBoundary
from hub.city_model_structure.attributes.polyhedron import Polyhedron from hub.city_model_structure.attributes.polyhedron import Polyhedron
@ -16,14 +18,16 @@ class InternalZone:
""" """
InternalZone class InternalZone class
""" """
def __init__(self, surfaces, area): def __init__(self, surfaces, area, volume, number_of_storeys=None):
self._surfaces = surfaces self._surfaces = surfaces
self._id = None self._id = None
self._geometry = None self._geometry = None
self._volume = None self._volume = volume
self._area = area self._area = area
self._thermal_zones = None self._number_of_storeys = number_of_storeys
self._thermal_zones_from_internal_zones = None
self._usages = None self._usages = None
self._thermal_archetype = None
@property @property
def id(self): def id(self):
@ -62,7 +66,7 @@ class InternalZone:
Get internal zone volume in cubic meters Get internal zone volume in cubic meters
:return: float :return: float
""" """
return self.geometry.volume return self._volume
@property @property
def area(self): def area(self):
@ -72,10 +76,18 @@ class InternalZone:
""" """
return self._area return self._area
@property
def mean_height(self):
"""
Get internal zone mean height in meters
:return: float
"""
return self.volume / self.area
@property @property
def usages(self) -> [Usage]: def usages(self) -> [Usage]:
""" """
Get internal zone usages Get usage archetypes
:return: [Usage] :return: [Usage]
""" """
return self._usages return self._usages
@ -83,23 +95,53 @@ class InternalZone:
@usages.setter @usages.setter
def usages(self, value): def usages(self, value):
""" """
Set internal zone usages Set usage archetypes
:param value: [Usage] :param value: [Usage]
""" """
self._usages = value self._usages = value
@property @property
def thermal_zones(self) -> Union[None, List[ThermalZone]]: def thermal_archetype(self) -> ThermalArchetype:
""" """
Get building thermal zones Get thermal archetype parameters
:return: ThermalArchetype
"""
return self._thermal_archetype
@thermal_archetype.setter
def thermal_archetype(self, value):
"""
Set thermal archetype parameters
:param value: ThermalArchetype
"""
self._thermal_archetype = value
@property
def thermal_zones_from_internal_zones(self) -> Union[None, List[ThermalZone]]:
"""
Get building thermal zones as one per internal zone
:return: [ThermalZone] :return: [ThermalZone]
""" """
return self._thermal_zones _thermal_boundaries = []
for surface in self.surfaces:
if surface.holes_polygons is None:
windows_areas = None
else:
windows_areas = []
for hole in surface.holes_polygons:
windows_areas.append(hole.area)
_thermal_boundary = ThermalBoundary(surface, surface.solid_polygon.area, windows_areas)
_thermal_boundaries.append(_thermal_boundary)
_thermal_zone = ThermalZone(_thermal_boundaries, self, self.volume, self.area, self._number_of_storeys)
for thermal_boundary in _thermal_zone.thermal_boundaries:
thermal_boundary.thermal_zones = [_thermal_zone]
self._thermal_zones_from_internal_zones = [_thermal_zone]
return self._thermal_zones_from_internal_zones
@thermal_zones.setter @thermal_zones_from_internal_zones.setter
def thermal_zones(self, value): def thermal_zones_from_internal_zones(self, value):
""" """
Set city object thermal zones Set city object thermal zones as one per internal zone
:param value: [ThermalZone] :param value: [ThermalZone]
""" """
self._thermal_zones = value self._thermal_zones_from_internal_zones = value

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 Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import uuid import uuid
from typing import Union from typing import Union
from hub.city_model_structure.building_demand.material import Material
class Layer: class Layer:
@ -14,9 +14,17 @@ class Layer:
Layer class Layer class
""" """
def __init__(self): def __init__(self):
self._material = None
self._thickness = None self._thickness = None
self._id = None self._id = None
self._name = None
self._conductivity = None
self._specific_heat = None
self._density = None
self._solar_absorptance = None
self._thermal_absorptance = None
self._visible_absorptance = None
self._no_mass = False
self._thermal_resistance = None
@property @property
def id(self): def id(self):
@ -28,22 +36,6 @@ class Layer:
self._id = uuid.uuid4() self._id = uuid.uuid4()
return self._id return self._id
@property
def material(self) -> Material:
"""
Get layer material
:return: Material
"""
return self._material
@material.setter
def material(self, value):
"""
Set layer material
:param value: Material
"""
self._material = value
@property @property
def thickness(self) -> Union[None, float]: def thickness(self) -> Union[None, float]:
""" """
@ -60,3 +52,155 @@ class Layer:
""" """
if value is not None: if value is not None:
self._thickness = float(value) self._thickness = float(value)
@property
def name(self):
"""
Get material name
:return: str
"""
return self._name
@name.setter
def name(self, value):
"""
Set material name
:param value: string
"""
self._name = str(value)
@property
def conductivity(self) -> Union[None, float]:
"""
Get material conductivity in W/mK
:return: None or float
"""
return self._conductivity
@conductivity.setter
def conductivity(self, value):
"""
Set material conductivity in W/mK
:param value: float
"""
if value is not None:
self._conductivity = float(value)
@property
def specific_heat(self) -> Union[None, float]:
"""
Get material conductivity in J/kgK
:return: None or float
"""
return self._specific_heat
@specific_heat.setter
def specific_heat(self, value):
"""
Get material conductivity in J/kgK
:param value: float
"""
if value is not None:
self._specific_heat = float(value)
@property
def density(self) -> Union[None, float]:
"""
Get material density in kg/m3
:return: None or float
"""
return self._density
@density.setter
def density(self, value):
"""
Set material density
:param value: float
"""
if value is not None:
self._density = float(value)
@property
def solar_absorptance(self) -> Union[None, float]:
"""
Get material solar absorptance
:return: None or float
"""
return self._solar_absorptance
@solar_absorptance.setter
def solar_absorptance(self, value):
"""
Set material solar absorptance
:param value: float
"""
if value is not None:
self._solar_absorptance = float(value)
@property
def thermal_absorptance(self) -> Union[None, float]:
"""
Get material thermal absorptance
:return: None or float
"""
return self._thermal_absorptance
@thermal_absorptance.setter
def thermal_absorptance(self, value):
"""
Set material thermal absorptance
:param value: float
"""
if value is not None:
self._thermal_absorptance = float(value)
@property
def visible_absorptance(self) -> Union[None, float]:
"""
Get material visible absorptance
:return: None or float
"""
return self._visible_absorptance
@visible_absorptance.setter
def visible_absorptance(self, value):
"""
Set material visible absorptance
:param value: float
"""
if value is not None:
self._visible_absorptance = float(value)
@property
def no_mass(self) -> Union[None, bool]:
"""
Get material no mass flag
:return: None or Boolean
"""
return self._no_mass
@no_mass.setter
def no_mass(self, value):
"""
Set material no mass flag
:param value: Boolean
"""
if value is not None:
self._no_mass = value
@property
def thermal_resistance(self) -> Union[None, float]:
"""
Get material thermal resistance in m2K/W
:return: None or float
"""
return self._thermal_resistance
@thermal_resistance.setter
def thermal_resistance(self, value):
"""
Set material thermal resistance in m2K/W
:param value: float
"""
if value is not None:
self._thermal_resistance = float(value)

View File

@ -1,193 +0,0 @@
"""
Material module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from typing import Union
class Material:
"""
Material class
"""
def __init__(self):
self._id = None
self._name = None
self._conductivity = None
self._specific_heat = None
self._density = None
self._solar_absorptance = None
self._thermal_absorptance = None
self._visible_absorptance = None
self._no_mass = False
self._thermal_resistance = None
@property
def id(self):
"""
Get material id
:return: str
"""
return self._id
@id.setter
def id(self, value):
"""
Set material id
:param value: str
"""
self._id = value
@property
def name(self):
"""
Get material name
:return: str
"""
return self._name
@name.setter
def name(self, value):
"""
Set material name
:param value: string
"""
self._name = str(value)
@property
def conductivity(self) -> Union[None, float]:
"""
Get material conductivity in W/mK
:return: None or float
"""
return self._conductivity
@conductivity.setter
def conductivity(self, value):
"""
Set material conductivity in W/mK
:param value: float
"""
if value is not None:
self._conductivity = float(value)
@property
def specific_heat(self) -> Union[None, float]:
"""
Get material conductivity in J/kgK
:return: None or float
"""
return self._specific_heat
@specific_heat.setter
def specific_heat(self, value):
"""
Get material conductivity in J/kgK
:param value: float
"""
if value is not None:
self._specific_heat = float(value)
@property
def density(self) -> Union[None, float]:
"""
Get material density in kg/m3
:return: None or float
"""
return self._density
@density.setter
def density(self, value):
"""
Set material density
:param value: float
"""
if value is not None:
self._density = float(value)
@property
def solar_absorptance(self) -> Union[None, float]:
"""
Get material solar absorptance
:return: None or float
"""
return self._solar_absorptance
@solar_absorptance.setter
def solar_absorptance(self, value):
"""
Set material solar absorptance
:param value: float
"""
if value is not None:
self._solar_absorptance = float(value)
@property
def thermal_absorptance(self) -> Union[None, float]:
"""
Get material thermal absorptance
:return: None or float
"""
return self._thermal_absorptance
@thermal_absorptance.setter
def thermal_absorptance(self, value):
"""
Set material thermal absorptance
:param value: float
"""
if value is not None:
self._thermal_absorptance = float(value)
@property
def visible_absorptance(self) -> Union[None, float]:
"""
Get material visible absorptance
:return: None or float
"""
return self._visible_absorptance
@visible_absorptance.setter
def visible_absorptance(self, value):
"""
Set material visible absorptance
:param value: float
"""
if value is not None:
self._visible_absorptance = float(value)
@property
def no_mass(self) -> Union[None, bool]:
"""
Get material no mass flag
:return: None or Boolean
"""
return self._no_mass
@no_mass.setter
def no_mass(self, value):
"""
Set material no mass flag
:param value: Boolean
"""
if value is not None:
self._no_mass = value
@property
def thermal_resistance(self) -> Union[None, float]:
"""
Get material thermal resistance in m2K/W
:return: None or float
"""
return self._thermal_resistance
@thermal_resistance.setter
def thermal_resistance(self, value):
"""
Set material thermal resistance in m2K/W
:param value: float
"""
if value is not None:
self._thermal_resistance = float(value)

View File

@ -0,0 +1,134 @@
"""
Thermal archetype 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
"""
from hub.city_model_structure.building_demand.construction import Construction
class ThermalArchetype:
"""
ThermalArchetype class
"""
def __init__(self):
self._constructions = None
self._average_storey_height = None
self._thermal_capacity = None
self._extra_loses_due_to_thermal_bridges = None
self._indirect_heated_ratio = None
self._infiltration_rate_for_ventilation_system_off = None
self._infiltration_rate_for_ventilation_system_on = None
@property
def constructions(self) -> [Construction]:
"""
Get archetype constructions
:return: [Construction]
"""
return self._constructions
@constructions.setter
def constructions(self, value):
"""
Set archetype constructions
:param value: [Construction]
"""
self._constructions = value
@property
def average_storey_height(self):
"""
Get average storey height in m
:return: float
"""
return self._average_storey_height
@average_storey_height.setter
def average_storey_height(self, value):
"""
Set average storey height in m
:param value: float
"""
self._average_storey_height = value
@property
def thermal_capacity(self):
"""
Get thermal capacity in J/m3K
:return: float
"""
return self._thermal_capacity
@thermal_capacity.setter
def thermal_capacity(self, value):
"""
Set thermal capacity in J/m3K
:param value: float
"""
self._thermal_capacity = value
@property
def extra_loses_due_to_thermal_bridges(self):
"""
Get extra loses due to thermal bridges in W/m2K
:return: float
"""
return self._extra_loses_due_to_thermal_bridges
@extra_loses_due_to_thermal_bridges.setter
def extra_loses_due_to_thermal_bridges(self, value):
"""
Set extra loses due to thermal bridges in W/m2K
:param value: float
"""
self._extra_loses_due_to_thermal_bridges = value
@property
def indirect_heated_ratio(self):
"""
Get indirect heated area ratio
:return: float
"""
return self._indirect_heated_ratio
@indirect_heated_ratio.setter
def indirect_heated_ratio(self, value):
"""
Set indirect heated area ratio
:param value: float
"""
self._indirect_heated_ratio = value
@property
def infiltration_rate_for_ventilation_system_off(self):
"""
Get infiltration rate for ventilation system off in ACH
:return: float
"""
return self._infiltration_rate_for_ventilation_system_off
@infiltration_rate_for_ventilation_system_off.setter
def infiltration_rate_for_ventilation_system_off(self, value):
"""
Set infiltration rate for ventilation system off in ACH
:param value: float
"""
self._infiltration_rate_for_ventilation_system_off = value
@property
def infiltration_rate_for_ventilation_system_on(self):
"""
Get infiltration rate for ventilation system on in ACH
:return: float
"""
return self._infiltration_rate_for_ventilation_system_on
@infiltration_rate_for_ventilation_system_on.setter
def infiltration_rate_for_ventilation_system_on(self, value):
"""
Set infiltration rate for ventilation system on in ACH
:param value: float
"""
self._infiltration_rate_for_ventilation_system_on = value

View File

@ -7,7 +7,9 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
""" """
import uuid import uuid
import math
from typing import List, Union, TypeVar from typing import List, Union, TypeVar
import logging
from hub.helpers.configuration_helper import ConfigurationHelper as ch from hub.helpers.configuration_helper import ConfigurationHelper as ch
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.city_model_structure.building_demand.layer import Layer from hub.city_model_structure.building_demand.layer import Layer
@ -35,7 +37,8 @@ class ThermalBoundary:
self._construction_name = None self._construction_name = None
self._thickness = None self._thickness = None
self._internal_surface = None self._internal_surface = None
self._window_ratio = None self._external_surface = None
self._window_ratio = 0
self._window_ratio_to_be_calculated = False self._window_ratio_to_be_calculated = False
if self._windows_areas is not None: if self._windows_areas is not None:
self._window_ratio_to_be_calculated = True self._window_ratio_to_be_calculated = True
@ -53,7 +56,7 @@ class ThermalBoundary:
@property @property
def parent_surface(self) -> Surface: def parent_surface(self) -> Surface:
""" """
Get the surface that belongs to the thermal boundary Get the surface that belongs to the thermal boundary, considered the external surface of that boundary
:return: Surface :return: Surface
""" """
return self._parent_surface return self._parent_surface
@ -92,7 +95,7 @@ class ThermalBoundary:
self._thickness = 0.0 self._thickness = 0.0
if self.layers is not None: if self.layers is not None:
for layer in self.layers: for layer in self.layers:
if not layer.material.no_mass: if not layer.no_mass:
self._thickness += layer.thickness self._thickness += layer.thickness
return self._thickness return self._thickness
@ -148,24 +151,21 @@ class ThermalBoundary:
else: else:
_area = self.opaque_area * self.window_ratio / (1-self.window_ratio) _area = self.opaque_area * self.window_ratio / (1-self.window_ratio)
_thermal_opening.area = _area _thermal_opening.area = _area
self._thermal_openings = [_thermal_opening]
for thermal_opening in self._thermal_openings:
thermal_opening.g_value = self._construction_archetype.window_g_value
thermal_opening.overall_u_value = self._construction_archetype.window_overall_u_value
thermal_opening.frame_ratio = self._construction_archetype.window_frame_ratio
thermal_opening.construction_name = self._construction_archetype.window_type
return self._thermal_openings return self._thermal_openings
@property @property
def construction_name(self) -> Union[None, str]: def _construction_archetype(self):
""" construction_archetypes = self.thermal_zones[0].parent_internal_zone.thermal_archetype.constructions
Get construction name for construction_archetype in construction_archetypes:
:return: None or str if str(self.type) == str(construction_archetype.type):
""" return construction_archetype
return self._construction_name return None
@construction_name.setter
def construction_name(self, value):
"""
Set construction name
:param value: str
"""
if value is not None:
self._construction_name = str(value)
@property @property
def layers(self) -> List[Layer]: def layers(self) -> List[Layer]:
@ -173,16 +173,13 @@ class ThermalBoundary:
Get thermal boundary layers Get thermal boundary layers
:return: [Layers] :return: [Layers]
""" """
if self._construction_archetype is not None:
self._layers = self._construction_archetype.layers
else:
logging.error('Layers not defined\n')
raise ValueError('Layers not defined')
return self._layers return self._layers
@layers.setter
def layers(self, value):
"""
Set thermal boundary layers
:param value: [Layer]
"""
self._layers = value
@property @property
def type(self): def type(self):
""" """
@ -209,18 +206,23 @@ class ThermalBoundary:
for window_area in self.windows_areas: for window_area in self.windows_areas:
total_window_area += window_area total_window_area += window_area
self._window_ratio = total_window_area / (self.opaque_area + total_window_area) self._window_ratio = total_window_area / (self.opaque_area + total_window_area)
else:
if self.type in (cte.WALL, cte.ROOF):
if -math.sqrt(2) / 2 < math.sin(self.parent_surface.azimuth) < math.sqrt(2) / 2:
if 0 < math.cos(self.parent_surface.azimuth):
self._window_ratio = \
float(self._construction_archetype.window_ratio['north']) / 100
else:
self._window_ratio = \
float(self._construction_archetype.window_ratio['south']) / 100
elif math.sqrt(2) / 2 <= math.sin(self._parent_surface.azimuth):
self._window_ratio = \
float(self._construction_archetype.window_ratio['east']) / 100
else:
self._window_ratio = \
float(self._construction_archetype.window_ratio['west']) / 100
return self._window_ratio return self._window_ratio
@window_ratio.setter
def window_ratio(self, value):
"""
Set thermal boundary window ratio
:param value: str
"""
if self._window_ratio_to_be_calculated:
raise ValueError('Window ratio cannot be assigned when the windows are defined in the geometry.')
self._window_ratio = float(value)
@property @property
def windows_areas(self) -> [float]: def windows_areas(self) -> [float]:
""" """
@ -245,10 +247,10 @@ class ThermalBoundary:
r_value = 1.0/h_i + 1.0/h_e r_value = 1.0/h_i + 1.0/h_e
try: try:
for layer in self.layers: for layer in self.layers:
if layer.material.no_mass: if layer.no_mass:
r_value += float(layer.material.thermal_resistance) r_value += float(layer.thermal_resistance)
else: else:
r_value += float(layer.thickness) / float(layer.material.conductivity) r_value += float(layer.thickness) / float(layer.conductivity)
self._u_value = 1.0/r_value self._u_value = 1.0/r_value
except TypeError: except TypeError:
raise TypeError('Constructions layers are not initialized') from TypeError raise TypeError('Constructions layers are not initialized') from TypeError
@ -305,4 +307,18 @@ class ThermalBoundary:
""" """
if self._internal_surface is None: if self._internal_surface is None:
self._internal_surface = self.parent_surface.inverse self._internal_surface = self.parent_surface.inverse
# The agreement is that the layers are defined from outside to inside
internal_layer = self.layers[len(self.layers) - 1]
self._internal_surface.short_wave_reflectance = 1 - internal_layer.solar_absorptance
self._internal_surface.long_wave_emittance = 1 - internal_layer.solar_absorptance
return self._internal_surface return self._internal_surface
@property
def external_surface(self) -> Surface:
if self._external_surface is None:
# The agreement is that the layers are defined from outside to inside
self._external_surface = self.parent_surface
self._external_surface.short_wave_reflectance = 1 - self.layers[0].solar_absorptance
self._external_surface.long_wave_emittance = 1 - self.layers[0].solar_absorptance
return self._external_surface

View File

@ -29,7 +29,12 @@ class ThermalZone:
ThermalZone class ThermalZone class
""" """
def __init__(self, thermal_boundaries, parent_internal_zone, volume, footprint_area, usage_name=None): def __init__(self, thermal_boundaries,
parent_internal_zone,
volume,
footprint_area,
number_of_storeys,
usage_name=None):
self._id = None self._id = None
self._parent_internal_zone = parent_internal_zone self._parent_internal_zone = parent_internal_zone
self._footprint_area = footprint_area self._footprint_area = footprint_area
@ -43,6 +48,7 @@ class ThermalZone:
self._ordinate_number = None self._ordinate_number = None
self._view_factors_matrix = None self._view_factors_matrix = None
self._total_floor_area = None self._total_floor_area = None
self._number_of_storeys = number_of_storeys
self._usage_name = usage_name self._usage_name = usage_name
self._usage_from_parent = False self._usage_from_parent = False
if usage_name is None: if usage_name is None:
@ -58,6 +64,14 @@ class ThermalZone:
self._domestic_hot_water = None self._domestic_hot_water = None
self._usages = None self._usages = None
@property
def parent_internal_zone(self) -> InternalZone:
"""
Get the internal zone to which this thermal zone belongs
:return: InternalZone
"""
return self._parent_internal_zone
@property @property
def usages(self): def usages(self):
""" """
@ -113,83 +127,45 @@ class ThermalZone:
Get thermal zone additional thermal bridge u value per footprint area W/m2K Get thermal zone additional thermal bridge u value per footprint area W/m2K
:return: None or float :return: None or float
""" """
self._additional_thermal_bridge_u_value = self.parent_internal_zone.thermal_archetype.extra_loses_due_to_thermal_bridges
return self._additional_thermal_bridge_u_value return self._additional_thermal_bridge_u_value
@additional_thermal_bridge_u_value.setter
def additional_thermal_bridge_u_value(self, value):
"""
Set thermal zone additional thermal bridge u value per footprint area W/m2K
:param value: float
"""
if value is not None:
self._additional_thermal_bridge_u_value = float(value)
@property @property
def effective_thermal_capacity(self) -> Union[None, float]: def effective_thermal_capacity(self) -> Union[None, float]:
""" """
Get thermal zone effective thermal capacity in J/m3K Get thermal zone effective thermal capacity in J/m3K
:return: None or float :return: None or float
""" """
self._effective_thermal_capacity = self._parent_internal_zone.thermal_archetype.thermal_capacity
return self._effective_thermal_capacity return self._effective_thermal_capacity
@effective_thermal_capacity.setter
def effective_thermal_capacity(self, value):
"""
Set thermal zone effective thermal capacity in J/m3K
:param value: float
"""
if value is not None:
self._effective_thermal_capacity = float(value)
@property @property
def indirectly_heated_area_ratio(self) -> Union[None, float]: def indirectly_heated_area_ratio(self) -> Union[None, float]:
""" """
Get thermal zone indirectly heated area ratio Get thermal zone indirectly heated area ratio
:return: None or float :return: None or float
""" """
self._indirectly_heated_area_ratio = self._parent_internal_zone.thermal_archetype.indirect_heated_ratio
return self._indirectly_heated_area_ratio return self._indirectly_heated_area_ratio
@indirectly_heated_area_ratio.setter
def indirectly_heated_area_ratio(self, value):
"""
Set thermal zone indirectly heated area ratio
:param value: float
"""
if value is not None:
self._indirectly_heated_area_ratio = float(value)
@property @property
def infiltration_rate_system_on(self): def infiltration_rate_system_on(self):
""" """
Get thermal zone infiltration rate system on in air changes per second (1/s) Get thermal zone infiltration rate system on in air changes per second (1/s)
:return: None or float :return: None or float
""" """
self._infiltration_rate_system_on = self._parent_internal_zone.thermal_archetype.infiltration_rate_for_ventilation_system_on
return self._infiltration_rate_system_on return self._infiltration_rate_system_on
@infiltration_rate_system_on.setter
def infiltration_rate_system_on(self, value):
"""
Set thermal zone infiltration rate system on in air changes per second (1/s)
:param value: float
"""
self._infiltration_rate_system_on = value
@property @property
def infiltration_rate_system_off(self): def infiltration_rate_system_off(self):
""" """
Get thermal zone infiltration rate system off in air changes per second (1/s) Get thermal zone infiltration rate system off in air changes per second (1/s)
:return: None or float :return: None or float
""" """
self._infiltration_rate_system_off = self._parent_internal_zone.thermal_archetype.infiltration_rate_for_ventilation_system_off
return self._infiltration_rate_system_off return self._infiltration_rate_system_off
@infiltration_rate_system_off.setter
def infiltration_rate_system_off(self, value):
"""
Set thermal zone infiltration rate system on in air changes per second (1/s)
:param value: float
"""
self._infiltration_rate_system_off = value
@property @property
def volume(self): def volume(self):
""" """
@ -221,15 +197,43 @@ class ThermalZone:
Get thermal zone view factors matrix Get thermal zone view factors matrix
:return: [[float]] :return: [[float]]
""" """
return self._view_factors_matrix # todo: review method if windows not in window_ratio but in geometry
if self._view_factors_matrix is None:
total_area = 0
for thermal_boundary in self.thermal_boundaries:
total_area += thermal_boundary.opaque_area
for thermal_opening in thermal_boundary.thermal_openings:
total_area += thermal_opening.area
@view_factors_matrix.setter view_factors_matrix = []
def view_factors_matrix(self, value): for thermal_boundary_1 in self.thermal_boundaries:
""" values = []
Set thermal zone view factors matrix for thermal_boundary_2 in self.thermal_boundaries:
:param value: [[float]] value = 0
""" if thermal_boundary_1.id != thermal_boundary_2.id:
self._view_factors_matrix = value value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
for thermal_boundary in self.thermal_boundaries:
for thermal_opening in thermal_boundary.thermal_openings:
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
view_factors_matrix.append(values)
for thermal_boundary_1 in self.thermal_boundaries:
values = []
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
for thermal_boundary_2 in self.thermal_boundaries:
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
values.append(value)
for thermal_boundary in self.thermal_boundaries:
for thermal_opening_2 in thermal_boundary.thermal_openings:
value = 0
if thermal_opening_1.id != thermal_opening_2.id:
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
values.append(value)
view_factors_matrix.append(values)
self._view_factors_matrix = view_factors_matrix
return self._view_factors_matrix
@property @property
def usage_name(self) -> Union[None, str]: def usage_name(self) -> Union[None, str]:
@ -656,12 +660,5 @@ class ThermalZone:
Get the total floor area of this thermal zone in m2 Get the total floor area of this thermal zone in m2
:return: float :return: float
""" """
self._total_floor_area = self.footprint_area * self._number_of_storeys
return self._total_floor_area return self._total_floor_area
@total_floor_area.setter
def total_floor_area(self, value):
"""
Set the total floor area of this thermal zone in m2
:param value: float
"""
self._total_floor_area = value

View File

@ -335,7 +335,7 @@ class EnergyAde:
def _thermal_zones(self, building, city): def _thermal_zones(self, building, city):
thermal_zones = [] thermal_zones = []
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for index, thermal_zone in enumerate(internal_zone.thermal_zones): for index, thermal_zone in enumerate(internal_zone.thermal_zones_from_internal_zones):
usages = [] usages = []
for usage in internal_zone.usages: for usage in internal_zone.usages:
usages.append({'@xlink:href': f'#GML_{usage.id}'}) usages.append({'@xlink:href': f'#GML_{usage.id}'})

View File

@ -512,9 +512,9 @@ class Idf:
for building in self._city.buildings: for building in self._city.buildings:
print('building name', building.name) print('building name', building.name)
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
if internal_zone.thermal_zones is None: if internal_zone.thermal_zones_from_internal_zones is None:
continue continue
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self._add_construction(thermal_boundary) self._add_construction(thermal_boundary)
if thermal_boundary.parent_surface.vegetation is not None: if thermal_boundary.parent_surface.vegetation is not None:
@ -558,7 +558,7 @@ class Idf:
self._add_dhw(thermal_zone, building.name) self._add_dhw(thermal_zone, building.name)
if self._export_type == "Surfaces": if self._export_type == "Surfaces":
if building.name in self._target_buildings or building.name in self._adjacent_buildings: if building.name in self._target_buildings or building.name in self._adjacent_buildings:
if building.internal_zones[0].thermal_zones is not None: if building.internal_zones[0].thermal_zones_from_internal_zones is not None:
self._add_surfaces(building, building.name) self._add_surfaces(building, building.name)
else: else:
self._add_pure_geometry(building, building.name) self._add_pure_geometry(building, building.name)
@ -613,7 +613,7 @@ class Idf:
num_stories=int(building.storeys_above_ground)) num_stories=int(building.storeys_above_ground))
for surface in self._idf.idfobjects[self._SURFACE]: for surface in self._idf.idfobjects[self._SURFACE]:
for thermal_zone in building.thermal_zones: for thermal_zone in building.thermal_zones_from_internal_zones:
for boundary in thermal_zone.thermal_boundaries: for boundary in thermal_zone.thermal_boundaries:
if surface.Type == self.idf_surfaces[boundary.surface.type]: if surface.Type == self.idf_surfaces[boundary.surface.type]:
surface.Construction_Name = boundary.construction_name surface.Construction_Name = boundary.construction_name
@ -666,7 +666,7 @@ class Idf:
idf_surface.setcoords(coordinates) idf_surface.setcoords(coordinates)
if self._lod >= 3: if self._lod >= 3:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
for boundary in thermal_zone.thermal_boundaries: for boundary in thermal_zone.thermal_boundaries:
self._add_windows_by_vertices(boundary) self._add_windows_by_vertices(boundary)
else: else:
@ -676,7 +676,7 @@ class Idf:
def _add_surfaces(self, building, zone_name): def _add_surfaces(self, building, zone_name):
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
for boundary in thermal_zone.thermal_boundaries: for boundary in thermal_zone.thermal_boundaries:
idf_surface_type = self.idf_surfaces[boundary.parent_surface.type] idf_surface_type = self.idf_surfaces[boundary.parent_surface.type]
outside_boundary_condition = 'Outdoors' outside_boundary_condition = 'Outdoors'
@ -713,7 +713,7 @@ class Idf:
if self._lod >= 3: if self._lod >= 3:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
for boundary in thermal_zone.thermal_boundaries: for boundary in thermal_zone.thermal_boundaries:
self._add_windows_by_vertices(boundary) self._add_windows_by_vertices(boundary)
else: else:

View File

@ -42,7 +42,7 @@ class InselMonthlyEnergyBalance:
self._insel_files_paths.append(building.name + '.insel') self._insel_files_paths.append(building.name + '.insel')
file_name_out = building.name + '.out' file_name_out = building.name + '.out'
output_path = Path(self._path / file_name_out).resolve() output_path = Path(self._path / file_name_out).resolve()
if building.thermal_zones is None: if building.thermal_zones_from_internal_zones is None:
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(
@ -124,7 +124,7 @@ class InselMonthlyEnergyBalance:
# todo: this method and the insel model have to be reviewed for more than one internal zone # todo: this method and the insel model have to be reviewed for more than one internal zone
internal_zone = building.internal_zones[0] internal_zone = building.internal_zones[0]
thermal_zone = internal_zone.thermal_zones[0] thermal_zone = internal_zone.thermal_zones_from_internal_zones[0]
parameters.append(f'{thermal_zone.indirectly_heated_area_ratio} % BP(6) Indirectly heated area ratio') parameters.append(f'{thermal_zone.indirectly_heated_area_ratio} % BP(6) Indirectly heated area ratio')
parameters.append(f'{thermal_zone.effective_thermal_capacity / 3600 / building.average_storey_height}' parameters.append(f'{thermal_zone.effective_thermal_capacity / 3600 / building.average_storey_height}'
f' % BP(7) Effective heat capacity (Wh/m2K)') f' % BP(7) Effective heat capacity (Wh/m2K)')
@ -137,7 +137,7 @@ class InselMonthlyEnergyBalance:
for i, usage in enumerate(internal_zone.usages): for i, usage in enumerate(internal_zone.usages):
percentage_usage = usage.percentage percentage_usage = usage.percentage
parameters.append(f'{internal_zone.thermal_zones[0].total_floor_area * percentage_usage} ' parameters.append(f'{internal_zone.thermal_zones_from_internal_zones[0].total_floor_area * percentage_usage} '
f'% BP(11) #1 Area of zone {i + 1} (m2)') f'% BP(11) #1 Area of zone {i + 1} (m2)')
total_internal_gain = 0 total_internal_gain = 0
for i_gain in usage.internal_gains: for i_gain in usage.internal_gains:
@ -167,11 +167,11 @@ class InselMonthlyEnergyBalance:
infiltration_day = 0 infiltration_day = 0
for value in schedule.values: for value in schedule.values:
if value == 0: if value == 0:
infiltration_day += internal_zone.thermal_zones[0].infiltration_rate_system_off / 24 * cte.HOUR_TO_SECONDS infiltration_day += internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_system_off / 24 * cte.HOUR_TO_SECONDS
ventilation_day += 0 ventilation_day += 0
else: else:
ventilation_value = usage.mechanical_air_change * value * cte.HOUR_TO_SECONDS ventilation_value = usage.mechanical_air_change * value * cte.HOUR_TO_SECONDS
infiltration_value = internal_zone.thermal_zones[0].infiltration_rate_system_off * value * cte.HOUR_TO_SECONDS infiltration_value = internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_system_off * value * cte.HOUR_TO_SECONDS
if ventilation_value >= infiltration_value: if ventilation_value >= infiltration_value:
ventilation_day += ventilation_value / 24 ventilation_day += ventilation_value / 24
infiltration_day += 0 infiltration_day += 0

View File

@ -64,7 +64,7 @@ class LoadsCalculation:
""" """
heating_load_transmitted = 0 heating_load_transmitted = 0
for internal_zone in self._building.internal_zones: for internal_zone in self._building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
heating_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature, heating_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
ground_temperature) ground_temperature)
@ -77,7 +77,7 @@ class LoadsCalculation:
""" """
cooling_load_transmitted = 0 cooling_load_transmitted = 0
for internal_zone in self._building.internal_zones: for internal_zone in self._building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
cooling_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature, cooling_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
ground_temperature) ground_temperature)
@ -90,7 +90,7 @@ class LoadsCalculation:
""" """
heating_ventilation_load = 0 heating_ventilation_load = 0
for internal_zone in self._building.internal_zones: for internal_zone in self._building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
heating_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature) heating_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
return heating_ventilation_load return heating_ventilation_load
@ -102,7 +102,7 @@ class LoadsCalculation:
""" """
cooling_ventilation_load = 0 cooling_ventilation_load = 0
for internal_zone in self._building.internal_zones: for internal_zone in self._building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
cooling_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature) cooling_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
return cooling_ventilation_load return cooling_ventilation_load
@ -116,7 +116,7 @@ class LoadsCalculation:
cooling_load_lighting = 0 cooling_load_lighting = 0
cooling_load_equipment_sensible = 0 cooling_load_equipment_sensible = 0
for internal_zone in self._building.internal_zones: for internal_zone in self._building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
cooling_load_occupancy_sensible += (thermal_zone.occupancy.sensible_convective_internal_gain cooling_load_occupancy_sensible += (thermal_zone.occupancy.sensible_convective_internal_gain
+ thermal_zone.occupancy.sensible_radiative_internal_gain) \ + thermal_zone.occupancy.sensible_radiative_internal_gain) \
* thermal_zone.footprint_area * thermal_zone.footprint_area
@ -138,7 +138,7 @@ class LoadsCalculation:
""" """
cooling_load_radiation = 0 cooling_load_radiation = 0
for internal_zone in self._building.internal_zones: for internal_zone in self._building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_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][hour] * cte.WATTS_HOUR_TO_JULES radiation = thermal_boundary.parent_surface.global_irradiance[cte.HOUR][hour] * cte.WATTS_HOUR_TO_JULES

View File

@ -0,0 +1,41 @@
"""
Thermal zones creation module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
class ThermalZonesCreation:
"""
PeakLoads class
"""
def __init__(self, building=None):
self._building = building
# # The agreement is that the layers are defined from outside to inside
# external_layer = catalog_construction.layers[0]
# external_surface = thermal_boundary.parent_surface
# external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
# external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
# internal_layer = catalog_construction.layers[len(catalog_construction.layers) - 1]
# internal_surface = thermal_boundary.internal_surface
# internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
# internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
@property
def thermal_zones_from_storeys(self):
"""
Create and get thermal zones as 1 per each storey
:return: [ThermalZone]
"""
raise NotImplementedError
@staticmethod
def _create_storeys(building, archetype, divide_in_storeys):
building.average_storey_height = archetype.average_storey_height
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
divide_in_storeys=divide_in_storeys).thermal_zones
building.internal_zones[0].thermal_zones_from_internal_zones = thermal_zones

View File

@ -6,15 +6,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import logging import logging
import math
import hub.helpers.constants as cte
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
from hub.city_model_structure.building_demand.construction import Construction
from hub.city_model_structure.building_demand.layer import Layer from hub.city_model_structure.building_demand.layer import Layer
from hub.city_model_structure.building_demand.material import Material
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction.helpers.construction_helper import ConstructionHelper from hub.imports.construction.helpers.construction_helper import ConstructionHelper
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
class EilatPhysicsParameters: class EilatPhysicsParameters:
@ -35,7 +33,7 @@ class EilatPhysicsParameters:
eilat_catalog = ConstructionCatalogFactory('eilat').catalog eilat_catalog = ConstructionCatalogFactory('eilat').catalog
for building in city.buildings: for building in city.buildings:
if building.function not in Dictionaries().hub_function_to_eilat_construction_function.keys(): if building.function not in Dictionaries().hub_function_to_eilat_construction_function.keys():
logging.error(f'Building %s has an unknown building function %s', building.name, building.function ) logging.error(f'Building %s has an unknown building function %s', building.name, building.function)
continue continue
function = Dictionaries().hub_function_to_eilat_construction_function[building.function] function = Dictionaries().hub_function_to_eilat_construction_function[building.function]
try: try:
@ -46,29 +44,10 @@ class EilatPhysicsParameters:
f'[%s], building year of construction: %s and climate zone %s', building.name, function, f'[%s], building year of construction: %s and climate zone %s', building.name, function,
building.function, building.year_of_construction, self._climate_zone) building.function, building.year_of_construction, self._climate_zone)
continue continue
thermal_archetype = ThermalArchetype()
# if building has no thermal zones defined from geometry, and the building will be divided in storeys, self._assign_values(thermal_archetype, archetype)
# one thermal zone per storey is assigned
if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype, self._divide_in_storeys)
if self._divide_in_storeys:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
thermal_zone.total_floor_area = thermal_zone.footprint_area
else:
number_of_storeys = int(building.eave_height / building.average_storey_height)
thermal_zone = building.internal_zones[0].thermal_zones[0]
thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys
else:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
thermal_zone.total_floor_area = thermal_zone.footprint_area
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._assign_values(internal_zone.thermal_zones, archetype) internal_zone.thermal_archetype = thermal_archetype
for thermal_zone in internal_zone.thermal_zones:
self._calculate_view_factors(thermal_zone)
@staticmethod @staticmethod
def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone): def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone):
@ -81,133 +60,51 @@ class EilatPhysicsParameters:
raise KeyError('archetype not found') raise KeyError('archetype not found')
@staticmethod @staticmethod
def _search_construction_in_archetype(archetype, construction_type): def _assign_values(thermal_archetype, catalog_archetype):
construction_archetypes = archetype.constructions thermal_archetype.average_storey_height = catalog_archetype.average_storey_height
for construction_archetype in construction_archetypes: thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
if str(construction_type) == str(construction_archetype.type): thermal_archetype.indirect_heated_ratio = 0
return construction_archetype thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
return None thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
effective_thermal_capacity = 0
_constructions = []
for catalog_construction in catalog_archetype.constructions:
construction = Construction()
construction.type = catalog_construction.type
if catalog_construction.window_ratio is not None:
for _orientation in catalog_construction.window_ratio:
if catalog_construction.window_ratio[_orientation] is None:
catalog_construction.window_ratio[_orientation] = 0
construction.window_ratio = catalog_construction.window_ratio
_layers = []
total_thickness = 0
for layer_archetype in catalog_construction.layers:
layer = Layer()
layer.thickness = layer_archetype.thickness
total_thickness += layer_archetype.thickness
archetype_material = layer_archetype.material
layer.name = archetype_material.name
layer.no_mass = archetype_material.no_mass
if archetype_material.no_mass:
layer.thermal_resistance = archetype_material.thermal_resistance
else:
layer.density = archetype_material.density
layer.conductivity = archetype_material.conductivity
layer.specific_heat = archetype_material.specific_heat
effective_thermal_capacity += archetype_material.specific_heat \
* archetype_material.density * layer_archetype.thickness
layer.solar_absorptance = archetype_material.solar_absorptance
layer.thermal_absorptance = archetype_material.thermal_absorptance
layer.visible_absorptance = archetype_material.visible_absorptance
_layers.append(layer)
construction.layers = _layers
effective_thermal_capacity = effective_thermal_capacity / total_thickness
def _assign_values(self, thermal_zones, archetype): if catalog_construction.window is not None:
for thermal_zone in thermal_zones: window_archetype = catalog_construction.window
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges construction.window_frame_ratio = window_archetype.frame_ratio
effective_thermal_capacity = 0 construction.window_g_value = window_archetype.g_value
thermal_zone.indirectly_heated_area_ratio = 0 construction.window_overall_u_value = window_archetype.overall_u_value
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on _constructions.append(construction)
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off thermal_archetype.constructions = _constructions
for thermal_boundary in thermal_zone.thermal_boundaries: thermal_archetype.thermal_capacity = effective_thermal_capacity
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
thermal_boundary.construction_name = f'{thermal_boundary.type}_{construction_archetype.name}'
try:
thermal_boundary.window_ratio = 0
if thermal_boundary.type in (cte.WALL, cte.ROOF):
if construction_archetype.window is not None:
if -math.sqrt(2) / 2 < math.sin(thermal_boundary.parent_surface.azimuth) < math.sqrt(2) / 2:
if 0 < math.cos(thermal_boundary.parent_surface.azimuth):
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['north']) / 100
else:
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['south']) / 100
elif math.sqrt(2) / 2 <= math.sin(thermal_boundary.parent_surface.azimuth):
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['east']) / 100
else:
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['west']) / 100
except ValueError:
# This is the normal operation way when the windows are defined in the geometry
continue
thermal_boundary.layers = []
total_thickness = 0
for layer_archetype in construction_archetype.layers:
layer = Layer()
layer.thickness = layer_archetype.thickness
total_thickness += layer_archetype.thickness
material = Material()
archetype_material = layer_archetype.material
material.name = archetype_material.name
material.id = archetype_material.id
material.no_mass = archetype_material.no_mass
if archetype_material.no_mass:
material.thermal_resistance = archetype_material.thermal_resistance
else:
material.density = archetype_material.density
material.conductivity = archetype_material.conductivity
material.specific_heat = archetype_material.specific_heat
effective_thermal_capacity += archetype_material.specific_heat \
* archetype_material.density * layer_archetype.thickness
material.solar_absorptance = archetype_material.solar_absorptance
material.thermal_absorptance = archetype_material.thermal_absorptance
material.visible_absorptance = archetype_material.visible_absorptance
layer.material = material
thermal_boundary.layers.append(layer)
effective_thermal_capacity = effective_thermal_capacity / total_thickness
# The agreement is that the layers are defined from outside to inside
external_layer = construction_archetype.layers[0]
external_surface = thermal_boundary.parent_surface
external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
internal_surface = thermal_boundary.internal_surface
internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
for thermal_opening in thermal_boundary.thermal_openings:
if construction_archetype.window is not None:
window_archetype = construction_archetype.window
thermal_opening.construction_name = window_archetype.name
thermal_opening.frame_ratio = window_archetype.frame_ratio
thermal_opening.g_value = window_archetype.g_value
thermal_opening.overall_u_value = window_archetype.overall_u_value
thermal_zone.effective_thermal_capacity = effective_thermal_capacity
@staticmethod
def _calculate_view_factors(thermal_zone):
"""
Get thermal zone view factors matrix
:return: [[float]]
"""
total_area = 0
for thermal_boundary in thermal_zone.thermal_boundaries:
total_area += thermal_boundary.opaque_area
for thermal_opening in thermal_boundary.thermal_openings:
total_area += thermal_opening.area
view_factors_matrix = []
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = 0
if thermal_boundary_1.id != thermal_boundary_2.id:
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening in thermal_boundary.thermal_openings:
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
view_factors_matrix.append(values)
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening_2 in thermal_boundary.thermal_openings:
value = 0
if thermal_opening_1.id != thermal_opening_2.id:
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
values.append(value)
view_factors_matrix.append(values)
thermal_zone.view_factors_matrix = view_factors_matrix
@staticmethod
def _create_storeys(building, archetype, divide_in_storeys):
building.average_storey_height = archetype.average_storey_height
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
divide_in_storeys=divide_in_storeys).thermal_zones
building.internal_zones[0].thermal_zones = thermal_zones

View File

@ -5,8 +5,6 @@ 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 hub.helpers import constants as cte
class ConstructionHelper: class ConstructionHelper:
""" """

View File

@ -6,15 +6,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import logging import logging
import math
import hub.helpers.constants as cte
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
from hub.city_model_structure.building_demand.construction import Construction
from hub.city_model_structure.building_demand.layer import Layer from hub.city_model_structure.building_demand.layer import Layer
from hub.city_model_structure.building_demand.material import Material
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction.helpers.construction_helper import ConstructionHelper from hub.imports.construction.helpers.construction_helper import ConstructionHelper
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
class NrcanPhysicsParameters: class NrcanPhysicsParameters:
@ -35,7 +33,7 @@ class NrcanPhysicsParameters:
nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog
for building in city.buildings: for building in city.buildings:
if building.function not in Dictionaries().hub_function_to_nrcan_construction_function.keys(): if building.function not in Dictionaries().hub_function_to_nrcan_construction_function.keys():
logging.error(f'Building %s has an unknown building function %s', building.name, building.function ) logging.error(f'Building %s has an unknown building function %s', building.name, building.function)
continue continue
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function] function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
try: try:
@ -46,29 +44,10 @@ class NrcanPhysicsParameters:
f'[%s], building year of construction: %s and climate zone %s', building.name, function, f'[%s], building year of construction: %s and climate zone %s', building.name, function,
building.function, building.year_of_construction, self._climate_zone) building.function, building.year_of_construction, self._climate_zone)
continue continue
thermal_archetype = ThermalArchetype()
# if building has no thermal zones defined from geometry, and the building will be divided in storeys, self._assign_values(thermal_archetype, archetype)
# one thermal zone per storey is assigned
if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype, self._divide_in_storeys)
if self._divide_in_storeys:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
thermal_zone.total_floor_area = thermal_zone.footprint_area
else:
number_of_storeys = int(building.eave_height / building.average_storey_height)
thermal_zone = building.internal_zones[0].thermal_zones[0]
thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys
else:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
thermal_zone.total_floor_area = thermal_zone.footprint_area
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._assign_values(internal_zone.thermal_zones, archetype) internal_zone.thermal_archetype = thermal_archetype
for thermal_zone in internal_zone.thermal_zones:
self._calculate_view_factors(thermal_zone)
@staticmethod @staticmethod
def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone): def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone):
@ -81,126 +60,45 @@ class NrcanPhysicsParameters:
raise KeyError('archetype not found') raise KeyError('archetype not found')
@staticmethod @staticmethod
def _search_construction_in_archetype(archetype, construction_type): def _assign_values(thermal_archetype, catalog_archetype):
construction_archetypes = archetype.constructions thermal_archetype.average_storey_height = catalog_archetype.average_storey_height
for construction_archetype in construction_archetypes: thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
if str(construction_type) == str(construction_archetype.type): thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity
return construction_archetype thermal_archetype.indirect_heated_ratio = 0
return None thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
_constructions = []
for catalog_construction in catalog_archetype.constructions:
construction = Construction()
construction.type = catalog_construction.type
if catalog_construction.window_ratio is not None:
for _orientation in catalog_construction.window_ratio:
if catalog_construction.window_ratio[_orientation] is None:
catalog_construction.window_ratio[_orientation] = 0
construction.window_ratio = catalog_construction.window_ratio
_layers = []
for layer_archetype in catalog_construction.layers:
layer = Layer()
layer.thickness = layer_archetype.thickness
archetype_material = layer_archetype.material
layer.name = archetype_material.name
layer.no_mass = archetype_material.no_mass
if archetype_material.no_mass:
layer.thermal_resistance = archetype_material.thermal_resistance
else:
layer.density = archetype_material.density
layer.conductivity = archetype_material.conductivity
layer.specific_heat = archetype_material.specific_heat
layer.solar_absorptance = archetype_material.solar_absorptance
layer.thermal_absorptance = archetype_material.thermal_absorptance
layer.visible_absorptance = archetype_material.visible_absorptance
_layers.append(layer)
construction.layers = _layers
def _assign_values(self, thermal_zones, archetype): if catalog_construction.window is not None:
for thermal_zone in thermal_zones: window_archetype = catalog_construction.window
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges construction.window_frame_ratio = window_archetype.frame_ratio
thermal_zone.effective_thermal_capacity = archetype.thermal_capacity construction.window_g_value = window_archetype.g_value
thermal_zone.indirectly_heated_area_ratio = 0 construction.window_overall_u_value = window_archetype.overall_u_value
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on _constructions.append(construction)
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off thermal_archetype.constructions = _constructions
for thermal_boundary in thermal_zone.thermal_boundaries:
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
thermal_boundary.construction_name = f'{thermal_boundary.type}_{construction_archetype.name}'
try:
thermal_boundary.window_ratio = 0
if thermal_boundary.type in ( cte.WALL, cte.ROOF):
if construction_archetype.window is not None:
if -math.sqrt(2) / 2 < math.sin(thermal_boundary.parent_surface.azimuth) < math.sqrt(2) / 2:
if 0 < math.cos(thermal_boundary.parent_surface.azimuth):
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['north']) / 100
else:
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['south']) / 100
elif math.sqrt(2) / 2 <= math.sin(thermal_boundary.parent_surface.azimuth):
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['east']) / 100
else:
thermal_boundary.window_ratio = \
float(construction_archetype.window_ratio['west']) / 100
except ValueError:
# This is the normal operation way when the windows are defined in the geometry
continue
thermal_boundary.layers = []
for layer_archetype in construction_archetype.layers:
layer = Layer()
layer.thickness = layer_archetype.thickness
material = Material()
archetype_material = layer_archetype.material
material.name = archetype_material.name
material.id = archetype_material.id
material.no_mass = archetype_material.no_mass
if archetype_material.no_mass:
material.thermal_resistance = archetype_material.thermal_resistance
else:
material.density = archetype_material.density
material.conductivity = archetype_material.conductivity
material.specific_heat = archetype_material.specific_heat
material.solar_absorptance = archetype_material.solar_absorptance
material.thermal_absorptance = archetype_material.thermal_absorptance
material.visible_absorptance = archetype_material.visible_absorptance
layer.material = material
thermal_boundary.layers.append(layer)
# The agreement is that the layers are defined from outside to inside
external_layer = construction_archetype.layers[0]
external_surface = thermal_boundary.parent_surface
external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
internal_surface = thermal_boundary.internal_surface
internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
for thermal_opening in thermal_boundary.thermal_openings:
if construction_archetype.window is not None:
window_archetype = construction_archetype.window
thermal_opening.construction_name = window_archetype.name
thermal_opening.frame_ratio = window_archetype.frame_ratio
thermal_opening.g_value = window_archetype.g_value
thermal_opening.overall_u_value = window_archetype.overall_u_value
# todo: verify windows
@staticmethod
def _calculate_view_factors(thermal_zone):
"""
Get thermal zone view factors matrix
:return: [[float]]
"""
total_area = 0
for thermal_boundary in thermal_zone.thermal_boundaries:
total_area += thermal_boundary.opaque_area
for thermal_opening in thermal_boundary.thermal_openings:
total_area += thermal_opening.area
view_factors_matrix = []
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = 0
if thermal_boundary_1.id != thermal_boundary_2.id:
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening in thermal_boundary.thermal_openings:
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
view_factors_matrix.append(values)
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening_2 in thermal_boundary.thermal_openings:
value = 0
if thermal_opening_1.id != thermal_opening_2.id:
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
values.append(value)
view_factors_matrix.append(values)
thermal_zone.view_factors_matrix = view_factors_matrix
@staticmethod
def _create_storeys(building, archetype, divide_in_storeys):
building.average_storey_height = archetype.average_storey_height
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
divide_in_storeys=divide_in_storeys).thermal_zones
building.internal_zones[0].thermal_zones = thermal_zones

View File

@ -8,11 +8,11 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
import logging import logging
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
from hub.city_model_structure.building_demand.construction import Construction
from hub.city_model_structure.building_demand.layer import Layer from hub.city_model_structure.building_demand.layer import Layer
from hub.city_model_structure.building_demand.material import Material
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction.helpers.construction_helper import ConstructionHelper from hub.imports.construction.helpers.construction_helper import ConstructionHelper
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
class NrelPhysicsParameters: class NrelPhysicsParameters:
@ -44,28 +44,10 @@ class NrelPhysicsParameters:
f' and climate zone {self._climate_zone}\n') f' and climate zone {self._climate_zone}\n')
continue continue
# if building has no thermal zones defined from geometry, and the building will be divided in storeys, thermal_archetype = ThermalArchetype()
# one thermal zone per storey is assigned self._assign_values(thermal_archetype, archetype)
if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype, self._divide_in_storeys)
if self._divide_in_storeys:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
thermal_zone.total_floor_area = thermal_zone.footprint_area
else:
number_of_storeys = int(building.eave_height / building.average_storey_height)
thermal_zone = building.internal_zones[0].thermal_zones[0]
thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys
else:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
thermal_zone.total_floor_area = thermal_zone.footprint_area
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._assign_values(internal_zone.thermal_zones, archetype) internal_zone.thermal_archetype = thermal_archetype
for thermal_zone in internal_zone.thermal_zones:
self._calculate_view_factors(thermal_zone)
@staticmethod @staticmethod
def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone): def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone):
@ -80,111 +62,46 @@ class NrelPhysicsParameters:
raise KeyError('archetype not found') raise KeyError('archetype not found')
@staticmethod @staticmethod
def _search_construction_in_archetype(archetype, construction_type): def _assign_values(thermal_archetype, catalog_archetype):
construction_archetypes = archetype.constructions thermal_archetype.average_storey_height = catalog_archetype.average_storey_height
for construction_archetype in construction_archetypes: thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
if str(construction_type) == str(construction_archetype.type): thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity
return construction_archetype thermal_archetype.indirect_heated_ratio = catalog_archetype.indirect_heated_ratio
return None thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
_constructions = []
for catalog_construction in catalog_archetype.constructions:
construction = Construction()
construction.type = catalog_construction.type
if catalog_construction.window_ratio is not None:
construction.window_ratio = {'north': catalog_construction.window_ratio,
'east': catalog_construction.window_ratio,
'south': catalog_construction.window_ratio,
'west': catalog_construction.window_ratio
}
_layers = []
for layer_archetype in catalog_construction.layers:
layer = Layer()
layer.thickness = layer_archetype.thickness
archetype_material = layer_archetype.material
layer.name = archetype_material.name
layer.no_mass = archetype_material.no_mass
if archetype_material.no_mass:
layer.thermal_resistance = archetype_material.thermal_resistance
else:
layer.density = archetype_material.density
layer.conductivity = archetype_material.conductivity
layer.specific_heat = archetype_material.specific_heat
layer.solar_absorptance = archetype_material.solar_absorptance
layer.thermal_absorptance = archetype_material.thermal_absorptance
layer.visible_absorptance = archetype_material.visible_absorptance
_layers.append(layer)
construction.layers = _layers
def _assign_values(self, thermal_zones, archetype): if catalog_construction.window is not None:
for thermal_zone in thermal_zones: window_archetype = catalog_construction.window
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges construction.window_frame_ratio = window_archetype.frame_ratio
thermal_zone.effective_thermal_capacity = archetype.thermal_capacity construction.window_g_value = window_archetype.g_value
thermal_zone.indirectly_heated_area_ratio = archetype.indirect_heated_ratio construction.window_overall_u_value = window_archetype.overall_u_value
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on _constructions.append(construction)
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off thermal_archetype.constructions = _constructions
for thermal_boundary in thermal_zone.thermal_boundaries:
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
thermal_boundary.construction_name = construction_archetype.name
try:
thermal_boundary.window_ratio = construction_archetype.window_ratio
except ValueError:
# This is the normal operation way when the windows are defined in the geometry
continue
thermal_boundary.layers = []
for layer_archetype in construction_archetype.layers:
layer = Layer()
layer.thickness = layer_archetype.thickness
material = Material()
archetype_material = layer_archetype.material
material.name = archetype_material.name
material.id = archetype_material.id
material.no_mass = archetype_material.no_mass
if archetype_material.no_mass:
material.thermal_resistance = archetype_material.thermal_resistance
else:
material.density = archetype_material.density
material.conductivity = archetype_material.conductivity
material.specific_heat = archetype_material.specific_heat
material.solar_absorptance = archetype_material.solar_absorptance
material.thermal_absorptance = archetype_material.thermal_absorptance
material.visible_absorptance = archetype_material.visible_absorptance
layer.material = material
thermal_boundary.layers.append(layer)
# The agreement is that the layers are defined from outside to inside
external_layer = construction_archetype.layers[0]
external_surface = thermal_boundary.parent_surface
external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
internal_surface = thermal_boundary.internal_surface
internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
for thermal_opening in thermal_boundary.thermal_openings:
if construction_archetype.window is not None:
window_archetype = construction_archetype.window
thermal_opening.construction_name = window_archetype.name
thermal_opening.frame_ratio = window_archetype.frame_ratio
thermal_opening.g_value = window_archetype.g_value
thermal_opening.overall_u_value = window_archetype.overall_u_value
# todo: verify windows
@staticmethod
def _calculate_view_factors(thermal_zone):
"""
Get thermal zone view factors matrix
:return: [[float]]
"""
total_area = 0
for thermal_boundary in thermal_zone.thermal_boundaries:
total_area += thermal_boundary.opaque_area
for thermal_opening in thermal_boundary.thermal_openings:
total_area += thermal_opening.area
view_factors_matrix = []
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = 0
if thermal_boundary_1.id != thermal_boundary_2.id:
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening in thermal_boundary.thermal_openings:
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
view_factors_matrix.append(values)
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening_2 in thermal_boundary.thermal_openings:
value = 0
if thermal_opening_1.id != thermal_opening_2.id:
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
values.append(value)
view_factors_matrix.append(values)
thermal_zone.view_factors_matrix = view_factors_matrix
@staticmethod
def _create_storeys(building, archetype, divide_in_storeys):
building.average_storey_height = archetype.average_storey_height
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
divide_in_storeys=divide_in_storeys).thermal_zones
building.internal_zones[0].thermal_zones = thermal_zones

View File

@ -43,12 +43,12 @@ class InselMonthlyEnergyBalance:
domestic_hot_water_demand = [] domestic_hot_water_demand = []
lighting_demand = [] lighting_demand = []
appliances_demand = [] appliances_demand = []
if building.internal_zones[0].thermal_zones is None: if building.internal_zones[0].thermal_zones_from_internal_zones is None:
domestic_hot_water_demand = [0] * 12 domestic_hot_water_demand = [0] * 12
lighting_demand = [0] * 12 lighting_demand = [0] * 12
appliances_demand = [0] * 12 appliances_demand = [0] * 12
else: else:
thermal_zone = building.internal_zones[0].thermal_zones[0] thermal_zone = building.internal_zones[0].thermal_zones_from_internal_zones[0]
area = thermal_zone.total_floor_area area = thermal_zone.total_floor_area
cold_water = building.cold_water_temperature[cte.MONTH] 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

View File

@ -60,7 +60,7 @@ class CityObject(Models):
self.wall_area = wall_area self.wall_area = wall_area
window_ratio = 0 window_ratio = 0
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
window_ratio = thermal_boundary.window_ratio window_ratio = thermal_boundary.window_ratio
break break

View File

@ -106,7 +106,7 @@ class TestConstructionFactory(TestCase):
self.assertIsNotNone(building.shell, 'building shell is none') self.assertIsNotNone(building.shell, 'building shell is none')
def _check_thermal_zones(self, internal_zone): def _check_thermal_zones(self, internal_zone):
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none') self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
self.assertIsNotNone(thermal_zone.footprint_area, 'thermal_zone floor area is none') self.assertIsNotNone(thermal_zone.footprint_area, 'thermal_zone floor area is none')
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined') self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
@ -138,7 +138,6 @@ class TestConstructionFactory(TestCase):
self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none') self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none')
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none') self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none') self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none')
self.assertIsNotNone(thermal_boundary.construction_name, 'construction_name is none')
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')
self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none') self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none')
self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none') self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none')
@ -150,17 +149,15 @@ class TestConstructionFactory(TestCase):
def _check_thermal_openings(self, thermal_boundary): def _check_thermal_openings(self, thermal_boundary):
for thermal_opening in thermal_boundary.thermal_openings: for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none') self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none')
self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction is none')
self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none') self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none')
self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none') self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none')
self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none') self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none')
self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none') self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none')
self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none') self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none')
self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none') self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none')
self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction_name is none')
def _check_surfaces(self, thermal_boundary): def _check_surfaces(self, thermal_boundary):
external_surface = thermal_boundary.parent_surface external_surface = thermal_boundary.external_surface
internal_surface = thermal_boundary.internal_surface internal_surface = thermal_boundary.internal_surface
self.assertIsNotNone(external_surface.short_wave_reflectance, self.assertIsNotNone(external_surface.short_wave_reflectance,
'external surface short_wave_reflectance id is not none') 'external surface short_wave_reflectance id is not none')
@ -184,7 +181,7 @@ class TestConstructionFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone) self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_boundaries(thermal_zone) self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
@ -202,25 +199,7 @@ class TestConstructionFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone) self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
self._check_thermal_openings(thermal_boundary)
self._check_surfaces(thermal_boundary)
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.year_of_construction = 2006
building.function = self._internal_function('hft', building.function)
ConstructionFactory('nrel', city).enrich()
self._check_buildings(city)
for building in city.buildings:
for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones:
self._check_thermal_boundaries(thermal_zone) self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
@ -238,7 +217,7 @@ class TestConstructionFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone) self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_boundaries(thermal_zone) self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
@ -256,7 +235,7 @@ class TestConstructionFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone) self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_boundaries(thermal_zone) self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
@ -277,7 +256,7 @@ class TestConstructionFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone) self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_boundaries(thermal_zone) self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
@ -299,7 +278,7 @@ class TestConstructionFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone) self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_boundaries(thermal_zone) self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
@ -321,7 +300,7 @@ class TestConstructionFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone) self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_boundaries(thermal_zone) self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNotNone(thermal_boundary.layers, 'layers is none')

View File

@ -101,7 +101,7 @@ class TestExports(TestCase):
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none') self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none') self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} ' self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
f'indirectly_heated_area_ratio is none') f'indirectly_heated_area_ratio is none')
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} ' self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
@ -114,11 +114,12 @@ class TestExports(TestCase):
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.type) self.assertIsNotNone(thermal_boundary.type)
self.assertIsNotNone(thermal_boundary.opaque_area) self.assertIsNotNone(thermal_boundary.opaque_area)
self.assertIsNotNone(thermal_boundary.window_ratio) if thermal_boundary.type in (cte.WALL, cte.ROOF):
self.assertIsNotNone(thermal_boundary.window_ratio)
self.assertIsNotNone(thermal_boundary.u_value) self.assertIsNotNone(thermal_boundary.u_value)
self.assertIsNotNone(thermal_boundary.thermal_openings) self.assertIsNotNone(thermal_boundary.thermal_openings)
if thermal_boundary.type is not cte.GROUND: if thermal_boundary.type is not cte.GROUND:
self.assertIsNotNone(thermal_boundary.parent_surface.short_wave_reflectance) self.assertIsNotNone(thermal_boundary.external_surface.short_wave_reflectance)
for usage in internal_zone.usages: for usage in internal_zone.usages:
self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none') self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none')

View File

@ -38,7 +38,7 @@ class TestGeometryFactory(TestCase):
self.assertIsNot(len(internal_zone.usages), 0, 'no building usages defined') self.assertIsNot(len(internal_zone.usages), 0, 'no building usages defined')
for usage in internal_zone.usages: for usage in internal_zone.usages:
self.assertIsNotNone(usage.id, 'usage id is none') self.assertIsNotNone(usage.id, 'usage id is none')
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_thermal_zone(thermal_zone) self._check_thermal_zone(thermal_zone)
def _check_buildings(self, city): def _check_buildings(self, city):
@ -46,7 +46,7 @@ class TestGeometryFactory(TestCase):
self.assertIsNotNone(building.internal_zones, 'no internal zones created') self.assertIsNotNone(building.internal_zones, 'no internal zones created')
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self.assertIsNotNone(internal_zone.usages, 'usage zones are not defined') self.assertIsNotNone(internal_zone.usages, 'usage zones are not defined')
self.assertIsNotNone(internal_zone.thermal_zones, 'thermal zones are not defined') self.assertIsNotNone(internal_zone.thermal_zones_from_internal_zones, 'thermal zones are not defined')
self.assertIsNone(building.basement_heated, 'building basement_heated is not none') self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none') self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none') self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
@ -105,7 +105,7 @@ class TestGeometryFactory(TestCase):
if usage_key == 'comnet': if usage_key == 'comnet':
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_extra_thermal_zone(thermal_zone) self._check_extra_thermal_zone(thermal_zone)
# usage factory called first # usage factory called first
city = self._get_citygml(file) city = self._get_citygml(file)
@ -117,7 +117,7 @@ class TestGeometryFactory(TestCase):
if usage_key == 'comnet': if usage_key == 'comnet':
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_extra_thermal_zone(thermal_zone) self._check_extra_thermal_zone(thermal_zone)
def _test_pluto(self, file): def _test_pluto(self, file):
@ -135,7 +135,7 @@ class TestGeometryFactory(TestCase):
if usage_key == 'comnet': if usage_key == 'comnet':
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_extra_thermal_zone(thermal_zone) self._check_extra_thermal_zone(thermal_zone)
# usage factory called first # usage factory called first
city = self._get_citygml(file) city = self._get_citygml(file)
@ -147,7 +147,7 @@ class TestGeometryFactory(TestCase):
if usage_key == 'comnet': if usage_key == 'comnet':
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self._check_extra_thermal_zone(thermal_zone) self._check_extra_thermal_zone(thermal_zone)
def test_enrichment(self): def test_enrichment(self):

View File

@ -120,6 +120,7 @@ class TestExports(TestCase):
EnergyBuildingsExportsFactory('idf', city, self._output_path).export() EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
UsageFactory('nrcan', city).enrich() UsageFactory('nrcan', city).enrich()
WeatherFactory('epw', city).enrich() WeatherFactory('epw', city).enrich()
print(self._output_path)
try: try:
EnergyBuildingsExportsFactory('idf', city, self._output_path).export() EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
except Exception: except Exception:

View File

@ -62,7 +62,7 @@ class TestGeometryFactory(TestCase):
self.assertIsNotNone(building.internal_zones, 'building internal zones is none') self.assertIsNotNone(building.internal_zones, 'building internal zones is none')
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self.assertIsNone(internal_zone.usages, 'usage zones are defined') self.assertIsNone(internal_zone.usages, 'usage zones are defined')
self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined') self.assertIsNone(internal_zone.thermal_archetype, 'thermal archetype is defined')
self.assertIsNone(building.basement_heated, 'building basement_heated is not none') self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none') self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNone(building.terrains, 'building terrains is not none') self.assertIsNone(building.terrains, 'building terrains is not none')

View File

@ -101,7 +101,7 @@ class TestExports(TestCase):
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none') self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none') self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} ' self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
f'indirectly_heated_area_ratio is none') f'indirectly_heated_area_ratio is none')
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} ' self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
@ -118,7 +118,7 @@ class TestExports(TestCase):
self.assertIsNotNone(thermal_boundary.u_value) self.assertIsNotNone(thermal_boundary.u_value)
self.assertIsNotNone(thermal_boundary.thermal_openings) self.assertIsNotNone(thermal_boundary.thermal_openings)
if thermal_boundary.type is not cte.GROUND: if thermal_boundary.type is not cte.GROUND:
self.assertIsNotNone(thermal_boundary.parent_surface.short_wave_reflectance) self.assertIsNotNone(thermal_boundary.external_surface.short_wave_reflectance)
for usage in internal_zone.usages: for usage in internal_zone.usages:
self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none') self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none')