From 949a6c268f8fc9548fff66c93b131982c0fd5cf8 Mon Sep 17 00:00:00 2001 From: guille Date: Mon, 1 May 2023 10:37:51 -0400 Subject: [PATCH] complete peak loads calculation --- hub/city_model_structure/building.py | 30 ++++----- hub/exports/exports_factory.py | 1 - .../formats/simplified_radiosity_algorithm.py | 1 - hub/helpers/peak_loads.py | 50 +++++++++------ hub/imports/weather/epw_weather_parameters.py | 1 - hub/imports/weather_factory.py | 4 ++ hub/unittests/test_imports.py | 61 +++++++++++++++++-- 7 files changed, 103 insertions(+), 45 deletions(-) diff --git a/hub/city_model_structure/building.py b/hub/city_model_structure/building.py index bf6907dc..97582a7c 100644 --- a/hub/city_model_structure/building.py +++ b/hub/city_model_structure/building.py @@ -374,14 +374,12 @@ class Building(CityObject): :return: dict{DataFrame(float)} """ results = {} - if self.heating[cte.HOUR] is not None: - monthly_values = pl.peak_loads_from_hourly(self.heating[cte.HOUR][0]) - results[cte.MONTH] = pd.DataFrame(monthly_values) - yearly_value = 0 - for month_value in monthly_values: - if month_value >= yearly_value: - yearly_value = month_value - results[cte.YEAR] = yearly_value + if cte.HOUR in self.heating: + monthly_values = pl.peak_loads_from_hourly(self.heating[cte.HOUR][next(iter(self.heating[cte.HOUR]))].values) + else: + monthly_values = pl.heating_peak_loads_from_methodology(self) + results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['heating peak loads']) + results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['heating peak loads']) return results @property @@ -391,15 +389,13 @@ class Building(CityObject): :return: dict{DataFrame(float)} """ results = {} - if self.heating[cte.HOUR] is not None: - monthly_values = pl.peak_loads_from_hourly(self.cooling[cte.HOUR][0]) - results[cte.MONTH] = pd.DataFrame(monthly_values) - yearly_value = 0 - for month_value in monthly_values: - if month_value >= yearly_value: - yearly_value = month_value - results[cte.YEAR] = yearly_value - + if cte.HOUR in self.cooling: + monthly_values = pl.peak_loads_from_hourly(self.cooling[cte.HOUR][next(iter(self.cooling[cte.HOUR]))]) + else: + monthly_values = pl.cooling_peak_loads_from_methodology(self) + results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['cooling peak loads']) + results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['cooling peak loads']) + return results @property def eave_height(self): diff --git a/hub/exports/exports_factory.py b/hub/exports/exports_factory.py index 2ac2ec95..ae99dd0d 100644 --- a/hub/exports/exports_factory.py +++ b/hub/exports/exports_factory.py @@ -79,7 +79,6 @@ class ExportsFactory: Export the city to Simplified Radiosity Algorithm xml format :return: None """ - print(self._weather_format, self._weather_file) return SimplifiedRadiosityAlgorithm(self._city, (self._path / f'{self._city.name}_sra.xml'), self._weather_file, diff --git a/hub/exports/formats/simplified_radiosity_algorithm.py b/hub/exports/formats/simplified_radiosity_algorithm.py index b6de68f6..03896901 100644 --- a/hub/exports/formats/simplified_radiosity_algorithm.py +++ b/hub/exports/formats/simplified_radiosity_algorithm.py @@ -36,7 +36,6 @@ class SimplifiedRadiosityAlgorithm: self._city = city self._city.climate_file = str((Path(file_name).parent / f'{city.name}.cli').resolve()) self._city.climate_reference_city = city.location - print(city.location) self._target_buildings = target_buildings self._weather_format = weather_format self._weather_file = weather_file diff --git a/hub/helpers/peak_loads.py b/hub/helpers/peak_loads.py index ce56a528..11bfc208 100644 --- a/hub/helpers/peak_loads.py +++ b/hub/helpers/peak_loads.py @@ -1,6 +1,9 @@ -import constants as cte +import math -_MONTH_STARTING_HOUR = [0, 744, 1416, 2160, 2880, 3624, 4344, 5088, 5832, 6552, 7296, 8016] +import hub.helpers.constants as cte +from hub.helpers.peak_calculation.loads_calculation import LoadsCalculation + +_MONTH_STARTING_HOUR = [0, 744, 1416, 2160, 2880, 3624, 4344, 5088, 5832, 6552, 7296, 8016, math.inf] def peak_loads_from_hourly(hourly_values): month = 1 @@ -10,18 +13,14 @@ def peak_loads_from_hourly(hourly_values): month += 1 if value > peaks[month-1]: peaks[month-1] = value - print(peaks) return peaks -def peak_loads_from_methodology(building): +def heating_peak_loads_from_methodology(building): monthly_heating_loads = [] - monthly_cooling_loads = [] - ambient_temperature = building.external_temperature[cte.HOUR][self._weather_format] + ambient_temperature = building.external_temperature[cte.HOUR]['epw'] for month in range(0, 12): ground_temperature = building.ground_temperature[cte.MONTH]['2'][month] heating_ambient_temperature = 100 - cooling_ambient_temperature = -100 - cooling_calculation_hour = -1 start_hour = _MONTH_STARTING_HOUR[month] end_hour = 8760 if month < 11: @@ -30,30 +29,43 @@ def peak_loads_from_methodology(building): temperature = ambient_temperature[hour] if temperature < heating_ambient_temperature: heating_ambient_temperature = temperature - if temperature > cooling_ambient_temperature: - cooling_ambient_temperature = temperature - cooling_calculation_hour = hour - loads = LoadsCalculation(building) heating_load_transmitted = loads.get_heating_transmitted_load(heating_ambient_temperature, ground_temperature) heating_load_ventilation_sensible = loads.get_heating_ventilation_load_sensible(heating_ambient_temperature) heating_load_ventilation_latent = 0 heating_load = heating_load_transmitted + heating_load_ventilation_sensible + heating_load_ventilation_latent + if heating_load < 0: + heating_load = 0 + monthly_heating_loads.append(heating_load) + return monthly_heating_loads +def cooling_peak_loads_from_methodology(building): + monthly_cooling_loads = [] + ambient_temperature = building.external_temperature[cte.HOUR]['epw'] + for month in range(0, 12): + ground_temperature = building.ground_temperature[cte.MONTH]['2'][month] + cooling_ambient_temperature = -100 + cooling_calculation_hour = -1 + start_hour = _MONTH_STARTING_HOUR[month] + end_hour = 8760 + if month < 11: + end_hour = _MONTH_STARTING_HOUR[month + 1] + for hour in range(start_hour, end_hour): + temperature = ambient_temperature[hour] + if temperature > cooling_ambient_temperature: + cooling_ambient_temperature = temperature + cooling_calculation_hour = hour + loads = LoadsCalculation(building) cooling_load_transmitted = loads.get_cooling_transmitted_load(cooling_ambient_temperature, ground_temperature) cooling_load_renovation_sensible = loads.get_cooling_ventilation_load_sensible(cooling_ambient_temperature) cooling_load_internal_gains_sensible = loads.get_internal_load_sensible() - cooling_load_radiation = loads.get_radiation_load(self._irradiance_format, cooling_calculation_hour) + cooling_load_radiation = loads.get_radiation_load('sra', cooling_calculation_hour) cooling_load_sensible = cooling_load_transmitted + cooling_load_renovation_sensible - cooling_load_radiation \ - cooling_load_internal_gains_sensible cooling_load_latent = 0 cooling_load = cooling_load_sensible + cooling_load_latent - if heating_load < 0: - heating_load = 0 if cooling_load > 0: cooling_load = 0 - monthly_heating_loads.append(heating_load) - monthly_cooling_loads.append(cooling_load) - {'monthly heating peak load': monthly_heating_loads, - 'monthly cooling peak load': monthly_cooling_loads} \ No newline at end of file + monthly_cooling_loads.append(abs(cooling_load)) + return monthly_cooling_loads diff --git a/hub/imports/weather/epw_weather_parameters.py b/hub/imports/weather/epw_weather_parameters.py index faaa91f0..2e3b407c 100644 --- a/hub/imports/weather/epw_weather_parameters.py +++ b/hub/imports/weather/epw_weather_parameters.py @@ -71,7 +71,6 @@ class EpwWeatherParameters: except SystemExit: sys.stderr.write(f'Error: wrong formatting of weather file {self._path}\n') sys.exit() - for building in self._city.buildings: building.ground_temperature[cte.MONTH] = ground_temperature ground_temperature = {} diff --git a/hub/imports/weather_factory.py b/hub/imports/weather_factory.py index 296755de..cae4bef6 100644 --- a/hub/imports/weather_factory.py +++ b/hub/imports/weather_factory.py @@ -52,3 +52,7 @@ class WeatherFactory: :return: None """ getattr(self, self._handler, lambda: None)() + + def enrich_debug(self): + _path = Path(self._base_path / 'epw').resolve() + return EpwWeatherParameters(self._city, _path, self._file_name) diff --git a/hub/unittests/test_imports.py b/hub/unittests/test_imports.py index d7fc634b..4df02e3c 100644 --- a/hub/unittests/test_imports.py +++ b/hub/unittests/test_imports.py @@ -7,16 +7,17 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca import subprocess from pathlib import Path from unittest import TestCase + import pandas as pd -from hub.imports.geometry_factory import GeometryFactory + +import hub.helpers.constants as cte +from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory +from hub.exports.exports_factory import ExportsFactory from hub.helpers.dictionaries import Dictionaries from hub.imports.construction_factory import ConstructionFactory -from hub.imports.usage_factory import UsageFactory -from hub.exports.exports_factory import ExportsFactory -from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory +from hub.imports.geometry_factory import GeometryFactory from hub.imports.results_factory import ResultFactory -import hub.helpers.constants as cte -from hub.city_model_structure.city import City +from hub.imports.usage_factory import UsageFactory class TestImports(TestCase): @@ -65,3 +66,51 @@ class TestImports(TestCase): self.assertIsNotNone(building.cooling[cte.MONTH][cte.INSEL_MEB]) self.assertIsNotNone(building.heating[cte.YEAR][cte.INSEL_MEB]) self.assertIsNotNone(building.cooling[cte.YEAR][cte.INSEL_MEB]) + + def test_peak_loads(self): + # todo: this is not technically a import + # WeatherFactory('epw', self._city, file_name='CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').enrich() + weather_file = (self._example_path / 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve() + ExportsFactory('sra', self._city, self._output_path, weather_file=weather_file, weather_format='epw').export() + sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve() + subprocess.run(['sra', str(sra_path)]) + ResultFactory('sra', self._city, self._output_path).enrich() + for building in self._city.buildings: + self.assertIsNotNone(building.heating_peak_load) + self.assertIsNotNone(building.cooling_peak_load) + + values = [0 for _ in range(8760)] + values[0] = 1000 + expected_yearly = pd.DataFrame([1000], columns=['expected']) + expected_monthly_list = [0 for _ in range(12)] + expected_monthly_list[0] = 1000 + expected_monthly = pd.DataFrame(expected_monthly_list, columns=['expected']) + for building in self._city.buildings: + building.heating[cte.HOUR] = pd.DataFrame(values, columns=['dummy']) + building.cooling[cte.HOUR] = pd.DataFrame(values, columns=['dummy']) + self.assertIsNotNone(building.heating_peak_load) + self.assertIsNotNone(building.cooling_peak_load) + pd.testing.assert_series_equal( + building.heating_peak_load[cte.YEAR]['heating peak loads'], + expected_yearly['expected'], + check_names=False + ) + pd.testing.assert_series_equal( + building.cooling_peak_load[cte.YEAR]['cooling peak loads'], + expected_yearly['expected'], + check_names=False + ) + pd.testing.assert_series_equal( + building.heating_peak_load[cte.MONTH]['heating peak loads'], + expected_monthly['expected'], + check_names=False + ) + pd.testing.assert_series_equal( + building.cooling_peak_load[cte.MONTH]['cooling peak loads'], + expected_monthly['expected'], + check_names=False + ) + + + +