Merge branch 'insel_exporter' into 'master'

Insel exporter

See merge request Guille/hub!40
This commit is contained in:
Guillermo Gutierrez Morote 2022-11-25 17:37:49 +00:00
commit 3be8de5cd1
15 changed files with 9250 additions and 119 deletions

View File

@ -51,7 +51,6 @@ class Idf:
_LOCATION = 'SITE:LOCATION'
_SIMPLE = 'Simple'
idf_surfaces = {
# todo: make an enum for all the surface types
cte.WALL: 'wall',

View File

@ -0,0 +1,184 @@
import numpy as np
from pathlib import Path
from exports.formats.insel import Insel
from imports.weather.helpers.weather import Weather
import helpers.constants as cte
_CONSTRUCTION_CODE = {
cte.WALL: '1',
cte.GROUND: '2',
cte.ROOF: '3',
cte.INTERIOR_WALL: '5',
cte.GROUND_WALL: '6',
cte.ATTIC_FLOOR: '7',
cte.INTERIOR_SLAB: '8'
}
class InselMonthlyEnergyBalance(Insel):
def __init__(self, city, path, radiation_calculation_method='sra', weather_format='epw'):
super().__init__(city, path)
self._radiation_calculation_method = radiation_calculation_method
self._weather_format = weather_format
self._contents = []
self._insel_files_paths = []
for building in city.buildings:
self._insel_files_paths.append(building.name + '.insel')
file_name_out = building.name + '.out'
output_path = Path(self._path / file_name_out).resolve()
self._contents.append(self.generate_meb_template(building, output_path, self._radiation_calculation_method,
self._weather_format))
self._export()
def _export(self):
for i_file, content in enumerate(self._contents):
file_name = self._insel_files_paths[i_file]
with open(Path(self._path / file_name).resolve(), 'w') as insel_file:
insel_file.write(content)
return
@staticmethod
def generate_meb_template(building, insel_outputs_path, radiation_calculation_method, weather_format):
file = ""
i_block = 1
parameters = ["1", "12", "1"]
file = Insel._add_block(file, i_block, 'DO', parameters=parameters)
i_block = 4
inputs = ["1.1", "20.1", "21.1"]
surfaces = building.surfaces
for i in range(1, len(surfaces) + 1):
inputs.append(f"{str(100 + i)}.1 % Radiation surface {str(i)}")
# BUILDING PARAMETERS
parameters = [f'{0.85 * building.volume} % BP(1) Heated Volume (vBrutto)',
f'{building.average_storey_height} % BP(2) Average storey height / m',
f'{building.storeys_above_ground} % BP(3) Number of storeys above ground',
f'{building.attic_heated} % BP(4) Attic heating type (0=no room, 1=unheated, 2=heated)',
f'{building.basement_heated} % BP(5) Cellar heating type (0=no room, 1=unheated, 2=heated, '
f'99=invalid)']
# todo: this method and the insel model have to be reviewed for more than one internal zone
internal_zone = building.internal_zones[0]
thermal_zone = internal_zone.thermal_zones[0]
parameters.append(f'{thermal_zone.indirectly_heated_area_ratio} % BP(6) Indirectly heated area ratio')
parameters.append(f'{thermal_zone.effective_thermal_capacity} % BP(7) Effective heat capacity')
parameters.append(f'{thermal_zone.additional_thermal_bridge_u_value * thermal_zone.total_floor_area} '
f'% BP(8) Additional U-value for heat bridge')
parameters.append('0 % BP(9) Usage type (0=standard, 1=IWU)')
# ZONES AND SURFACES
parameters.append(f'{len(internal_zone.usage_zones)} % BP(10) Number $z$ of zones')
for i, usage_zone in enumerate(internal_zone.usage_zones):
percentage_usage = usage_zone.percentage
parameters.append(f'{float(internal_zone.area) * percentage_usage} % BP(11) #1 Area of zone {i + 1} (sqm)')
total_internal_gain = 0
for ig in usage_zone.internal_gains:
total_internal_gain += float(ig.average_internal_gain) * \
(float(ig.convective_fraction) + float(ig.radiative_fraction))
parameters.append(f'{total_internal_gain} % BP(12) #2 Internal gains of zone {i + 1}')
parameters.append(f'{usage_zone.thermal_control.mean_heating_set_point} % BP(13) #3 Heating setpoint temperature '
f'zone {i + 1} (tSetHeat)')
parameters.append(f'{usage_zone.thermal_control.heating_set_back} % BP(14) #4 Heating setback temperature '
f'zone {i + 1} (tSetbackHeat)')
parameters.append(f'{usage_zone.thermal_control.mean_cooling_set_point} % BP(15) #5 Cooling setpoint temperature '
f'zone {i + 1} (tSetCool)')
parameters.append(f'{usage_zone.hours_day} % BP(16) #6 Usage hours per day zone {i + 1}')
parameters.append(f'{usage_zone.days_year} % BP(17) #7 Usage days per year zone {i + 1}')
parameters.append(f'{usage_zone.mechanical_air_change} % BP(18) #8 Minimum air change rate zone {i + 1} (h^-1)')
parameters.append(f'{len(thermal_zone.thermal_boundaries)} % Number of surfaces = BP(11+8z) \n'
f'% 1. Surface type (1=wall, 2=ground 3=roof, 4=flat roof)\n'
f'% 2. Areas above ground\n'
f'% 3. Areas below ground\n'
f'% 4. U-value\n'
f'% 5. Window area\n'
f'% 6. Window frame fraction\n'
f'% 7. Window U-value\n'
f'% 8. Window g-value\n'
f'% 9. Short-wave reflectance\n'
f'% #1 #2 #3 #4 #5 #6 #7 #8 #9\n')
for thermal_boundary in thermal_zone.thermal_boundaries:
type_code = _CONSTRUCTION_CODE[thermal_boundary.type]
window_area = thermal_boundary.opaque_area * thermal_boundary.window_ratio / (1 - thermal_boundary.window_ratio)
parameters.append(type_code)
parameters.append(0.85 * thermal_boundary.opaque_area)
parameters.append('0.0')
parameters.append(thermal_boundary.u_value)
parameters.append(0.85 * window_area)
if window_area <= 0.001:
parameters.append(0.0)
parameters.append(0.0)
parameters.append(0.0)
else:
thermal_opening = thermal_boundary.thermal_openings[0]
parameters.append(thermal_opening.frame_ratio)
parameters.append(thermal_opening.overall_u_value)
parameters.append(thermal_opening.g_value)
if thermal_boundary.type is not cte.GROUND:
parameters.append(thermal_boundary.parent_surface.short_wave_reflectance)
else:
parameters.append(0.0)
file = Insel._add_block(file, i_block, 'd18599', inputs=inputs, parameters=parameters)
i_block = 20
inputs = ['1']
parameters = ['12 % Monthly ambient temperature']
external_temperature = building.external_temperature[cte.MONTH]
for i in range(0, len(external_temperature)):
parameters.append(f'{i + 1} {external_temperature.at[i, weather_format]}')
file = Insel._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters)
i_block = 21
inputs = ['1']
parameters = ['12 % Monthly sky temperature']
sky_temperature = Weather.sky_temperature(external_temperature[[weather_format]].to_numpy().T[0])
for i, temperature in enumerate(sky_temperature):
parameters.append(f'{i + 1} {temperature}')
file = Insel._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters)
for i, surface in enumerate(surfaces):
i_block = 101 + i
inputs = ['1 % Monthly surface radiation (W/sqm)']
parameters = [f'12 % Azimuth {np.rad2deg(surface.azimuth)}, '
f'inclination {np.rad2deg(surface.inclination)} degrees']
if surface.type != 'Ground':
global_irradiance = surface.global_irradiance[cte.MONTH]
for j in range(0, len(global_irradiance)):
parameters.append(f'{j + 1} {global_irradiance.at[j, radiation_calculation_method]}')
else:
for j in range(0, 12):
parameters.append(f'{j + 1} 0.0')
file = Insel._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters)
i_block = 300
inputs = ['4.1', '4.2']
file = Insel._add_block(file, i_block, 'cum', inputs=inputs)
i_block = 303
inputs = ['300.1', '300.2']
file = Insel._add_block(file, i_block, 'atend', inputs=inputs)
i_block = 310
inputs = ['4.1', '4.2']
parameters = ['1 % Mode',
'0 % Suppress FNQ inputs',
f"'{str(insel_outputs_path)}' % File name",
"'*' % Fortran format"]
file = Insel._add_block(file, i_block, 'WRITE', inputs=inputs, parameters=parameters)
return file

