From 4e46b6bc0de7ac8115f750e7c020bcf59c466d5e Mon Sep 17 00:00:00 2001 From: s_ranjbar Date: Fri, 18 Oct 2024 12:28:38 +0200 Subject: [PATCH] fix: the small bug in test units is resolved, the construction and usage factories can be loaded without any order --- hub/imports/usage/comnet_usage_parameters.py | 48 +++++++++++++++++-- hub/imports/usage/nrcan_usage_parameters.py | 49 ++++++++++++++++++-- tests/test_usage_factory.py | 2 +- 3 files changed, 89 insertions(+), 10 deletions(-) diff --git a/hub/imports/usage/comnet_usage_parameters.py b/hub/imports/usage/comnet_usage_parameters.py index a48089fd..a3a6a613 100644 --- a/hub/imports/usage/comnet_usage_parameters.py +++ b/hub/imports/usage/comnet_usage_parameters.py @@ -19,6 +19,8 @@ from hub.city_model_structure.building_demand.domestic_hot_water import Domestic from hub.city_model_structure.attributes.schedule import Schedule from hub.city_model_structure.building_demand.internal_gain import InternalGain from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory +from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory +from hub.imports.construction.helpers.construction_helper import ConstructionHelper class ComnetUsageParameters: @@ -73,11 +75,13 @@ class ComnetUsageParameters: self._calculate_reduced_values_from_extended_library(usage, comnet_archetype_usages[i]) internal_zone_usages.append(usage) else: - if building.storeys_above_ground is None: - logging.error('Building %s no number of storeys assigned, ACH cannot be calculated for usage %s', - building.name, usages) - continue - volume_per_area = building.volume / building.floor_area / building.storeys_above_ground + storeys_above_ground = building.storeys_above_ground + if storeys_above_ground is None: + logging.error('Building %s no number of storeys assigned, ACH cannot be calculated for usage %s. ' + 'NRCAN construction data for the year %s is used to calculated number of storeys above ' + 'ground', building.name, usages, building.year_of_construction) + storeys_above_ground = self.average_storey_height_calculator(self._city, building) + volume_per_area = building.volume / building.floor_area / storeys_above_ground for (j, mixed_usage) in enumerate(usages): usage = Usage() usage.name = mixed_usage[-1] @@ -261,3 +265,37 @@ class ComnetUsageParameters: _mean_internal_gain.schedules = _schedules return [_mean_internal_gain] + + @staticmethod + def average_storey_height_calculator(city, building): + climate_zone = ConstructionHelper.city_to_nrcan_climate_zone(city.climate_reference_city) + nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog + main_function = None + functions = building.function.split('_') + if len(functions) > 1: + maximum_percentage = 0 + for function in functions: + percentage_and_function = function.split('-') + if float(percentage_and_function[0]) > maximum_percentage: + maximum_percentage = float(percentage_and_function[0]) + main_function = percentage_and_function[-1] + else: + main_function = functions[-1] + if main_function not in Dictionaries().hub_function_to_nrcan_construction_function: + logging.error('Building %s has an unknown building function %s', building.name, main_function) + function = Dictionaries().hub_function_to_nrcan_construction_function[main_function] + construction_archetype = None + average_storey_height = None + nrcan_archetypes = nrcan_catalog.entries('archetypes') + for building_archetype in nrcan_archetypes: + construction_period_limits = building_archetype.construction_period.split('_') + if int(construction_period_limits[0]) <= int(building.year_of_construction) <= int(construction_period_limits[1]): + if str(function) == str(building_archetype.function) and climate_zone == str(building_archetype.climate_zone): + construction_archetype = building_archetype + average_storey_height = building_archetype.average_storey_height + if construction_archetype is None: + logging.error('Building %s has unknown construction archetype for building function: %s ' + '[%s], building year of construction: %s and climate zone %s', building.name, function, + building.function, building.year_of_construction, climate_zone) + + return average_storey_height \ No newline at end of file diff --git a/hub/imports/usage/nrcan_usage_parameters.py b/hub/imports/usage/nrcan_usage_parameters.py index 9c88bc05..854d7051 100644 --- a/hub/imports/usage/nrcan_usage_parameters.py +++ b/hub/imports/usage/nrcan_usage_parameters.py @@ -9,6 +9,7 @@ Project Collaborator Saeed Ranjbar saeed.ranjbar@concordia.ca import logging import hub.helpers.constants as cte +from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory from hub.helpers.dictionaries import Dictionaries from hub.city_model_structure.building_demand.usage import Usage from hub.city_model_structure.building_demand.lighting import Lighting @@ -17,6 +18,7 @@ from hub.city_model_structure.building_demand.appliances import Appliances from hub.city_model_structure.building_demand.thermal_control import ThermalControl from hub.city_model_structure.building_demand.domestic_hot_water import DomesticHotWater from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory +from hub.imports.construction.helpers.construction_helper import ConstructionHelper class NrcanUsageParameters: @@ -82,11 +84,14 @@ class NrcanUsageParameters: self._calculate_reduced_values_from_extended_library(usage, nrcan_archetype_usages[i]) internal_zone_usages.append(usage) else: - if building.storeys_above_ground is None: - logging.error('Building %s no number of storeys assigned, ACH cannot be calculated for usage %s', - building.name, usages) + storeys_above_ground = building.storeys_above_ground + if storeys_above_ground is None: + logging.error('Building %s no number of storeys assigned, ACH cannot be calculated for usage %s. ' + 'NRCAN construction data for the year %s is used to calculated number of storeys above ' + 'ground', building.name, usages, building.year_of_construction) + storeys_above_ground = self.average_storey_height_calculator(self._city, building) continue - volume_per_area = building.volume / building.floor_area / building.storeys_above_ground + volume_per_area = building.volume / building.floor_area / storeys_above_ground for (j, mixed_usage) in enumerate(usages): usage = Usage() usage.name = mixed_usage[-1] @@ -217,3 +222,39 @@ class NrcanUsageParameters: usage.thermal_control.mean_heating_set_point = max_heating_setpoint usage.thermal_control.heating_set_back = min_heating_setpoint usage.thermal_control.mean_cooling_set_point = min_cooling_setpoint + + @staticmethod + def average_storey_height_calculator(city, building): + climate_zone = ConstructionHelper.city_to_nrcan_climate_zone(city.climate_reference_city) + nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog + main_function = None + functions = building.function.split('_') + if len(functions) > 1: + maximum_percentage = 0 + for function in functions: + percentage_and_function = function.split('-') + if float(percentage_and_function[0]) > maximum_percentage: + maximum_percentage = float(percentage_and_function[0]) + main_function = percentage_and_function[-1] + else: + main_function = functions[-1] + if main_function not in Dictionaries().hub_function_to_nrcan_construction_function: + logging.error('Building %s has an unknown building function %s', building.name, main_function) + function = Dictionaries().hub_function_to_nrcan_construction_function[main_function] + construction_archetype = None + average_storey_height = None + nrcan_archetypes = nrcan_catalog.entries('archetypes') + for building_archetype in nrcan_archetypes: + construction_period_limits = building_archetype.construction_period.split('_') + if int(construction_period_limits[0]) <= int(building.year_of_construction) <= int(construction_period_limits[1]): + if str(function) == str(building_archetype.function) and climate_zone == str(building_archetype.climate_zone): + construction_archetype = building_archetype + average_storey_height = building_archetype.average_storey_height + if construction_archetype is None: + logging.error('Building %s has unknown construction archetype for building function: %s ' + '[%s], building year of construction: %s and climate zone %s', building.name, function, + building.function, building.year_of_construction, climate_zone) + + return average_storey_height + + diff --git a/tests/test_usage_factory.py b/tests/test_usage_factory.py index 6b6d821a..5c180f09 100644 --- a/tests/test_usage_factory.py +++ b/tests/test_usage_factory.py @@ -83,7 +83,7 @@ class TestUsageFactory(TestCase): city = self._get_citygml(file) for building in city.buildings: building.function = Dictionaries().pluto_function_to_hub_function[building.function] - + ConstructionFactory('nrcan', city).enrich() UsageFactory('comnet', city).enrich() self._check_buildings(city) for building in city.buildings: