Merge branch 'updating_central_data_model' into 'master'

Updating central data model

See merge request Guille/hub!31
This commit is contained in:
Guillermo Gutierrez Morote 2022-11-10 19:20:27 +00:00
commit 15eea30d81
14 changed files with 317 additions and 479 deletions

View File

@ -8,6 +8,7 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
from typing import List, Union
import numpy as np
import helpers.constants as cte
from city_model_structure.building_demand.surface import Surface
from city_model_structure.city_object import CityObject
from city_model_structure.building_demand.household import Household
@ -48,11 +49,11 @@ class Building(CityObject):
self._min_z = min(self._min_z, surface.lower_corner[2])
surface.id = surface_id
# todo: consider all type of surfaces, not only these four
if surface.type == 'Ground':
if surface.type == cte.GROUND:
self._grounds.append(surface)
elif surface.type == 'Wall':
elif surface.type == cte.WALL:
self._walls.append(surface)
elif surface.type == 'Roof':
elif surface.type == cte.ROOF:
self._roofs.append(surface)
else:
self._internal_walls.append(surface)
@ -60,11 +61,18 @@ class Building(CityObject):
@property
def shell(self) -> Polyhedron:
"""
Get building shell
Get building's external polyhedron
:return: [Polyhedron]
"""
polygons = []
for surface in self.surfaces:
if surface.type is not cte.INTERIOR_WALL:
polygons.append(surface.solid_polygon)
if surface.holes_polygons is not None:
for hole in surface.holes_polygons:
polygons.append(hole)
if self._shell is None:
self._shell = Polyhedron(self.surfaces)
self._shell = Polyhedron(polygons)
return self._shell
@property
@ -103,6 +111,14 @@ class Building(CityObject):
"""
return self._walls
@property
def internal_walls(self) -> List[Surface]:
"""
Get building internal wall surfaces
:return: [Surface]
"""
return self._internal_walls
@property
def terrains(self) -> Union[None, List[Surface]]:
"""
@ -327,7 +343,7 @@ class Building(CityObject):
@property
def human_readable_name(self):
"""
Get the human readable name for the building
Get the human-readable name for the building
:return: str
"""
return self._human_readable_name
@ -335,6 +351,6 @@ class Building(CityObject):
@human_readable_name.setter
def human_readable_name(self, value):
"""
Set the human readable name for the building
Set the human-readable name for the building
"""
self._human_readable_name = value

View File

@ -66,7 +66,9 @@ class Storey:
windows_areas = []
for hole in surface.holes_polygons:
windows_areas.append(hole.area)
self._thermal_boundaries.append(ThermalBoundary(surface, surface.solid_polygon.area, windows_areas))
new_thermal_boundary = ThermalBoundary(surface, surface.solid_polygon.area, windows_areas)
surface.associated_thermal_boundaries.append(new_thermal_boundary)
self._thermal_boundaries.append(new_thermal_boundary)
return self._thermal_boundaries
@property
@ -78,7 +80,7 @@ class Storey:
if self._virtual_surfaces is None:
self._virtual_surfaces = []
for thermal_boundary in self.thermal_boundaries:
self._virtual_surfaces.append(thermal_boundary.virtual_internal_surface)
self._virtual_surfaces.append(thermal_boundary.internal_surface)
return self._virtual_surfaces
@property

View File

@ -13,6 +13,8 @@ from typing import List, Union
from city_model_structure.attributes.polygon import Polygon
from city_model_structure.attributes.plane import Plane
from city_model_structure.attributes.point import Point
from city_model_structure.greenery.vegetation import Vegetation
from city_model_structure.building_demand.thermal_boundary import ThermalBoundary
import helpers.constants as cte
@ -21,15 +23,13 @@ class Surface:
Surface class
"""
def __init__(self, solid_polygon, perimeter_polygon, holes_polygons=None, name=None, surface_type=None, swr=None):
def __init__(self, solid_polygon, perimeter_polygon, holes_polygons=None, name=None, surface_type=None):
self._type = surface_type
self._swr = swr
self._name = name
self._id = None
self._azimuth = None
self._inclination = None
self._area_above_ground = None
self._area_below_ground = None
self._area = None
self._lower_corner = None
self._upper_corner = None
self._shared_surfaces = []
@ -37,9 +37,11 @@ class Surface:
self._perimeter_polygon = perimeter_polygon
self._holes_polygons = holes_polygons
self._solid_polygon = solid_polygon
self._pv_system_installed = None
self._short_wave_reflectance = None
self._long_wave_emittance = None
self._inverse = None
# todo: create self._associated_thermal_boundaries and bring the vegetation here instead of in thermal_boundary
self._associated_thermal_boundaries = []
self._vegetation = None
@property
def name(self):
@ -78,23 +80,6 @@ class Surface:
"""
raise NotImplementedError
@property
def swr(self) -> Union[None, float]:
"""
Get surface short wave reflectance
:return: None or float
"""
return self._swr
@swr.setter
def swr(self, value):
"""
Set surface short wave reflectance
:param value: float
"""
if value is not None:
self._swr = float(value)
def _max_coord(self, axis):
if axis == 'x':
axis = 0
@ -146,23 +131,13 @@ class Surface:
return self._upper_corner
@property
def area_above_ground(self):
def perimeter_area(self):
"""
Get surface area above ground in square meters
Get perimeter surface area in square meters (opaque + transparent)
:return: float
"""
if self._area_above_ground is None:
self._area_above_ground = self.perimeter_polygon.area - self.area_below_ground
return self._area_above_ground
# todo: to be implemented when adding terrains
@property
def area_below_ground(self):
"""
Get surface area below ground in square meters
:return: float
"""
return 0.0
self._area = self.perimeter_polygon.area
return self._area
@property
def azimuth(self):
@ -262,6 +237,42 @@ class Surface:
"""
self._holes_polygons = value
@property
def short_wave_reflectance(self):
"""
Get the short wave reflectance, this includes all solar spectrum, visible and not visible
The absorptance as an opaque surface, can be calculated as 1-short_wave_reflectance
:return: float
"""
return self._short_wave_reflectance
@short_wave_reflectance.setter
def short_wave_reflectance(self, value):
"""
Set the short wave reflectance, this includes all solar spectrum, visible and not visible
The absorptance as an opaque surface, can be calculated as 1-short_wave_reflectance
:param value: float
"""
self._short_wave_reflectance = value
@property
def long_wave_emittance(self):
"""
Get the long wave emittance af the surface
The thermal absorptance can be calculated as 1-long_wave_emittance
:return: float
"""
return self._long_wave_emittance
@long_wave_emittance.setter
def long_wave_emittance(self, value):
"""
Set the long wave emittance af the surface
The thermal absorptance can be calculated as 1-long_wave_emittance
:param value: float
"""
self._long_wave_emittance = value
@property
def inverse(self) -> Surface:
"""
@ -302,3 +313,35 @@ class Surface:
surface_child = Surface(part_1, part_1, name=self.name, surface_type=self.type)
rest_surface = Surface(part_2, part_2, name=self.name, surface_type=self.type)
return surface_child, rest_surface, intersection
@property
def vegetation(self) -> Union[None, Vegetation]:
"""
Get the vegetation construction at the external surface of the thermal boundary
:return: None or Vegetation
"""
return self._vegetation
@vegetation.setter
def vegetation(self, value):
"""
Set the vegetation construction at the external surface of the thermal boundary
:param value: Vegetation
"""
self._vegetation = value
@property
def associated_thermal_boundaries(self) -> Union[None, List[ThermalBoundary]]:
"""
Get the list of thermal boundaries that has this surface as external face
:return: None or [ThermalBoundary]
"""
return self._associated_thermal_boundaries
@associated_thermal_boundaries.setter
def associated_thermal_boundaries(self, value):
"""
Set the list of thermal boundaries that has this surface as external face
:param value: None or [ThermalBoundary]
"""
self._associated_thermal_boundaries = value

View File

