From e2b882723ba54117b442009342fbd2796a7e2001 Mon Sep 17 00:00:00 2001 From: Pilar Date: Tue, 19 Apr 2022 15:49:41 -0400 Subject: [PATCH] Modified construction factory to read from catalogs instead of file --- .../construction/construction_helpers.py | 10 + .../construction/nrel_catalog.py | 7 +- .../construction_catalog_factory.py | 1 + .../data_models/construction/archetype.py | 11 ++ .../data_models/construction/content.py | 1 + .../data_models/construction/layer.py | 1 + .../data_models/construction/material.py | 1 + .../data_models/construction/window.py | 1 + .../building_demand/material.py | 1 - .../construction/nrel_physics_interface.py | 186 +----------------- imports/construction/us_physics_parameters.py | 105 +++++----- imports/construction_factory.py | 2 +- unittests/test_construction_factory.py | 19 +- 13 files changed, 103 insertions(+), 243 deletions(-) diff --git a/catalog_factories/construction/construction_helpers.py b/catalog_factories/construction/construction_helpers.py index 1d9e4bf4..b35f7c30 100644 --- a/catalog_factories/construction/construction_helpers.py +++ b/catalog_factories/construction/construction_helpers.py @@ -28,4 +28,14 @@ nrcan_to_function = { reference_standard_to_construction_period = { 'ASHRAE 90.1_2004': '2004 - 2009', 'ASHRAE 189.1_2009': '2009 - PRESENT' +} + +nrel_surfaces_types_to_hub_types = { + 'exterior wall': cte.WALL, + 'interior wall': cte.INTERIOR_WALL, + 'ground wall': cte.GROUND_WALL, + 'exterior slab': cte.GROUND, + 'attic floor': cte.ATTIC_FLOOR, + 'interior slab': cte.INTERIOR_SLAB, + 'roof': cte.ROOF } \ No newline at end of file diff --git a/catalog_factories/construction/nrel_catalog.py b/catalog_factories/construction/nrel_catalog.py index 7014b1bb..72939b4f 100644 --- a/catalog_factories/construction/nrel_catalog.py +++ b/catalog_factories/construction/nrel_catalog.py @@ -16,6 +16,7 @@ from catalog_factories.data_models.construction.content import Content from catalog_factories.data_models.construction.archetype import Archetype from catalog_factories.construction.construction_helpers import nrel_to_function from catalog_factories.construction.construction_helpers import reference_standard_to_construction_period +from catalog_factories.construction.construction_helpers import nrel_surfaces_types_to_hub_types class NrelCatalog(Catalog): @@ -88,7 +89,7 @@ class NrelCatalog(Catalog): constructions = self._constructions['library']['constructions']['construction'] for construction in constructions: construction_id = construction['@id'] - construction_type = construction['@type'] + construction_type = nrel_surfaces_types_to_hub_types[construction['@type']] name = construction['@name'] layers = [] for layer in construction['layers']['layer']: @@ -111,7 +112,8 @@ class NrelCatalog(Catalog): for archetype in archetypes: archetype_id = archetype['@id'] function = nrel_to_function[archetype['@building_type']] - name = f"{function} {archetype['@reference_standard']}" + name = f"{function} {archetype['@climate_zone']} {archetype['@reference_standard']}" + climate_zone = archetype['@climate_zone'] construction_period = reference_standard_to_construction_period[archetype['@reference_standard']] average_storey_height = archetype['average_storey_height']['#text'] number_of_storeys = archetype['number_of_storeys']['#text'] @@ -145,6 +147,7 @@ class NrelCatalog(Catalog): _catalog_archetypes.append(Archetype(archetype_id, name, function, + climate_zone, construction_period, archetype_constructions, average_storey_height, diff --git a/catalog_factories/construction_catalog_factory.py b/catalog_factories/construction_catalog_factory.py index dcc9664c..8a33107b 100644 --- a/catalog_factories/construction_catalog_factory.py +++ b/catalog_factories/construction_catalog_factory.py @@ -10,6 +10,7 @@ from typing import TypeVar from catalog_factories.construction.nrel_catalog import NrelCatalog Catalog = TypeVar('Catalog') + class ConstructionCatalogFactory: def __init__(self, file_type, base_path=None): if base_path is None: diff --git a/catalog_factories/data_models/construction/archetype.py b/catalog_factories/data_models/construction/archetype.py index 70ab99e5..3468864c 100644 --- a/catalog_factories/data_models/construction/archetype.py +++ b/catalog_factories/data_models/construction/archetype.py @@ -7,10 +7,12 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca from catalog_factories.data_models.construction.construction import Construction + class Archetype: def __init__(self, archetype_id, name, function, + climate_zone, construction_period, constructions, average_storey_height, @@ -23,6 +25,7 @@ class Archetype: self._id = archetype_id self._name = name self._function = function + self._climate_zone = climate_zone self._construction_period = construction_period self._constructions = constructions self._average_storey_height = average_storey_height @@ -57,6 +60,14 @@ class Archetype: """ return self._function + @property + def climate_zone(self): + """ + Get archetype climate zone + :return: str + """ + return self._climate_zone + @property def constructions(self) -> [Construction]: """ diff --git a/catalog_factories/data_models/construction/content.py b/catalog_factories/data_models/construction/content.py index c7d5f7a2..3fa2f596 100644 --- a/catalog_factories/data_models/construction/content.py +++ b/catalog_factories/data_models/construction/content.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class Content: def __init__(self, archetypes, constructions, materials, windows): self._archetypes = archetypes diff --git a/catalog_factories/data_models/construction/layer.py b/catalog_factories/data_models/construction/layer.py index 4bdd1bf6..afcbfe14 100644 --- a/catalog_factories/data_models/construction/layer.py +++ b/catalog_factories/data_models/construction/layer.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class Layer: def __init__(self, layer_id, name, material, thickness): self._id = layer_id diff --git a/catalog_factories/data_models/construction/material.py b/catalog_factories/data_models/construction/material.py index 3df24df8..d701a827 100644 --- a/catalog_factories/data_models/construction/material.py +++ b/catalog_factories/data_models/construction/material.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class Material: def __init__(self, material_id, name, diff --git a/catalog_factories/data_models/construction/window.py b/catalog_factories/data_models/construction/window.py index 60c31a0b..8d4ba44f 100644 --- a/catalog_factories/data_models/construction/window.py +++ b/catalog_factories/data_models/construction/window.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class Window: def __init__(self, window_id, frame_ratio, g_value, overall_u_value, name): self._id = window_id diff --git a/city_model_structure/building_demand/material.py b/city_model_structure/building_demand/material.py index fe54d19e..6320c4ff 100644 --- a/city_model_structure/building_demand/material.py +++ b/city_model_structure/building_demand/material.py @@ -5,7 +5,6 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ -import ast from typing import Union diff --git a/imports/construction/nrel_physics_interface.py b/imports/construction/nrel_physics_interface.py index 4a0f9c8c..f5133568 100644 --- a/imports/construction/nrel_physics_interface.py +++ b/imports/construction/nrel_physics_interface.py @@ -5,12 +5,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ -import xmltodict -from imports.construction.data_classes.building_achetype import BuildingArchetype as nba -from imports.construction.data_classes.thermal_boundary_archetype import ThermalBoundaryArchetype as ntba -from imports.construction.data_classes.thermal_opening_archetype import ThermalOpeningArchetype as ntoa -from imports.construction.data_classes.layer_archetype import LayerArchetype as nla from imports.construction.helpers.storeys_generation import StoreysGeneration @@ -19,173 +14,6 @@ class NrelPhysicsInterface: NrelPhysicsInterface abstract class """ - def __init__(self, base_path, constructions_file='us_constructions.xml', - archetypes_file='us_archetypes.xml'): - self._building_archetypes = [] - # load construction Library, CERC-NREL format - path = str(base_path / constructions_file) - with open(path) as xml: - self._library = xmltodict.parse(xml.read(), force_list='layer') - - # load archetypes Library, CERC-NREL format - path = str(base_path / archetypes_file) - with open(path) as xml: - self._archetypes = xmltodict.parse(xml.read(), force_list='layer') - - for archetype in self._archetypes['archetypes']['archetype']: - archetype_keys = {} - for key, value in archetype.items(): - if key[0] == '@': - archetype_keys[key] = value - average_storey_height = archetype['average_storey_height']['#text'] - units = archetype['average_storey_height']['@units'] - if units != 'm': - raise Exception(f'average storey height units = {units}, expected meters') - storeys_above_ground = archetype['number_of_storeys']['#text'] - effective_thermal_capacity = float(archetype['thermal_capacity']['#text']) * 1000 - units = archetype['thermal_capacity']['@units'] - if units != 'kJ/K m2': - raise Exception(f'thermal capacity units = {units}, expected kJ/K m2') - additional_thermal_bridge_u_value = archetype['extra_loses_due_to_thermal_bridges']['#text'] - units = archetype['extra_loses_due_to_thermal_bridges']['@units'] - if units != 'W/K m2': - raise Exception(f'extra loses due to thermal bridges units = {units}, expected W/K m2') - indirectly_heated_area_ratio = archetype['indirect_heated_ratio']['#text'] - # todo: check how infiltration rate is used in the model - infiltration_rate_system_off = archetype['infiltration_rate_for_ventilation_system_off']['#text'] - units = archetype['infiltration_rate_for_ventilation_system_off']['@units'] - if units != 'ACH': - raise Exception(f'infiltration rate for ventilation when system off units = {units}, expected ACH') - infiltration_rate_system_on = archetype['infiltration_rate_for_ventilation_system_on']['#text'] - units = archetype['infiltration_rate_for_ventilation_system_on']['@units'] - if units != 'ACH': - raise Exception(f'infiltration rate for ventilation when system on units = {units}, expected ACH') - - thermal_boundary_archetypes = [] - for construction in archetype['constructions']['construction']: - construction_type = construction['@type'] - construction_id = construction['@id'] - - c_lib = self._search_construction_type('construction', construction_id) - construction_name = c_lib['@name'] - layers = [] - if 'layers' in c_lib: - for current_layer in c_lib['layers']['layer']: - material_lib = self._search_construction_type('material', current_layer['material']) - name = material_lib['@name'] - solar_absorptance = material_lib['solar_absorptance']['#text'] - thermal_absorptance = material_lib['thermal_absorptance']['#text'] - visible_absorptance = material_lib['visible_absorptance']['#text'] - no_mass = 'no_mass' in material_lib - if no_mass: - thermal_resistance = material_lib['thermal_resistance']['#text'] - units = material_lib['thermal_resistance']['@units'] - if units != 'm2 K/W': - raise Exception(f'thermal resistance units = {units}, expected m2 K/W') - layer = nla(name, solar_absorptance, thermal_absorptance, visible_absorptance, no_mass=no_mass, - thermal_resistance=thermal_resistance) - else: - thickness = current_layer['thickness']['#text'] - units = current_layer['thickness']['@units'] - if units != 'm': - raise Exception(f'thickness units = {units}, expected m') - conductivity = material_lib['conductivity']['#text'] - units = material_lib['conductivity']['@units'] - if units != 'W/m K': - raise Exception(f'conductivity units = {units}, expected W/m K') - specific_heat = material_lib['specific_heat']['#text'] - units = material_lib['specific_heat']['@units'] - if units != 'J/kg K': - raise Exception(f'specific_heat units = {units}, expected J/kg K') - density = material_lib['density']['#text'] - units = material_lib['density']['@units'] - if units != 'kg/m3': - raise Exception(f'density units = {units}, expected kg/m3') - layer = nla(name, solar_absorptance, thermal_absorptance, visible_absorptance, thickness=thickness, - conductivity=conductivity, specific_heat=specific_heat, density=density) - layers.append(layer) - - thermal_opening = None - window_ratio = 0 - if 'window' in construction and construction['window'] is not None: - window_ratio = construction['window_ratio']['#text'] - w_lib = self._search_construction_type('window', construction['window']) - window_construction_name = w_lib['@name'] - frame_ratio = w_lib['frame_ratio']['#text'] - if 'conductivity' in w_lib: - conductivity = w_lib['conductivity']['#text'] - units = w_lib['conductivity']['@units'] - if units != 'W/m K': - raise Exception(f'conductivity units = {units}, expected W/m K') - thickness = w_lib['thickness']['#text'] - units = w_lib['thickness']['@units'] - if units != 'm': - raise Exception(f'thickness units = {units}, expected m') - g_value = w_lib['solar_transmittance_at_normal_incidence']['#text'] - back_side_solar_transmittance_at_normal_incidence = \ - w_lib['back_side_solar_transmittance_at_normal_incidence']['#text'] - front_side_solar_transmittance_at_normal_incidence = \ - w_lib['front_side_solar_transmittance_at_normal_incidence']['#text'] - thermal_opening = ntoa(conductivity=conductivity, frame_ratio=frame_ratio, g_value=g_value, - thickness=thickness, back_side_solar_transmittance_at_normal_incidence= - back_side_solar_transmittance_at_normal_incidence, - front_side_solar_transmittance_at_normal_incidence= - front_side_solar_transmittance_at_normal_incidence, - construction_name=window_construction_name) - else: - overall_u_value = w_lib['overall_u_value']['#text'] - units = w_lib['overall_u_value']['@units'] - if units != 'W/m2 K': - raise Exception(f'overall U-value units = {units}, expected W/m2 K') - g_value = w_lib['g_value'] - thermal_opening = ntoa(frame_ratio=frame_ratio, g_value=g_value, overall_u_value=overall_u_value, - construction_name=window_construction_name) - - if 'outside_thermal_absorptance' in c_lib: - outside_solar_absorptance = c_lib['outside_solar_absorptance']['#text'] - outside_thermal_absorptance = c_lib['outside_thermal_absorptance']['#text'] - outside_visible_absorptance = c_lib['outside_visible_absorptance']['#text'] - thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers, thermal_opening, - outside_solar_absorptance, outside_thermal_absorptance, - outside_visible_absorptance) - else: - if 'overall_u_value' in c_lib: - overall_u_value = c_lib['overall_u_value']['#text'] - units = c_lib['overall_u_value']['@units'] - if units != 'W/m2 K': - raise Exception(f'overall U-value units = {units}, expected W/m2 K') - if 'outside_solar_absorptance' in c_lib: - outside_solar_absorptance = c_lib['outside_solar_absorptance']['#text'] - thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers, - thermal_opening, outside_solar_absorptance=outside_solar_absorptance, - overall_u_value=overall_u_value) - else: - thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers, - thermal_opening, overall_u_value=overall_u_value) - else: - thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers, - thermal_opening) - - thermal_boundary_archetypes.append(thermal_boundary_archetype) - building_archetype = nba(archetype_keys, average_storey_height, storeys_above_ground, - effective_thermal_capacity, additional_thermal_bridge_u_value, - indirectly_heated_area_ratio, infiltration_rate_system_off, - infiltration_rate_system_on, thermal_boundary_archetypes) - self._building_archetypes.append(building_archetype) - - def _search_construction_type(self, construction_type, construction_id): - for c_lib in self._library['library'][construction_type + 's'][construction_type]: - if construction_id == c_lib['@id']: - return c_lib - raise Exception('Archetype definition contains elements that does not exist in the library') - - @staticmethod - def _search_construction_in_archetype(building_archetype, construction_type): - for thermal_boundary in building_archetype.thermal_boundary_archetypes: - if thermal_boundary.boundary_type == construction_type: - return thermal_boundary - raise Exception('Construction type not found') - # todo: verify windows @staticmethod def _calculate_view_factors(thermal_zone): @@ -228,15 +56,15 @@ class NrelPhysicsInterface: view_factors_matrix.append(values) thermal_zone.view_factors_matrix = view_factors_matrix + @staticmethod + def _create_storeys(building, archetype): + building.average_storey_height = archetype.average_storey_height + building.storeys_above_ground = 1 + thermal_zones = StoreysGeneration(building, building.internal_zones[0]).thermal_zones + building.internal_zones[0].thermal_zones = thermal_zones + def enrich_buildings(self): """ Raise not implemented error """ raise NotImplementedError - - @staticmethod - def _create_storeys(building, archetype): - building.average_storey_height = archetype.average_storey_height - building.storeys_above_ground = archetype.storeys_above_ground - thermal_zones = StoreysGeneration(building, building.internal_zones[0]).thermal_zones - building.internal_zones[0].thermal_zones = thermal_zones diff --git a/imports/construction/us_physics_parameters.py b/imports/construction/us_physics_parameters.py index 0828e41b..858eba9c 100644 --- a/imports/construction/us_physics_parameters.py +++ b/imports/construction/us_physics_parameters.py @@ -8,9 +8,10 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord import sys from imports.construction.nrel_physics_interface import NrelPhysicsInterface -from imports.construction.helpers.construction_helper import ConstructionHelper +from catalog_factories.construction.nrel_catalog import NrelCatalog from city_model_structure.building_demand.layer import Layer from city_model_structure.building_demand.material import Material +from imports.construction.helpers.construction_helper import ConstructionHelper class UsPhysicsParameters(NrelPhysicsInterface): @@ -19,24 +20,18 @@ class UsPhysicsParameters(NrelPhysicsInterface): """ def __init__(self, city, base_path): self._city = city + self._path = base_path self._climate_zone = ConstructionHelper.city_to_nrel_climate_zone(city.name) - super().__init__(base_path, 'us_constructions.xml', 'us_archetypes.xml') + super().__init__() def enrich_buildings(self): """ Returns the city with the construction parameters assigned to the buildings - :return: None """ city = self._city - # it is assumed that all buildings have the same archetypes' keys for building in city.buildings: - building_type = ConstructionHelper.nrel_from_libs_function(building.function) - if building_type is None: - return try: - archetype = self._search_archetype(building_type, - ConstructionHelper.yoc_to_nrel_standard(building.year_of_construction), - self._climate_zone) + archetype = self._search_archetype(building.function, building.year_of_construction, self._climate_zone) except KeyError: sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} ' f'and building year of construction: {building.year_of_construction}\n') @@ -52,60 +47,72 @@ class UsPhysicsParameters(NrelPhysicsInterface): for thermal_zone in internal_zone.thermal_zones: self._calculate_view_factors(thermal_zone) - def _search_archetype(self, building_type, standard, climate_zone): - for building_archetype in self._building_archetypes: - a_yc = str(building_archetype.archetype_keys['@reference_standard']) - a_bt = str(building_archetype.archetype_keys['@building_type']) - a_cz = str(building_archetype.archetype_keys['@climate_zone']) - if (a_yc == str(standard)) and (a_bt == str(building_type)) and (a_cz == str(climate_zone)): - return building_archetype + def _search_archetype(self, function, year_of_construction, climate_zone): + nrel_archetypes = NrelCatalog(self._path).entries('archetypes') + for building_archetype in nrel_archetypes: + construction_period_limits = building_archetype.construction_period.split(' - ') + if construction_period_limits[1] == 'PRESENT': + construction_period_limits[1] = 3000 + if int(construction_period_limits[0]) <= year_of_construction < int(construction_period_limits[1]): + if (str(function) == str(building_archetype.function)) and \ + (climate_zone == str(building_archetype.climate_zone)): + return building_archetype + return None + + @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(self, internal_zones, archetype): for internal_zone in internal_zones: for thermal_zone in internal_zone.thermal_zones: - thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value - thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity - thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio - thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on - thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off + 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_type = ConstructionHelper.nrel_construction_types[thermal_boundary.type] - thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type) - thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance - thermal_boundary.outside_thermal_absorptance = thermal_boundary_archetype.outside_thermal_absorptance - thermal_boundary.outside_visible_absorptance = thermal_boundary_archetype.outside_visible_absorptance - thermal_boundary.construction_name = thermal_boundary_archetype.construction_name + construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type) + print('wa', construction_archetype.window) + thermal_boundary.construction_name = construction_archetype.name try: - thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio + 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 thermal_boundary_archetype.layers: + for layer_archetype in construction_archetype.layers: layer = Layer() layer.thickness = layer_archetype.thickness material = Material() + archetype_material = layer_archetype.material material.name = layer_archetype.name - material.no_mass = layer_archetype.no_mass - material.density = layer_archetype.density - material.conductivity = layer_archetype.conductivity - material.specific_heat = layer_archetype.specific_heat - material.solar_absorptance = layer_archetype.solar_absorptance - material.thermal_absorptance = layer_archetype.thermal_absorptance - material.visible_absorptance = layer_archetype.visible_absorptance - material.thermal_resistance = layer_archetype.thermal_resistance + 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] + thermal_boundary.outside_solar_absorptance = external_layer.material.solar_absorptance + thermal_boundary.outside_thermal_absorptance = external_layer.material.thermal_absorptance + thermal_boundary.outside_visible_absorptance = external_layer.material.visible_absorptance + for thermal_opening in thermal_boundary.thermal_openings: - if thermal_boundary_archetype.thermal_opening_archetype is not None: - thermal_opening_archetype = thermal_boundary_archetype.thermal_opening_archetype - thermal_opening.construction_name = thermal_opening_archetype.construction_name - thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio - thermal_opening.g_value = thermal_opening_archetype.g_value - thermal_opening.conductivity = thermal_opening_archetype.conductivity - thermal_opening.thickness = thermal_opening_archetype.thickness - thermal_opening.back_side_solar_transmittance_at_normal_incidence = \ - thermal_opening_archetype.back_side_solar_transmittance_at_normal_incidence - thermal_opening.front_side_solar_transmittance_at_normal_incidence = \ - thermal_opening_archetype.front_side_solar_transmittance_at_normal_incidence + 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 diff --git a/imports/construction_factory.py b/imports/construction_factory.py index b201555b..94190b65 100644 --- a/imports/construction_factory.py +++ b/imports/construction_factory.py @@ -30,4 +30,4 @@ class ConstructionFactory: Enrich the city given to the class using the class given handler :return: None """ - getattr(self, self._handler, lambda: None)() \ No newline at end of file + getattr(self, self._handler, lambda: None)() diff --git a/unittests/test_construction_factory.py b/unittests/test_construction_factory.py index b04cc901..55213ea8 100644 --- a/unittests/test_construction_factory.py +++ b/unittests/test_construction_factory.py @@ -108,12 +108,8 @@ class TestConstructionFactory(TestCase): self.assertIsNotNone(thermal_boundary.inclination, 'thermal_boundary inclination is none') self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none') self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none') - if thermal_boundary.type is not cte.GROUND: - self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') - self.assertIsNotNone(thermal_boundary.shortwave_reflectance, 'shortwave_reflectance is none') - else: - self.assertIsNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is not none') - self.assertIsNone(thermal_boundary.shortwave_reflectance, 'shortwave_reflectance is not none') + self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') + self.assertIsNotNone(thermal_boundary.shortwave_reflectance, 'shortwave_reflectance is none') self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none') self.assertIsNotNone(thermal_boundary.construction_name, 'construction_name is none') self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') @@ -132,11 +128,11 @@ class TestConstructionFactory(TestCase): self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none') self.assertRaises(Exception, lambda: thermal_opening.openable_ratio, 'thermal_opening openable_ratio is not raising an exception') - self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is not none') - self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is not none') - self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is not none') - self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is not none') - self.assertIsNotNone(thermal_opening.he, 'thermal opening he 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.assertIsNone(thermal_opening.inside_emissivity, 'thermal opening inside_emissivity is not none') self.assertIsNone(thermal_opening.alpha_coefficient, 'thermal opening alpha_coefficient is not none') self.assertIsNone(thermal_opening.radiative_coefficient, 'thermal opening radiative_coefficient is not none') @@ -175,6 +171,7 @@ class TestConstructionFactory(TestCase): file = 'pluto_building.gml' city = self._get_citygml(file) for building in city.buildings: + building.year_of_construction = 2005 building.function = GeometryHelper.libs_function_from_pluto(building.function) ConstructionFactory('nrel', city).enrich()