Compare commits

..

2 Commits

23 changed files with 723 additions and 722 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,23 @@ 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)] self._internal_zones = [InternalZone(self.surfaces, self.floor_area, self.volume)]
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]:
@ -621,7 +618,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

@ -9,6 +9,7 @@ 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_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
from hub.city_model_structure.energy_systems.hvac_system import HvacSystem from hub.city_model_structure.energy_systems.hvac_system import HvacSystem
@ -17,13 +18,13 @@ class InternalZone:
""" """
InternalZone class InternalZone class
""" """
def __init__(self, surfaces, area): def __init__(self, surfaces, area, volume):
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._thermal_zones_from_internal_zones = None
self._usages = None self._usages = None
self._hvac_system = None self._hvac_system = None
@ -64,7 +65,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):
@ -107,17 +108,29 @@ class InternalZone:
self._hvac_system = value self._hvac_system = value
@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 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._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,126 @@
"""
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
@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

@ -221,15 +221,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]:

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

@ -510,9 +510,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:
@ -556,7 +556,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)
@ -611,7 +611,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
@ -664,7 +664,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:
@ -674,7 +674,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'
@ -711,7 +711,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

@ -44,7 +44,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(
@ -126,7 +126,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)')
@ -139,7 +139,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:
@ -169,11 +169,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 infiltration_day += internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_system_off / 24
ventilation_day += 0 ventilation_day += 0
else: else:
ventilation_value = usage.mechanical_air_change * value ventilation_value = usage.mechanical_air_change * value
infiltration_value = internal_zone.thermal_zones[0].infiltration_rate_system_off * value infiltration_value = internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_system_off * value
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

@ -65,7 +65,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)
@ -78,7 +78,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)
@ -91,7 +91,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
@ -103,7 +103,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
@ -117,7 +117,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
@ -139,7 +139,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][irradiance_format][hour] radiation = thermal_boundary.parent_surface.global_irradiance[cte.HOUR][irradiance_format][hour]

View File

@ -0,0 +1,72 @@
"""
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
# todo: ATTENTION!!
# try:
# thermal_boundary.window_ratio = catalog_construction.window_ratio
# except ValueError:
# # This is the normal operation way when the windows are defined in the geometry
# continue
# # 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
# if thermal_boundary.type in (cte.WALL, cte.ROOF):
# if catalog_construction.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(catalog_construction.window_ratio['north']) / 100
# else:
# thermal_boundary.window_ratio = \
# float(catalog_construction.window_ratio['south']) / 100
# elif math.sqrt(2) / 2 <= math.sin(thermal_boundary.parent_surface.azimuth):
# thermal_boundary.window_ratio = \
# float(catalog_construction.window_ratio['east']) / 100
# else:
# thermal_boundary.window_ratio = \
# float(catalog_construction.window_ratio['west']) / 100
@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
@staticmethod
def _search_construction_in_archetype(archetype, construction_type):
construction_archetypes = archetype.constructions
for construction_archetype in construction_archetypes:
if str(construction_type) == str(construction_archetype.type):
return construction_archetype
return None

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,8 @@ 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:
self._assign_values(internal_zone.thermal_zones, 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 +58,43 @@ 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.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
for construction_archetype in construction_archetypes: thermal_archetype.indirect_heated_ratio = 0
if str(construction_type) == str(construction_archetype.type): thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
return construction_archetype thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
return None
def _assign_values(self, thermal_zones, archetype):
for thermal_zone in thermal_zones:
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges
effective_thermal_capacity = 0 effective_thermal_capacity = 0
thermal_zone.indirectly_heated_area_ratio = 0 for catalog_construction in catalog_archetype.constructions:
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on construction = Construction()
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off construction.window_ratio = catalog_construction.window_ratio
for thermal_boundary in thermal_zone.thermal_boundaries: _layers = []
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
thermal_boundary.construction_name = 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 total_thickness = 0
for layer_archetype in construction_archetype.layers: for layer_archetype in catalog_construction.layers:
layer = Layer() layer = Layer()
layer.thickness = layer_archetype.thickness layer.thickness = layer_archetype.thickness
total_thickness += layer_archetype.thickness total_thickness += layer_archetype.thickness
material = Material()
archetype_material = layer_archetype.material archetype_material = layer_archetype.material
material.name = archetype_material.name layer.name = archetype_material.name
material.id = archetype_material.id layer.no_mass = archetype_material.no_mass
material.no_mass = archetype_material.no_mass
if archetype_material.no_mass: if archetype_material.no_mass:
material.thermal_resistance = archetype_material.thermal_resistance layer.thermal_resistance = archetype_material.thermal_resistance
else: else:
material.density = archetype_material.density layer.density = archetype_material.density
material.conductivity = archetype_material.conductivity layer.conductivity = archetype_material.conductivity
material.specific_heat = archetype_material.specific_heat layer.specific_heat = archetype_material.specific_heat
effective_thermal_capacity += archetype_material.specific_heat \ effective_thermal_capacity += archetype_material.specific_heat \
* archetype_material.density * layer_archetype.thickness * archetype_material.density * layer_archetype.thickness
material.solar_absorptance = archetype_material.solar_absorptance layer.solar_absorptance = archetype_material.solar_absorptance
material.thermal_absorptance = archetype_material.thermal_absorptance layer.thermal_absorptance = archetype_material.thermal_absorptance
material.visible_absorptance = archetype_material.visible_absorptance layer.visible_absorptance = archetype_material.visible_absorptance
layer.material = material _layers.append(layer)
thermal_boundary.layers.append(layer) construction.layers = _layers
effective_thermal_capacity = effective_thermal_capacity / total_thickness 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 catalog_construction.window is not None:
if construction_archetype.window is not None: window_archetype = catalog_construction.window
window_archetype = construction_archetype.window construction.window_frame_ratio = window_archetype.frame_ratio
thermal_opening.construction_name = window_archetype.name construction.window_g_value = window_archetype.g_value
thermal_opening.frame_ratio = window_archetype.frame_ratio construction.window_overall_u_value = window_archetype.overall_u_value
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 thermal_archetype.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

@ -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,8 @@ 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:
self._assign_values(internal_zone.thermal_zones, 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 +58,36 @@ 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.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
for construction_archetype in construction_archetypes: thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity
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
for catalog_construction in catalog_archetype.constructions:
def _assign_values(self, thermal_zones, archetype): construction = Construction()
for thermal_zone in thermal_zones: construction.window_ratio = catalog_construction.window_ratio
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges _layers = []
thermal_zone.effective_thermal_capacity = archetype.thermal_capacity for layer_archetype in catalog_construction.layers:
thermal_zone.indirectly_heated_area_ratio = 0
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off
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 = 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 = Layer()
layer.thickness = layer_archetype.thickness layer.thickness = layer_archetype.thickness
material = Material()
archetype_material = layer_archetype.material archetype_material = layer_archetype.material
material.name = archetype_material.name layer.name = archetype_material.name
material.id = archetype_material.id layer.no_mass = archetype_material.no_mass
material.no_mass = archetype_material.no_mass
if archetype_material.no_mass: if archetype_material.no_mass:
material.thermal_resistance = archetype_material.thermal_resistance layer.thermal_resistance = archetype_material.thermal_resistance
else: else:
material.density = archetype_material.density layer.density = archetype_material.density
material.conductivity = archetype_material.conductivity layer.conductivity = archetype_material.conductivity
material.specific_heat = archetype_material.specific_heat layer.specific_heat = archetype_material.specific_heat
material.solar_absorptance = archetype_material.solar_absorptance layer.solar_absorptance = archetype_material.solar_absorptance
material.thermal_absorptance = archetype_material.thermal_absorptance layer.thermal_absorptance = archetype_material.thermal_absorptance
material.visible_absorptance = archetype_material.visible_absorptance layer.visible_absorptance = archetype_material.visible_absorptance
layer.material = material _layers.append(layer)
thermal_boundary.layers.append(layer) construction.layers = _layers
# 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 catalog_construction.window is not None:
if construction_archetype.window is not None: window_archetype = catalog_construction.window
window_archetype = construction_archetype.window construction.window_frame_ratio = window_archetype.frame_ratio
thermal_opening.construction_name = window_archetype.name construction.window_g_value = window_archetype.g_value
thermal_opening.frame_ratio = window_archetype.frame_ratio construction.window_overall_u_value = window_archetype.overall_u_value
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,8 @@ 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:
self._assign_values(internal_zone.thermal_zones, 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 +60,36 @@ 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.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
for construction_archetype in construction_archetypes: thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity
if str(construction_type) == str(construction_archetype.type): thermal_archetype.indirect_heated_ratio = catalog_archetype.indirect_heated_ratio
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
for catalog_construction in catalog_archetype.constructions:
def _assign_values(self, thermal_zones, archetype): construction = Construction()
for thermal_zone in thermal_zones: construction.window_ratio = catalog_construction.window_ratio
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges _layers = []
thermal_zone.effective_thermal_capacity = archetype.thermal_capacity for layer_archetype in catalog_construction.layers:
thermal_zone.indirectly_heated_area_ratio = archetype.indirect_heated_ratio
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off
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 = Layer()
layer.thickness = layer_archetype.thickness layer.thickness = layer_archetype.thickness
material = Material()
archetype_material = layer_archetype.material archetype_material = layer_archetype.material
material.name = archetype_material.name layer.name = archetype_material.name
material.id = archetype_material.id layer.no_mass = archetype_material.no_mass
material.no_mass = archetype_material.no_mass
if archetype_material.no_mass: if archetype_material.no_mass:
material.thermal_resistance = archetype_material.thermal_resistance layer.thermal_resistance = archetype_material.thermal_resistance
else: else:
material.density = archetype_material.density layer.density = archetype_material.density
material.conductivity = archetype_material.conductivity layer.conductivity = archetype_material.conductivity
material.specific_heat = archetype_material.specific_heat layer.specific_heat = archetype_material.specific_heat
material.solar_absorptance = archetype_material.solar_absorptance layer.solar_absorptance = archetype_material.solar_absorptance
material.thermal_absorptance = archetype_material.thermal_absorptance layer.thermal_absorptance = archetype_material.thermal_absorptance
material.visible_absorptance = archetype_material.visible_absorptance layer.visible_absorptance = archetype_material.visible_absorptance
layer.material = material _layers.append(layer)
thermal_boundary.layers.append(layer) construction.layers = _layers
# 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 catalog_construction.window is not None:
if construction_archetype.window is not None: window_archetype = catalog_construction.window
window_archetype = construction_archetype.window construction.window_frame_ratio = window_archetype.frame_ratio
thermal_opening.construction_name = window_archetype.name construction.window_g_value = window_archetype.g_value
thermal_opening.frame_ratio = window_archetype.frame_ratio construction.window_overall_u_value = window_archetype.overall_u_value
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

@ -45,12 +45,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]['epw'] cold_water = building.cold_water_temperature[cte.MONTH]['epw']
peak_flow = thermal_zone.domestic_hot_water.peak_flow peak_flow = thermal_zone.domestic_hot_water.peak_flow

View File

@ -58,7 +58,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')
@ -133,7 +133,7 @@ class TestConstructionFactory(TestCase):
for thermal_boundary in thermal_zone.thermal_boundaries: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.id, 'thermal_boundary id is none') self.assertIsNotNone(thermal_boundary.id, 'thermal_boundary id is none')
self.assertIsNotNone(thermal_boundary.parent_surface, 'thermal_boundary surface is none') self.assertIsNotNone(thermal_boundary.parent_surface, 'thermal_boundary surface is none')
self.assertIsNotNone(thermal_boundary.thermal_zones, 'thermal_boundary delimits no thermal zone') self.assertIsNotNone(thermal_boundary.thermal_zones_from_internal_zones, 'thermal_boundary delimits no thermal zone')
self.assertIsNotNone(thermal_boundary.opaque_area, 'thermal_boundary area is none') self.assertIsNotNone(thermal_boundary.opaque_area, 'thermal_boundary area is none')
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')
@ -184,7 +184,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,7 +202,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')
@ -220,7 +220,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')
@ -238,7 +238,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 +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')
@ -277,7 +277,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 +299,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 +321,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

@ -115,7 +115,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} '

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_zones_from_internal_zones, 'thermal zones are 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

@ -115,7 +115,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} '