diff --git a/factories/physics_factory.py b/factories/physics_factory.py index 5675f52b..e34bf194 100644 --- a/factories/physics_factory.py +++ b/factories/physics_factory.py @@ -19,12 +19,11 @@ class PhysicsFactory: self._base_path = base_path self.factory() - # todo: adapt us_new_york and us to the new version with interface def _us_new_york(self): - UsNewYorkCityPhysicsParameters(self._city, self._base_path) + UsNewYorkCityPhysicsParameters(self._city, self._base_path).enrich_buildings() def _us(self): - UsPhysicsParameters(self._city, self._base_path) + UsPhysicsParameters(self._city, self._base_path).enrich_buildings() def _ca(self): CaPhysicsParameters(self._city, self._base_path).enrich_buildings() diff --git a/factories/physics_feeders/ca_physics_parameters.py b/factories/physics_feeders/ca_physics_parameters.py index e318865d..d8b9c9be 100644 --- a/factories/physics_feeders/ca_physics_parameters.py +++ b/factories/physics_feeders/ca_physics_parameters.py @@ -25,21 +25,21 @@ class CaPhysicsParameters(NrelPhysicsInterface): city = self._city # it is assumed that all buildings have the same archetypes' keys for building in city.buildings: - archetype = self._search_archetype([building.function, building.year_of_construction]) + archetype = self._search_archetype(building.function, building.year_of_construction) if archetype is None: 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') continue self._assign_values(building, archetype) - def _search_archetype(self, keys): + def _search_archetype(self, function, year_of_construction): for building_archetype in self._building_archetypes: a_ft = str(building_archetype.archetype_keys['@function']) a_pc = str(building_archetype.archetype_keys['@periodOfConstruction']) a_yc1 = int(a_pc.split(sep='-')[0]) a_yc2 = int(a_pc.split(sep='-')[1]) - if a_ft == str(keys[0]): - if a_yc1 <= int(keys[1]) <= a_yc2: + if a_ft == str(function): + if a_yc1 <= int(year_of_construction) <= a_yc2: return building_archetype return None diff --git a/factories/physics_feeders/us_new_york_city_physics_parameters.py b/factories/physics_feeders/us_new_york_city_physics_parameters.py index 0268799c..752c1ff1 100644 --- a/factories/physics_feeders/us_new_york_city_physics_parameters.py +++ b/factories/physics_feeders/us_new_york_city_physics_parameters.py @@ -2,16 +2,95 @@ UsNewYorkCityPhysicsParameters import the construction and material information for new york city SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca +Contributors Pilar Monsalvete pilar_monsalvete@yahoo.es """ +import sys + +from factories.physics_feeders.nrel_physics_interface import NrelPhysicsInterface from factories.physics_feeders.helpers.us_pluto_to_function import UsPlutoToFunction as pf -from factories.physics_feeders.cerc_base_physics_parameters import CercBasePhysicsParameters +from factories.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes +from city_model_structure.attributes.layer import Layer +from city_model_structure.attributes.material import Material -class UsNewYorkCityPhysicsParameters(CercBasePhysicsParameters): +class UsNewYorkCityPhysicsParameters(NrelPhysicsInterface): """ UsNewYorkCityPhysicsParameters class """ def __init__(self, city, base_path): self._city = city - climate_zone = 'ASHRAE_2004:4A' - super().__init__(climate_zone, self._city.buildings, pf.function, base_path) + self._climate_zone = 'ASHRAE_2004:4A' + super().__init__(base_path, 'us_constructions.xml', 'us_archetypes.xml') + + def enrich_buildings(self): + """ + Returns the city with the physics parameters assigned to the buildings + :return: + """ + city = self._city + # it is assumed that all buildings have the same archetypes' keys + for building in city.buildings: + building_type = pf.function(building.function) + if building_type is None: + return + archetype = self._search_archetype(building_type, + UsToLibraryTypes.yoc_to_standard(building.year_of_construction), + self._climate_zone) + if archetype is None: + 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') + continue + self._assign_values(building, archetype) + + 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 + return None + + def _assign_values(self, building, archetype): + building.average_storey_height = archetype.average_storey_height + building.storeys_above_ground = archetype.storeys_above_ground + for thermal_zone in building.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 + for thermal_boundary in thermal_zone.bounded: + construction_type = UsToLibraryTypes.construction_types[thermal_boundary.type] + thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type) + if thermal_boundary_archetype.outside_solar_absorptance is not None: + 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 + thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio + for layer_archetype in thermal_boundary_archetype.layers: + layer = Layer() + layer.thickness = layer_archetype.thickness + material = 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 + layer.material = material + for thermal_opening in thermal_boundary.thermal_openings: + if thermal_boundary_archetype.thermal_opening is not None: + thermal_opening_archetype = thermal_boundary_archetype.thermal_opening + 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 diff --git a/factories/physics_feeders/us_physics_parameters.py b/factories/physics_feeders/us_physics_parameters.py index c4a11659..96dfea2b 100644 --- a/factories/physics_feeders/us_physics_parameters.py +++ b/factories/physics_feeders/us_physics_parameters.py @@ -2,16 +2,94 @@ UsPhysicsParameters import the construction and material information for US SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca +Contributors Pilar Monsalvete pilar_monsalvete@yahoo.es """ +import sys + +from factories.physics_feeders.nrel_physics_interface import NrelPhysicsInterface from factories.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes -from factories.physics_feeders.cerc_base_physics_parameters import CercBasePhysicsParameters +from city_model_structure.attributes.layer import Layer +from city_model_structure.attributes.material import Material -class UsPhysicsParameters(CercBasePhysicsParameters): +class UsNewYorkCityPhysicsParameters(NrelPhysicsInterface): """ UsPhysicsParameters class """ def __init__(self, city, base_path): self._city = city self._climate_zone = UsToLibraryTypes.city_to_climate_zone(city.name) - super().__init__(self._climate_zone, self._city.buildings, lambda function: function, base_path) + super().__init__(base_path, 'us_constructions.xml', 'us_archetypes.xml') + + def enrich_buildings(self): + """ + Returns the city with the physics parameters assigned to the buildings + :return: + """ + city = self._city + # it is assumed that all buildings have the same archetypes' keys + for building in city.buildings: + building_type = building.function + if building_type is None: + return + archetype = self._search_archetype(building_type, + UsToLibraryTypes.yoc_to_standard(building.year_of_construction), + self._climate_zone) + if archetype is None: + 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') + continue + self._assign_values(building, archetype) + + 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 + return None + + def _assign_values(self, building, archetype): + building.average_storey_height = archetype.average_storey_height + building.storeys_above_ground = archetype.storeys_above_ground + for thermal_zone in building.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 + for thermal_boundary in thermal_zone.bounded: + construction_type = UsToLibraryTypes.construction_types[thermal_boundary.type] + thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type) + if thermal_boundary_archetype.outside_solar_absorptance is not None: + 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 + thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio + for layer_archetype in thermal_boundary_archetype.layers: + layer = Layer() + layer.thickness = layer_archetype.thickness + material = 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 + layer.material = material + for thermal_opening in thermal_boundary.thermal_openings: + if thermal_boundary_archetype.thermal_opening is not None: + thermal_opening_archetype = thermal_boundary_archetype.thermal_opening + 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 diff --git a/factories/usage_feeders/de_usage_parameters.py b/factories/usage_feeders/de_usage_parameters.py index ec8dbd34..521ef672 100644 --- a/factories/usage_feeders/de_usage_parameters.py +++ b/factories/usage_feeders/de_usage_parameters.py @@ -28,7 +28,8 @@ class DeUsageParameters(HftUsageInterface): for building in city.buildings: archetype = self._search_archetype(fu.usage(building.function)) if archetype is None: - sys.stderr.write(f'Building {building.name} has unknown archetype for building usage: {building.function}\n') + sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' + f' {building.function}, that assigns building usage as {fu.usage(building.function)}\n') continue # todo: what to do with mix-usage usages from gml? mix_usage = False diff --git a/factories/usage_feeders/us_base_usage_parameters.py b/factories/usage_feeders/us_base_usage_parameters.py deleted file mode 100644 index 8e05dde3..00000000 --- a/factories/usage_feeders/us_base_usage_parameters.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -CercBaseUsageParameters base class to model the usage properties for a building in NYC and US -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributors Pilar Monsalvete pilar_monsalvete@yahoo.es -""" -from pathlib import Path - -import xmltodict - -from city_model_structure.attributes.internal_gains import InternalGains -from city_model_structure.attributes.usage_zone import UsageZone - - -class UsBaseUsageParameters: - """ - UsBaseUsageParameters class - """ - def __init__(self, city, function_to_usage): - self._city = city - # todo: control not archetype found - # ToDo: this is using the german library as a temporary approach, need to use/define a library for US - path = str(Path(__file__).parent.parent.parent / 'data/usage/de_library.xml') - with open(path) as xml: - self._library = xmltodict.parse(xml.read(), force_list='zoneUsageVariant') - for city_object in self._city.buildings: - # ToDo: Right now is just one usage zone but will be multiple in the future - usage_zone = UsageZone() - usage_zone.usage = function_to_usage(city_object.function) - for zone_usage_type in self._library['buildingUsageLibrary']['zoneUsageType']: - if zone_usage_type['id'] != usage_zone.usage: - if 'zoneUsageVariant' in zone_usage_type: - for usage_zone_variant in zone_usage_type['zoneUsageVariant']: - if usage_zone_variant['id'] == usage_zone.usage: - # pre-initialize the usage zone with the main type - usage_zone = UsBaseUsageParameters._parse_zone_usage_type(zone_usage_type, usage_zone) - usage_zone = UsBaseUsageParameters._parse_zone_usage_variant(usage_zone_variant, usage_zone) - city_object.usage_zone = [usage_zone] - break - continue - city_object.usage_zones = [UsBaseUsageParameters._parse_zone_usage_type(zone_usage_type, usage_zone)] - break - if city_object.usage_zones is None: - raise Exception('Usage not found for building function') - - @staticmethod - def _parse_zone_usage_type(zone_usage_type, usage_zone): - usage_zone.occupancy_density = zone_usage_type['occupancy']['occupancyDensity'] - usage_zone.hours_day = zone_usage_type['occupancy']['usageHoursPerDay'] - usage_zone.days_year = zone_usage_type['occupancy']['usageDaysPerYear'] - usage_zone.cooling_setpoint = zone_usage_type['endUses']['space_cooling']['coolingSetPointTemperature'] - usage_zone.heating_setpoint = zone_usage_type['endUses']['space_heating']['heatingSetPointTemperature'] - usage_zone.heating_setback = zone_usage_type['endUses']['space_heating']['heatingSetBackTemperature'] - # todo: schedules set points!!! - if 'ventilation' in zone_usage_type['endUses'] and zone_usage_type['endUses']['ventilation'] is not None: - usage_zone.mechanical_air_change = zone_usage_type['endUses']['ventilation']['mechanicalAirChangeRate'] - usage_zone.dhw_average_volume_pers_day = \ - zone_usage_type['endUses']['domestic_hot_water']['averageVolumePerPersAndDay'] - usage_zone.dhw_preparation_temperature = \ - zone_usage_type['endUses']['domestic_hot_water']['preparationTemperature'] - # todo: are there more than one of these electrical values? - # todo: schedules!! - if 'all_electrical_appliances' in zone_usage_type['endUses']: - if 'averageConsumptionPerSqmAndYear' in zone_usage_type['endUses']['all_electrical_appliances']: - usage_zone.electrical_app_average_consumption_sqm_year = \ - zone_usage_type['endUses']['all_electrical_appliances']['averageConsumptionPerSqmAndYear'] - - int_gains = InternalGains() - int_gains.latent_fraction = zone_usage_type['occupancy']['internGains']['latentFraction'] - int_gains.convective_fraction = zone_usage_type['occupancy']['internGains']['convectiveFraction'] - int_gains.average_internal_gain = zone_usage_type['occupancy']['internGains']['averageInternGainPerSqm'] - int_gains.radiative_fraction = zone_usage_type['occupancy']['internGains']['radiantFraction'] - usage_zone.internal_gains = [int_gains] - return usage_zone - - @staticmethod - def _parse_zone_usage_variant(usage_zone_variant, usage_zone): - # for the variants all is optional because it mimics the inheritance concept from OOP - if 'usageHoursPerDay' in usage_zone_variant['occupancy']: - usage_zone.hours_day = usage_zone_variant['occupancy']['usageHoursPerDay'] - if 'usageDaysPerYear' in usage_zone_variant['occupancy']: - usage_zone.days_year = usage_zone_variant['occupancy']['usageDaysPerYear'] - if 'coolingSetPointTemperature' in usage_zone_variant['endUses']['space_cooling']: - usage_zone.cooling_setpoint = usage_zone_variant['endUses']['space_cooling']['coolingSetPointTemperature'] - if 'heatingSetPointTemperature' in usage_zone_variant['endUses']['space_heating']: - usage_zone.heating_setpoint = usage_zone_variant['endUses']['space_heating']['heatingSetPointTemperature'] - if 'heatingSetBackTemperature' in usage_zone_variant['endUses']['space_heating']: - usage_zone.heating_setback = usage_zone_variant['endUses']['space_heating']['heatingSetBackTemperature'] - if 'ventilation' in usage_zone_variant['endUses'] and usage_zone_variant['endUses']['ventilation'] is not None: - usage_zone.mechanical_air_change = usage_zone_variant['endUses']['ventilation']['mechanicalAirChangeRate'] - if 'latentFraction' in usage_zone_variant['occupancy']['internGains']: - usage_zone.int_gains[0].latent_fraction = usage_zone_variant['occupancy']['internGains']['latentFraction'] - if 'convectiveFraction' in usage_zone_variant['occupancy']['internGains']: - usage_zone.int_gains[0].convective_fraction = usage_zone_variant['occupancy']['internGains']['convectiveFraction'] - if 'averageInternGainPerSqm' in usage_zone_variant['occupancy']['internGains']: - usage_zone.int_gains[0].average_internal_gain = \ - usage_zone_variant['occupancy']['internGains']['averageInternGainPerSqm'] - if 'radiantFraction' in usage_zone_variant['occupancy']['internGains']: - usage_zone.int_gains[0].radiative_fraction = usage_zone_variant['occupancy']['internGains']['radiantFraction'] - return usage_zone diff --git a/factories/usage_feeders/us_new_york_city_usage_parameters.py b/factories/usage_feeders/us_new_york_city_usage_parameters.py index 25c722d4..68e9de81 100644 --- a/factories/usage_feeders/us_new_york_city_usage_parameters.py +++ b/factories/usage_feeders/us_new_york_city_usage_parameters.py @@ -28,7 +28,8 @@ class UsNewYorkCityUsageParameters(HftUsageInterface): for building in city.buildings: archetype = self._search_archetype(pu.usage(building.function)) if archetype is None: - sys.stderr.write(f'Building {building.name} has unknown archetype for building usage: {building.function}\n') + sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' + f' {building.function}, that assigns building usage as {pu.usage(building.function)}\n') continue # todo: what to do with mix-usage usages from gml? mix_usage = False diff --git a/factories/usage_feeders/us_usage_parameters.py b/factories/usage_feeders/us_usage_parameters.py index c72cbf0b..c1191ad1 100644 --- a/factories/usage_feeders/us_usage_parameters.py +++ b/factories/usage_feeders/us_usage_parameters.py @@ -1,15 +1,60 @@ """ -UsUsageParameters model the usage properties for a Us building +UsUsageParameters model the usage properties for a USA building except those from NYC SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca +Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es """ -from factories.usage_feeders.helpers.us_function_to_usage import UsFunctionToUsage -from factories.usage_feeders.us_base_usage_parameters import UsBaseUsageParameters +import sys + +from factories.usage_feeders.helpers.us_function_to_usage import UsFunctionToUsage as fu +from factories.usage_feeders.hft_usage_interface import HftUsageInterface +from city_model_structure.attributes.usage_zone import UsageZone -class UsUsageParameters(UsBaseUsageParameters): +class UsUsageParameters(HftUsageInterface): """ UsUsageParameters class """ - def __init__(self, city): - super().__init__(city, UsFunctionToUsage.usage) + def __init__(self, city, base_path): + super().__init__(base_path, 'de_library.xml') + self._city = city + + def enrich_buildings(self): + """ + Returns the city with the usage parameters assigned to the buildings + :return: + """ + city = self._city + for building in city.buildings: + archetype = self._search_archetype(fu.usage(building.function)) + if archetype is None: + sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' + f' {building.function}, that assigns building usage as {fu.usage(building.function)}\n') + continue + # todo: what to do with mix-usage usages from gml? + mix_usage = False + if not mix_usage: + # just one usage_zone + usage_zone = UsageZone() + self._assign_values(usage_zone, archetype) + building.usage_zones = [usage_zone] + + def _search_archetype(self, building_usage): + for building_archetype in self._usage_archetypes: + if building_archetype.usage == building_usage: + return building_archetype + return None + + @staticmethod + def _assign_values(usage_zone, archetype): + usage_zone.usage = archetype.usage + usage_zone.internal_gains = archetype.internal_gains + usage_zone.heating_setpoint = archetype.heating_setpoint + usage_zone.heating_setback = archetype.heating_setback + usage_zone.cooling_setpoint = archetype.cooling_setpoint + usage_zone.occupancy_density = archetype.occupancy_density + usage_zone.hours_day = archetype.hours_day + usage_zone.days_year = archetype.days_year + usage_zone.dhw_average_volume_pers_day = archetype.dhw_average_volume_pers_day + usage_zone.dhw_preparation_temperature = archetype.dhw_preparation_temperature + usage_zone.electrical_app_average_consumption_sqm_year = archetype.electrical_app_average_consumption_sqm_year + usage_zone.mechanical_air_change = archetype.mechanical_air_change diff --git a/tests/test_physics_factory.py b/tests/test_physics_factory.py index a3d9b12e..81bfaed5 100644 --- a/tests/test_physics_factory.py +++ b/tests/test_physics_factory.py @@ -23,20 +23,20 @@ class TestPhysicsFactory(TestCase): self._nyc_with_physics = None self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve() - def _get_citygml(self): + def _get_citygml(self, file_path): if self._city_gml is None: - file_path = (self._example_path / 'lod2_buildings.gml').resolve() self._city_gml = GeometryFactory('citygml', file_path).city self.assertIsNotNone(self._city_gml, 'city is none') return self._city_gml def _get_city_with_physics(self): if self._nyc_with_physics is None: - self._nyc_with_physics = self._get_citygml() + file_path = (self._example_path / '20buildings.gml').resolve() + self._nyc_with_physics = self._get_citygml(file_path) PhysicsFactory('us_new_york', self._nyc_with_physics) return self._nyc_with_physics - def test_city_with_physics(self): + def test_city_with_physics_extended_library(self): """ Enrich the city with the physic information and verify it :return: None @@ -56,13 +56,22 @@ class TestPhysicsFactory(TestCase): for thermal_boundary in thermal_zone.bounded: self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') - self.assertIsNotNone(thermal_boundary.layers, 'layers is none') - def test_nrel_interface(self): - city = self._get_citygml() - # todo: extended library using the us case - #PhysicsFactory('us_new_york', city) - print('Extended passed') - # reduced library + def test_reduced_library(self): + file_path = (self._example_path / 'lod2_buildings.gml').resolve() + city = self._get_citygml(file_path) PhysicsFactory('ca', city) - print('Reduced passed') + for building in city.buildings: + self.assertIsNotNone(building.average_storey_height, 'average_storey_height is none') + self.assertIsNotNone(building.storeys_above_ground, 'storeys_above_ground is none') + for thermal_zone in building.thermal_zones: + self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'effective_thermal_capacity is none') + self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, + 'additional_thermal_bridge_u_value is none') + self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, 'indirectly_heated_area_ratio is none') + self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'infiltration_rate_system_on is none') + self.assertIsNotNone(thermal_zone.infiltration_rate_system_off, 'infiltration_rate_system_off is none') + self.assertIsNotNone(thermal_zone.bounded, 'bounded is none') + for thermal_boundary in thermal_zone.bounded: + self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') + self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')