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 f517abba..966c7586 100644 --- a/hub/exports/building_energy/insel/insel_monthly_energy_balance.py +++ b/hub/exports/building_energy/insel/insel_monthly_energy_balance.py @@ -33,6 +33,7 @@ class InselMonthlyEnergyBalance(Insel): self._weather_format = weather_format self._contents = [] self._insel_files_paths = [] + self._sanity_check() for building in city.buildings: self._insel_files_paths.append(building.name + '.insel') file_name_out = building.name + '.out' @@ -46,7 +47,7 @@ class InselMonthlyEnergyBalance(Insel): f'Monthly Energy Balance cannot be processed\n') break self._contents.append( - self.generate_meb_template(building, output_path, self._radiation_calculation_method,self._weather_format) + self._generate_meb_template(building, output_path, self._radiation_calculation_method,self._weather_format) ) self._export() @@ -57,8 +58,30 @@ class InselMonthlyEnergyBalance(Insel): insel_file.write(content) return + def _sanity_check(self): + levels_of_detail = self._city.level_of_detail + if levels_of_detail.geometry is None: + raise Exception(f'Level of detail of geometry not assigned') + if levels_of_detail.geometry < 1: + raise Exception(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 1') + if levels_of_detail.construction is None: + raise Exception(f'Level of detail of construction not assigned') + if levels_of_detail.construction < 1: + raise Exception(f'Level of detail of construction = {levels_of_detail.construction}. Required minimum level 1') + if levels_of_detail.usage is None: + raise Exception(f'Level of detail of usage not assigned') + if levels_of_detail.usage < 1: + raise Exception(f'Level of detail of usage = {levels_of_detail.usage}. Required minimum level 1') + for building in self._city.buildings: + if cte.MONTH not in building.external_temperature: + raise Exception(f'Building {building.name} does not have external temperature assigned') + for surface in building.surfaces: + if surface.type != cte.GROUND: + if cte.MONTH not in surface.global_irradiance: + raise Exception(f'Building {building.name} does not have global irradiance on surfaces assigned') + @staticmethod - def generate_meb_template(building, insel_outputs_path, radiation_calculation_method, weather_format): + def _generate_meb_template(building, insel_outputs_path, radiation_calculation_method, weather_format): file = "" i_block = 1 parameters = ["1", "12", "1"] diff --git a/hub/imports/results/insel_monthly_energry_balance.py b/hub/imports/results/insel_monthly_energry_balance.py index 3ded75d2..82594c3f 100644 --- a/hub/imports/results/insel_monthly_energry_balance.py +++ b/hub/imports/results/insel_monthly_energry_balance.py @@ -10,6 +10,15 @@ import pandas as pd import csv import hub.helpers.constants as cte +_DAYS_A_MONTH = {cte.MONDAY: [5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 5], + cte.TUESDAY: [5, 4, 4, 4, 5, 4, 5, 4, 4, 5, 4, 4], + cte.WEDNESDAY: [5, 4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4], + cte.THURSDAY: [4, 4, 5, 4, 5, 4, 4, 5, 4, 4, 5, 4], + cte.FRIDAY: [4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5, 4], + cte.SATURDAY: [4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5], + cte.SUNDAY: [4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5], + cte.HOLIDAY: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} + class InselMonthlyEnergyBalance: """ @@ -21,7 +30,7 @@ class InselMonthlyEnergyBalance: self._base_path = base_path @staticmethod - def _demand(insel_output_file_path): + def _conditioning_demand(insel_output_file_path): heating = [] cooling = [] with open(Path(insel_output_file_path).resolve()) as csv_file: @@ -40,15 +49,74 @@ class InselMonthlyEnergyBalance: monthly_cooling = pd.DataFrame(cooling, columns=[cte.INSEL_MEB]).astype(float) return monthly_heating, monthly_cooling + def _dhw_demand(self): + for building in self._city.buildings: + domestic_hot_water_demand = [] + if building.internal_zones[0].thermal_zones is None: + domestic_hot_water_demand = [0] * 12 + else: + thermal_zone = building.internal_zones[0].thermal_zones[0] + area = thermal_zone.total_floor_area + cold_water = building.cold_water_temperature[cte.MONTH]['epw'] + for month in range(0, 12): + total_dhw_demand = 0 + for schedule in thermal_zone.domestic_hot_water.schedules: + total_day = 0 + for value in schedule.values: + total_day += value + for day_type in schedule.day_types: + demand = thermal_zone.domestic_hot_water.peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY \ + * (thermal_zone.domestic_hot_water.service_temperature - cold_water[month]) + total_dhw_demand += total_day * _DAYS_A_MONTH[day_type][month] * demand + domestic_hot_water_demand.append(total_dhw_demand * area) + + building.domestic_hot_water_heat_demand[cte.MONTH] = \ + pd.DataFrame(domestic_hot_water_demand, columns=[cte.INSEL_MEB]) + + def _electrical_demand(self): + for building in self._city.buildings: + lighting_demand = [] + appliances_demand = [] + if building.internal_zones[0].thermal_zones is None: + lighting_demand = [0] * 12 + appliances_demand = [0] * 12 + else: + thermal_zone = building.internal_zones[0].thermal_zones[0] + area = thermal_zone.total_floor_area + + for month in range(0, 12): + total_lighting = 0 + for schedule in thermal_zone.lighting.schedules: + total_day = 0 + for value in schedule.values: + total_day += value + for day_type in schedule.day_types: + total_lighting += total_day * _DAYS_A_MONTH[day_type][month] * thermal_zone.lighting.density + lighting_demand.append(total_lighting * area) + + total_appliances = 0 + for schedule in thermal_zone.appliances.schedules: + total_day = 0 + for value in schedule.values: + total_day += value + for day_type in schedule.day_types: + total_appliances += total_day * _DAYS_A_MONTH[day_type][month] * thermal_zone.appliances.density + appliances_demand.append(total_appliances * area) + + building.lighting_electrical_demand[cte.MONTH] = pd.DataFrame(lighting_demand, columns=[cte.INSEL_MEB]) + building.appliances_electrical_demand[cte.MONTH] = pd.DataFrame(appliances_demand, columns=[cte.INSEL_MEB]) + def enrich(self): for building in self._city.buildings: file_name = building.name + '.out' insel_output_file_path = Path(self._base_path / file_name).resolve() if insel_output_file_path.is_file(): - building.heating[cte.MONTH], building.cooling[cte.MONTH] = self._demand(insel_output_file_path) + building.heating[cte.MONTH], building.cooling[cte.MONTH] = self._conditioning_demand(insel_output_file_path) building.heating[cte.YEAR] = pd.DataFrame( [building.heating[cte.MONTH][cte.INSEL_MEB].astype(float).sum()], columns=[cte.INSEL_MEB] ) building.cooling[cte.YEAR] = pd.DataFrame( [building.cooling[cte.MONTH][cte.INSEL_MEB].astype(float).sum()], columns=[cte.INSEL_MEB] ) + self._dhw_demand() + self._electrical_demand() diff --git a/hub/imports/usage/nrcan_usage_parameters.py b/hub/imports/usage/nrcan_usage_parameters.py index 2577a781..77afb9d0 100644 --- a/hub/imports/usage/nrcan_usage_parameters.py +++ b/hub/imports/usage/nrcan_usage_parameters.py @@ -83,7 +83,6 @@ class NrcanUsageParameters: if archetype.mechanical_air_change > 0: usage.mechanical_air_change = archetype.mechanical_air_change elif archetype.ventilation_rate > 0: - print(volume_per_area) usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area * cte.HOUR_TO_SECONDS else: usage.mechanical_air_change = 0