monthly_energy_balance/tests/test_meb_workflow.py

182 lines
8.3 KiB
Python

"""
TestMebWorkflow tests and validates the complete Monthly Energy Balance workflow
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
"""
from pathlib import Path
from unittest import TestCase
import numpy as np
import subprocess
from subprocess import SubprocessError, TimeoutExpired, CalledProcessError
from insel.insel import Insel
from insel.templates.monthly_energy_balance import MonthlyEnergyBalance as templates
from imports.geometry_factory import GeometryFactory
from populate import Populate
from imports.weather_factory import WeatherFactory
from helpers import monthly_values as mv
from simplified_radiosity_algorithm.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm as sralgorithm
from city_model_structure.city import City
class TestMebWorkflow(TestCase):
"""
TestMebWorkflow TestCase 1
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve()
self._geometry_type = 'citygml'
self._use_cached_sra_file = False
self._input_geometry_file = (self._example_path / 'gis' / '2050_bp_2buildings.gml').resolve()
self._project_folder = Path(__file__).parent.parent
self._cli_weather_file = (self._example_path / 'weather' / 'inseldb_new_york_city.cli').resolve()
self._city_gml = None
self._city = None
self._populated_city = None
self._monthly_temperatures = None
self._city_with_weather = None
self._city_with_cli = None
self._city_with_dat = None
self._pickle_file = (self._example_path / 'gis' / 'kelowna_test_case.pickle').resolve()
self._pickle_file_populated = Path(str(self._pickle_file).replace('.pickle', '_populated.pickle'))
self._pickle_file_populated_weather = Path(str(self._pickle_file_populated).replace('.pickle', '_weather.pickle'))
self._city_name = 'Summerland'
def _get_citygml(self, use_pickle=False):
if self._city_gml is None:
if use_pickle:
self._city_gml = City.load(self._pickle_file)
else:
file_path = self._input_geometry_file
self._city_gml = GeometryFactory('citygml', file_path).city
self.assertIsNotNone(self._city_gml, 'city is none')
return self._city_gml
def _get_citygml_populated(self, use_pickle):
if self._populated_city is None:
self._city = self._get_citygml(use_pickle=use_pickle)
self._populated_city = Populate(self._city).populated_city
return self._populated_city
def _get_citygml_with_weather(self, use_pickle):
if self._city_with_weather is None:
weather_format = 'epw'
self._city_with_weather = self._get_citygml(use_pickle=use_pickle)
weather_path = (self._example_path / 'weather').resolve()
WeatherFactory(weather_format, self._city_with_weather, base_path=weather_path)
for building in self._city_with_weather.buildings:
building.external_temperature['month'] = mv.MonthlyValues(). \
get_mean_values(building.external_temperature['hour'][['epw']])
sra_file_name = 'SRA'
sra = sralgorithm(Path(self._project_folder).resolve(), sra_file_name, Path(self._cli_weather_file).resolve(),
self._city_with_weather.city_objects, lower_corner=self._city_with_weather.lower_corner)
if self._use_cached_sra_file:
sra.results()
else:
sra.call_sra(weather_format, keep_files=True)
sra.set_irradiance_surfaces(self._city_with_weather)
return self._city_with_weather
def _get_cli_single_building(self, building_name, radius, use_pickle):
weather_format = 'epw'
self._city_with_cli = self._get_citygml(use_pickle=use_pickle)
building = self._city_with_cli.city_object(building_name)
new_city = self._city_with_cli.region(building.centroid, radius)
sra_file_name = 'SRA'
print('location', building.centroid)
print('lower corner', new_city.lower_corner)
full_path_cli = (self._example_path / 'weather' / 'inseldb_Summerland.cli').resolve()
sra = sralgorithm(Path(self._project_folder).resolve(), sra_file_name, full_path_cli, new_city.city_objects,
lower_corner=new_city.lower_corner)
sra.call_sra(weather_format, keep_files=True)
sra.set_irradiance_surfaces(self._city_with_cli, building_name=building_name)
return self._city_with_cli
def test_populate_city(self):
"""
Test populate class
:return: none
"""
# populated_city = self._get_citygml_populated(True)
# populated_city.save(pickle_file_populated)
populated_city = City.load(self._pickle_file_populated)
self.assertIsNotNone(populated_city.city_objects, 'city_objects is none')
for building in populated_city.buildings:
self.assertIsNotNone(building.usage_zones, 'city_object return none')
self.assertIsNotNone(building.thermal_zones, 'city_object return none')
def test_weather_assignment(self):
"""
Test the weather assignment
:return: none
"""
weather_city = self._get_citygml_with_weather(False)
for building in weather_city.buildings:
self.assertFalse(building.external_temperature['month'].empty, 'monthly external temperature return none')
for surface in building.surfaces:
if surface.type != 'Ground':
self.assertIsNotNone(surface.global_irradiance['month'], 'monthly irradiance return none')
def test_insel_call(self):
"""
Test the insel template generation and engine call
:return: none
"""
self._get_citygml_populated(False)
city = self._get_citygml_with_weather(False)
expected_values = [[13619.57, 3.65], [14886.33, 1.67]]
i = 0
for building in city.buildings:
full_path_out = Path(self._project_folder / 'outputs' / (building.name + '_insel.out')).resolve()
full_path_out.parent.mkdir(parents=True, exist_ok=True)
insel_file_name = building.name + '.insel'
content = templates.generate_meb_template(building, full_path_out)
self.assertIsNotNone(content, 'content return empty')
Insel(Path(self._project_folder).resolve(), insel_file_name, content, mode=2,
keep_files=True).run()
building.heating['month'], building.cooling['month'] = templates.demand(full_path_out)
values = building.heating['month'][['INSEL']].to_numpy()
self.assertEqual(expected_values[i][0], np.around(float(values[11]), decimals=2), 'wrong value monthly heating')
values = building.cooling['month'][['INSEL']].to_numpy()
self.assertEqual(expected_values[i][1], np.around(float(values[11]), decimals=2), 'wrong value monthly cooling')
i += 1
def test_city_with_weather_building_by_building(self):
radius = 100
building_names = ['BLD100086', 'BLD131702', 'BLD132148', 'BLD126221', 'BLD131081', 'BLD135303', 'BLD130088',
'BLD128703', 'BLD121900', 'BLD141378', 'BLD135375', 'BLD126801', 'BLD120774', 'BLD118577',
'BLD129395', 'BLD126848', 'BLD115972', 'BLD138959', 'BLD122103', 'BLD114335', 'BLD124272',
'BLD107027', 'BLD105415', 'BLD129867', 'BLD133164', 'BLD119241', 'BLD106658', 'BLD114097',
'BLD130182', 'BLD121456', 'BLD123516', 'BLD126061', 'BLD128845', 'BLD138802', 'BLD129673']
building_names = ['BLD100086']
city = self._get_city_with_dat(True)
for building in city.buildings:
self.assertTrue(building.external_temperature, 'external temperature return none')
for building_name in building_names:
print(building_name)
weather_city = self._get_cli_single_building(building_name, radius, True)
# for building in weather_city.city_objects:
# if building.name == building_name:
# for surface in building.surfaces:
# if surface.type != 'Ground':
# self.assertTrue(surface.global_irradiance, 'global irradiance return none in calculated building')
# else:
# for surface in building.surfaces:
# self.assertFalse(surface.global_irradiance, 'global irradiance return not none in not calculated building')
def test_sra(self):
_executable = 'shortwave_integer'
_full_path_in = (Path(__file__).parent.parent / 'tmp\SRA.xml').resolve()
try:
completed = subprocess.run([_executable, str(_full_path_in)])
except (SubprocessError, TimeoutExpired, CalledProcessError) as error:
raise Exception(error)