View File

@ -0,0 +1,74 @@
"""
EnergyBuildingsExportsFactory exports a city into several formats related to energy in buildings
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de uribarri pilar.monsalvete@concordia.ca
"""
from pathlib import Path
from exports.building_energy.energy_ade import EnergyAde
from exports.building_energy.idf import Idf
from exports.building_energy.insel.insel_monthly_energy_balance import InselMonthlyEnergyBalance
class EnergyBuildingsExportsFactory:
"""
Energy Buildings exports factory class
"""
def __init__(self, export_type, city, path, target_buildings=None, adjacent_buildings=None):
self._city = city
self._export_type = '_' + export_type.lower()
if isinstance(path, str):
path = Path(path)
self._path = path
self._target_buildings = target_buildings
self._adjacent_buildings = adjacent_buildings
@property
def _energy_ade(self):
"""
Export to citygml with application domain extensions
:return: None
"""
return EnergyAde(self._city, self._path)
@property
def _idf(self):
"""
Export the city to Energy+ idf format
When target_buildings is set, only those will be calculated and their energy consumption output, non adjacent
buildings will be considered shading objects and adjacent buildings will be considered adiabatic.
Adjacent buildings are provided they will be considered heated so energy plus calculations are more precise but
no results will be calculated to speed up the calculation process.
:return: None
"""
idf_data_path = (Path(__file__).parent / './building_energy/idf_files/').resolve()
# todo: create a get epw file function based on the city
weather_path = (Path(__file__).parent / '../data/weather/epw/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'), weather_path,
target_buildings=self._target_buildings, adjacent_buildings=self._adjacent_buildings)
@property
def _insel_monthly_energy_balance(self):
"""
Export to Insel MonthlyEnergyBalance
:return: None
"""
return InselMonthlyEnergyBalance(self._city, self._path)
def export(self):
"""
Export the city given to the class using the given export type handler
:return: None
"""
return getattr(self, self._export_type, lambda: None)
def export_debug(self):
"""
Export the city given to the class using the given export type handler
:return: None
"""
return getattr(self, self._export_type)

