From 07926fcd10da270075c58f2f1dd8b9a3762da2a1 Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 12:24:57 -0400 Subject: [PATCH 1/9] Add c40 --- exports/formats/idf.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/exports/formats/idf.py b/exports/formats/idf.py index 842ae3ce..23c2e469 100644 --- a/exports/formats/idf.py +++ b/exports/formats/idf.py @@ -41,14 +41,6 @@ class Idf: IDF.setiddname(self._idd_file_path) self._idf = IDF(self._idf_file_path, self._epw_file_path) - def _add_components(self, building): - for zone in building.usage_zones: - self._add_occupancy_schedule(zone) - self._add_heating_system(zone) - for zone in building.thermal_zones: - for boundary in zone.bounded: - self._add_construction(boundary) - def _add_material(self, layer): for material in self._idf.idfobjects[self._MATERIAL]: if material.Name == layer.material.name: @@ -260,10 +252,9 @@ class Idf: for building in city.buildings: if export_type == "Surfaces": self._add_surfaces(building) - else + else: self._add_block(building) - def _add_block(self, building): _points = self._matrix_to_2d_list(building.foot_print.coordinates) self._idf.add_block(name=building.name, coordinates=_points, height=building.max_height, From 49d97de3ddf1528318f9a045712a37c9025fcc66 Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 15:11:00 -0400 Subject: [PATCH 2/9] idf changes --- city_model_structure/building.py | 1 + .../building_demand/thermal_opening.py | 2 + .../building_demand/thermal_zone.py | 2 +- exports/formats/idf.py | 253 ++++++++---------- .../helpers/construction_helper.py | 2 +- non_functional_tests/tests_data/C40_Final.gml | 29 +- 6 files changed, 130 insertions(+), 159 deletions(-) diff --git a/city_model_structure/building.py b/city_model_structure/building.py index 38364726..95c8d56f 100644 --- a/city_model_structure/building.py +++ b/city_model_structure/building.py @@ -113,6 +113,7 @@ class Building(CityObject): """ if len(self._usage_zones) == 0: for thermal_zone in self.thermal_zones: + print('thermal zone') self._usage_zones.extend(thermal_zone.usage_zones) return self._usage_zones diff --git a/city_model_structure/building_demand/thermal_opening.py b/city_model_structure/building_demand/thermal_opening.py index 5eb6f4b0..01aebd2d 100644 --- a/city_model_structure/building_demand/thermal_opening.py +++ b/city_model_structure/building_demand/thermal_opening.py @@ -127,6 +127,8 @@ class ThermalOpening: if self._overall_u_value is None and self.conductivity is not None: h_i = self.hi h_e = self.he + h_i = 1 + h_e = 1 r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness) self._overall_u_value = 1 / r_value diff --git a/city_model_structure/building_demand/thermal_zone.py b/city_model_structure/building_demand/thermal_zone.py index b88a1d86..f5fcdf02 100644 --- a/city_model_structure/building_demand/thermal_zone.py +++ b/city_model_structure/building_demand/thermal_zone.py @@ -25,7 +25,7 @@ class ThermalZone: self._indirectly_heated_area_ratio = None self._infiltration_rate_system_on = None self._infiltration_rate_system_off = None - self._usage_zones = None + self._usage_zones = [] self._volume = None self._volume_geometry = None self._id = None diff --git a/exports/formats/idf.py b/exports/formats/idf.py index 23c2e469..57707351 100644 --- a/exports/formats/idf.py +++ b/exports/formats/idf.py @@ -4,11 +4,6 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Soroush Samareh Abolhassani - soroush.samarehabolhassani@mail.concordia.ca """ from geomeppy import IDF -import os -import esoreader -from pathlib import Path -from city_model_structure.city import City - class Idf: _THERMOSTAT = 'HVACTEMPLATE:THERMOSTAT' @@ -18,9 +13,13 @@ class Idf: _MATERIAL = 'MATERIAL' _MATERIAL_NOMASS = 'MATERIAL:NOMASS' _ROUGHNESS = "MediumRough" - _OCCUPANCY_HOURLY_SCHEDULE = "SCHEDULE:DAY:HOURLY" + _HOURLY_SCHEDULE = "SCHEDULE:DAY:HOURLY" _ZONE = "ZONE" _LIGHTS = "LIGHTS" + _PEOPLE = "PEOPLE" + _ELECTRIC_EQUIPMEN = "ELECTRICEQUIPMENT" + _INFILTRATION = "ZONEINFILTRATION:DESIGNFLOWRATE" + _BUILDING_SURFACE = "BuildingSurfaceDetailed" idf_surfaces = { # todo: make an enum for all the surface types @@ -41,6 +40,22 @@ class Idf: IDF.setiddname(self._idd_file_path) self._idf = IDF(self._idf_file_path, self._epw_file_path) + @staticmethod + def _matrix_to_list(points): + points_list = [] + for point in points: + point_tuple = (point[0], point[1], point[2]) + points_list.append(point_tuple) + return points_list + + @staticmethod + def _matrix_to_2d_list(points): + points_list = [] + for point in points: + point_tuple = (point[0], point[1]) + points_list.append(point_tuple) + return points_list + def _add_material(self, layer): for material in self._idf.idfobjects[self._MATERIAL]: if material.Name == layer.material.name: @@ -74,32 +89,34 @@ class Idf: for schedule in self._idf.idfobjects[schedule_type]: if schedule.Name == f'{schedule_type} schedules {usage_zone.usage}': return - schedule_occupancy = self._idf.newidfobject(self._OCCUPANCY_HOURLY_SCHEDULE) - schedule_occupancy.Name = f'occupant schedules {usage_zone.usage}' - schedule_occupancy.Hour_1 = usage_zone.schedules[schedule_type] .occupants.occupant_schedule[0] - schedule_occupancy.Hour_2 = usage_zone.occupants.occupant_schedule[1] - schedule_occupancy.Hour_3 = usage_zone.occupants.occupant_schedule[2] - schedule_occupancy.Hour_4 = usage_zone.occupants.occupant_schedule[3] - schedule_occupancy.Hour_5 = usage_zone.occupants.occupant_schedule[4] - schedule_occupancy.Hour_6 = usage_zone.occupants.occupant_schedule[5] - schedule_occupancy.Hour_7 = usage_zone.occupants.occupant_schedule[6] - schedule_occupancy.Hour_8 = usage_zone.occupants.occupant_schedule[7] - schedule_occupancy.Hour_9 = usage_zone.occupants.occupant_schedule[8] - schedule_occupancy.Hour_10 = usage_zone.occupants.occupant_schedule[9] - schedule_occupancy.Hour_11 = usage_zone.occupants.occupant_schedule[10] - schedule_occupancy.Hour_12 = usage_zone.occupants.occupant_schedule[11] - schedule_occupancy.Hour_13 = usage_zone.occupants.occupant_schedule[12] - schedule_occupancy.Hour_14 = usage_zone.occupants.occupant_schedule[13] - schedule_occupancy.Hour_15 = usage_zone.occupants.occupant_schedule[14] - schedule_occupancy.Hour_16 = usage_zone.occupants.occupant_schedule[15] - schedule_occupancy.Hour_17 = usage_zone.occupants.occupant_schedule[16] - schedule_occupancy.Hour_18 = usage_zone.occupants.occupant_schedule[17] - schedule_occupancy.Hour_19 = usage_zone.occupants.occupant_schedule[18] - schedule_occupancy.Hour_20 = usage_zone.occupants.occupant_schedule[19] - schedule_occupancy.Hour_21 = usage_zone.occupants.occupant_schedule[20] - schedule_occupancy.Hour_22 = usage_zone.occupants.occupant_schedule[21] - schedule_occupancy.Hour_23 = usage_zone.occupants.occupant_schedule[22] - schedule_occupancy.Hour_24 = usage_zone.occupants.occupant_schedule[23] + schedule = self._idf.newidfobject(self._HOURLY_SCHEDULE) + schedule.Name = f'{schedule_type} schedules {usage_zone.usage}' + schedule.Schedule_Type_Limits_Name = 'Any Number' + + schedule.Hour_1 = usage_zone.schedules[schedule_type]["WD"][0] + schedule.Hour_2 = usage_zone.schedules[schedule_type]["WD"][1] + schedule.Hour_3 = usage_zone.schedules[schedule_type]["WD"][2] + schedule.Hour_4 = usage_zone.schedules[schedule_type]["WD"][3] + schedule.Hour_5 = usage_zone.schedules[schedule_type]["WD"][4] + schedule.Hour_6 = usage_zone.schedules[schedule_type]["WD"][5] + schedule.Hour_7 = usage_zone.schedules[schedule_type]["WD"][6] + schedule.Hour_8 = usage_zone.schedules[schedule_type]["WD"][7] + schedule.Hour_9 = usage_zone.schedules[schedule_type]["WD"][8] + schedule.Hour_10 = usage_zone.schedules[schedule_type]["WD"][9] + schedule.Hour_11 = usage_zone.schedules[schedule_type]["WD"][10] + schedule.Hour_12 = usage_zone.schedules[schedule_type]["WD"][11] + schedule.Hour_13 = usage_zone.schedules[schedule_type]["WD"][12] + schedule.Hour_14 = usage_zone.schedules[schedule_type]["WD"][13] + schedule.Hour_15 = usage_zone.schedules[schedule_type]["WD"][14] + schedule.Hour_16 = usage_zone.schedules[schedule_type]["WD"][15] + schedule.Hour_17 = usage_zone.schedules[schedule_type]["WD"][16] + schedule.Hour_18 = usage_zone.schedules[schedule_type]["WD"][17] + schedule.Hour_19 = usage_zone.schedules[schedule_type]["WD"][18] + schedule.Hour_20 = usage_zone.schedules[schedule_type]["WD"][19] + schedule.Hour_21 = usage_zone.schedules[schedule_type]["WD"][20] + schedule.Hour_22 = usage_zone.schedules[schedule_type]["WD"][21] + schedule.Hour_23 = usage_zone.schedules[schedule_type]["WD"][22] + schedule.Hour_24 = usage_zone.schedules[schedule_type]["WD"][23] def _add_construction(self, thermal_boundary): for construction in self._idf.idfobjects[self._CONSTRUCTION]: @@ -121,8 +138,6 @@ class Idf: # todo: what does we need to define a zone in energy plus? self._idf.newidfobject(self._ZONE, Name=usage_zone.id) self._add_heating_system(usage_zone) - lighting = self._add_lighting(usage_zone) - lighting.Zone_or_ZoneList_Name= usage_zone.id, def _add_thermostat(self, usage_zone): thermostat_name = f'Thermostat {usage_zone.usage}' @@ -141,115 +156,54 @@ class Idf: Zone_Name=usage_zone.id, Template_Thermostat_Name=thermostat.Name) - def _add_lighting(self, usage_zone): - for lights in self._idf.idfobjects[self._LIGHTS]: - if lights.Name == f'{usage_zone.usage}_lighting': - return - - self._idf.newidfobject(self._LIGHTS, - Name=f'{usage_zone.id}_lighting', - - Schedule_Name="Lighting_Weekday", # todo: from where? - Design_Level_Calculation_Method='Watts/Area', # todo: to constant - Watts_per_Zone_Floor_Area=15, # todo: from usage library - Return_Air_Fraction=0, # todo: to constant/document it. - Fraction_Radiant=0.7, # todo: from usage library - Fraction_Visible=0.2, # todo: ???? - Fraction_Replaceable=1, # todo: to constant/document it. - Return_Air_Fraction_Calculated_from_Plenum_Temperature='No' # todo: to constant/document it. - ) - - def add_occupancy(self): - for zone in self._idf.idfobjects["ZONE"]: - self._idf.newidfobject("PEOPLE", - Name=zone.Name + "_" + "schedules", - Zone_or_ZoneList_Name=zone.Name, - Number_of_People_Schedule_Name='occupant schedules', + def _add_occupancy(self, usage_zone): + self._idf.newidfobject(self._PEOPLE, + Name=f'{usage_zone.id}_occupancy', + Zone_or_ZoneList_Name=usage_zone.id, + Number_of_People_Schedule_Name=f'Occupancy schedules {usage_zone.usage}', Number_of_People_Calculation_Method="People", - Number_of_People=500, - Fraction_Radiant=0.3, + Number_of_People=500, # todo: get people from where? + Fraction_Radiant=0.3, # todo: howto get this from InternalGains Activity_Level_Schedule_Name='occupant schedules' ) - def add_equipment(self): - for zone in self._idf.idfobjects["ZONE"]: - self._idf.newidfobject("ELECTRICEQUIPMENT", - Name=zone.Name + "_" + 'electricload', - Zone_or_ZoneList_Name=zone.Name, - Schedule_Name='ElectricalEquipment', - Design_Level_Calculation_Method='EquipmentLevel', - Design_Level=566000 - ) + def _add_equipment(self, usage_zone): + self._idf.newidfobject(self._ELECTRIC_EQUIPMENT, + Name=f'{usage_zone.id}_electricload', + Zone_or_ZoneList_Name=usage_zone.id, + Schedule_Name=f'Electrical schedules {usage_zone.usage}', # todo: add electrical schedules + Design_Level_Calculation_Method='EquipmentLevel', + Design_Level=566000 # todo: change it from usage catalog + ) - def add_infiltration(self): + def _add_infiltration(self, usage_zone): for zone in self._idf.idfobjects["ZONE"]: - self._idf.newidfobject("ZONEINFILTRATION:DESIGNFLOWRATE", - Name=zone.Name + "_" + "infiltration", - Zone_or_ZoneList_Name=zone.Name, - Schedule_Name='Infiltration_schedule', + self._idf.newidfobject(self._INFILTRATION, + Name=f'{usage_zone.id}_infiltration', + Zone_or_ZoneList_Name=usage_zone.id, + Schedule_Name=f'Infiltration schedules {usage_zone.usage}', Design_Flow_Rate_Calculation_Method='AirChanges/Hour', - Air_Changes_per_Hour=0.35, - Constant_Term_Coefficient=0.606, - Temperature_Term_Coefficient=3.6359996E-02, - Velocity_Term_Coefficient=0.1177165, - Velocity_Squared_Term_Coefficient=0.0000000E+00 + Air_Changes_per_Hour=0.35, # todo: change it from usage catalog + Constant_Term_Coefficient=0.606, # todo: change it from usage catalog + Temperature_Term_Coefficient=3.6359996E-02, # todo: change it from usage catalog + Velocity_Term_Coefficient=0.1177165, # todo: change it from usage catalog + Velocity_Squared_Term_Coefficient=0.0000000E+00 # todo: change it from usage catalog ) - def run(self, energy_plus_path, output_directory, window_ratio=0.35, display_render=False, output_prefix=None, - keep_file=None): - # todo: doesn't really make sense to run energy+ from here, should just return the path to files. - self._idf.set_default_constructions() - # todo: calculate window ratio in the workflow - self._idf.set_wwr(window_ratio, construction="Project External Window") - self._idf.translate_to_origin() - if display_render: - self._idf.view_model() - # Run - self._idf.newidfobject("OUTPUT:METER", Key_Name="Heating:DistrictHeating", Reporting_Frequency="hourly") - self._idf.newidfobject("OUTPUT:METER", Key_Name="Cooling:DistrictCooling", Reporting_Frequency="hourly") - idf_path = None - if keep_file is not None: - idf_path = (keep_file / 'in.idf').resolve() - self._idf.saveas(str(idf_path)) - if idf_path is None: - idf_path = (Path(__file__).parent / 'in.idf').resolve() - - # There is a bug in the IDF class, when called, it return an error, as a work around we call call energy+ directly - run_command = f"{energy_plus_path} --weather {self._epw_file_path} --output-directory {output_directory} --idd " \ - f"{self._idd_file_path} --expandobjects --output-prefix {output_prefix} {idf_path}" - os.system(run_command) - - if keep_file is None: - os.remove(idf_path) - return - - @staticmethod - def read_eso(eso_file_path): - # todo: the heating and cooling values need to go into the city_model_structure - dd, data = esoreader.read(eso_file_path) - list_values = [v for v in data.values()] - heating = [(float(x)) / 3600000.0 for x in list_values[0]] - cooling = [(float(x)) / 3600000.0 for x in list_values[1]] - return heating, cooling - - @staticmethod - def _matrix_to_list(points): - points_list = [] - for point in points: - point_tuple = (point[0], point[1], point[2]) - points_list.append(point_tuple) - return points_list - - @staticmethod - def _matrix_to_2d_list(points): - points_list = [] - for point in points: - point_tuple = (point[0], point[1]) - points_list.append(point_tuple) - return points_list - - def _export(self, city, export_type="Surfaces"): + def export(self, city, export_type="Surfaces"): + """ + Export the idf file into the given path + export type = "Surfaces|Block" + """ for building in city.buildings: + for usage_zone in building.usage_zones: + self._add_schedule(usage_zone, "Infiltration") + self._add_schedule(usage_zone, "Lights") + self._add_schedule(usage_zone, "Occupancy") + self._add_zone(usage_zone) + self._add_heating_system(usage_zone) + self._add_equipment(usage_zone) + self._add_construction(usage_zone) if export_type == "Surfaces": self._add_surfaces(building) else: @@ -260,21 +214,26 @@ class Idf: self._idf.add_block(name=building.name, coordinates=_points, height=building.max_height, num_stories=int(building.storeys_above_ground)) + for surface in self._idf.idfobjects[self._SURFACE]: + for thermal_zone in building.thermal_zones: + for boundary in thermal_zone.bounded: + if surface.Type == self.idf_surfaces[boundary.surface.type]: + surface.Construction_Name = boundary.construction_name + break + for usage_zone in thermal_zone.usage_zones: + surface.Zone_Name = usage_zone.id + break + break self._idf.intersect_match() def _add_surfaces(self, building): - index = 0 - for zone in building.thermal_zones: - zone_name = f'Building {building.name} usage zone {index}' - self._idf.newidfobject('ZONE', Name=zone_name) - for boundary in zone.bounded: - self._add_construction(boundary) + for thermal_zone in building.thermal_zones: + for boundary in thermal_zone.bounded: idf_surface = self.idf_surfaces[boundary.surface.type] - surface = self._idf.newidfobject(self._SURFACE, Name=f'{building.name}-{boundary.surface.name}', - Surface_Type=idf_surface, Zone_Name=zone_name, - Construction_Name=boundary.construction_name) - coordinates = self._matrix_to_list(boundary.surface.coordinates) - surface.setcoords(coordinates) - index += 1 - self._add_heating_system(building) - self._idf.intersect_match() + for usage_zone in thermal_zone.usage_zones: + surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.surface.name}', + Surface_Type=idf_surface, Zone_Name=usage_zone.id, + Construction_Name=boundary.construction_name) + coordinates = self._matrix_to_list(boundary.surface.coordinates) + surface.setcoords(coordinates) + self._idf.intersect_match() diff --git a/imports/construction/helpers/construction_helper.py b/imports/construction/helpers/construction_helper.py index f1dca0cf..81368a00 100644 --- a/imports/construction/helpers/construction_helper.py +++ b/imports/construction/helpers/construction_helper.py @@ -73,7 +73,7 @@ class ConstructionHelper: cte.SECONDARY_SCHOOL: 'secondary school', cte.OFFICE: 'office', cte.LARGE_OFFICE: 'large office', - cte.OFFICE_WORKSHOP: 'large office' + cte.OFFICE_WORKSHOP: 'residential' } nrcan_function_default_value = 'residential' nrcan_window_types = [cte.WINDOW] diff --git a/non_functional_tests/tests_data/C40_Final.gml b/non_functional_tests/tests_data/C40_Final.gml index 60c6fc69..8c992c3d 100644 --- a/non_functional_tests/tests_data/C40_Final.gml +++ b/non_functional_tests/tests_data/C40_Final.gml @@ -10,7 +10,7 @@ -large office +residential 2020 12.822875976562045 2 @@ -135,7 +135,8 @@ -office/workshop +residential +2020 17.09716796875 2 6 @@ -259,7 +260,8 @@ -office/workshop +residential +2020 6.411376953125 1 4.5 @@ -671,7 +673,8 @@ -office/workshop +residential +2020 6.411376953125 1 4.5 @@ -939,7 +942,8 @@ -Corridors/heated +residential +2020 6.411437988281023 1 4.5 @@ -1063,7 +1067,8 @@ -office/workshop +residential +2020 6.411376953125 1 4.5 @@ -1191,7 +1196,8 @@ -office/workshop +residential +2020 14.532531738281023 3 3.4 @@ -1873,7 +1879,8 @@ -office/workshop +residential +2020 7.002624511718977 1 5 @@ -2073,7 +2080,8 @@ -office/workshop +residential +2020 24.220886230468977 5 3.4 @@ -3097,7 +3105,8 @@ -office/workshop +residential +2020 7.002685546875 1 5 From 06a8a397b36c11d915df53d008b09cfdce0c03cb Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 15:23:57 -0400 Subject: [PATCH 3/9] correct idf factory --- exports/exports_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports/exports_factory.py b/exports/exports_factory.py index eaa07e0f..77e2d8d7 100644 --- a/exports/exports_factory.py +++ b/exports/exports_factory.py @@ -66,7 +66,7 @@ class ExportsFactory: Export the city to Energy+ idf format :return: """ - return Idf() + return Idf(self._city, (self._path / f'{self._city.name}.idf'), (self._path / f'{self._city.name}.idd'),(self._path / f'{self._city.name}.epw')) @property def _sra(self): From 36553e0d0d6f6227b3a175ca9bd52bcae36b6c4d Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 15:38:07 -0400 Subject: [PATCH 4/9] correct idf factory --- exports/exports_factory.py | 6 +++++- exports/formats/idf.py | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/exports/exports_factory.py b/exports/exports_factory.py index 77e2d8d7..02597ba8 100644 --- a/exports/exports_factory.py +++ b/exports/exports_factory.py @@ -9,6 +9,7 @@ from exports.formats.obj import Obj from exports.formats.energy_ade import EnergyAde from exports.formats.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm from exports.formats.idf import Idf +from pathlib import Path class ExportsFactory: @@ -66,7 +67,10 @@ class ExportsFactory: Export the city to Energy+ idf format :return: """ - return Idf(self._city, (self._path / f'{self._city.name}.idf'), (self._path / f'{self._city.name}.idd'),(self._path / f'{self._city.name}.epw')) + # todo: this need to be generalized + data_path = Path('../test/test/data').resolve() + return Idf(self._city, self._path, (data_path / f'minimal.idf'), (data_path / f'energy+.idd'), + (self._path / f'montreal.epw')) @property def _sra(self): diff --git a/exports/formats/idf.py b/exports/formats/idf.py index 57707351..c1d337df 100644 --- a/exports/formats/idf.py +++ b/exports/formats/idf.py @@ -32,8 +32,9 @@ class Idf: 'residential': 'residential_building' } - def __init__(self, city, idf_file_path, idd_file_path, epw_file_path): + def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path): self._city = city + self._output_path = str(output_path) self._idd_file_path = str(idd_file_path) self._idf_file_path = str(idf_file_path) self._epw_file_path = str(epw_file_path) @@ -208,6 +209,7 @@ class Idf: self._add_surfaces(building) else: self._add_block(building) + self._idf.saveas(str(self._output_path)) def _add_block(self, building): _points = self._matrix_to_2d_list(building.foot_print.coordinates) From e53f9cc675b6b4bf0a6679c20dc2dbf8feb3297e Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 15:40:57 -0400 Subject: [PATCH 5/9] correct idf factory --- exports/exports_factory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exports/exports_factory.py b/exports/exports_factory.py index 02597ba8..6eff9843 100644 --- a/exports/exports_factory.py +++ b/exports/exports_factory.py @@ -69,8 +69,8 @@ class ExportsFactory: """ # todo: this need to be generalized data_path = Path('../test/test/data').resolve() - return Idf(self._city, self._path, (data_path / f'minimal.idf'), (data_path / f'energy+.idd'), - (self._path / f'montreal.epw')) + return Idf(self._city, self._path, (data_path / f'minimal.idf').resolve(), (data_path / f'energy+.idd').resolve(), + (self._path / f'montreal.epw').resolve()) @property def _sra(self): From 719342cb299a7654e8f45afdfc7b345b266397f5 Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 15:42:00 -0400 Subject: [PATCH 6/9] correct idf factory --- exports/exports_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports/exports_factory.py b/exports/exports_factory.py index 6eff9843..575b5c07 100644 --- a/exports/exports_factory.py +++ b/exports/exports_factory.py @@ -70,7 +70,7 @@ class ExportsFactory: # todo: this need to be generalized data_path = Path('../test/test/data').resolve() return Idf(self._city, self._path, (data_path / f'minimal.idf').resolve(), (data_path / f'energy+.idd').resolve(), - (self._path / f'montreal.epw').resolve()) + (data_path / f'montreal.epw').resolve()) @property def _sra(self): From 1bec0cf2dd31d53a7d400f6073532f93d2dc1662 Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 15:43:15 -0400 Subject: [PATCH 7/9] correct idf factory --- exports/exports_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports/exports_factory.py b/exports/exports_factory.py index 575b5c07..763d7774 100644 --- a/exports/exports_factory.py +++ b/exports/exports_factory.py @@ -68,7 +68,7 @@ class ExportsFactory: :return: """ # todo: this need to be generalized - data_path = Path('../test/test/data').resolve() + data_path = Path('test/data').resolve() return Idf(self._city, self._path, (data_path / f'minimal.idf').resolve(), (data_path / f'energy+.idd').resolve(), (data_path / f'montreal.epw').resolve()) From 92d35d8c8a599f406ae1e52746d96983a613cbcf Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 11 Aug 2021 15:43:48 -0400 Subject: [PATCH 8/9] correct idf factory --- exports/exports_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports/exports_factory.py b/exports/exports_factory.py index 763d7774..69919cc2 100644 --- a/exports/exports_factory.py +++ b/exports/exports_factory.py @@ -68,7 +68,7 @@ class ExportsFactory: :return: """ # todo: this need to be generalized - data_path = Path('test/data').resolve() + data_path = Path('./test/data').resolve() return Idf(self._city, self._path, (data_path / f'minimal.idf').resolve(), (data_path / f'energy+.idd').resolve(), (data_path / f'montreal.epw').resolve()) From cab4df33dbf4c0fe698c2d7ca8d5ea474bd42806 Mon Sep 17 00:00:00 2001 From: Soroush Samareh Abolhassani Date: Wed, 11 Aug 2021 16:16:15 -0400 Subject: [PATCH 9/9] Fine tuning the idf export --- exports/exports_factory.py | 2 +- exports/formats/idf.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/exports/exports_factory.py b/exports/exports_factory.py index 69919cc2..0f386d37 100644 --- a/exports/exports_factory.py +++ b/exports/exports_factory.py @@ -68,7 +68,7 @@ class ExportsFactory: :return: """ # todo: this need to be generalized - data_path = Path('./test/data').resolve() + data_path = Path('../libs_Final/tests/tests_data').resolve() return Idf(self._city, self._path, (data_path / f'minimal.idf').resolve(), (data_path / f'energy+.idd').resolve(), (data_path / f'montreal.epw').resolve()) diff --git a/exports/formats/idf.py b/exports/formats/idf.py index c1d337df..f4c40893 100644 --- a/exports/formats/idf.py +++ b/exports/formats/idf.py @@ -4,7 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Soroush Samareh Abolhassani - soroush.samarehabolhassani@mail.concordia.ca """ from geomeppy import IDF - +from pathlib import Path class Idf: _THERMOSTAT = 'HVACTEMPLATE:THERMOSTAT' _IDEAL_LOAD_AIR_SYSTEM = 'HVACTEMPLATE:ZONE:IDEALLOADSAIRSYSTEM' @@ -34,12 +34,14 @@ class Idf: def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path): self._city = city - self._output_path = str(output_path) + self._output_path = str(output_path.resolve()) + print(self._output_path) self._idd_file_path = str(idd_file_path) self._idf_file_path = str(idf_file_path) self._epw_file_path = str(epw_file_path) IDF.setiddname(self._idd_file_path) self._idf = IDF(self._idf_file_path, self._epw_file_path) + self._export() @staticmethod def _matrix_to_list(points): @@ -87,7 +89,7 @@ class Idf: ) def _add_schedule(self, usage_zone, schedule_type): - for schedule in self._idf.idfobjects[schedule_type]: + for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]: if schedule.Name == f'{schedule_type} schedules {usage_zone.usage}': return schedule = self._idf.newidfobject(self._HOURLY_SCHEDULE) @@ -123,6 +125,7 @@ class Idf: for construction in self._idf.idfobjects[self._CONSTRUCTION]: if construction.Name == thermal_boundary.construction_name: return + for layer in thermal_boundary.layers: self._add_material(layer) layers = thermal_boundary.layers @@ -191,24 +194,28 @@ class Idf: Velocity_Squared_Term_Coefficient=0.0000000E+00 # todo: change it from usage catalog ) - def export(self, city, export_type="Surfaces"): + def _export(self, export_type="Surfaces"): """ Export the idf file into the given path export type = "Surfaces|Block" """ - for building in city.buildings: + print("called") + for building in self._city.buildings: + print('add building') for usage_zone in building.usage_zones: self._add_schedule(usage_zone, "Infiltration") self._add_schedule(usage_zone, "Lights") self._add_schedule(usage_zone, "Occupancy") self._add_zone(usage_zone) self._add_heating_system(usage_zone) - self._add_equipment(usage_zone) self._add_construction(usage_zone) + print('zone construction') + print('add surfaces') if export_type == "Surfaces": self._add_surfaces(building) else: self._add_block(building) + print(' =out path', str(self._output_path)) self._idf.saveas(str(self._output_path)) def _add_block(self, building):