From 4ccf16411c7258586bed95c6af2956b3f51f917f Mon Sep 17 00:00:00 2001 From: p_monsalvete Date: Tue, 6 Jun 2023 16:09:33 -0400 Subject: [PATCH] solved feature in idf generator --- .../building_demand/thermal_zone.py | 9 ++-- hub/exports/building_energy/idf.py | 52 ++++++++++++++----- .../insel/insel_monthly_energy_balance.py | 2 +- .../energy_building_exports_factory.py | 2 +- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/hub/city_model_structure/building_demand/thermal_zone.py b/hub/city_model_structure/building_demand/thermal_zone.py index aad93286..845e161d 100644 --- a/hub/city_model_structure/building_demand/thermal_zone.py +++ b/hub/city_model_structure/building_demand/thermal_zone.py @@ -617,9 +617,12 @@ class ThermalZone: _mean_peak_flow = 0 _mean_service_temperature = 0 for usage in self.usages: - _mean_peak_density_load += usage.percentage * usage.domestic_hot_water.density - _mean_peak_flow += usage.percentage * usage.domestic_hot_water.peak_flow - _mean_service_temperature += usage.percentage * usage.domestic_hot_water.service_temperature + if usage.domestic_hot_water.density is not None: + _mean_peak_density_load += usage.percentage * usage.domestic_hot_water.density + if usage.domestic_hot_water.peak_flow is not None: + _mean_peak_flow += usage.percentage * usage.domestic_hot_water.peak_flow + if usage.domestic_hot_water.service_temperature is not None: + _mean_service_temperature += usage.percentage * usage.domestic_hot_water.service_temperature self._domestic_hot_water.density = _mean_peak_density_load self._domestic_hot_water.peak_flow = _mean_peak_flow self._domestic_hot_water.service_temperature = _mean_service_temperature diff --git a/hub/exports/building_energy/idf.py b/hub/exports/building_energy/idf.py index 2b68f241..860e1f5e 100644 --- a/hub/exports/building_energy/idf.py +++ b/hub/exports/building_energy/idf.py @@ -83,6 +83,7 @@ class Idf: def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, export_type="Surfaces", target_buildings=None): self._city = city + self._sanity_check() self._output_path = str(output_path.resolve()) self._output_file = str((output_path / f'{city.name}.idf').resolve()) self._export_type = export_type @@ -106,6 +107,25 @@ class Idf: self._adjacent_buildings += building.neighbours self._export() + def _sanity_check(self): + levels_of_detail = self._city.level_of_detail + if levels_of_detail.geometry is None: + raise AttributeError('Level of detail of geometry not assigned') + if levels_of_detail.geometry < 1: + raise AttributeError(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 1') + if levels_of_detail.construction is None: + raise AttributeError('Level of detail of construction not assigned') + if levels_of_detail.construction < 2: + raise AttributeError(f'Level of detail of construction = {levels_of_detail.construction}. Required minimum level 2') + if levels_of_detail.usage is None: + raise AttributeError('Level of detail of usage not assigned') + if levels_of_detail.usage < 2: + raise AttributeError(f'Level of detail of usage = {levels_of_detail.usage}. Required minimum level 2') + if levels_of_detail.weather is None: + raise AttributeError('Level of detail of weather not assigned') + if levels_of_detail.weather < 2: + raise AttributeError(f'Level of detail of weather = {levels_of_detail.weather}. Required minimum level 2') + @staticmethod def _matrix_to_list(points, lower_corner): lower_x = lower_corner[0] @@ -294,9 +314,9 @@ class Idf: return def _add_construction(self, thermal_boundary): - vegetation_name = f'{thermal_boundary.construction_name}_{thermal_boundary.parent_surface.vegetation.name}' for construction in self._idf.idfobjects[self._CONSTRUCTION]: if thermal_boundary.parent_surface.vegetation is not None: + vegetation_name = f'{thermal_boundary.construction_name}_{thermal_boundary.parent_surface.vegetation.name}' if construction.Name == vegetation_name: return else: @@ -313,6 +333,7 @@ class Idf: layers = thermal_boundary.layers # The constructions should have at least one layer if thermal_boundary.parent_surface.vegetation is not None: + vegetation_name = f'{thermal_boundary.construction_name}_{thermal_boundary.parent_surface.vegetation.name}' _kwargs = {'Name': vegetation_name, 'Outside_Layer': thermal_boundary.parent_surface.vegetation.name} for i in range(0, len(layers) - 1): @@ -429,25 +450,28 @@ class Idf: for zone in self._idf.idfobjects["ZONE"]: if zone.Name == f'{zone_name}_infiltration': return - schedule = f'Infiltration schedules {thermal_zone.usage_name}' - if schedule not in self._idf.idfobjects[self._HOURLY_SCHEDULE]: - return - self._idf.newidfobject(self._INFILTRATION, - Name=f'{zone_name}_infiltration', - Zone_or_ZoneList_Name=zone_name, - Schedule_Name=schedule, - Design_Flow_Rate_Calculation_Method='AirChanges/Hour', - Air_Changes_per_Hour=thermal_zone.infiltration_rate_system_off - ) + schedule = f'Infiltration schedules {thermal_zone.usage_name}' + # todo: if the schedule doesn't exist, does the idf notices?? + # We shouldn't check this because the schedules could be written later +# if schedule not in self._idf.idfobjects[self._COMPACT_SCHEDULE]: +# return + self._idf.newidfobject(self._INFILTRATION, + Name=f'{zone_name}_infiltration', + Zone_or_ZoneList_Name=zone_name, + Schedule_Name=schedule, + Design_Flow_Rate_Calculation_Method='AirChanges/Hour', + Air_Changes_per_Hour=thermal_zone.infiltration_rate_system_off + ) def _add_ventilation(self, thermal_zone, zone_name): for zone in self._idf.idfobjects["ZONE"]: if zone.Name == f'{zone_name}_ventilation': return schedule = f'Ventilation schedules {thermal_zone.usage_name}' - #if schedule not in self._idf.idfobjects[self._HOURLY_SCHEDULE]: - # return - # todo: revise ventilation with Pilar + # todo: if the schedule doesn't exist, does the idf notices?? + # We shouldn't check this because the schedules could be written later +# if schedule not in self._idf.idfobjects[self._COMPACT_SCHEDULE]: +# return self._idf.newidfobject(self._VENTILATION, Name=f'{zone_name}_ventilation', Zone_or_ZoneList_Name=zone_name, diff --git a/hub/exports/building_energy/insel/insel_monthly_energy_balance.py b/hub/exports/building_energy/insel/insel_monthly_energy_balance.py index 38e42c5a..5121f17f 100644 --- a/hub/exports/building_energy/insel/insel_monthly_energy_balance.py +++ b/hub/exports/building_energy/insel/insel_monthly_energy_balance.py @@ -76,7 +76,7 @@ class InselMonthlyEnergyBalance: if levels_of_detail.geometry is None: raise AttributeError('Level of detail of geometry not assigned') if levels_of_detail.geometry < 1: - raise AttributeError(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 0.5') + raise AttributeError(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 1') if levels_of_detail.construction is None: raise AttributeError('Level of detail of construction not assigned') if levels_of_detail.construction < 1: diff --git a/hub/exports/energy_building_exports_factory.py b/hub/exports/energy_building_exports_factory.py index 5f736dfb..3fefaeea 100644 --- a/hub/exports/energy_building_exports_factory.py +++ b/hub/exports/energy_building_exports_factory.py @@ -67,4 +67,4 @@ class EnergyBuildingsExportsFactory: Export the city given to the class using the given export type handler :return: None """ - return getattr(self, self._export_type, lambda: None) \ No newline at end of file + return getattr(self, self._export_type, lambda: None)