View File

@ -6,8 +6,6 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from pathlib import Path
from exports.formats.energy_ade import EnergyAde
from exports.formats.idf import Idf
from exports.formats.obj import Obj
from exports.formats.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
from exports.formats.stl import Stl
@ -38,14 +36,6 @@ class ExportsFactory:
def _collada(self):
raise NotImplementedError
@property
def _energy_ade(self):
"""
Export to citygml with application domain extensions
:return: None
"""
return EnergyAde(self._city, self._path)
@property
def _stl(self):
"""
@ -70,25 +60,6 @@ class ExportsFactory:
"""
return Obj(self._city, self._path).to_ground_points()
@property
def _idf(self):
"""
Export the city to Energy+ idf format
When target_buildings is set, only those will be calculated and their energy consumption output, non adjacent
buildings will be considered shading objects and adjacent buildings will be considered adiabatic.
Adjacent buildings are provided they will be considered heated so energy plus calculations are more precise but
no results will be calculated to speed up the calculation process.
:return: None
"""
idf_data_path = (Path(__file__).parent / './formats/idf_files/').resolve()
# todo: create a get epw file function based on the city
weather_path = (Path(__file__).parent / '../data/weather/epw/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'), weather_path,
target_buildings=self._target_buildings, adjacent_buildings=self._adjacent_buildings)
@property
def _sra(self):
"""

30
exports/formats/insel.py Normal file
View File

@ -0,0 +1,30 @@
"""
Insel export models to insel format
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from abc import ABC
class Insel(ABC):
def __init__(self, city, path):
self._city = city
self._path = path
self._results = None
@staticmethod
def _add_block(file, block_number, block_type, inputs='', parameters=''):
file += "S " + str(block_number) + " " + block_type + "\n"
for block_input in inputs:
file += str(block_input) + "\n"
if len(parameters) > 0:
file += "P " + str(block_number) + "\n"
for block_parameter in parameters:
file += str(block_parameter) + "\n"
return file
def _export(self):
raise NotImplementedError

