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:
commit
2dbaaefd74
|
@ -30,6 +30,7 @@ from helpers.location import Location
|
||||||
from city_model_structure.energy_system import EnergySystem
|
from city_model_structure.energy_system import EnergySystem
|
||||||
from city_model_structure.lca_material import LcaMaterial
|
from city_model_structure.lca_material import LcaMaterial
|
||||||
|
|
||||||
|
|
||||||
class City:
|
class City:
|
||||||
"""
|
"""
|
||||||
City class
|
City class
|
||||||
|
@ -82,8 +83,6 @@ class City:
|
||||||
if self._location is None:
|
if self._location is None:
|
||||||
gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth
|
gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth
|
||||||
try:
|
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
|
input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data
|
||||||
except pyproj.exceptions.CRSError:
|
except pyproj.exceptions.CRSError:
|
||||||
sys.stderr.write('Invalid projection reference system, please check the input data. '
|
sys.stderr.write('Invalid projection reference system, please check the input data. '
|
||||||
|
@ -108,9 +107,7 @@ class City:
|
||||||
Get city name
|
Get city name
|
||||||
:return: str
|
:return: str
|
||||||
"""
|
"""
|
||||||
if self._name is None:
|
return self._get_location().city
|
||||||
return self._get_location().city
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def climate_reference_city(self) -> Union[None, str]:
|
def climate_reference_city(self) -> Union[None, str]:
|
||||||
|
@ -455,5 +452,5 @@ class City:
|
||||||
return _merge_city
|
return _merge_city
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def level_of_detail(self) -> LevelOfDetail:
|
def level_of_detail(self):
|
||||||
return self._level_of_detail
|
return self._level_of_detail
|
||||||
|
|
|
@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class LevelOfDetail:
|
class LevelOfDetail:
|
||||||
"""
|
"""
|
||||||
Level of detail for the city class
|
Level of detail for the city class
|
||||||
|
@ -17,41 +18,44 @@ class LevelOfDetail:
|
||||||
@property
|
@property
|
||||||
def geometry(self):
|
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
|
return self._geometry
|
||||||
|
|
||||||
@geometry.setter
|
@geometry.setter
|
||||||
def geometry(self, value):
|
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
|
self._geometry = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def construction(self):
|
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
|
return self._construction
|
||||||
|
|
||||||
@construction.setter
|
@construction.setter
|
||||||
def construction(self, value):
|
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
|
self._construction = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def usage(self):
|
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
|
return self._usage
|
||||||
|
|
||||||
@usage.setter
|
@usage.setter
|
||||||
def usage(self, value):
|
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
|
self._usage = value
|
||||||
|
|
|
@ -7,7 +7,6 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
||||||
Soroush Samareh Abolhassani soroush.samarehabolhassani@mail.concordia.ca
|
Soroush Samareh Abolhassani soroush.samarehabolhassani@mail.concordia.ca
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
import math
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from geomeppy import IDF
|
from geomeppy import IDF
|
||||||
import helpers.constants as cte
|
import helpers.constants as cte
|
||||||
|
@ -57,10 +56,6 @@ class Idf:
|
||||||
cte.GROUND: 'floor',
|
cte.GROUND: 'floor',
|
||||||
cte.ROOF: 'roof'
|
cte.ROOF: 'roof'
|
||||||
}
|
}
|
||||||
idf_usage = {
|
|
||||||
# todo: make an enum for all the usage types
|
|
||||||
cte.RESIDENTIAL: 'residential_building'
|
|
||||||
}
|
|
||||||
idf_type_limits = {
|
idf_type_limits = {
|
||||||
cte.ON_OFF: 'on/off',
|
cte.ON_OFF: 'on/off',
|
||||||
cte.FRACTION: 'Fraction',
|
cte.FRACTION: 'Fraction',
|
||||||
|
@ -80,20 +75,6 @@ class Idf:
|
||||||
cte.WINTER_DESIGN_DAY: 'WinterDesignDay',
|
cte.WINTER_DESIGN_DAY: 'WinterDesignDay',
|
||||||
cte.SUMMER_DESIGN_DAY: 'SummerDesignDay'
|
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",
|
def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, export_type="Surfaces",
|
||||||
target_buildings=None, adjacent_buildings=None):
|
target_buildings=None, adjacent_buildings=None):
|
||||||
|
@ -395,6 +376,7 @@ class Idf:
|
||||||
self._remove_location()
|
self._remove_location()
|
||||||
self._remove_sizing_periods()
|
self._remove_sizing_periods()
|
||||||
self._rename_building(self._city.name)
|
self._rename_building(self._city.name)
|
||||||
|
self._lod = self._city.level_of_detail.geometry
|
||||||
for building in self._city.buildings:
|
for building in self._city.buildings:
|
||||||
|
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
|
@ -518,19 +500,22 @@ class Idf:
|
||||||
self._city.lower_corner)
|
self._city.lower_corner)
|
||||||
|
|
||||||
surface.setcoords(coordinates)
|
surface.setcoords(coordinates)
|
||||||
self._add_windows(boundary)
|
|
||||||
|
|
||||||
def _add_windows(self, boundary):
|
if self._lod >= 3:
|
||||||
for opening in boundary.thermal_openings:
|
for internal_zone in building.internal_zones:
|
||||||
for construction in self._idf.idfobjects[self._CONSTRUCTION]:
|
for thermal_zone in internal_zone.thermal_zones:
|
||||||
if construction['Outside_Layer'].split('_')[0] == 'glazing':
|
for boundary in thermal_zone.thermal_boundaries:
|
||||||
window_construction = construction
|
self._add_windows_by_vertices(boundary)
|
||||||
if self._compare_window_constructions(window_construction, opening):
|
else:
|
||||||
opening_name = 'window_' + str(len(self._idf.idfobjects[self._WINDOW]) + 1)
|
# idf only allows setting wwr for external walls
|
||||||
opening_length = math.sqrt(opening.area)
|
wwr = 0
|
||||||
self._idf.newidfobject(self._WINDOW, Name=f'{opening_name}', Construction_Name=window_construction['Name'],
|
for surface in building.surfaces:
|
||||||
Building_Surface_Name=boundary.parent_surface.name, Multiplier='1',
|
if surface.type == cte.WALL:
|
||||||
Length=opening_length, Height=opening_length)
|
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):
|
def _compare_window_constructions(self, window_construction, opening):
|
||||||
glazing = window_construction['Outside_Layer']
|
glazing = window_construction['Outside_Layer']
|
||||||
|
|
|
@ -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)
|
|
|
@ -14,6 +14,7 @@ from imports.geometry.helpers.geometry_helper import GeometryHelper
|
||||||
from imports.construction_factory import ConstructionFactory
|
from imports.construction_factory import ConstructionFactory
|
||||||
from imports.usage_factory import UsageFactory
|
from imports.usage_factory import UsageFactory
|
||||||
from exports.exports_factory import ExportsFactory
|
from exports.exports_factory import ExportsFactory
|
||||||
|
from exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||||
import helpers.constants as cte
|
import helpers.constants as cte
|
||||||
from city_model_structure.city import City
|
from city_model_structure.city import City
|
||||||
|
|
||||||
|
@ -102,8 +103,9 @@ class TestExports(TestCase):
|
||||||
ConstructionFactory('nrel', city).enrich()
|
ConstructionFactory('nrel', city).enrich()
|
||||||
UsageFactory('comnet', city).enrich()
|
UsageFactory('comnet', city).enrich()
|
||||||
try:
|
try:
|
||||||
ExportsFactory('idf', city, self._output_path).export()
|
EnergyBuildingsExportsFactory('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,
|
||||||
|
target_buildings=['gml_1066158', 'gml_1066159']).export()
|
||||||
except Exception:
|
except Exception:
|
||||||
self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")
|
self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user