diff --git a/hub/exports/building_energy/idf.py b/hub/exports/building_energy/idf.py index 3f713be3..93b03cdf 100644 --- a/hub/exports/building_energy/idf.py +++ b/hub/exports/building_energy/idf.py @@ -7,6 +7,9 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord Oriol Gavalda Torrellas oriol.gavalda@concordia.ca """ import copy +import datetime +import glob +import os from pathlib import Path from geomeppy import IDF import hub.helpers.constants as cte @@ -275,11 +278,12 @@ class Idf: _kwargs[f'Field_{counter + 2}'] = 'Until: 24:00,0.0' self._idf.newidfobject(self._COMPACT_SCHEDULE, **_kwargs) - def _write_schedules_file(self, usage, schedule): - file_name = str((Path(self._output_path) / f'{schedule.type} schedules {usage}.csv').resolve()) - with open(file_name, 'w', encoding='utf8') as file: - for value in schedule.values: - file.write(f'{str(value)},\n') + def _write_schedules_file(self, schedule, usage): + file_name = str((Path(self._output_path) / f'{schedule.type} schedules {usage.replace("/","_")}.csv').resolve()) + if not Path(file_name).exists(): + with open(file_name, 'w', encoding='utf8') as file: + for value in schedule.values: + file.write(f'{str(value)},\n') return Path(file_name).name def _add_file_schedule(self, usage, schedule, file_name): @@ -304,7 +308,7 @@ class Idf: for schedule in self._idf.idfobjects[self._FILE_SCHEDULE]: if schedule.Name == f'{schedule_type} schedules {usage}': return - file_name = self._write_schedules_file(usage, new_schedules[0]) + file_name = self._write_schedules_file(new_schedules[0], usage) self._add_file_schedule(usage, new_schedules[0], file_name) return @@ -321,7 +325,7 @@ class Idf: if construction.Name == vegetation_name: return else: - if construction.Name == thermal_boundary.construction_name: + if construction.Name == f'{thermal_boundary.construction_name} {thermal_boundary.parent_surface.type}': return if thermal_boundary.layers is None: for material in self._idf.idfobjects[self._MATERIAL]: @@ -340,7 +344,8 @@ class Idf: for i in range(0, len(layers) - 1): _kwargs[f'Layer_{i + 2}'] = layers[i].material_name else: - _kwargs = {'Name': thermal_boundary.construction_name, 'Outside_Layer': layers[0].material_name} + _kwargs = {'Name': f'{thermal_boundary.construction_name} {thermal_boundary.parent_surface.type}', + 'Outside_Layer': layers[0].material_name} for i in range(1, len(layers) - 1): _kwargs[f'Layer_{i + 1}'] = layers[i].material_name self._idf.newidfobject(self._CONSTRUCTION, **_kwargs) @@ -470,7 +475,7 @@ class Idf: Air_Changes_per_Hour=_air_change ) - def _add_dhw(self, thermal_zone, zone_name): + def _add_dhw(self, thermal_zone, zone_name, usage): peak_flow_rate = thermal_zone.domestic_hot_water.peak_flow * thermal_zone.total_floor_area self._idf.newidfobject(self._DHW, Name=f'DHW {zone_name}', @@ -478,7 +483,7 @@ class Idf: Flow_Rate_Fraction_Schedule_Name=f'DHW_prof schedules {thermal_zone.usage_name}', Target_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}', Hot_Water_Supply_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}', - Cold_Water_Supply_Temperature_Schedule_Name=f'cold_temp schedules {zone_name}', + Cold_Water_Supply_Temperature_Schedule_Name=f'cold_temp schedules {usage}', EndUse_Subcategory=f'DHW {zone_name}', Zone_Name=zone_name ) @@ -512,19 +517,25 @@ class Idf: self._rename_building(self._city.name) self._lod = self._city.level_of_detail.geometry for building in self._city.buildings: + is_target = building.name in self._target_buildings or building.name in self._adjacent_buildings for internal_zone in building.internal_zones: if internal_zone.thermal_zones_from_internal_zones is None: - self._add_shading(building) # if the building has not archetype use it as shadow object + self._target_buildings.remoidf_surface_typeve(building.name) + is_target = False continue for thermal_zone in internal_zone.thermal_zones_from_internal_zones: + for thermal_boundary in thermal_zone.thermal_boundaries: self._add_construction(thermal_boundary) if thermal_boundary.parent_surface.vegetation is not None: 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_name - if building.name in self._target_buildings or building.name in self._adjacent_buildings: + + if is_target: + start = datetime.datetime.now() + service_temperature = thermal_zone.domestic_hot_water.service_temperature + usage = thermal_zone.usage_name _new_schedules = self._create_infiltration_schedules(thermal_zone) self._add_schedules(usage, 'Infiltration', _new_schedules) _new_schedules = self._create_ventilation_schedules(thermal_zone) @@ -536,11 +547,10 @@ class Idf: self._add_schedules(usage, 'Lighting', thermal_zone.lighting.schedules) self._add_schedules(usage, 'Appliance', thermal_zone.appliances.schedules) self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules) - _new_schedules = self._create_yearly_values_schedules('cold_temp', - building.cold_water_temperature[cte.HOUR]) - self._add_schedules(building.name, 'cold_temp', _new_schedules) - value = thermal_zone.domestic_hot_water.service_temperature - _new_schedules = self._create_constant_value_schedules('DHW_temp', value) + _new_schedules = self._create_yearly_values_schedules('cold_temp', building.cold_water_temperature[cte.HOUR]) + self._add_schedules(usage, 'cold_temp', _new_schedules) + + _new_schedules = self._create_constant_value_schedules('DHW_temp', service_temperature) self._add_schedules(usage, 'DHW_temp', _new_schedules) _occ = thermal_zone.occupancy if _occ.occupancy_density == 0: @@ -557,11 +567,13 @@ class Idf: self._add_occupancy(thermal_zone, building.name) self._add_lighting(thermal_zone, building.name) self._add_appliances(thermal_zone, building.name) - self._add_dhw(thermal_zone, building.name) + self._add_dhw(thermal_zone, building.name, usage) if self._export_type == "Surfaces": - if building.name in self._target_buildings or building.name in self._adjacent_buildings: + if is_target: if building.thermal_zones_from_internal_zones is not None: + start = datetime.datetime.now() self._add_surfaces(building, building.name) + print(f'add surfaces {datetime.datetime.now() - start}') else: self._add_pure_geometry(building, building.name) else: @@ -717,7 +729,7 @@ class Idf: if boundary.parent_surface.vegetation is not None: construction_name = f'{boundary.construction_name}_{boundary.parent_surface.vegetation.name}' else: - construction_name = boundary.construction_name + construction_name = f'{boundary.construction_name} {boundary.parent_surface.type}' _kwargs['Construction_Name'] = construction_name surface = self._idf.newidfobject(self._SURFACE, **_kwargs) diff --git a/hub/imports/geometry/geojson.py b/hub/imports/geometry/geojson.py index b07a6a7b..3c39a9ee 100644 --- a/hub/imports/geometry/geojson.py +++ b/hub/imports/geometry/geojson.py @@ -135,6 +135,8 @@ class Geojson: building_aliases = [] if 'id' in feature: building_name = feature['id'] + elif 'id' in feature['properties']: + building_name = feature['properties']['id'] else: building_name = uuid.uuid4() if self._aliases_field is not None: