2021-02-04 11:17:31 -05:00
|
|
|
"""
|
|
|
|
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
|
2021-04-13 19:01:30 -04:00
|
|
|
from imports.geometry_factory import GeometryFactory
|
2021-02-04 11:17:31 -05:00
|
|
|
from populate import Populate
|
2021-04-13 19:01:30 -04:00
|
|
|
from imports.weather_factory import WeatherFactory
|
2021-02-04 11:17:31 -05:00
|
|
|
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
|
2021-04-13 19:01:30 -04:00
|
|
|
self._input_geometry_file = (self._example_path / 'gis' / '2050_bp_2buildings.gml').resolve()
|
2021-02-04 11:17:31 -05:00
|
|
|
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:
|
2021-06-08 12:50:38 -04:00
|
|
|
weather_format = 'epw'
|
2021-02-04 11:17:31 -05:00
|
|
|
self._city_with_weather = self._get_citygml(use_pickle=use_pickle)
|
|
|
|
weather_path = (self._example_path / 'weather').resolve()
|
2021-06-08 12:50:38 -04:00
|
|
|
WeatherFactory(weather_format, self._city_with_weather, base_path=weather_path)
|
2021-02-04 11:17:31 -05:00
|
|
|
for building in self._city_with_weather.buildings:
|
|
|
|
building.external_temperature['month'] = mv.MonthlyValues(). \
|
2021-04-13 19:01:30 -04:00
|
|
|
get_mean_values(building.external_temperature['hour'][['epw']])
|
2021-02-04 11:17:31 -05:00
|
|
|
|
|
|
|
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:
|
2021-06-08 12:50:38 -04:00
|
|
|
sra.call_sra(weather_format, keep_files=True)
|
2021-02-04 11:17:31 -05:00
|
|
|
sra.set_irradiance_surfaces(self._city_with_weather)
|
|
|
|
return self._city_with_weather
|
|
|
|
|
|
|
|
def _get_cli_single_building(self, building_name, radius, use_pickle):
|
2021-06-08 12:50:38 -04:00
|
|
|
weather_format = 'epw'
|
2021-02-04 11:17:31 -05:00
|
|
|
self._city_with_cli = self._get_citygml(use_pickle=use_pickle)
|
|
|
|
building = self._city_with_cli.city_object(building_name)
|
2021-04-13 19:01:30 -04:00
|
|
|
new_city = self._city_with_cli.region(building.centroid, radius)
|
2021-02-04 11:17:31 -05:00
|
|
|
sra_file_name = 'SRA'
|
2021-04-13 19:01:30 -04:00
|
|
|
print('location', building.centroid)
|
2021-02-04 11:17:31 -05:00
|
|
|
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)
|
2021-06-08 12:50:38 -04:00
|
|
|
sra.call_sra(weather_format, keep_files=True)
|
2021-02-04 11:17:31 -05:00
|
|
|
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)
|