@ -7,13 +7,13 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
"""
import uuid
from typing import List, Union
from typing import List, Union, TypeVar
from helpers.configuration_helper import ConfigurationHelper as ch
from city_model_structure.building_demand.layer import Layer
from city_model_structure.building_demand.thermal_opening import ThermalOpening
from city_model_structure.building_demand.thermal_zone import ThermalZone
from city_model_structure.building_demand.surface import Surface
from city_model_structure.greenery.vegetation import Vegetation
Surface = TypeVar('Surface')
class ThermalBoundary:
@ -28,22 +28,14 @@ class ThermalBoundary:
self._thermal_zones = None
self._thermal_openings = None
self._layers = None
self._outside_solar_absorptance = None
self._outside_thermal_absorptance = None
self._outside_visible_absorptance = None
self._u_value = None
self._outside_shortwave_reflectance = None
self._construction_name = None
self._hi = ch().convective_heat_transfer_coefficient_interior
self._he = ch().convective_heat_transfer_coefficient_exterior
self._hi = ch().convective_heat_transfer_coefficient_interior
self._u_value = None
self._construction_name = None
self._thickness = None
self._virtual_internal_surface = None
self._inside_emissivity = None
self._alpha_coefficient = None
self._radiative_coefficient = None
self._internal_surface = None
self._window_ratio = None
self._window_ratio_is_calculated = False
self._vegetation = None
@property
def id(self):
@ -79,23 +71,6 @@ class ThermalBoundary:
"""
self._thermal_zones = value
# todo: do I need these two??
@property
def azimuth(self):
"""
Get the thermal boundary azimuth in radians
:return: float
"""
return self.parent_surface.azimuth
@property
def inclination(self):
"""
Get the thermal boundary inclination in radians
:return: float
"""
return self.parent_surface.inclination
@property
def opaque_area(self):
"""
@ -118,58 +93,6 @@ class ThermalBoundary:
self._thickness += layer.thickness
return self._thickness
@property
def outside_solar_absorptance(self) -> Union[None, float]:
"""
Get thermal boundary outside solar absorptance
:return: None or float
"""
return self._outside_solar_absorptance
@outside_solar_absorptance.setter
def outside_solar_absorptance(self, value):
"""
Set thermal boundary outside solar absorptance
:param value: float
"""
if value is not None:
self._outside_solar_absorptance = float(value)
self._outside_shortwave_reflectance = 1.0 - float(value)
@property
def outside_thermal_absorptance(self) -> Union[None, float]:
"""
Get thermal boundary outside thermal absorptance
:return: float
"""
return self._outside_thermal_absorptance
@outside_thermal_absorptance.setter
def outside_thermal_absorptance(self, value):
"""
Set thermal boundary outside thermal absorptance
:param value: float
"""
if value is not None:
self._outside_thermal_absorptance = float(value)
@property
def outside_visible_absorptance(self) -> Union[None, float]:
"""
Get thermal boundary outside visible absorptance
:return: None or float
"""
return self._outside_visible_absorptance
@outside_visible_absorptance.setter
def outside_visible_absorptance(self, value):
"""
Set thermal boundary outside visible absorptance
:param value: float
"""
if value is not None:
self._outside_visible_absorptance = float(value)
@property
def thermal_openings(self) -> Union[None, List[ThermalOpening]]:
"""
@ -311,24 +234,6 @@ class ThermalBoundary:
if value is not None:
self._u_value = float(value)
@property
def outside_shortwave_reflectance(self) -> Union[None, float]:
"""
Get thermal boundary external shortwave reflectance
:return: None or float
"""
return self._outside_shortwave_reflectance
@outside_shortwave_reflectance.setter
def outside_shortwave_reflectance(self, value):
"""
Set thermal boundary external shortwave reflectance
:param value: float
"""
if value is not None:
self._outside_shortwave_reflectance = float(value)
self._outside_solar_absorptance = 1.0 - float(value)
@property
def hi(self) -> Union[None, float]:
"""
@ -364,78 +269,11 @@ class ThermalBoundary:
self._he = value
@property
def virtual_internal_surface(self) -> Surface:
def internal_surface(self) -> Surface:
"""
Get the internal surface of the thermal boundary
:return: Surface
"""
if self._virtual_internal_surface is None:
self._virtual_internal_surface = self.parent_surface.inverse
return self._virtual_internal_surface
@property
def inside_emissivity(self) -> Union[None, float]:
"""
Get the short wave emissivity factor of the thermal boundary's internal surface (-)
:return: None or float
"""
return self._inside_emissivity
@inside_emissivity.setter
def inside_emissivity(self, value):
"""
Set short wave emissivity factor of the thermal boundary's internal surface (-)
:param value: float
"""
if value is not None:
self._inside_emissivity = float(value)
@property
def alpha_coefficient(self) -> Union[None, float]:
"""
Get the long wave emissivity factor of the thermal boundary's internal surface (-)
:return: None or float
"""
return self._alpha_coefficient
@alpha_coefficient.setter
def alpha_coefficient(self, value):
"""
Set long wave emissivity factor of the thermal boundary's internal surface (-)
:param value: float
"""
if value is not None:
self._alpha_coefficient = float(value)
@property
def radiative_coefficient(self) -> Union[None, float]:
"""
Get the radiative coefficient of the thermal boundary's external surface (-)
:return: None or float
"""
return self._radiative_coefficient
@radiative_coefficient.setter
def radiative_coefficient(self, value):
"""
Set radiative coefficient of the thermal boundary's external surface (-)
:param value: float
"""
if value is not None:
self._radiative_coefficient = float(value)
@property
def vegetation(self) -> Union[None, Vegetation]:
"""
Get the vegetation construction at the external surface of the thermal boundary
:return: None or Vegetation
"""
return self._vegetation
@vegetation.setter
def vegetation(self, value):
"""
Set the vegetation construction at the external surface of the thermal boundary
:param value: Vegetation
"""
self._vegetation = value
if self._internal_surface is None:
self._internal_surface = self.parent_surface.inverse
return self._internal_surface

View File

@ -19,19 +19,13 @@ class ThermalOpening:
def __init__(self):
self._id = None
self._area = None
self._openable_ratio = None
self._conductivity = None
self._frame_ratio = None
self._g_value = None
self._thickness = None
self._front_side_solar_transmittance_at_normal_incidence = None
self._back_side_solar_transmittance_at_normal_incidence = None
self._overall_u_value = None
self._hi = ch().convective_heat_transfer_coefficient_interior
self._he = ch().convective_heat_transfer_coefficient_exterior
self._inside_emissivity = None
self._alpha_coefficient = None
self._radiative_coefficient = None
self._construction_name = None
@property
@ -61,20 +55,6 @@ class ThermalOpening:
if value is not None:
self._area = float(value)
@property
def openable_ratio(self):
"""
Raises not implemented error
"""
raise NotImplementedError
@openable_ratio.setter
def openable_ratio(self, value):
"""
Raises not implemented error
"""
raise NotImplementedError
@property
def conductivity(self) -> Union[None, float]:
"""
@ -119,7 +99,7 @@ class ThermalOpening:
@property
def g_value(self) -> Union[None, float]:
"""
Get thermal opening g-value
Get thermal opening transmittance at normal incidence
:return: None or float
"""
return self._g_value
@ -127,7 +107,7 @@ class ThermalOpening:
@g_value.setter
def g_value(self, value):
"""
Set thermal opening g-value
Set thermal opening transmittance at normal incidence
:param value: float
"""
if value is not None:
@ -157,40 +137,6 @@ class ThermalOpening:
r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self._thickness)
self._overall_u_value = 1 / r_value
@property
def front_side_solar_transmittance_at_normal_incidence(self) -> Union[None, float]:
"""
Get thermal opening front side solar transmittance at normal incidence
:return: None or float
"""
return self._front_side_solar_transmittance_at_normal_incidence
@front_side_solar_transmittance_at_normal_incidence.setter
def front_side_solar_transmittance_at_normal_incidence(self, value):
"""
Set thermal opening front side solar transmittance at normal incidence
:param value: float
"""
if value is not None:
self._front_side_solar_transmittance_at_normal_incidence = float(value)
@property
def back_side_solar_transmittance_at_normal_incidence(self) -> Union[None, float]:
"""
Get thermal opening back side solar transmittance at normal incidence
:return: None or float
"""
return self._back_side_solar_transmittance_at_normal_incidence
@back_side_solar_transmittance_at_normal_incidence.setter
def back_side_solar_transmittance_at_normal_incidence(self, value):
"""
Set thermal opening back side solar transmittance at normal incidence
:param value: float
"""
if value is not None:
self._back_side_solar_transmittance_at_normal_incidence = float(value)
@property
def overall_u_value(self) -> Union[None, float]:
"""
@ -242,57 +188,6 @@ class ThermalOpening:
if value is not None:
self._he = float(value)
@property
def inside_emissivity(self) -> Union[None, float]:
"""
Get the short wave emissivity factor of the thermal opening's internal surface (-)
:return: None or float
"""
return self._inside_emissivity
@inside_emissivity.setter
def inside_emissivity(self, value):
"""
Set short wave emissivity factor of the thermal opening's internal surface (-)
:param value: float
"""
if value is not None:
self._inside_emissivity = float(value)
@property
def alpha_coefficient(self) -> Union[None, float]:
"""
Get the long wave emissivity factor of the thermal opening's internal surface (-)
:return: None or float
"""
return self._alpha_coefficient
@alpha_coefficient.setter
def alpha_coefficient(self, value):
"""
Set long wave emissivity factor of the thermal opening's internal surface (-)
:param value: float
"""
if value is not None:
self._alpha_coefficient = float(value)
@property
def radiative_coefficient(self) -> Union[None, float]:
"""
Get the radiative coefficient of the thermal opening's external surface (-)
:return: None or float
"""
return self._radiative_coefficient
@radiative_coefficient.setter
def radiative_coefficient(self, value):
"""
Set radiative coefficient of the thermal opening's external surface (-)
:param value: float
"""
if value is not None:
self._radiative_coefficient = float(value)
@property
def construction_name(self):
"""