47
helpers/monthly_values.py Normal file
View File

@ -0,0 +1,47 @@
"""
Monthly values
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
"""
import pandas as pd
import numpy as np
import calendar as cal
class MonthlyValues:
def __init__(self):
self._month_hour = None
def get_mean_values(self, values):
out = None
if values is not None:
if 'month' not in values.columns:
values = pd.concat([self.month_hour, pd.DataFrame(values)], axis=1)
out = values.groupby('month', as_index=False).mean()
del out['month']
return out
def get_total_month(self, values):
out = None
if values is not None:
if 'month' not in values.columns:
values = pd.concat([self.month_hour, pd.DataFrame(values)], axis=1)
out = pd.DataFrame(values).groupby('month', as_index=False).sum()
del out['month']
return out
@property
def month_hour(self):
"""
returns a DataFrame that has x values of the month number (January = 1, February = 2...),
being x the number of hours of the corresponding month
:return: DataFrame(int)
"""
array = []
for i in range(0, 12):
days_of_month = cal.monthrange(2015, i+1)[1]
total_hours = days_of_month * 24
array = np.concatenate((array, np.full(total_hours, i + 1)))
self._month_hour = pd.DataFrame(array, columns=['month'])
return self._month_hour

View File

@ -9,7 +9,7 @@ from unittest import TestCase
from imports.geometry_factory import GeometryFactory
from imports.usage_factory import UsageFactory
from imports.construction_factory import ConstructionFactory
from exports.exports_factory import ExportsFactory
from exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
class TestBuildings(TestCase):
@ -32,7 +32,7 @@ class TestBuildings(TestCase):
building.year_of_construction = 2006
ConstructionFactory('nrel', city).enrich()
UsageFactory('comnet', city).enrich()
ExportsFactory('idf', city, output_path).export()
EnergyBuildingsExportsFactory('idf', city, output_path).export()
self.assertEqual(1, len(city.buildings))
for building in city.buildings:

View File

@ -8,11 +8,9 @@ from pathlib import Path
from unittest import TestCase
from numpy import inf
from pyproj import Proj, transform
from imports.geometry_factory import GeometryFactory
from imports.construction_factory import ConstructionFactory
import geopandas
class TestGeometryFactory(TestCase):
@ -169,16 +167,3 @@ class TestGeometryFactory(TestCase):
self._check_surfaces(building)
self.assertEqual(1912.0898135701814, building.volume)
self.assertEqual(146.19493345171213, building.floor_area)
# osm
def test_subway(self):
"""
Test subway parsing
:return:
"""
file_path = (self._example_path / 'subway.osm').resolve()
city = GeometryFactory('osm_subway', path=file_path).city
self.assertIsNotNone(city, 'subway entrances is none')
self.assertEqual(len(city.city_objects), 20, 'Wrong number of subway entrances')

View File

@ -11,7 +11,7 @@ from unittest import TestCase
from imports.geometry_factory import GeometryFactory
from imports.usage_factory import UsageFactory
from imports.construction_factory import ConstructionFactory
from exports.exports_factory import ExportsFactory
from exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
from city_model_structure.greenery.vegetation import Vegetation
from city_model_structure.greenery.soil import Soil
from city_model_structure.greenery.plant import Plant
@ -66,7 +66,7 @@ class GreeneryInIdf(TestCase):
if surface.type == cte.ROOF:
surface.vegetation = vegetation
_idf_2 = ExportsFactory('idf', city, output_path).export_debug()
_idf_2 = EnergyBuildingsExportsFactory('idf', city, output_path).export_debug()
_idf_2.run()
with open((output_path / f'{city.name}_out.csv').resolve()) as f:
reader = csv.reader(f, delimiter=',')
@ -85,7 +85,7 @@ class GreeneryInIdf(TestCase):
building.year_of_construction = 2006
ConstructionFactory('nrel', city).enrich()
UsageFactory('comnet', city).enrich()
_idf = ExportsFactory('idf', city, output_path).export()
_idf = EnergyBuildingsExportsFactory('idf', city, output_path).export()
_idf.run()
with open((output_path / f'{city.name}_out.csv').resolve()) as f:
reader = csv.reader(f, delimiter=',')

View File

@ -0,0 +1,149 @@
"""
TestInselExports test
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from pathlib import Path
from unittest import TestCase
import pandas as pd
import helpers.constants as cte
from helpers.monthly_values import MonthlyValues
from imports.geometry_factory import GeometryFactory
from imports.construction_factory import ConstructionFactory
from imports.usage_factory import UsageFactory
from exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
from imports.weather_factory import WeatherFactory
class TestExports(TestCase):
"""
TestExports class contains the unittest for export functionality
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._city = None
self._complete_city = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
def _get_citygml(self, file):
file_path = (self._example_path / file).resolve()
self._city = GeometryFactory('citygml', path=file_path).city
self.assertIsNotNone(self._city, 'city is none')
return self._city
@property
def _read_sra_file(self) -> []:
path = (self._example_path / "one_building_in_kelowna_sra_SW.out").resolve()
_results = pd.read_csv(path, sep='\s+', header=0)
id_building = ''
header_building = []
_radiation = []
for column in _results.columns.values:
if id_building != column.split(':')[1]:
id_building = column.split(':')[1]
if len(header_building) > 0:
_radiation.append(pd.concat([MonthlyValues().month_hour, _results[header_building]], axis=1))
header_building = [column]
else:
header_building.append(column)
_radiation.append(pd.concat([MonthlyValues().month_hour, _results[header_building]], axis=1))
return _radiation
def _set_irradiance_surfaces(self, city):
"""
saves in building surfaces the correspondent irradiance at different time-scales depending on the mode
if building is None, it saves all buildings' surfaces in file, if building is specified, it saves only that
specific building values
:parameter city: city
:return: none
"""
for radiation in self._read_sra_file:
city_object_name = radiation.columns.values.tolist()[1].split(':')[1]
building = city.city_object(city_object_name)
for column in radiation.columns.values:
if column == cte.MONTH:
continue
header_id = column
surface_id = header_id.split(':')[2]
surface = building.surface_by_id(surface_id)
new_value = pd.DataFrame(radiation[[header_id]].to_numpy(), columns=['sra'])
surface.global_irradiance[cte.HOUR] = new_value
month_new_value = MonthlyValues().get_mean_values(new_value)
surface.global_irradiance[cte.MONTH] = month_new_value
def test_insel_monthly_energy_balance_export(self):
"""
export to Insel MonthlyEnergyBalance
"""
city = self._get_citygml('one_building_in_kelowna.gml')
WeatherFactory('epw', city, file_name='CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').enrich()
for building in city.buildings:
building.external_temperature[cte.MONTH] = MonthlyValues().\
get_mean_values(building.external_temperature[cte.HOUR][['epw']])
self._set_irradiance_surfaces(city)
for building in city.buildings:
self.assertIsNotNone(building.external_temperature[cte.MONTH], f'building {building.name} '
f'external_temperature is none')
for surface in building.surfaces:
if surface.type != 'Ground':
self.assertIsNotNone(surface.global_irradiance[cte.MONTH], f'surface in building {building.name} '
f'global_irradiance is none')
for building in city.buildings:
building.year_of_construction = 2006
if building.function is None:
building.function = 'large office'
building.attic_heated = False
building.basement_heated = False
ConstructionFactory('nrel', city).enrich()
UsageFactory('comnet', city).enrich()
# parameters written:
for building in city.buildings:
self.assertIsNotNone(building.volume, f'building {building.name} volume is none')
self.assertIsNotNone(building.average_storey_height, f'building {building.name} average_storey_height is none')
self.assertIsNotNone(building.storeys_above_ground, f'building {building.name} storeys_above_ground is none')
self.assertIsNotNone(building.attic_heated, f'building {building.name} attic_heated is none')
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
for internal_zone in building.internal_zones:
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
for thermal_zone in internal_zone.thermal_zones:
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
f'indirectly_heated_area_ratio is none')
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
f'effective_thermal_capacity is none')
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, f'thermal zone {thermal_zone.id} '
f'additional_thermal_bridge_u_value '
f'is none')
self.assertIsNotNone(thermal_zone.total_floor_area, f'thermal zone {thermal_zone.id} '
f'total_floor_area is none')
for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.type)
self.assertIsNotNone(thermal_boundary.opaque_area)
self.assertIsNotNone(thermal_boundary.window_ratio)
self.assertIsNotNone(thermal_boundary.u_value)
self.assertIsNotNone(thermal_boundary.thermal_openings)
if thermal_boundary.type is not cte.GROUND:
self.assertIsNotNone(thermal_boundary.parent_surface.short_wave_reflectance)
for usage_zone in internal_zone.usage_zones:
self.assertIsNotNone(usage_zone.percentage, f'usage zone {usage_zone.usage} percentage is none')
self.assertIsNotNone(usage_zone.internal_gains, f'usage zone {usage_zone.usage} internal_gains is none')
self.assertIsNotNone(usage_zone.thermal_control, f'usage zone {usage_zone.usage} thermal_control is none')
self.assertIsNotNone(usage_zone.hours_day, f'usage zone {usage_zone.usage} hours_day is none')
self.assertIsNotNone(usage_zone.days_year, f'usage zone {usage_zone.usage} days_year is none')
self.assertIsNotNone(usage_zone.mechanical_air_change, f'usage zone {usage_zone.usage} '
f'mechanical_air_change is none')
# export files
try:
EnergyBuildingsExportsFactory('insel_monthly_energy_balance', city, self._output_path).export_debug()
except Exception:
self.fail("Insel MonthlyEnergyBalance ExportsFactory raised ExceptionType unexpectedly!")

View File

@ -1,69 +0,0 @@
"""
TestSchedulesFactory test and validate the city model structure schedules
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from pathlib import Path
from unittest import TestCase
from imports.geometry_factory import GeometryFactory
from imports.usage_factory import UsageFactory
from imports.construction_factory import ConstructionFactory
from imports.schedules_factory import SchedulesFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper
class TestSchedulesFactory(TestCase):
"""
TestSchedulesFactory TestCase
"""
def setUp(self) -> None:
"""
Configure test environment
:return:
"""
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def _get_citygml(self, file):
file_path = (self._example_path / file).resolve()
_city = GeometryFactory('citygml', path=file_path).city
for building in _city.buildings:
building.year_of_construction = 2006
ConstructionFactory('nrel', _city).enrich()
self.assertIsNotNone(_city, 'city is none')
for building in _city.buildings:
building.function = GeometryHelper.libs_function_from_hft(building.function)
building.year_of_construction = 2005
UsageFactory('hft', _city).enrich()
return _city
def test_doe_idf_archetypes(self):
"""
Enrich the city with doe_idf schedule archetypes and verify it
"""
file = (self._example_path / 'C40_Final.gml').resolve()
city = self._get_citygml(file)
occupancy_handler = 'doe_idf'
SchedulesFactory(occupancy_handler, city).enrich()
for building in city.buildings:
for internal_zone in building.internal_zones:
self.assertTrue(len(internal_zone.usage_zones) > 0)
for usage_zone in internal_zone.usage_zones:
self.assertIsNot(len(usage_zone.occupancy.occupancy_schedules), 0, 'no occupancy schedules defined')
for schedule in usage_zone.occupancy.occupancy_schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)
self.assertIsNot(len(usage_zone.lighting.schedules), 0, 'no lighting schedules defined')
for schedule in usage_zone.lighting.schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)

File diff suppressed because it is too large Load Diff