From 7a358806f3947c1284ff6cbd196a6b0ee51c1d83 Mon Sep 17 00:00:00 2001 From: Pilar Date: Mon, 21 Nov 2022 11:03:28 -0500 Subject: [PATCH] starting with the nrcan_usage_parameters class. Not working! --- .../data_models/usages/internal_gain.py | 1 + catalog_factories/usage/comnet_catalog.py | 4 +- .../building_demand/internal_zone.py | 4 +- .../building_demand/thermal_zone.py | 4 +- .../{usage_zone.py => usage.py} | 18 ++++----- exports/formats/energy_ade.py | 2 +- exports/formats/idf.py | 28 +++++++------- imports/geometry/helpers/geometry_helper.py | 4 ++ .../schedules/comnet_schedules_parameters.py | 2 +- imports/schedules/doe_idf.py | 2 +- imports/usage/comnet_usage_parameters.py | 8 ++-- imports/usage/hft_usage_interface.py | 14 +++---- imports/usage/nrcan_usage_parameters.py | 38 +++++++++++++++++++ unittests/test_construction_factory.py | 2 +- unittests/test_enrichement.py | 2 +- unittests/test_usage_factory.py | 2 +- 16 files changed, 89 insertions(+), 46 deletions(-) rename city_model_structure/building_demand/{usage_zone.py => usage.py} (97%) create mode 100644 imports/usage/nrcan_usage_parameters.py diff --git a/catalog_factories/data_models/usages/internal_gain.py b/catalog_factories/data_models/usages/internal_gain.py index ee7a0ec8..f1d8ad7f 100644 --- a/catalog_factories/data_models/usages/internal_gain.py +++ b/catalog_factories/data_models/usages/internal_gain.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class InternalGain: """ InternalGain class diff --git a/catalog_factories/usage/comnet_catalog.py b/catalog_factories/usage/comnet_catalog.py index e2fb294d..0667d94d 100644 --- a/catalog_factories/usage/comnet_catalog.py +++ b/catalog_factories/usage/comnet_catalog.py @@ -220,7 +220,7 @@ class ComnetCatalog(Catalog): """ _names = {'usages': []} for usage in self._content.usages: - _names['usages'].append(usage.usage) + _names['usages'].append(usage.name) return _names def entries(self, category=None): @@ -236,6 +236,6 @@ class ComnetCatalog(Catalog): :parm: entry name """ for usage in self._content.usages: - if usage.usage.lower() == name.lower(): + if usage.name.lower() == name.lower(): return usage raise IndexError(f"{name} doesn't exists in the catalog") diff --git a/city_model_structure/building_demand/internal_zone.py b/city_model_structure/building_demand/internal_zone.py index 8c1d3376..6c1a536e 100644 --- a/city_model_structure/building_demand/internal_zone.py +++ b/city_model_structure/building_demand/internal_zone.py @@ -7,7 +7,7 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca import uuid from typing import Union, List -from city_model_structure.building_demand.usage_zone import UsageZone +from city_model_structure.building_demand.usage import Usage from city_model_structure.building_demand.thermal_zone import ThermalZone from city_model_structure.attributes.polyhedron import Polyhedron from city_model_structure.energy_systems.hvac_system import HvacSystem @@ -75,7 +75,7 @@ class InternalZone: return self._area @property - def usage_zones(self) -> [UsageZone]: + def usage_zones(self) -> [Usage]: """ Get internal zone usage zones :return: [UsageZone] diff --git a/city_model_structure/building_demand/thermal_zone.py b/city_model_structure/building_demand/thermal_zone.py index 417a6b39..f3b09d1f 100644 --- a/city_model_structure/building_demand/thermal_zone.py +++ b/city_model_structure/building_demand/thermal_zone.py @@ -67,7 +67,7 @@ class ThermalZone: self._usage_zones = [] for parent_usage_zone in self._parent_internal_zone.usage_zones: for value in usages: - if parent_usage_zone.usage == value[1]: + if parent_usage_zone.name == value[1]: new_usage_zone = copy.deepcopy(parent_usage_zone) new_usage_zone.percentage = float(value[0])/100 self._usage_zones.append(new_usage_zone) @@ -234,7 +234,7 @@ class ThermalZone: return None self._usage = '' for usage_zone in self._parent_internal_zone.usage_zones: - self._usage += str(round(usage_zone.percentage * 100)) + '-' + usage_zone.usage + '_' + self._usage += str(round(usage_zone.percentage * 100)) + '-' + usage_zone.name + '_' self._usage = self._usage[:-1] return self._usage diff --git a/city_model_structure/building_demand/usage_zone.py b/city_model_structure/building_demand/usage.py similarity index 97% rename from city_model_structure/building_demand/usage_zone.py rename to city_model_structure/building_demand/usage.py index 225f9cb2..0a86b625 100644 --- a/city_model_structure/building_demand/usage_zone.py +++ b/city_model_structure/building_demand/usage.py @@ -1,5 +1,5 @@ """ -UsageZone module +Usage 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 @@ -15,13 +15,13 @@ from city_model_structure.building_demand.thermal_control import ThermalControl from city_model_structure.building_demand.internal_gain import InternalGain -class UsageZone: +class Usage: """ - UsageZone class + Usage class """ def __init__(self): self._id = None - self._usage = None + self._name = None self._percentage = None self._internal_gains = None self._hours_day = None @@ -44,21 +44,21 @@ class UsageZone: return self._id @property - def usage(self) -> Union[None, str]: + def name(self) -> Union[None, str]: """ Get usage zone usage :return: None or str """ - return self._usage + return self._name - @usage.setter - def usage(self, value): + @name.setter + def name(self, value): """ Set usage zone usage :param value: str """ if value is not None: - self._usage = str(value) + self._name = str(value) @property def percentage(self): diff --git a/exports/formats/energy_ade.py b/exports/formats/energy_ade.py index 8e618f4f..9b9d1e6e 100644 --- a/exports/formats/energy_ade.py +++ b/exports/formats/energy_ade.py @@ -169,7 +169,7 @@ class EnergyAde: def _building_geometry(self, building, building_dic, city): building_dic['bldg:Building']['bldg:function'] = building.function - building_dic['bldg:Building']['bldg:usage'] = ', '.join([u.usage for u in building.usage_zones]) + building_dic['bldg:Building']['bldg:usage'] = ', '.join([u.name for u in building.usage_zones]) building_dic['bldg:Building']['bldg:yearOfConstruction'] = building.year_of_construction building_dic['bldg:Building']['bldg:roofType'] = building.roof_type building_dic['bldg:Building']['bldg:measuredHeight'] = { diff --git a/exports/formats/idf.py b/exports/formats/idf.py index 5972a991..f5487b78 100644 --- a/exports/formats/idf.py +++ b/exports/formats/idf.py @@ -226,9 +226,9 @@ class Idf: _schedule.values = _infiltration_values _infiltration_schedules.append(_schedule) for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]: - if schedule.Name == f'Infiltration schedules {thermal_zone.usage}': + if schedule.Name == f'Infiltration schedules {thermal_zone.name}': return - return self._add_standard_compact_hourly_schedule(thermal_zone.usage, 'Infiltration', _infiltration_schedules) + return self._add_standard_compact_hourly_schedule(thermal_zone.name, 'Infiltration', _infiltration_schedules) def _add_people_activity_level_schedules(self, thermal_zone): _occ = thermal_zone.occupancy @@ -238,9 +238,9 @@ class Idf: _total_heat = (_occ.sensible_convective_internal_gain + _occ.sensible_radiative_internal_gain + _occ.latent_internal_gain) / _occ.occupancy_density for schedule in self._idf.idfobjects[self._COMPACT_SCHEDULE]: - if schedule.Name == f'Activity Level schedules {thermal_zone.usage}': + if schedule.Name == f'Activity Level schedules {thermal_zone.name}': return - _kwargs = {'Name': f'Activity Level schedules {thermal_zone.usage}', + _kwargs = {'Name': f'Activity Level schedules {thermal_zone.name}', 'Schedule_Type_Limits_Name': self.idf_type_limits[cte.ANY_NUMBER], 'Field_1': 'Through: 12/31', 'Field_2': 'For AllDays', @@ -319,15 +319,15 @@ class Idf: self._add_heating_system(thermal_zone, name) def _add_thermostat(self, thermal_zone): - thermostat_name = f'Thermostat {thermal_zone.usage}' + thermostat_name = f'Thermostat {thermal_zone.name}' for thermostat in self._idf.idfobjects[self._THERMOSTAT]: if thermostat.Name == thermostat_name: return thermostat # todo: change schedules to schedule name and create schedules using the add_schedule function return self._idf.newidfobject(self._THERMOSTAT, Name=thermostat_name, - Heating_Setpoint_Schedule_Name=f'Heating thermostat schedules {thermal_zone.usage}', - Cooling_Setpoint_Schedule_Name=f'Cooling thermostat schedules {thermal_zone.usage}') + Heating_Setpoint_Schedule_Name=f'Heating thermostat schedules {thermal_zone.name}', + Cooling_Setpoint_Schedule_Name=f'Cooling thermostat schedules {thermal_zone.name}') def _add_heating_system(self, thermal_zone, zone_name): for air_system in self._idf.idfobjects[self._IDEAL_LOAD_AIR_SYSTEM]: @@ -336,9 +336,9 @@ class Idf: thermostat = self._add_thermostat(thermal_zone) self._idf.newidfobject(self._IDEAL_LOAD_AIR_SYSTEM, Zone_Name=zone_name, - System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}', - Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}', - Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}', + System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.name}', + Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.name}', + Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.name}', Template_Thermostat_Name=thermostat.Name) def _add_occupancy(self, thermal_zone, zone_name): @@ -349,11 +349,11 @@ class Idf: self._idf.newidfobject(self._PEOPLE, Name=f'{zone_name}_occupancy', Zone_or_ZoneList_Name=zone_name, - Number_of_People_Schedule_Name=f'Occupancy schedules {thermal_zone.usage}', + Number_of_People_Schedule_Name=f'Occupancy schedules {thermal_zone.name}', Number_of_People_Calculation_Method="People", Number_of_People=number_of_people, Fraction_Radiant=fraction_radiant, - Activity_Level_Schedule_Name=f'Activity Level schedules {thermal_zone.usage}' + Activity_Level_Schedule_Name=f'Activity Level schedules {thermal_zone.name}' ) def _add_infiltration(self, thermal_zone, zone_name): @@ -363,7 +363,7 @@ class Idf: self._idf.newidfobject(self._INFILTRATION, Name=f'{zone_name}_infiltration', Zone_or_ZoneList_Name=zone_name, - Schedule_Name=f'Infiltration schedules {thermal_zone.usage}', + Schedule_Name=f'Infiltration schedules {thermal_zone.name}', Design_Flow_Rate_Calculation_Method='AirChanges/Hour', Air_Changes_per_Hour=thermal_zone.mechanical_air_change ) @@ -405,7 +405,7 @@ class Idf: self._add_vegetation_material(thermal_boundary.parent_surface.vegetation) for thermal_opening in thermal_boundary.thermal_openings: self._add_window_construction_and_material(thermal_opening) - usage = thermal_zone.usage + usage = thermal_zone.name if building.name in self._target_buildings or building.name in self._adjacent_buildings: self._add_infiltration_schedules(thermal_zone) self._add_schedules(usage, 'Occupancy', thermal_zone.occupancy.occupancy_schedules) diff --git a/imports/geometry/helpers/geometry_helper.py b/imports/geometry/helpers/geometry_helper.py index 8a9f5951..b43487d4 100644 --- a/imports/geometry/helpers/geometry_helper.py +++ b/imports/geometry/helpers/geometry_helper.py @@ -228,6 +228,10 @@ class GeometryHelper: 'office': cte.MEDIUM_OFFICE, 'large office': cte.LARGE_OFFICE } + # function + _alkis_to_function = { + + } # usage _function_to_usage = { diff --git a/imports/schedules/comnet_schedules_parameters.py b/imports/schedules/comnet_schedules_parameters.py index deaca3b0..0f957306 100644 --- a/imports/schedules/comnet_schedules_parameters.py +++ b/imports/schedules/comnet_schedules_parameters.py @@ -23,7 +23,7 @@ class ComnetSchedules: for usage_zone in building.usage_zones: schedules = [] usage_schedules = pd.read_excel(xls, - sheet_name=SchedulesHelper.comnet_from_usage(usage_zone.usage), + sheet_name=SchedulesHelper.comnet_from_usage(usage_zone.name), skiprows=[0, 1, 2, 3], nrows=39, usecols="A:AA") number_of_schedule_types = 13 schedules_per_schedule_type = 3 diff --git a/imports/schedules/doe_idf.py b/imports/schedules/doe_idf.py index eeb72168..18048efc 100644 --- a/imports/schedules/doe_idf.py +++ b/imports/schedules/doe_idf.py @@ -59,7 +59,7 @@ class DoeIdf: for usage_zone in internal_zone.usage_zones: for schedule_archetype in self._schedule_library['archetypes']['archetypes']: function = schedule_archetype['@building_type'] - if SchedulesHelper.usage_from_function(function) == usage_zone.usage: + if SchedulesHelper.usage_from_function(function) == usage_zone.name: self._idf_schedules_path = (base_path / schedule_archetype['idf']['path']).resolve() with open(self._idf_schedules_path, 'r') as file: idf = parseidf.parse(file.read()) diff --git a/imports/usage/comnet_usage_parameters.py b/imports/usage/comnet_usage_parameters.py index 8ad563f9..a9505f83 100644 --- a/imports/usage/comnet_usage_parameters.py +++ b/imports/usage/comnet_usage_parameters.py @@ -15,7 +15,7 @@ from helpers.configuration_helper import ConfigurationHelper as ch from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.usage.helpers.usage_helper import UsageHelper from imports.schedules.helpers.schedules_helper import SchedulesHelper -from city_model_structure.building_demand.usage_zone import UsageZone +from city_model_structure.building_demand.usage import Usage from city_model_structure.building_demand.lighting import Lighting from city_model_structure.building_demand.occupancy import Occupancy from city_model_structure.building_demand.appliances import Appliances @@ -74,7 +74,7 @@ class ComnetUsageParameters: @staticmethod def _parse_usage_type(comnet_usage, data, schedules_data): - _usage_zone = UsageZone() + _usage_zone = Usage() # lighting _lighting = Lighting() @@ -213,8 +213,8 @@ class ComnetUsageParameters: if internal_zone.volume <= 0: raise Exception('Internal zone volume is zero, ACH cannot be calculated') volume_per_area = internal_zone.volume / internal_zone.area - usage_zone = UsageZone() - usage_zone.usage = usage + usage_zone = Usage() + usage_zone.name = usage self._assign_values_usage_zone(usage_zone, archetype_usage, volume_per_area) usage_zone.percentage = 1 self._calculate_reduced_values_from_extended_library(usage_zone, archetype_usage) diff --git a/imports/usage/hft_usage_interface.py b/imports/usage/hft_usage_interface.py index 0eeea969..e44832d4 100644 --- a/imports/usage/hft_usage_interface.py +++ b/imports/usage/hft_usage_interface.py @@ -7,7 +7,7 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ import xmltodict import copy -from city_model_structure.building_demand.usage_zone import UsageZone +from city_model_structure.building_demand.usage import Usage from city_model_structure.building_demand.internal_gain import InternalGain from city_model_structure.building_demand.occupancy import Occupancy from city_model_structure.building_demand.appliances import Appliances @@ -39,8 +39,8 @@ class HftUsageInterface: @staticmethod def _parse_zone_usage_type(usage, zone_usage_type): - usage_zone_archetype = UsageZone() - usage_zone_archetype.usage = usage + usage_zone_archetype = Usage() + usage_zone_archetype.name = usage if 'occupancy' in zone_usage_type: _occupancy = Occupancy() @@ -153,7 +153,7 @@ class HftUsageInterface: def _parse_zone_usage_variant(usage, usage_zone, usage_zone_variant): # the variants mimic the inheritance concept from OOP usage_zone_archetype = copy.deepcopy(usage_zone) - usage_zone_archetype.usage = usage + usage_zone_archetype.name = usage if 'occupancy' in usage_zone_variant: _occupancy = Occupancy() @@ -262,14 +262,14 @@ class HftUsageInterface: def _search_archetype(self, libs_usage): building_usage = UsageHelper().hft_from_libs_usage(libs_usage) for building_archetype in self._usage_archetypes: - if building_archetype.usage == building_usage: + if building_archetype.name == building_usage: return building_archetype return None @staticmethod def _assign_values(usage, archetype): - usage_zone = UsageZone() - usage_zone.usage = usage + usage_zone = Usage() + usage_zone.name = usage usage_zone.internal_gains = copy.deepcopy(archetype.internal_gains) usage_zone.mechanical_air_change = archetype.mechanical_air_change usage_zone.occupancy = copy.deepcopy(archetype.occupancy) diff --git a/imports/usage/nrcan_usage_parameters.py b/imports/usage/nrcan_usage_parameters.py new file mode 100644 index 00000000..19034827 --- /dev/null +++ b/imports/usage/nrcan_usage_parameters.py @@ -0,0 +1,38 @@ +""" +NrcanUsageParameters imports the usage information for Canada and feeds the central data model classes with it +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 catalog_factories.usage_catalog_factory import UsageCatalogFactory + +class NrcanUsageParameters: + """ + NrcanUsageParameters class + """ + @staticmethod + def _search_archetype(usage_name, year_of_construction, climate_zone): + nrcan_catalog = UsageCatalogFactory('nrcan').catalog + nrcan_archetypes = nrcan_catalog.entries('archetypes') + for building_archetype in nrcan_archetypes: + + return None + + @staticmethod + def _search_usage_in_archetype(archetype, usage_name): + usage_archetypes = archetype. + for usage_archetype in archetypes_archetypes: + if str(usage_name) == str(usage_archetype.type): + return usage_archetype + return None + + def _assign_values(self, usage, archetype): + for thermal_zone in thermal_zones: + thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges + + def enrich_buildings(self): + """ + Raise not implemented error + """ + raise NotImplementedError diff --git a/unittests/test_construction_factory.py b/unittests/test_construction_factory.py index 6ca15a2c..a3f43e38 100644 --- a/unittests/test_construction_factory.py +++ b/unittests/test_construction_factory.py @@ -122,7 +122,7 @@ class TestConstructionFactory(TestCase): self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not none') self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none') self.assertIsNotNone(thermal_zone.total_floor_area, 'thermal zone total_floor_area is none') - self.assertIsNone(thermal_zone.usage, 'thermal_zone usage is not none') + self.assertIsNone(thermal_zone.name, 'thermal_zone usage is not none') self.assertIsNone(thermal_zone.hours_day, 'thermal_zone hours a day is not none') self.assertIsNone(thermal_zone.days_year, 'thermal_zone days a year is not none') self.assertIsNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is not none') diff --git a/unittests/test_enrichement.py b/unittests/test_enrichement.py index 16831dea..f8cc2011 100644 --- a/unittests/test_enrichement.py +++ b/unittests/test_enrichement.py @@ -55,7 +55,7 @@ class TestGeometryFactory(TestCase): def _check_thermal_zone(self, thermal_zone): self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none') - self.assertIsNotNone(thermal_zone.usage, 'thermal_zone usage is not none') + self.assertIsNotNone(thermal_zone.name, 'thermal_zone usage is not none') self.assertIsNotNone(thermal_zone.hours_day, 'thermal_zone hours a day is none') self.assertIsNotNone(thermal_zone.days_year, 'thermal_zone days a year is none') self.assertIsNotNone(thermal_zone.occupancy, 'thermal_zone occupancy is none') diff --git a/unittests/test_usage_factory.py b/unittests/test_usage_factory.py index 15138579..0267f703 100644 --- a/unittests/test_usage_factory.py +++ b/unittests/test_usage_factory.py @@ -70,7 +70,7 @@ class TestUsageFactory(TestCase): self.assertTrue(building.is_conditioned, 'building is not conditioned') def _check_usage_zone(self, usage_zone): - self.assertIsNotNone(usage_zone.usage, 'usage is none') + self.assertIsNotNone(usage_zone.name, 'usage is none') self.assertIsNotNone(usage_zone.percentage, 'usage percentage is none') self.assertIsNotNone(usage_zone.hours_day, 'hours per day is none') self.assertIsNotNone(usage_zone.days_year, 'days per year is none')