View File

@ -15,7 +15,6 @@ from city_model_structure.building_demand.appliances import Appliances
from city_model_structure.building_demand.lighting import Lighting
from city_model_structure.building_demand.internal_gain import InternalGain
from city_model_structure.building_demand.thermal_control import ThermalControl
from city_model_structure.energy_systems.hvac_system import HvacSystem
from city_model_structure.attributes.schedule import Schedule
import helpers.constants as cte
@ -208,15 +207,6 @@ class ThermalZone:
if value is not None:
self._ordinate_number = int(value)
@property
def hvac_system(self) -> Union[None, HvacSystem]:
"""
Get HVAC system installed for this thermal zone
From internal_zone
:return: None or HvacSystem
"""
return self._parent_internal_zone.hvac_system
@property
def view_factors_matrix(self):
"""

View File

@ -4,7 +4,8 @@ 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 typing import Union
from typing import Union, List
from city_model_structure.building_demand.thermal_zone import ThermalZone
class HvacSystem:
@ -13,11 +14,12 @@ class HvacSystem:
"""
def __init__(self):
self._type = None
self._thermal_zones = None
@property
def type(self) -> Union[None, str]:
"""
Get hvac system type a thermal zone
Get hvac system type
:return: None or str
"""
return self._type
@ -25,9 +27,24 @@ class HvacSystem:
@type.setter
def type(self, value):
"""
Set heating set point defined for a thermal zone
Set hvac system type
:param value: str
"""
if value is not None:
self._type = str(value)
@property
def thermal_zones(self) -> Union[None, List[ThermalZone]]:
"""
Get list of zones that this unit serves
:return: None or [ThermalZone]
"""
return self._thermal_zones
@thermal_zones.setter
def thermal_zones(self, value):
"""
Set list of zones that this unit serves
:param value: [ThermalZone]
"""
self._thermal_zones = value

View File

@ -0,0 +1,33 @@
"""
HvacTerminalUnit module
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 typing import Union
class HvacTerminalUnit:
"""
HvacTerminalUnit class
"""
def __init__(self):
self._type = None
@property
def type(self) -> Union[None, str]:
"""
Get type of hvac terminal unit defined for a thermal zone
:return: None or str
"""
return self._type
@type.setter
def type(self, value):
"""
Set type of hvac terminal unit defined for a thermal zone
:param value: str
"""
if value is not None:
self._type = str(value)

View File

@ -267,8 +267,8 @@ class Idf:
def _add_construction(self, thermal_boundary):
for construction in self._idf.idfobjects[self._CONSTRUCTION]:
if thermal_boundary.vegetation is not None:
if construction.Name == f'{thermal_boundary.construction_name}_{thermal_boundary.vegetation.name}':
if thermal_boundary.parent_surface.vegetation is not None:
if construction.Name == f'{thermal_boundary.construction_name}_{thermal_boundary.parent_surface.vegetation.name}':
return
else:
if construction.Name == thermal_boundary.construction_name:
@ -283,9 +283,9 @@ class Idf:
self._add_material(layer)
layers = thermal_boundary.layers
# The constructions should have at least one layer
if thermal_boundary.vegetation is not None:
_kwargs = {'Name': f'{thermal_boundary.construction_name}_{thermal_boundary.vegetation.name}',
'Outside_Layer': thermal_boundary.vegetation.name}
if thermal_boundary.parent_surface.vegetation is not None:
_kwargs = {'Name': f'{thermal_boundary.construction_name}_{thermal_boundary.parent_surface.vegetation.name}',
'Outside_Layer': thermal_boundary.parent_surface.vegetation.name}
for i in range(0, len(layers) - 1):
_kwargs[f'Layer_{i + 2}'] = layers[i].material.name
else:
@ -401,8 +401,8 @@ class Idf:
for thermal_zone in internal_zone.thermal_zones:
for thermal_boundary in thermal_zone.thermal_boundaries:
self._add_construction(thermal_boundary)
if thermal_boundary.vegetation is not None:
self._add_vegetation_material(thermal_boundary.vegetation)
if thermal_boundary.parent_surface.vegetation is not None:
self._add_vegetation_material(thermal_boundary.parent_surface.vegetation)
for thermal_opening in thermal_boundary.thermal_openings:
self._add_window_construction_and_material(thermal_opening)
usage = thermal_zone.usage
@ -503,8 +503,8 @@ class Idf:
outside_boundary_condition = 'Ground'
sun_exposure = 'NoSun'
wind_exposure = 'NoWind'
if boundary.vegetation is not None:
construction_name = f'{boundary.construction_name}_{boundary.vegetation.name}'
if boundary.parent_surface.vegetation is not None:
construction_name = f'{boundary.construction_name}_{boundary.parent_surface.vegetation.name}'
else:
construction_name = boundary.construction_name
surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.parent_surface.name}',

View File

@ -99,7 +99,7 @@ class StoreysGeneration:
polygon = Polygon(coordinates)
ceiling = Surface(polygon, polygon, surface_type=cte.INTERIOR_SLAB)
surfaces_child.append(ceiling)
volume = ceiling.area_above_ground * height
volume = ceiling.perimeter_area * height
total_volume += volume
storeys.append(Storey(name, surfaces_child, neighbours, volume, self._internal_zone, self._floor_area))
name = 'storey_' + str(number_of_storeys - 1)

View File

@ -29,7 +29,6 @@ class UsPhysicsParameters(NrelPhysicsInterface):
"""
Returns the city with the construction parameters assigned to the buildings
"""
# todo: erase
city = self._city
for building in city.buildings:
try:
@ -40,7 +39,8 @@ class UsPhysicsParameters(NrelPhysicsInterface):
f'and climate zone reference norm {self._climate_zone}\n')
return
# if building has no thermal zones defined from geometry, one thermal zone per storey is assigned
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
# one thermal zone per storey is assigned
if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype, self._divide_in_storeys)
@ -121,9 +121,13 @@ class UsPhysicsParameters(NrelPhysicsInterface):
thermal_boundary.layers.append(layer)
# The agreement is that the layers are defined from outside to inside
external_layer = construction_archetype.layers[0]
thermal_boundary.outside_solar_absorptance = external_layer.material.solar_absorptance
thermal_boundary.outside_thermal_absorptance = external_layer.material.thermal_absorptance
thermal_boundary.outside_visible_absorptance = external_layer.material.visible_absorptance
external_surface = thermal_boundary.parent_surface
external_surface.short_wave_reflectance = 1 - float(external_layer.material.solar_absorptance)
external_surface.long_wave_emittance = 1 - float(external_layer.material.solar_absorptance)
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
internal_surface = thermal_boundary.internal_surface
internal_surface.short_wave_reflectance = 1 - float(internal_layer.material.solar_absorptance)
internal_surface.long_wave_emittance = 1 - float(internal_layer.material.solar_absorptance)
for thermal_opening in thermal_boundary.thermal_openings:
if construction_archetype.window is not None:

View File

@ -30,110 +30,15 @@ class TestConstructionFactory(TestCase):
self.assertIsNotNone(self._city, 'city is none')
return self._city
def _check_buildings(self, city):
for building in city.buildings:
self.assertIsNotNone(building.name, 'building name is none')
self.assertIsNotNone(building.lod, 'building lod is none')
self.assertIsNotNone(building.type, 'building type is none')
self.assertIsNotNone(building.volume, 'building volume is none')
self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
self.assertIsNotNone(building.centroid, 'building centroid is none')
self.assertIsNotNone(building.max_height, 'building max_height is none')
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none')
self.assertIsNotNone(building.roofs, 'building roofs is none')
for internal_zone in building.internal_zones:
self.assertIsNone(internal_zone.usage_zones, 'usage zones are defined')
self.assertTrue(len(internal_zone.thermal_zones) > 0, 'thermal zones are not defined')
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNone(building.terrains, 'building terrains is not none')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none')
self.assertEqual(len(building.heating), 0, 'building heating is not none')
self.assertEqual(len(building.cooling), 0, 'building cooling is not none')
self.assertIsNotNone(building.eave_height, 'building eave height is none')
self.assertIsNotNone(building.roof_type, 'building roof type is none')
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
self.assertIsNone(building.households, 'building households is not none')
self.assertFalse(building.is_conditioned, 'building is conditioned')
def _check_thermal_zones(self, internal_zone):
for thermal_zone in internal_zone.thermal_zones:
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
self.assertIsNotNone(thermal_zone.footprint_area, 'thermal_zone floor area is none')
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, 'additional_thermal_bridge_u_value is none')
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'thermal_zone effective_thermal_capacity is none')
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio,
'thermal_zone indirectly_heated_area_ratio is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_off,
'thermal_zone infiltration_rate_system_off is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'thermal_zone infiltration_rate_system_on is none')
self.assertIsNotNone(thermal_zone.volume, 'thermal_zone volume is none')
self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not none')
self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none')
self.assertIsNone(thermal_zone.hvac_system, 'thermal_zone hvac_system is not none')
self.assertIsNone(thermal_zone.usage, 'thermal_zone usage is not none')
self.assertIsNone(thermal_zone.hours_day, 'thermal_zone hours a day is not none')
self.assertIsNone(thermal_zone.days_year, 'thermal_zone days a year is not none')
self.assertIsNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is not none')
self.assertIsNone(thermal_zone.occupancy, 'thermal_zone occupancy is not none')
self.assertIsNone(thermal_zone.lighting, 'thermal_zone lighting is not none')
self.assertIsNone(thermal_zone.appliances, 'thermal_zone appliances is not none')
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal control is not none')
self.assertIsNone(thermal_zone.internal_gains, 'thermal_zone internal gains not returns none')
def _check_thermal_boundaries(self, thermal_zone):
for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.id, 'thermal_boundary id is none')
self.assertIsNotNone(thermal_boundary.parent_surface, 'thermal_boundary surface is none')
self.assertIsNotNone(thermal_boundary.thermal_zones, 'thermal_boundary delimits no thermal zone')
self.assertIsNotNone(thermal_boundary.opaque_area, 'thermal_boundary area is none')
self.assertIsNotNone(thermal_boundary.azimuth, 'thermal_boundary azimuth is none')
self.assertIsNotNone(thermal_boundary.inclination, 'thermal_boundary inclination is none')
self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none')
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none')
self.assertIsNotNone(thermal_boundary.outside_shortwave_reflectance, 'shortwave_reflectance is none')
self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none')
self.assertIsNotNone(thermal_boundary.construction_name, 'construction_name is none')
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')
self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none')
self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none')
self.assertIsNotNone(thermal_boundary.hi, 'hi is none')
self.assertIsNotNone(thermal_boundary.he, 'he is none')
self.assertIsNotNone(thermal_boundary.virtual_internal_surface, 'virtual_internal_surface is none')
self.assertIsNone(thermal_boundary.inside_emissivity, 'inside_emissivity is not none')
self.assertIsNone(thermal_boundary.alpha_coefficient, 'alpha_coefficient is not none')
self.assertIsNone(thermal_boundary.radiative_coefficient, 'radiative_coefficient is not none')
def _check_thermal_openings(self, thermal_boundary):
for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none')
self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction is not none')
self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none')
self.assertRaises(Exception, lambda: thermal_opening.openable_ratio,
'thermal_opening openable_ratio is not raising an exception')
self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none')
self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none')
self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none')
self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none')
self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none')
self.assertIsNone(thermal_opening.inside_emissivity, 'thermal opening inside_emissivity is not none')
self.assertIsNone(thermal_opening.alpha_coefficient, 'thermal opening alpha_coefficient is not none')
self.assertIsNone(thermal_opening.radiative_coefficient, 'thermal opening radiative_coefficient is not none')
@staticmethod
def _internal_function(function_format, original_function):
if function_format == 'hft':
new_function = GeometryHelper.libs_function_from_hft(original_function)
elif function_format == 'pluto':
new_function = GeometryHelper.libs_function_from_pluto(original_function)
else:
raise Exception('Function key not recognized. Implemented only "hft" and "pluto"')
return new_function
def test_citygml_function(self):
"""
@ -162,6 +67,111 @@ class TestConstructionFactory(TestCase):
for building in city.buildings:
self.assertRaises(Exception, lambda: self._internal_function(function_format, building.function))
def _check_buildings(self, city):
for building in city.buildings:
self.assertIsNotNone(building.name, 'building name is none')
self.assertIsNotNone(building.lod, 'building lod is none')
self.assertIsNotNone(building.type, 'building type is none')
self.assertIsNotNone(building.volume, 'building volume is none')
self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
self.assertIsNotNone(building.centroid, 'building centroid is none')
self.assertIsNotNone(building.max_height, 'building max_height is none')
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none')
self.assertIsNotNone(building.roofs, 'building roofs is none')
self.assertIsNotNone(building.internal_walls, 'building internal walls is none')
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNone(building.terrains, 'building terrains is not none')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none')
self.assertEqual(len(building.heating), 0, 'building heating is not none')
self.assertEqual(len(building.cooling), 0, 'building cooling is not none')
self.assertIsNotNone(building.eave_height, 'building eave height is none')
self.assertIsNotNone(building.roof_type, 'building roof type is none')
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
self.assertIsNone(building.households, 'building households is not none')
self.assertFalse(building.is_conditioned, 'building is conditioned')
self.assertIsNotNone(building.shell, 'building shell is none')
self.assertIsNone(building.human_readable_name, 'building human_readable_name is not none')
def _check_thermal_zones(self, internal_zone):
for thermal_zone in internal_zone.thermal_zones:
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
self.assertIsNotNone(thermal_zone.footprint_area, 'thermal_zone floor area is none')
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, 'additional_thermal_bridge_u_value is none')
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'thermal_zone effective_thermal_capacity is none')
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio,
'thermal_zone indirectly_heated_area_ratio is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_off,
'thermal_zone infiltration_rate_system_off is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'thermal_zone infiltration_rate_system_on is none')
self.assertIsNotNone(thermal_zone.volume, 'thermal_zone volume is none')
self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not none')
self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none')
self.assertIsNotNone(thermal_zone.total_floor_area, 'thermal zone total_floor_area is none')
self.assertIsNone(thermal_zone.usage, 'thermal_zone usage is not none')
self.assertIsNone(thermal_zone.hours_day, 'thermal_zone hours a day is not none')
self.assertIsNone(thermal_zone.days_year, 'thermal_zone days a year is not none')
self.assertIsNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is not none')
self.assertIsNone(thermal_zone.occupancy, 'thermal_zone occupancy is not none')
self.assertIsNone(thermal_zone.lighting, 'thermal_zone lighting is not none')
self.assertIsNone(thermal_zone.appliances, 'thermal_zone appliances is not none')
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal control is not none')
self.assertIsNone(thermal_zone.internal_gains, 'thermal_zone internal gains not returns none')
def _check_thermal_boundaries(self, thermal_zone):
for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.id, 'thermal_boundary id is none')
self.assertIsNotNone(thermal_boundary.parent_surface, 'thermal_boundary surface is none')
self.assertIsNotNone(thermal_boundary.thermal_zones, 'thermal_boundary delimits no thermal zone')
self.assertIsNotNone(thermal_boundary.opaque_area, 'thermal_boundary area is none')
self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none')
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none')
self.assertIsNotNone(thermal_boundary.construction_name, 'construction_name is none')
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')
self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none')
self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none')
self.assertIsNotNone(thermal_boundary.hi, 'hi is none')
self.assertIsNotNone(thermal_boundary.he, 'he is none')
self.assertIsNotNone(thermal_boundary.internal_surface, 'virtual_internal_surface is none')
self.assertIsNotNone(thermal_boundary.layers, 'layers is not none')
def _check_thermal_openings(self, thermal_boundary):
for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none')
self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction is not none')
self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none')
self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none')
self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none')
self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none')
self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none')
self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none')
self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction_name is none')
def _check_surfaces(self, thermal_boundary):
external_surface = thermal_boundary.parent_surface
internal_surface = thermal_boundary.internal_surface
self.assertIsNotNone(external_surface.short_wave_reflectance,
'external surface short_wave_reflectance id is not none')
self.assertIsNotNone(external_surface.long_wave_emittance, 'external surface long_wave_emittance id is not none')
self.assertIsNotNone(internal_surface.short_wave_reflectance,
'external surface short_wave_reflectance id is not none')
self.assertIsNotNone(internal_surface.long_wave_emittance, 'external surface long_wave_emittance id is not none')
def test_city_with_construction_extended_library(self):
"""
Enrich the city with the construction information and verify it
@ -180,17 +190,6 @@ class TestConstructionFactory(TestCase):
for thermal_zone in internal_zone.thermal_zones:
self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is none')
self.assertIsNotNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is none')
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
self._check_thermal_openings(thermal_boundary)
@staticmethod
def _internal_function(function_format, original_function):
if function_format == 'hft':
new_function = GeometryHelper.libs_function_from_hft(original_function)
elif function_format == 'pluto':
new_function = GeometryHelper.libs_function_from_pluto(original_function)
else:
raise Exception('Function key not recognized. Implemented only "hft" and "pluto"')
return new_function
self._check_surfaces(thermal_boundary)

View File

@ -89,18 +89,21 @@ class TestGeometryFactory(TestCase):
for surface in building.surfaces:
self.assertIsNotNone(surface.name, 'surface name is none')
self.assertIsNotNone(surface.id, 'surface id is none')
self.assertIsNone(surface.swr, 'surface swr is not none')
self.assertIsNotNone(surface.lower_corner, 'surface envelope_lower_corner is none')
self.assertIsNotNone(surface.upper_corner, 'surface envelope_upper_corner is none')
self.assertIsNotNone(surface.area_below_ground, 'surface area_below_ground is none')
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
self.assertIsNotNone(surface.perimeter_area, 'surface area_above_ground is none')
self.assertIsNotNone(surface.azimuth, 'surface azimuth is none')
self.assertIsNotNone(surface.type, 'surface type is none')
self.assertIsNotNone(surface.inclination, 'surface inclination is none')
self.assertIsNotNone(surface.type, 'surface type is none')
self.assertEqual(len(surface.global_irradiance), 0, 'global irradiance is calculated')
self.assertIsNotNone(surface.perimeter_polygon, 'surface perimeter_polygon is none')
self.assertIsNone(surface.holes_polygons, 'surface hole_polygons is not none')
self.assertIsNotNone(surface.solid_polygon, 'surface solid_polygon is none')
self.assertIsNone(surface.short_wave_reflectance, 'surface short_wave_reflectance is not none')
self.assertIsNone(surface.long_wave_emittance, 'surface long_wave_emittance is not none')
self.assertIsNotNone(surface.inverse, 'surface inverse is none')
self.assertEqual(len(surface.associated_thermal_boundaries), 0, 'associated_thermal_boundaries are assigned')
self.assertIsNone(surface.vegetation, 'surface vegetation is not none')
# citygml_classes
def test_import_citygml(self):

View File

@ -62,11 +62,9 @@ class GreeneryInIdf(TestCase):
plants = [plant]
vegetation = Vegetation(vegetation_name, soil, soil_thickness, plants)
for building in city.buildings:
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
for thermal_boundary in thermal_zone.thermal_boundaries:
if thermal_boundary.type == cte.ROOF:
thermal_boundary.vegetation = vegetation
for surface in building.surfaces:
if surface.type == cte.ROOF:
surface.vegetation = vegetation
_idf_2 = ExportsFactory('idf', city, output_path).export_debug()
_idf_2.run()