From f3208f1735228c89d1ff38e952c330db967d3017 Mon Sep 17 00:00:00 2001 From: p_monsalvete Date: Tue, 25 Jul 2023 11:40:47 -0400 Subject: [PATCH] starting the process of changing thermal_zones generation, NOT working version --- hub/city_model_structure/building.py | 2 +- .../building_demand/construction.py | 134 ++++++++++++ .../building_demand/internal_zone.py | 7 +- .../building_demand/layer.py | 180 ++++++++++++++-- .../building_demand/material.py | 193 ----------------- .../building_demand/thermal_archetype.py | 126 +++++++++++ hub/helpers/thermal_zones_creation.py | 138 ++++++++++++ .../construction/eilat_physics_parameters.py | 199 ++++-------------- .../construction/nrcan_physics_parameters.py | 187 ++++------------ .../construction/nrel_physics_parameters.py | 167 ++++----------- tests/test_exports.py | 1 + 11 files changed, 682 insertions(+), 652 deletions(-) create mode 100644 hub/city_model_structure/building_demand/construction.py delete mode 100644 hub/city_model_structure/building_demand/material.py create mode 100644 hub/city_model_structure/building_demand/thermal_archetype.py create mode 100644 hub/helpers/thermal_zones_creation.py diff --git a/hub/city_model_structure/building.py b/hub/city_model_structure/building.py index 67f2add3..3c318232 100644 --- a/hub/city_model_structure/building.py +++ b/hub/city_model_structure/building.py @@ -114,7 +114,7 @@ class Building(CityObject): :return: [InternalZone] """ 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 @property diff --git a/hub/city_model_structure/building_demand/construction.py b/hub/city_model_structure/building_demand/construction.py new file mode 100644 index 00000000..ad82999d --- /dev/null +++ b/hub/city_model_structure/building_demand/construction.py @@ -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 diff --git a/hub/city_model_structure/building_demand/internal_zone.py b/hub/city_model_structure/building_demand/internal_zone.py index c8669652..6bc2f776 100644 --- a/hub/city_model_structure/building_demand/internal_zone.py +++ b/hub/city_model_structure/building_demand/internal_zone.py @@ -11,17 +11,18 @@ 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.attributes.polyhedron import Polyhedron from hub.city_model_structure.energy_systems.hvac_system import HvacSystem +from hub.helpers.thermal_zones_creation import ThermalZonesCreation class InternalZone: """ InternalZone class """ - def __init__(self, surfaces, area): + def __init__(self, surfaces, area, volume): self._surfaces = surfaces self._id = None self._geometry = None - self._volume = None + self._volume = volume self._area = area self._thermal_zones = None self._usages = None @@ -64,7 +65,7 @@ class InternalZone: Get internal zone volume in cubic meters :return: float """ - return self.geometry.volume + return self._volume @property def area(self): diff --git a/hub/city_model_structure/building_demand/layer.py b/hub/city_model_structure/building_demand/layer.py index 09853c62..3075f0bc 100644 --- a/hub/city_model_structure/building_demand/layer.py +++ b/hub/city_model_structure/building_demand/layer.py @@ -4,9 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + import uuid from typing import Union -from hub.city_model_structure.building_demand.material import Material class Layer: @@ -14,9 +14,17 @@ class Layer: Layer class """ def __init__(self): - self._material = None self._thickness = 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 def id(self): @@ -28,22 +36,6 @@ class Layer: self._id = uuid.uuid4() 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 def thickness(self) -> Union[None, float]: """ @@ -60,3 +52,155 @@ class Layer: """ if value is not None: 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) diff --git a/hub/city_model_structure/building_demand/material.py b/hub/city_model_structure/building_demand/material.py deleted file mode 100644 index ebf97ced..00000000 --- a/hub/city_model_structure/building_demand/material.py +++ /dev/null @@ -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) diff --git a/hub/city_model_structure/building_demand/thermal_archetype.py b/hub/city_model_structure/building_demand/thermal_archetype.py new file mode 100644 index 00000000..47daf8a0 --- /dev/null +++ b/hub/city_model_structure/building_demand/thermal_archetype.py @@ -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 diff --git a/hub/helpers/thermal_zones_creation.py b/hub/helpers/thermal_zones_creation.py new file mode 100644 index 00000000..1f5edc2e --- /dev/null +++ b/hub/helpers/thermal_zones_creation.py @@ -0,0 +1,138 @@ +""" +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 +from hub.city_model_structure.building_demand.thermal_zone import ThermalZone +from hub.city_model_structure.building_demand.thermal_boundary import ThermalBoundary + + +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_internal_zones(self) -> [ThermalZone]: + """ + Create and get thermal zones as 1 per each internal zone + :return: [ThermalZone] + """ + _thermal_zones = [] + _thermal_boundaries = [] + for internal_zone in self._building.internal_zones: + for surface in internal_zone.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, internal_zone, internal_zone.volume, internal_zone.floor_area) + _thermal_zones.append(_thermal_zone) + return _thermal_zones + + @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 = thermal_zones + + # 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 _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 diff --git a/hub/imports/construction/eilat_physics_parameters.py b/hub/imports/construction/eilat_physics_parameters.py index 607af32b..664ea121 100644 --- a/hub/imports/construction/eilat_physics_parameters.py +++ b/hub/imports/construction/eilat_physics_parameters.py @@ -6,15 +6,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ import logging -import math -import hub.helpers.constants as cte 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.material import Material from hub.helpers.dictionaries import Dictionaries from hub.imports.construction.helpers.construction_helper import ConstructionHelper -from hub.imports.construction.helpers.storeys_generation import StoreysGeneration class EilatPhysicsParameters: @@ -35,7 +33,7 @@ class EilatPhysicsParameters: eilat_catalog = ConstructionCatalogFactory('eilat').catalog for building in city.buildings: 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 function = Dictionaries().hub_function_to_eilat_construction_function[building.function] try: @@ -46,29 +44,8 @@ class EilatPhysicsParameters: f'[%s], building year of construction: %s and climate zone %s', building.name, function, building.function, building.year_of_construction, self._climate_zone) continue - - # if building has no thermal zones defined from geometry, and the building will be divided in storeys, - # 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) + thermal_archetype = ThermalArchetype() + self._assign_values(thermal_archetype, archetype) @staticmethod def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone): @@ -81,133 +58,43 @@ class EilatPhysicsParameters: raise KeyError('archetype not found') @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 + def _assign_values(thermal_archetype, catalog_archetype): + thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges + thermal_archetype.indirect_heated_ratio = 0 + 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 + effective_thermal_capacity = 0 + for catalog_construction in catalog_archetype.constructions: + construction = Construction() + 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): - for thermal_zone in thermal_zones: - thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges - effective_thermal_capacity = 0 - 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 = [] - 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) + if catalog_construction.window is not None: + window_archetype = catalog_construction.window + construction.window_frame_ratio = window_archetype.frame_ratio + construction.window_g_value = window_archetype.g_value + construction.window_overall_u_value = window_archetype.overall_u_value - 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 + thermal_archetype.thermal_capacity = effective_thermal_capacity diff --git a/hub/imports/construction/nrcan_physics_parameters.py b/hub/imports/construction/nrcan_physics_parameters.py index cf4debcf..523243cc 100644 --- a/hub/imports/construction/nrcan_physics_parameters.py +++ b/hub/imports/construction/nrcan_physics_parameters.py @@ -6,15 +6,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ import logging -import math -import hub.helpers.constants as cte 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.material import Material from hub.helpers.dictionaries import Dictionaries from hub.imports.construction.helpers.construction_helper import ConstructionHelper -from hub.imports.construction.helpers.storeys_generation import StoreysGeneration class NrcanPhysicsParameters: @@ -35,7 +33,7 @@ class NrcanPhysicsParameters: nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog for building in city.buildings: 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 function = Dictionaries().hub_function_to_nrcan_construction_function[building.function] try: @@ -46,29 +44,8 @@ class NrcanPhysicsParameters: f'[%s], building year of construction: %s and climate zone %s', building.name, function, building.function, building.year_of_construction, self._climate_zone) continue - - # if building has no thermal zones defined from geometry, and the building will be divided in storeys, - # 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) + thermal_archetype = ThermalArchetype() + self._assign_values(thermal_archetype, archetype) @staticmethod def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone): @@ -81,126 +58,36 @@ class NrcanPhysicsParameters: raise KeyError('archetype not found') @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 + def _assign_values(thermal_archetype, catalog_archetype): + thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges + thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity + thermal_archetype.indirect_heated_ratio = 0 + 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 + for catalog_construction in catalog_archetype.constructions: + construction = Construction() + 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): - for thermal_zone in thermal_zones: - thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges - thermal_zone.effective_thermal_capacity = archetype.thermal_capacity - 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.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 + if catalog_construction.window is not None: + window_archetype = catalog_construction.window + construction.window_frame_ratio = window_archetype.frame_ratio + construction.window_g_value = window_archetype.g_value + construction.window_overall_u_value = window_archetype.overall_u_value diff --git a/hub/imports/construction/nrel_physics_parameters.py b/hub/imports/construction/nrel_physics_parameters.py index e01e3cbf..3e1139fa 100644 --- a/hub/imports/construction/nrel_physics_parameters.py +++ b/hub/imports/construction/nrel_physics_parameters.py @@ -8,11 +8,11 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord import logging 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.material import Material from hub.helpers.dictionaries import Dictionaries from hub.imports.construction.helpers.construction_helper import ConstructionHelper -from hub.imports.construction.helpers.storeys_generation import StoreysGeneration class NrelPhysicsParameters: @@ -44,28 +44,8 @@ class NrelPhysicsParameters: f' and climate zone {self._climate_zone}\n') continue - # if building has no thermal zones defined from geometry, and the building will be divided in storeys, - # 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) + thermal_archetype = ThermalArchetype() + self._assign_values(thermal_archetype, archetype) @staticmethod def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone): @@ -80,111 +60,36 @@ class NrelPhysicsParameters: raise KeyError('archetype not found') @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 + def _assign_values(thermal_archetype, catalog_archetype): + thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges + thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity + thermal_archetype.indirect_heated_ratio = catalog_archetype.indirect_heated_ratio + 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 + for catalog_construction in catalog_archetype.constructions: + construction = Construction() + 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): - for thermal_zone in thermal_zones: - thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges - thermal_zone.effective_thermal_capacity = archetype.thermal_capacity - 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.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 + if catalog_construction.window is not None: + window_archetype = catalog_construction.window + construction.window_frame_ratio = window_archetype.frame_ratio + construction.window_g_value = window_archetype.g_value + construction.window_overall_u_value = window_archetype.overall_u_value diff --git a/tests/test_exports.py b/tests/test_exports.py index 7607c964..ff0ef9c0 100644 --- a/tests/test_exports.py +++ b/tests/test_exports.py @@ -120,6 +120,7 @@ class TestExports(TestCase): EnergyBuildingsExportsFactory('idf', city, self._output_path).export() UsageFactory('nrcan', city).enrich() WeatherFactory('epw', city).enrich() + print(self._output_path) try: EnergyBuildingsExportsFactory('idf', city, self._output_path).export() except Exception: