Merge branch 'bug_in_idf_exporter_wwr' into 'master'

Bug in idf exporter wwr

See merge request Guille/hub!43
This commit is contained in:
Guillermo Gutierrez Morote 2022-12-01 20:17:57 +00:00
commit 2dbaaefd74
5 changed files with 33 additions and 102 deletions

View File

@ -30,6 +30,7 @@ from helpers.location import Location
from city_model_structure.energy_system import EnergySystem
from city_model_structure.lca_material import LcaMaterial
class City:
"""
City class
@ -82,8 +83,6 @@ class City:
if self._location is None:
gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth
try:
if self._srs_name in GeometryHelper.srs_transformations.keys():
self._srs_name = GeometryHelper.srs_transformations[self._srs_name]
input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data
except pyproj.exceptions.CRSError:
sys.stderr.write('Invalid projection reference system, please check the input data. '
@ -108,9 +107,7 @@ class City:
Get city name
:return: str
"""
if self._name is None:
return self._get_location().city
return self._name
@property
def climate_reference_city(self) -> Union[None, str]:
@ -455,5 +452,5 @@ class City:
return _merge_city
@property
def level_of_detail(self) -> LevelOfDetail:
def level_of_detail(self):
return self._level_of_detail

View File

@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
class LevelOfDetail:
"""
Level of detail for the city class
@ -17,41 +18,44 @@ class LevelOfDetail:
@property
def geometry(self):
"""
Get the city minimal geometry level of detail
Get the city minimal geometry level of detail from 0 to 4
:return: int
"""
return self._geometry
@geometry.setter
def geometry(self, value):
"""
Set the city minimal geometry level of detail
Set the city minimal geometry level of detail from 0 to 4
"""
self._geometry = value
@property
def construction(self):
"""
Get the city minimal construction level of detail
Get the city minimal construction level of detail, 1 or 2
:return: int
"""
return self._construction
@construction.setter
def construction(self, value):
"""
Set the city minimal construction level of detail
Set the city minimal construction level of detail, 1 or 2
"""
self._construction = value
@property
def usage(self):
"""
Get the city minimal usage level of detail
Get the city minimal usage level of detail, 1 or 2
:return: int
"""
return self._usage
@usage.setter
def usage(self, value):
"""
Set the city minimal usage level of detail
Set the city minimal usage level of detail, 1 or 2
"""
self._usage = value

View File

@ -7,7 +7,6 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
Soroush Samareh Abolhassani soroush.samarehabolhassani@mail.concordia.ca
"""
import copy
import math
from pathlib import Path
from geomeppy import IDF
import helpers.constants as cte
@ -57,10 +56,6 @@ class Idf:
cte.GROUND: 'floor',
cte.ROOF: 'roof'
}
idf_usage = {
# todo: make an enum for all the usage types
cte.RESIDENTIAL: 'residential_building'
}
idf_type_limits = {
cte.ON_OFF: 'on/off',
cte.FRACTION: 'Fraction',
@ -80,20 +75,6 @@ class Idf:
cte.WINTER_DESIGN_DAY: 'WinterDesignDay',
cte.SUMMER_DESIGN_DAY: 'SummerDesignDay'
}
idf_schedule_types = {
'compact': 'Compact',
cte.DAY: 'Day',
cte.WEEK: 'Week',
cte.YEAR: 'Year',
'file': 'File'
}
idf_schedule_data_type = {
'compact': 'Compact',
'hourly': 'Hourly',
'daily': 'Daily',
'interval': 'Interval',
'list': 'List',
}
def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, export_type="Surfaces",
target_buildings=None, adjacent_buildings=None):
@ -395,6 +376,7 @@ class Idf:
self._remove_location()
self._remove_sizing_periods()
self._rename_building(self._city.name)
self._lod = self._city.level_of_detail.geometry
for building in self._city.buildings:
for internal_zone in building.internal_zones:
@ -518,19 +500,22 @@ class Idf:
self._city.lower_corner)
surface.setcoords(coordinates)
self._add_windows(boundary)
def _add_windows(self, boundary):
for opening in boundary.thermal_openings:
for construction in self._idf.idfobjects[self._CONSTRUCTION]:
if construction['Outside_Layer'].split('_')[0] == 'glazing':
window_construction = construction
if self._compare_window_constructions(window_construction, opening):
opening_name = 'window_' + str(len(self._idf.idfobjects[self._WINDOW]) + 1)
opening_length = math.sqrt(opening.area)
self._idf.newidfobject(self._WINDOW, Name=f'{opening_name}', Construction_Name=window_construction['Name'],
Building_Surface_Name=boundary.parent_surface.name, Multiplier='1',
Length=opening_length, Height=opening_length)
if self._lod >= 3:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
for boundary in thermal_zone.thermal_boundaries:
self._add_windows_by_vertices(boundary)
else:
# idf only allows setting wwr for external walls
wwr = 0
for surface in building.surfaces:
if surface.type == cte.WALL:
wwr = surface.associated_thermal_boundaries[0].window_ratio
self._idf.set_wwr(wwr, construction='glazing_1')
def _add_windows_by_vertices(self, boundary):
raise NotImplementedError
def _compare_window_constructions(self, window_construction, opening):
glazing = window_construction['Outside_Layer']

View File

@ -1,57 +0,0 @@
"""
Building test
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez Morote Guillermo.GutierrezMorote@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 exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
class TestBuildings(TestCase):
"""
TestBuilding TestCase 1
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._city_gml = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def test_doe_idf(self):
city_file = "../unittests/tests_data/one_building_in_kelowna.gml"
output_path = Path('../unittests/tests_outputs/').resolve()
city = GeometryFactory('citygml', path=city_file).city
for building in city.buildings:
building.year_of_construction = 2006
ConstructionFactory('nrel', city).enrich()
UsageFactory('comnet', city).enrich()
EnergyBuildingsExportsFactory('idf', city, output_path).export()
self.assertEqual(1, len(city.buildings))
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)

View File

@ -14,6 +14,7 @@ from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.construction_factory import ConstructionFactory
from imports.usage_factory import UsageFactory
from exports.exports_factory import ExportsFactory
from exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
import helpers.constants as cte
from city_model_structure.city import City
@ -102,8 +103,9 @@ class TestExports(TestCase):
ConstructionFactory('nrel', city).enrich()
UsageFactory('comnet', city).enrich()
try:
ExportsFactory('idf', city, self._output_path).export()
ExportsFactory('idf', city, self._output_path, target_buildings=['gml_1066158', 'gml_1066159']).export()
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
EnergyBuildingsExportsFactory('idf', city, self._output_path,
target_buildings=['gml_1066158', 'gml_1066159']).export()
except Exception:
self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")