diff --git a/hub/city_model_structure/building_demand/thermal_boundary.py b/hub/city_model_structure/building_demand/thermal_boundary.py index 5858007c..c3ee0128 100644 --- a/hub/city_model_structure/building_demand/thermal_boundary.py +++ b/hub/city_model_structure/building_demand/thermal_boundary.py @@ -37,6 +37,7 @@ class ThermalBoundary: self._construction_name = None self._thickness = None self._internal_surface = None + self._external_surface = None self._window_ratio = None self._window_ratio_to_be_calculated = False if self._windows_areas is not None: @@ -55,7 +56,7 @@ class ThermalBoundary: @property def parent_surface(self) -> Surface: """ - Get the surface that belongs to the thermal boundary + Get the surface that belongs to the thermal boundary, considered the external surface of that boundary :return: Surface """ return self._parent_surface @@ -306,4 +307,18 @@ class ThermalBoundary: """ if self._internal_surface is None: self._internal_surface = self.parent_surface.inverse + # The agreement is that the layers are defined from outside to inside + internal_layer = self.layers[len(self.layers) - 1] + self._internal_surface.short_wave_reflectance = 1 - internal_layer.solar_absorptance + self._internal_surface.long_wave_emittance = 1 - internal_layer.solar_absorptance + return self._internal_surface + + @property + def external_surface(self) -> Surface: + if self._external_surface is None: + # The agreement is that the layers are defined from outside to inside + self._external_surface = self.parent_surface + self._external_surface.short_wave_reflectance = 1 - self.layers[0].solar_absorptance + self._external_surface.long_wave_emittance = 1 - self.layers[0].solar_absorptance + return self._external_surface diff --git a/hub/helpers/thermal_zones_creation.py b/hub/helpers/thermal_zones_creation.py index f116a272..636eab06 100644 --- a/hub/helpers/thermal_zones_creation.py +++ b/hub/helpers/thermal_zones_creation.py @@ -15,13 +15,6 @@ class ThermalZonesCreation: 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 @@ -32,22 +25,6 @@ class ThermalZonesCreation: # 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): """ diff --git a/hub/imports/construction/eilat_physics_parameters.py b/hub/imports/construction/eilat_physics_parameters.py index d048dbd1..51760e03 100644 --- a/hub/imports/construction/eilat_physics_parameters.py +++ b/hub/imports/construction/eilat_physics_parameters.py @@ -46,6 +46,8 @@ class EilatPhysicsParameters: continue thermal_archetype = ThermalArchetype() self._assign_values(thermal_archetype, archetype) + for internal_zone in building.internal_zones: + internal_zone.thermal_archetype = thermal_archetype @staticmethod def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone): @@ -65,8 +67,14 @@ class EilatPhysicsParameters: 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 + _constructions = [] for catalog_construction in catalog_archetype.constructions: construction = Construction() + construction.type = catalog_construction.type + if catalog_construction.window_ratio is not None: + for _orientation in catalog_construction.window_ratio: + if catalog_construction.window_ratio[_orientation] is None: + catalog_construction.window_ratio[_orientation] = 0 construction.window_ratio = catalog_construction.window_ratio _layers = [] total_thickness = 0 @@ -97,5 +105,6 @@ class EilatPhysicsParameters: 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 - + _constructions.append(construction) + thermal_archetype.constructions = _constructions thermal_archetype.thermal_capacity = effective_thermal_capacity diff --git a/hub/imports/construction/nrel_physics_parameters.py b/hub/imports/construction/nrel_physics_parameters.py index 9a5503cf..8fd2e46f 100644 --- a/hub/imports/construction/nrel_physics_parameters.py +++ b/hub/imports/construction/nrel_physics_parameters.py @@ -46,6 +46,8 @@ class NrelPhysicsParameters: continue thermal_archetype = ThermalArchetype() self._assign_values(thermal_archetype, archetype) + for internal_zone in building.internal_zones: + internal_zone.thermal_archetype = thermal_archetype @staticmethod def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone): @@ -67,9 +69,16 @@ class NrelPhysicsParameters: 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 + _constructions = [] for catalog_construction in catalog_archetype.constructions: construction = Construction() - construction.window_ratio = catalog_construction.window_ratio + construction.type = catalog_construction.type + if catalog_construction.window_ratio is not None: + construction.window_ratio = {'north': catalog_construction.window_ratio, + 'east': catalog_construction.window_ratio, + 'south': catalog_construction.window_ratio, + 'west': catalog_construction.window_ratio + } _layers = [] for layer_archetype in catalog_construction.layers: layer = Layer() @@ -94,3 +103,5 @@ class NrelPhysicsParameters: 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 + _constructions.append(construction) + thermal_archetype.constructions = _constructions \ No newline at end of file diff --git a/tests/test_construction_factory.py b/tests/test_construction_factory.py index 02d6a0c2..49d93d7e 100644 --- a/tests/test_construction_factory.py +++ b/tests/test_construction_factory.py @@ -10,6 +10,7 @@ from unittest import TestCase from hub.imports.geometry_factory import GeometryFactory from hub.imports.construction_factory import ConstructionFactory from hub.helpers.dictionaries import Dictionaries +import hub.helpers.constants as cte class TestConstructionFactory(TestCase): @@ -138,7 +139,10 @@ class TestConstructionFactory(TestCase): self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none') self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none') self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none') - self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') + if thermal_boundary.type in (cte.WALL, cte.ROOF): + self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') + else: + self.assertIsNone(thermal_boundary.window_ratio, 'window_ratio is not none') self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none') self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none') self.assertIsNotNone(thermal_boundary.hi, 'hi is none') @@ -149,17 +153,15 @@ class TestConstructionFactory(TestCase): def _check_thermal_openings(self, thermal_boundary): for thermal_opening in thermal_boundary.thermal_openings: self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none') - self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction is none') self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none') self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none') self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none') self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none') self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none') self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none') - self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction_name is none') def _check_surfaces(self, thermal_boundary): - external_surface = thermal_boundary.parent_surface + external_surface = thermal_boundary.external_surface internal_surface = thermal_boundary.internal_surface self.assertIsNotNone(external_surface.short_wave_reflectance, 'external surface short_wave_reflectance id is not none') @@ -197,24 +199,6 @@ class TestConstructionFactory(TestCase): building.function = self._internal_function('pluto', building.function) ConstructionFactory('nrcan', city).enrich() - self._check_buildings(city) - for building in city.buildings: - for internal_zone in building.internal_zones: - self._check_thermal_zones(internal_zone) - for thermal_zone in internal_zone.thermal_zones_from_internal_zones: - self._check_thermal_boundaries(thermal_zone) - for thermal_boundary in thermal_zone.thermal_boundaries: - self.assertIsNotNone(thermal_boundary.layers, 'layers is none') - self._check_thermal_openings(thermal_boundary) - self._check_surfaces(thermal_boundary) - - file = 'one_building_in_kelowna.gml' - city = self._get_citygml(file) - for building in city.buildings: - building.year_of_construction = 2006 - building.function = self._internal_function('hft', building.function) - ConstructionFactory('nrel', city).enrich() - self._check_buildings(city) for building in city.buildings: for internal_zone in building.internal_zones: