Add code comment to the classes and improve overall quality
This commit is contained in:
parent
22dc10c532
commit
145520c8a2
|
@ -4,10 +4,10 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
from typing import Union
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pyny3d.geoms as pn
|
import pyny3d.geoms as pn
|
||||||
from helpers.geometry import Geometry
|
from helpers.geometry import Geometry
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
|
|
||||||
class Surface:
|
class Surface:
|
||||||
|
@ -207,9 +207,9 @@ class Surface:
|
||||||
|
|
||||||
def _is_almost_same_terrain(self, terrain_points, ground_points):
|
def _is_almost_same_terrain(self, terrain_points, ground_points):
|
||||||
equal = 0
|
equal = 0
|
||||||
for t in terrain_points:
|
for terrain_point in terrain_points:
|
||||||
for g in ground_points:
|
for ground_point in ground_points:
|
||||||
if self._geometry.almost_equal(t, g):
|
if self._geometry.almost_equal(terrain_point, ground_point):
|
||||||
equal += 1
|
equal += 1
|
||||||
return equal == len(terrain_points)
|
return equal == len(terrain_points)
|
||||||
|
|
||||||
|
@ -250,8 +250,8 @@ class Surface:
|
||||||
"""
|
"""
|
||||||
if self._normal is None:
|
if self._normal is None:
|
||||||
points = self.points
|
points = self.points
|
||||||
n = np.cross(points[1] - points[0], points[2] - points[0])
|
cross_product = np.cross(points[1] - points[0], points[2] - points[0])
|
||||||
self._normal = n / np.linalg.norm(n)
|
self._normal = cross_product / np.linalg.norm(cross_product)
|
||||||
return self._normal
|
return self._normal
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -283,7 +283,7 @@ class Surface:
|
||||||
"""
|
"""
|
||||||
if self._type is None:
|
if self._type is None:
|
||||||
grad = np.rad2deg(self.inclination)
|
grad = np.rad2deg(self.inclination)
|
||||||
if 170 <= grad:
|
if grad >= 170:
|
||||||
self._type = 'Ground'
|
self._type = 'Ground'
|
||||||
elif 80 <= grad <= 100:
|
elif 80 <= grad <= 100:
|
||||||
self._type = 'Wall'
|
self._type = 'Wall'
|
||||||
|
@ -307,7 +307,7 @@ class Surface:
|
||||||
:param surface: Surface
|
:param surface: Surface
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if self.type is not 'Wall' or surface.type is not 'Wall':
|
if self.type != 'Wall' or surface.type != 'Wall':
|
||||||
return
|
return
|
||||||
if self._geometry.is_almost_same_surface(self, surface):
|
if self._geometry.is_almost_same_surface(self, surface):
|
||||||
intersection_area = self.intersect(surface).area
|
intersection_area = self.intersect(surface).area
|
||||||
|
|
|
@ -3,14 +3,17 @@ ThermalBoundary module
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
from typing import List
|
||||||
from city_model_structure.thermal_opening import ThermalOpening
|
from city_model_structure.thermal_opening import ThermalOpening
|
||||||
from city_model_structure.thermal_zone import ThermalZone
|
from city_model_structure.thermal_zone import ThermalZone
|
||||||
from city_model_structure.layer import Layer
|
from city_model_structure.layer import Layer
|
||||||
from helpers.configuration import Configuration
|
from helpers.configuration import Configuration
|
||||||
from typing import List
|
|
||||||
|
|
||||||
|
|
||||||
class ThermalBoundary:
|
class ThermalBoundary:
|
||||||
|
"""
|
||||||
|
ThermalBoundary class
|
||||||
|
"""
|
||||||
def __init__(self, surface, delimits):
|
def __init__(self, surface, delimits):
|
||||||
self._surface = surface
|
self._surface = surface
|
||||||
self._delimits = delimits
|
self._delimits = delimits
|
||||||
|
@ -27,83 +30,169 @@ class ThermalBoundary:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def delimits(self) -> List[ThermalZone]:
|
def delimits(self) -> List[ThermalZone]:
|
||||||
|
"""
|
||||||
|
Get the thermal zones delimited by the thermal boundary
|
||||||
|
:return: [ThermalZone]
|
||||||
|
"""
|
||||||
return self._delimits
|
return self._delimits
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def azimuth(self):
|
def azimuth(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary azimuth in radians
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._surface.azimuth
|
return self._surface.azimuth
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def inclination(self):
|
def inclination(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary inclination in radians
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._surface.inclination
|
return self._surface.inclination
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def area(self):
|
def area(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary area in square meters
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._surface.area
|
return self._surface.area
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def area_above_ground(self):
|
def area_above_ground(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary area above ground in square meters
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._surface.area_above_ground
|
return self._surface.area_above_ground
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def area_below_ground(self):
|
def area_below_ground(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary area below ground in square meters
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._surface.area_below_ground
|
return self._surface.area_below_ground
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def outside_solar_absorptance(self):
|
def outside_solar_absorptance(self):
|
||||||
|
"""
|
||||||
|
Get thermal boundary outside solar absorptance
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._outside_solar_absorptance
|
return self._outside_solar_absorptance
|
||||||
|
|
||||||
@outside_solar_absorptance.setter
|
@outside_solar_absorptance.setter
|
||||||
def outside_solar_absorptance(self, value):
|
def outside_solar_absorptance(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal boundary outside solar absorptance
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._outside_solar_absorptance = value
|
self._outside_solar_absorptance = value
|
||||||
self._shortwave_reflectance = 1.0 - float(value)
|
self._shortwave_reflectance = 1.0 - float(value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def outside_thermal_absorptance(self):
|
def outside_thermal_absorptance(self):
|
||||||
|
"""
|
||||||
|
Get thermal boundary outside thermal absorptance
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._outside_thermal_absorptance
|
return self._outside_thermal_absorptance
|
||||||
|
|
||||||
@outside_thermal_absorptance.setter
|
@outside_thermal_absorptance.setter
|
||||||
def outside_thermal_absorptance(self, value):
|
def outside_thermal_absorptance(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal boundary outside thermal absorptance
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._outside_thermal_absorptance = value
|
self._outside_thermal_absorptance = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def outside_visible_absorptance(self):
|
def outside_visible_absorptance(self):
|
||||||
|
"""
|
||||||
|
Get thermal boundary outside visible absorptance
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._outside_visible_absorptance
|
return self._outside_visible_absorptance
|
||||||
|
|
||||||
@outside_visible_absorptance.setter
|
@outside_visible_absorptance.setter
|
||||||
def outside_visible_absorptance(self, value):
|
def outside_visible_absorptance(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal boundary outside visible absorptance
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._outside_visible_absorptance = value
|
self._outside_visible_absorptance = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thermal_openings(self) -> List[ThermalOpening]:
|
def thermal_openings(self) -> List[ThermalOpening]:
|
||||||
|
"""
|
||||||
|
Get thermal boundary thermal openings
|
||||||
|
:return: [ThermalOpening]
|
||||||
|
"""
|
||||||
return self._thermal_openings
|
return self._thermal_openings
|
||||||
|
|
||||||
@thermal_openings.setter
|
@thermal_openings.setter
|
||||||
def thermal_openings(self, value):
|
def thermal_openings(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal boundary thermal openings
|
||||||
|
:param value: [ThermalOpening]
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._thermal_openings = value
|
self._thermal_openings = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def layers(self) -> List[Layer]:
|
def layers(self) -> List[Layer]:
|
||||||
|
"""
|
||||||
|
Get thermal boundary layers
|
||||||
|
:return: [Layers]
|
||||||
|
"""
|
||||||
return self._layers
|
return self._layers
|
||||||
|
|
||||||
@layers.setter
|
@layers.setter
|
||||||
def layers(self, value):
|
def layers(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal boundary layers
|
||||||
|
:param value: [Layer]
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._layers = value
|
self._layers = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary surface type
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
return self._surface.type
|
return self._surface.type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def window_ratio(self):
|
def window_ratio(self):
|
||||||
|
"""
|
||||||
|
Get thermal boundary window ratio
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._window_ratio
|
return self._window_ratio
|
||||||
|
|
||||||
@window_ratio.setter
|
@window_ratio.setter
|
||||||
def window_ratio(self, value):
|
def window_ratio(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal boundary window ratio
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._window_ratio = value
|
self._window_ratio = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def window_area(self):
|
def window_area(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary window area in square meters
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
if self._window_area is None:
|
if self._window_area is None:
|
||||||
try:
|
try:
|
||||||
self._window_area = float(self._surface.area) * float(self.window_ratio)
|
self._window_area = float(self._surface.area) * float(self.window_ratio)
|
||||||
|
@ -113,6 +202,11 @@ class ThermalBoundary:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def u_value(self):
|
def u_value(self):
|
||||||
|
"""
|
||||||
|
Thermal boundary u value in W/m2K
|
||||||
|
internal and external convective coefficient in W/m2K values, can be configured at configuration.ini
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
if self._u_value is None:
|
if self._u_value is None:
|
||||||
h_i = Configuration().h_i
|
h_i = Configuration().h_i
|
||||||
h_e = Configuration().h_e
|
h_e = Configuration().h_e
|
||||||
|
@ -130,9 +224,18 @@ class ThermalBoundary:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def shortwave_reflectance(self):
|
def shortwave_reflectance(self):
|
||||||
|
"""
|
||||||
|
Get thermal boundary shortwave reflectance
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._shortwave_reflectance
|
return self._shortwave_reflectance
|
||||||
|
|
||||||
@shortwave_reflectance.setter
|
@shortwave_reflectance.setter
|
||||||
def shortwave_reflectance(self, value):
|
def shortwave_reflectance(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal boundary shortwave reflectance
|
||||||
|
:param value: float
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self._shortwave_reflectance = value
|
self._shortwave_reflectance = value
|
||||||
self._outside_solar_absorptance = 1.0 - float(value)
|
self._outside_solar_absorptance = 1.0 - float(value)
|
||||||
|
|
|
@ -7,90 +7,165 @@ from helpers.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
class ThermalOpening:
|
class ThermalOpening:
|
||||||
|
"""
|
||||||
|
ThermalOpening class
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._openable_ratio = None
|
self._openable_ratio = None
|
||||||
self._conductivity_w_mk = None
|
self._conductivity = None
|
||||||
self._frame_ratio = Configuration().frame_ratio
|
self._frame_ratio = Configuration().frame_ratio
|
||||||
self._g_value = None
|
self._g_value = None
|
||||||
self._thickness_m = None
|
self._thickness = None
|
||||||
self._front_side_solar_transmittance_at_normal_incidence = None
|
self._front_side_solar_transmittance_at_normal_incidence = None
|
||||||
self._back_side_solar_transmittance_at_normal_incidence = None
|
self._back_side_solar_transmittance_at_normal_incidence = None
|
||||||
self._overall_u_value = None
|
self._overall_u_value = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def openable_ratio(self):
|
def openable_ratio(self):
|
||||||
|
"""
|
||||||
|
Get thermal opening openable ratio, NOT IMPLEMENTED
|
||||||
|
:return: Exception
|
||||||
|
"""
|
||||||
raise Exception('Not implemented')
|
raise Exception('Not implemented')
|
||||||
|
|
||||||
@openable_ratio.setter
|
@openable_ratio.setter
|
||||||
def openable_ratio(self, value):
|
def openable_ratio(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal opening openable ratio, NOT IMPLEMENTED
|
||||||
|
:param value: Any
|
||||||
|
:return: Exception
|
||||||
|
"""
|
||||||
raise Exception('Not implemented')
|
raise Exception('Not implemented')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def conductivity_w_mk(self):
|
def conductivity(self):
|
||||||
return self._conductivity_w_mk
|
"""
|
||||||
|
Get thermal opening conductivity in W/mK
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._conductivity
|
||||||
|
|
||||||
@conductivity_w_mk.setter
|
@conductivity.setter
|
||||||
def conductivity_w_mk(self, value):
|
def conductivity(self, value):
|
||||||
|
"""
|
||||||
|
Get thermal opening conductivity in W/mK
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
# The code to calculate overall_u_value is duplicated here and in thickness_m.
|
# The code to calculate overall_u_value is duplicated here and in thickness_m.
|
||||||
# This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read.
|
# This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read.
|
||||||
self._conductivity_w_mk = value
|
self._conductivity = value
|
||||||
if self._overall_u_value is None and self.thickness_m is not None:
|
if self._overall_u_value is None and self.thickness is not None:
|
||||||
h_i = Configuration().h_i
|
h_i = Configuration().h_i
|
||||||
h_e = Configuration().h_e
|
h_e = Configuration().h_e
|
||||||
r_value = 1 / h_i + 1 / h_e + float(self.conductivity_w_mk) / float(self.thickness_m)
|
r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness)
|
||||||
self._overall_u_value = 1 / r_value
|
self._overall_u_value = 1 / r_value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def frame_ratio(self):
|
def frame_ratio(self):
|
||||||
|
"""
|
||||||
|
Get thermal opening frame ratio
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._frame_ratio
|
return self._frame_ratio
|
||||||
|
|
||||||
@frame_ratio.setter
|
@frame_ratio.setter
|
||||||
def frame_ratio(self, value):
|
def frame_ratio(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal opening frame ratio
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._frame_ratio = value
|
self._frame_ratio = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def g_value(self):
|
def g_value(self):
|
||||||
|
"""
|
||||||
|
Get thermal opening g value
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._g_value
|
return self._g_value
|
||||||
|
|
||||||
@g_value.setter
|
@g_value.setter
|
||||||
def g_value(self, value):
|
def g_value(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal opening g value
|
||||||
|
:param value:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self._g_value = value
|
self._g_value = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thickness_m(self):
|
def thickness(self):
|
||||||
return self._thickness_m
|
"""
|
||||||
|
Get thermal opening thickness in meters
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return self._thickness
|
||||||
|
|
||||||
@thickness_m.setter
|
@thickness.setter
|
||||||
def thickness_m(self, value):
|
def thickness(self, value):
|
||||||
# The code to calculate overall_u_value is duplicated here and in conductivity_w_mk.
|
"""
|
||||||
|
Set thermal opening thickness in meters
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
# The code to calculate overall_u_value is duplicated here and in conductivity.
|
||||||
# This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read.
|
# This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read.
|
||||||
self._thickness_m = value
|
self._thickness = value
|
||||||
if self._overall_u_value is None and self.conductivity_w_mk is not None:
|
if self._overall_u_value is None and self.conductivity is not None:
|
||||||
h_i = Configuration().h_i
|
h_i = Configuration().h_i
|
||||||
h_e = Configuration().h_e
|
h_e = Configuration().h_e
|
||||||
r_value = 1 / h_i + 1 / h_e + float(self.conductivity_w_mk) / float(self.thickness_m)
|
r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness)
|
||||||
self._overall_u_value = 1 / r_value
|
self._overall_u_value = 1 / r_value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def front_side_solar_transmittance_at_normal_incidence(self):
|
def front_side_solar_transmittance_at_normal_incidence(self):
|
||||||
|
"""
|
||||||
|
Get thermal opening front side solar transmittance at normal incidence
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._front_side_solar_transmittance_at_normal_incidence
|
return self._front_side_solar_transmittance_at_normal_incidence
|
||||||
|
|
||||||
@front_side_solar_transmittance_at_normal_incidence.setter
|
@front_side_solar_transmittance_at_normal_incidence.setter
|
||||||
def front_side_solar_transmittance_at_normal_incidence(self, value):
|
def front_side_solar_transmittance_at_normal_incidence(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal opening front side solar transmittance at normal incidence
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._front_side_solar_transmittance_at_normal_incidence = value
|
self._front_side_solar_transmittance_at_normal_incidence = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def back_side_solar_transmittance_at_normal_incidence(self):
|
def back_side_solar_transmittance_at_normal_incidence(self):
|
||||||
|
"""
|
||||||
|
Get thermal opening back side solar transmittance at normal incidence
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._back_side_solar_transmittance_at_normal_incidence
|
return self._back_side_solar_transmittance_at_normal_incidence
|
||||||
|
|
||||||
@back_side_solar_transmittance_at_normal_incidence.setter
|
@back_side_solar_transmittance_at_normal_incidence.setter
|
||||||
def back_side_solar_transmittance_at_normal_incidence(self, value):
|
def back_side_solar_transmittance_at_normal_incidence(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal opening back side solar transmittance at normal incidence
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._back_side_solar_transmittance_at_normal_incidence = value
|
self._back_side_solar_transmittance_at_normal_incidence = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def overall_u_value(self):
|
def overall_u_value(self):
|
||||||
|
"""
|
||||||
|
Get thermal opening overall u value
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._overall_u_value
|
return self._overall_u_value
|
||||||
|
|
||||||
@overall_u_value.setter
|
@overall_u_value.setter
|
||||||
def overall_u_value(self, value):
|
def overall_u_value(self, value):
|
||||||
|
"""
|
||||||
|
Get thermal opening overall u value
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._overall_u_value = value
|
self._overall_u_value = value
|
||||||
|
|
|
@ -3,8 +3,8 @@ UsageZone module
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
from city_model_structure.internal_gains import InternalGains
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from city_model_structure.internal_gains import InternalGains
|
||||||
|
|
||||||
|
|
||||||
class UsageZone:
|
class UsageZone:
|
||||||
|
@ -41,59 +41,118 @@ class UsageZone:
|
||||||
@property
|
@property
|
||||||
def heating_setpoint(self):
|
def heating_setpoint(self):
|
||||||
"""
|
"""
|
||||||
|
Get usage zone heating set point in celsius grads
|
||||||
:return:
|
:return: float
|
||||||
"""
|
"""
|
||||||
return self._heating_setpoint
|
return self._heating_setpoint
|
||||||
|
|
||||||
@heating_setpoint.setter
|
@heating_setpoint.setter
|
||||||
def heating_setpoint(self, value):
|
def heating_setpoint(self, value):
|
||||||
|
"""
|
||||||
|
Set usage zone heating set point in celsius grads
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._heating_setpoint = value
|
self._heating_setpoint = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def heating_setback(self):
|
def heating_setback(self):
|
||||||
|
"""
|
||||||
|
Get usage zone heating setback in celsius grads
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._heating_setback
|
return self._heating_setback
|
||||||
|
|
||||||
@heating_setback.setter
|
@heating_setback.setter
|
||||||
def heating_setback(self, value):
|
def heating_setback(self, value):
|
||||||
|
"""
|
||||||
|
Set usage zone heating setback in celsius grads
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._heating_setback = value
|
self._heating_setback = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cooling_setpoint(self):
|
def cooling_setpoint(self):
|
||||||
|
"""
|
||||||
|
Get usage zone cooling setpoint in celsius grads
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._cooling_setpoint
|
return self._cooling_setpoint
|
||||||
|
|
||||||
@cooling_setpoint.setter
|
@cooling_setpoint.setter
|
||||||
def cooling_setpoint(self, value):
|
def cooling_setpoint(self, value):
|
||||||
|
"""
|
||||||
|
Set usage zone cooling setpoint in celsius grads
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._cooling_setpoint = value
|
self._cooling_setpoint = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hours_day(self):
|
def hours_day(self):
|
||||||
|
"""
|
||||||
|
Get usage zone usage hours per day
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._hours_day
|
return self._hours_day
|
||||||
|
|
||||||
@hours_day.setter
|
@hours_day.setter
|
||||||
def hours_day(self, value):
|
def hours_day(self, value):
|
||||||
|
"""
|
||||||
|
Set usage zone usage hours per day
|
||||||
|
:param value: float
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
self._hours_day = value
|
self._hours_day = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def days_year(self):
|
def days_year(self):
|
||||||
|
"""
|
||||||
|
Get usage zone usage days per year
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._days_year
|
return self._days_year
|
||||||
|
|
||||||
@days_year.setter
|
@days_year.setter
|
||||||
def days_year(self, value):
|
def days_year(self, value):
|
||||||
|
"""
|
||||||
|
Set usage zone usage days per year
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._days_year = value
|
self._days_year = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mechanical_air_change(self):
|
def mechanical_air_change(self):
|
||||||
|
"""
|
||||||
|
Set usage zone mechanical air change in air change per hour
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._mechanical_air_change
|
return self._mechanical_air_change
|
||||||
|
|
||||||
@mechanical_air_change.setter
|
@mechanical_air_change.setter
|
||||||
def mechanical_air_change(self, value):
|
def mechanical_air_change(self, value):
|
||||||
|
"""
|
||||||
|
Get usage zone mechanical air change in air change per hour
|
||||||
|
:param value: float
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._mechanical_air_change = value
|
self._mechanical_air_change = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def usage(self):
|
def usage(self):
|
||||||
|
"""
|
||||||
|
Get usage zone usage
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
return self._usage
|
return self._usage
|
||||||
|
|
||||||
@usage.setter
|
@usage.setter
|
||||||
def usage(self, value):
|
def usage(self, value):
|
||||||
|
"""
|
||||||
|
Get usage zone usage
|
||||||
|
:param value: str
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._usage = value
|
self._usage = value
|
||||||
|
|
|
@ -9,21 +9,25 @@ from city_model_structure.city import City
|
||||||
|
|
||||||
class GeometryFactory:
|
class GeometryFactory:
|
||||||
def __init__(self, file_type, path):
|
def __init__(self, file_type, path):
|
||||||
self._file_type = file_type.lower()
|
self._file_type = '_' + file_type.lower()
|
||||||
self._path = path
|
self._path = path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def citygml(self):
|
def _citygml(self):
|
||||||
return CityGml(self._path).city
|
return CityGml(self._path).city
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def geojson(self):
|
def _geojson(self):
|
||||||
raise Exception('Not implemented')
|
raise Exception('Not implemented')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bim(self):
|
def _bim(self):
|
||||||
raise Exception('Not implemented')
|
raise Exception('Not implemented')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def city(self) -> City:
|
def city(self) -> City:
|
||||||
|
"""
|
||||||
|
Geometry factory city model structure with geometry
|
||||||
|
:return: City
|
||||||
|
"""
|
||||||
return getattr(self, self._file_type, lambda: None)
|
return getattr(self, self._file_type, lambda: None)
|
||||||
|
|
|
@ -12,6 +12,9 @@ from helpers.geometry import Geometry
|
||||||
|
|
||||||
|
|
||||||
class CityGml:
|
class CityGml:
|
||||||
|
"""
|
||||||
|
CityGml class
|
||||||
|
"""
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self._city = None
|
self._city = None
|
||||||
with open(path) as gml:
|
with open(path) as gml:
|
||||||
|
@ -42,10 +45,18 @@ class CityGml:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def content(self):
|
def content(self):
|
||||||
|
"""
|
||||||
|
CityGml raw content
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
return self._gml
|
return self._gml
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def city(self):
|
def city(self) -> City:
|
||||||
|
"""
|
||||||
|
City model structure enriched with the geometry information
|
||||||
|
:return: City
|
||||||
|
"""
|
||||||
if self._city is None:
|
if self._city is None:
|
||||||
self._city = City(self._lower_corner, self._upper_corner, self._srs_name)
|
self._city = City(self._lower_corner, self._upper_corner, self._srs_name)
|
||||||
for o in self._gml['CityModel']['cityObjectMember']:
|
for o in self._gml['CityModel']['cityObjectMember']:
|
||||||
|
|
|
@ -8,6 +8,9 @@ from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
class Configuration:
|
class Configuration:
|
||||||
|
"""
|
||||||
|
Configuration class
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
base_path = Path().resolve().parent
|
base_path = Path().resolve().parent
|
||||||
config_file = Path(base_path / 'libs/config/configuration.ini').resolve()
|
config_file = Path(base_path / 'libs/config/configuration.ini').resolve()
|
||||||
|
@ -16,36 +19,73 @@ class Configuration:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def h_i(self):
|
def h_i(self):
|
||||||
|
"""
|
||||||
|
Configured internal convective coefficient in W/m2K
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._config.getfloat('convective_fluxes', 'h_i')
|
return self._config.getfloat('convective_fluxes', 'h_i')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def h_e(self):
|
def h_e(self):
|
||||||
|
"""
|
||||||
|
Configured external convective coefficient in W/m2K
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._config.getfloat('convective_fluxes', 'h_e')
|
return self._config.getfloat('convective_fluxes', 'h_e')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def frame_ratio(self):
|
def frame_ratio(self):
|
||||||
|
"""
|
||||||
|
Configured frame ratio
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._config.getfloat('windows', 'frame_ratio')
|
return self._config.getfloat('windows', 'frame_ratio')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def heated(self):
|
def heated(self):
|
||||||
|
"""
|
||||||
|
Configured heated flag
|
||||||
|
:return: Boolean
|
||||||
|
"""
|
||||||
return self._config.getboolean('thermal_zones', 'heated')
|
return self._config.getboolean('thermal_zones', 'heated')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cooled(self):
|
def cooled(self):
|
||||||
|
"""
|
||||||
|
Configured cooled flag
|
||||||
|
:return: Boolean
|
||||||
|
"""
|
||||||
return self._config.getboolean('thermal_zones', 'cooled')
|
return self._config.getboolean('thermal_zones', 'cooled')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def additional_thermal_bridge_u_value(self):
|
def additional_thermal_bridge_u_value(self):
|
||||||
|
"""
|
||||||
|
Configured additional thermal bridge u value W/m2K
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
return self._config.getfloat('thermal_zones', 'additional_thermal_bridge_u_value')
|
return self._config.getfloat('thermal_zones', 'additional_thermal_bridge_u_value')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def indirectly_heated_area_ratio(self):
|
def indirectly_heated_area_ratio(self):
|
||||||
|
"""
|
||||||
|
Configured indirectly heated area ratio
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
|
||||||
return self._config.getfloat('thermal_zones', 'indirectly_heated_area_ratio')
|
return self._config.getfloat('thermal_zones', 'indirectly_heated_area_ratio')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def infiltration_rate_system_on(self):
|
def infiltration_rate_system_on(self):
|
||||||
|
"""
|
||||||
|
Configured infiltration rate system on in air change per hour
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._config.getfloat('thermal_zones', 'infiltration_rate_system_on')
|
return self._config.getfloat('thermal_zones', 'infiltration_rate_system_on')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def outside_solar_absorptance(self):
|
def outside_solar_absorptance(self):
|
||||||
|
"""
|
||||||
|
Configured infiltration rate system off in air change per hour
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
return self._config.getfloat('thermal_zones', 'outside_solar_absorptance')
|
return self._config.getfloat('thermal_zones', 'outside_solar_absorptance')
|
||||||
|
|
|
@ -11,14 +11,29 @@ import open3d as o3d
|
||||||
|
|
||||||
|
|
||||||
class Geometry:
|
class Geometry:
|
||||||
|
"""
|
||||||
|
Geometry helper class
|
||||||
|
"""
|
||||||
def __init__(self, delta=0.5):
|
def __init__(self, delta=0.5):
|
||||||
self._delta = delta
|
self._delta = delta
|
||||||
|
|
||||||
def almost_equal(self, v1, v2):
|
def almost_equal(self, v1, v2):
|
||||||
|
"""
|
||||||
|
Compare two points and decides if they are almost equal (quadratic error under delta)
|
||||||
|
:param v1: [x,y,z]
|
||||||
|
:param v2: [x,y,z]
|
||||||
|
:return: Boolean
|
||||||
|
"""
|
||||||
delta = math.sqrt(pow((v1[0] - v2[0]), 2) + pow((v1[1] - v2[1]), 2) + pow((v1[2] - v2[2]), 2))
|
delta = math.sqrt(pow((v1[0] - v2[0]), 2) + pow((v1[1] - v2[1]), 2) + pow((v1[2] - v2[2]), 2))
|
||||||
return delta <= self._delta
|
return delta <= self._delta
|
||||||
|
|
||||||
def is_almost_same_surface(self, s1, s2):
|
def is_almost_same_surface(self, s1, s2):
|
||||||
|
"""
|
||||||
|
Compare two surfaces and decides if they are almost equal (quadratic error under delta)
|
||||||
|
:param s1: Surface
|
||||||
|
:param s2: Surface
|
||||||
|
:return: Boolean
|
||||||
|
"""
|
||||||
# delta is grads an need to be converted into radians
|
# delta is grads an need to be converted into radians
|
||||||
delta = np.rad2deg(self._delta)
|
delta = np.rad2deg(self._delta)
|
||||||
difference = (s1.inclination - s2.inclination) % math.pi
|
difference = (s1.inclination - s2.inclination) % math.pi
|
||||||
|
@ -49,6 +64,12 @@ class Geometry:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_points_matrix(points, remove_last=False):
|
def to_points_matrix(points, remove_last=False):
|
||||||
|
"""
|
||||||
|
Transform a point vector into a point matrix
|
||||||
|
:param points: [x, y, z, x, y, z ...]
|
||||||
|
:param remove_last: Boolean
|
||||||
|
:return: [[x,y,z],[x,y,z]...]
|
||||||
|
"""
|
||||||
rows = points.size // 3
|
rows = points.size // 3
|
||||||
points = points.reshape(rows, 3)
|
points = points.reshape(rows, 3)
|
||||||
if remove_last:
|
if remove_last:
|
||||||
|
@ -107,6 +128,13 @@ class Geometry:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def divide_mesh_by_plane(mesh, normal_plane, point_plane):
|
def divide_mesh_by_plane(mesh, normal_plane, point_plane):
|
||||||
|
"""
|
||||||
|
Divide a mesh by a plane
|
||||||
|
:param mesh: Trimesh
|
||||||
|
:param normal_plane: [x, y, z]
|
||||||
|
:param point_plane: [x, y, z]
|
||||||
|
:return: [Trimesh]
|
||||||
|
"""
|
||||||
# The first mesh returns the positive side of the plane and the second the negative side.
|
# The first mesh returns the positive side of the plane and the second the negative side.
|
||||||
# If the plane does not divide the mesh (i.e. it does not touch it or it is coplanar with one or more faces),
|
# If the plane does not divide the mesh (i.e. it does not touch it or it is coplanar with one or more faces),
|
||||||
# then it returns only the original mesh.
|
# then it returns only the original mesh.
|
||||||
|
|
|
@ -8,26 +8,33 @@ from physics.physics_feeders.us_physics_parameters import UsPhysicsParameters
|
||||||
|
|
||||||
|
|
||||||
class PhysicsFactory:
|
class PhysicsFactory:
|
||||||
|
"""
|
||||||
|
PhysicsFactor class
|
||||||
|
"""
|
||||||
def __init__(self, handler, city, base_path='data/physics'):
|
def __init__(self, handler, city, base_path='data/physics'):
|
||||||
self._handler = handler.lower().replace(' ', '_')
|
self._handler = '_' + handler.lower().replace(' ', '_')
|
||||||
self._city = city
|
self._city = city
|
||||||
self._base_path = base_path
|
self._base_path = base_path
|
||||||
self.factory()
|
self.factory()
|
||||||
|
|
||||||
def us_new_york_city(self):
|
def _us_new_york_city(self):
|
||||||
UsNewYorkCityPhysicsParameters(self._city, self._base_path)
|
UsNewYorkCityPhysicsParameters(self._city, self._base_path)
|
||||||
|
|
||||||
def us(self):
|
def _us(self):
|
||||||
UsPhysicsParameters(self._city, self._base_path)
|
UsPhysicsParameters(self._city, self._base_path)
|
||||||
|
|
||||||
def ca(self):
|
def _ca(self):
|
||||||
raise Exception('Not implemented')
|
raise Exception('Not implemented')
|
||||||
|
|
||||||
def de(self):
|
def _de(self):
|
||||||
raise Exception('Not implemented')
|
raise Exception('Not implemented')
|
||||||
|
|
||||||
def es(self):
|
def _es(self):
|
||||||
raise Exception('Not implemented')
|
raise Exception('Not implemented')
|
||||||
|
|
||||||
def factory(self):
|
def factory(self):
|
||||||
|
"""
|
||||||
|
Enrich the city with the physics information
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
getattr(self, self._handler, lambda: None)()
|
getattr(self, self._handler, lambda: None)()
|
||||||
|
|
|
@ -6,6 +6,9 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
|
||||||
|
|
||||||
|
|
||||||
class UsPlutoToFunction:
|
class UsPlutoToFunction:
|
||||||
|
"""
|
||||||
|
UsPlutoToFunction
|
||||||
|
"""
|
||||||
building_function = {
|
building_function = {
|
||||||
'A0': 'single family house',
|
'A0': 'single family house',
|
||||||
'A1': 'single family house',
|
'A1': 'single family house',
|
||||||
|
|
|
@ -5,7 +5,10 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class UsToLibraryTypes(object):
|
class UsToLibraryTypes:
|
||||||
|
"""
|
||||||
|
UsToLibraryTypes
|
||||||
|
"""
|
||||||
standards = {
|
standards = {
|
||||||
'ASHRAE Std189': 1,
|
'ASHRAE Std189': 1,
|
||||||
'ASHRAE 90.1-2004': 2
|
'ASHRAE 90.1-2004': 2
|
||||||
|
@ -44,6 +47,11 @@ class UsToLibraryTypes(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def yoc_to_standard(year_of_construction):
|
def yoc_to_standard(year_of_construction):
|
||||||
|
"""
|
||||||
|
Year of construction to standard
|
||||||
|
:param year_of_construction: int
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
if int(year_of_construction) < 2009:
|
if int(year_of_construction) < 2009:
|
||||||
standard = 'ASHRAE 90.1_2004'
|
standard = 'ASHRAE 90.1_2004'
|
||||||
else:
|
else:
|
||||||
|
@ -52,6 +60,11 @@ class UsToLibraryTypes(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def city_to_reference_city(city):
|
def city_to_reference_city(city):
|
||||||
|
"""
|
||||||
|
City name to reference city
|
||||||
|
:param city: str
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
# ToDo: Dummy function that need to be implemented
|
# ToDo: Dummy function that need to be implemented
|
||||||
reference_city = 'Baltimore'
|
reference_city = 'Baltimore'
|
||||||
if city is not None:
|
if city is not None:
|
||||||
|
@ -60,5 +73,10 @@ class UsToLibraryTypes(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def city_to_climate_zone(city):
|
def city_to_climate_zone(city):
|
||||||
|
"""
|
||||||
|
City name to climate zone
|
||||||
|
:param city: str
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
reference_city = UsToLibraryTypes.city_to_reference_city(city)
|
reference_city = UsToLibraryTypes.city_to_reference_city(city)
|
||||||
return UsToLibraryTypes.reference_city_climate_zone[reference_city]
|
return UsToLibraryTypes.reference_city_climate_zone[reference_city]
|
||||||
|
|
|
@ -4,14 +4,17 @@ UsPhysicsParameters as base class
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
from pathlib import Path
|
||||||
import xmltodict
|
import xmltodict
|
||||||
from city_model_structure.layer import Layer
|
from city_model_structure.layer import Layer
|
||||||
from city_model_structure.material import Material
|
from city_model_structure.material import Material
|
||||||
from pathlib import Path
|
|
||||||
from physics.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes
|
from physics.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes
|
||||||
|
|
||||||
|
|
||||||
class UsBasePhysicsParameters:
|
class UsBasePhysicsParameters:
|
||||||
|
"""
|
||||||
|
UsBasePhysicsParameters class
|
||||||
|
"""
|
||||||
def __init__(self, climate_zone, city_objects, function_to_type, base_path):
|
def __init__(self, climate_zone, city_objects, function_to_type, base_path):
|
||||||
self._climate_zone = climate_zone
|
self._climate_zone = climate_zone
|
||||||
self._city_objects = city_objects
|
self._city_objects = city_objects
|
||||||
|
@ -29,7 +32,7 @@ class UsBasePhysicsParameters:
|
||||||
building_type = function_to_type(city_object.function)
|
building_type = function_to_type(city_object.function)
|
||||||
if building_type is None:
|
if building_type is None:
|
||||||
return
|
return
|
||||||
archetype = self.search_archetype(building_type,
|
archetype = self._search_archetype(building_type,
|
||||||
UsToLibraryTypes.yoc_to_standard(city_object.year_of_construction),
|
UsToLibraryTypes.yoc_to_standard(city_object.year_of_construction),
|
||||||
self._climate_zone)
|
self._climate_zone)
|
||||||
# ToDo:remove this in the future
|
# ToDo:remove this in the future
|
||||||
|
@ -50,9 +53,9 @@ class UsBasePhysicsParameters:
|
||||||
thermal_zone.infiltration_rate_system_on = archetype['infiltration_rate_for_ventilation_system_on']['#text']
|
thermal_zone.infiltration_rate_system_on = archetype['infiltration_rate_for_ventilation_system_on']['#text']
|
||||||
for thermal_boundary in thermal_zone.bounded:
|
for thermal_boundary in thermal_zone.bounded:
|
||||||
construction_type = UsToLibraryTypes.construction_types[thermal_boundary.type]
|
construction_type = UsToLibraryTypes.construction_types[thermal_boundary.type]
|
||||||
construction = UsBasePhysicsParameters.search_construction_in_archetype(archetype, construction_type)
|
construction = UsBasePhysicsParameters._search_construction_in_archetype(archetype, construction_type)
|
||||||
construction_id = construction['@id']
|
construction_id = construction['@id']
|
||||||
c_lib = self.search_construction_type('construction', construction_id)
|
c_lib = self._search_construction_type('construction', construction_id)
|
||||||
if 'outside_solar_absorptance' in c_lib:
|
if 'outside_solar_absorptance' in c_lib:
|
||||||
thermal_boundary.outside_solar_absorptance = c_lib['outside_solar_absorptance']['#text']
|
thermal_boundary.outside_solar_absorptance = c_lib['outside_solar_absorptance']['#text']
|
||||||
thermal_boundary.outside_thermal_absorptance = c_lib['outside_thermal_absorptance']['#text']
|
thermal_boundary.outside_thermal_absorptance = c_lib['outside_thermal_absorptance']['#text']
|
||||||
|
@ -63,7 +66,7 @@ class UsBasePhysicsParameters:
|
||||||
layer = Layer()
|
layer = Layer()
|
||||||
if 'thickness' in current_layer:
|
if 'thickness' in current_layer:
|
||||||
layer.thickness = current_layer['thickness']['#text']
|
layer.thickness = current_layer['thickness']['#text']
|
||||||
material_lib = self.search_construction_type('material', current_layer['material'])
|
material_lib = self._search_construction_type('material', current_layer['material'])
|
||||||
material = Material()
|
material = Material()
|
||||||
if 'conductivity' in material_lib:
|
if 'conductivity' in material_lib:
|
||||||
material.conductivity = material_lib['conductivity']['#text']
|
material.conductivity = material_lib['conductivity']['#text']
|
||||||
|
@ -80,8 +83,8 @@ class UsBasePhysicsParameters:
|
||||||
for opening in thermal_boundary.thermal_openings:
|
for opening in thermal_boundary.thermal_openings:
|
||||||
if construction['window'] is None:
|
if construction['window'] is None:
|
||||||
continue
|
continue
|
||||||
w_lib = self.search_construction_type('window', construction['window'])
|
w_lib = self._search_construction_type('window', construction['window'])
|
||||||
opening.conductivity_w_mk = w_lib['conductivity']['#text']
|
opening.conductivity = w_lib['conductivity']['#text']
|
||||||
opening.frame_ratio = w_lib['frame_ratio']['#text']
|
opening.frame_ratio = w_lib['frame_ratio']['#text']
|
||||||
opening.g_value = w_lib['solar_transmittance_at_normal_incidence']['#text']
|
opening.g_value = w_lib['solar_transmittance_at_normal_incidence']['#text']
|
||||||
opening.thickness = w_lib['thickness']['#text']
|
opening.thickness = w_lib['thickness']['#text']
|
||||||
|
@ -90,7 +93,7 @@ class UsBasePhysicsParameters:
|
||||||
opening.front_side_solar_transmittance_at_normal_incidence = \
|
opening.front_side_solar_transmittance_at_normal_incidence = \
|
||||||
w_lib['front_side_solar_transmittance_at_normal_incidence']['#text']
|
w_lib['front_side_solar_transmittance_at_normal_incidence']['#text']
|
||||||
|
|
||||||
def search_archetype(self, building_type, standard, climate_zone):
|
def _search_archetype(self, building_type, standard, climate_zone):
|
||||||
for archetype in self._archetypes['archetypes']['archetype']:
|
for archetype in self._archetypes['archetypes']['archetype']:
|
||||||
a_yc = str(archetype['@reference_standard'])
|
a_yc = str(archetype['@reference_standard'])
|
||||||
a_bt = str(archetype['@building_type'])
|
a_bt = str(archetype['@building_type'])
|
||||||
|
@ -99,14 +102,14 @@ class UsBasePhysicsParameters:
|
||||||
return archetype
|
return archetype
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def search_construction_type(self, construction_type, construction_id):
|
def _search_construction_type(self, construction_type, construction_id):
|
||||||
for c_lib in self._library['library'][construction_type + 's'][construction_type]:
|
for c_lib in self._library['library'][construction_type + 's'][construction_type]:
|
||||||
if construction_id == c_lib['@id']:
|
if construction_id == c_lib['@id']:
|
||||||
return c_lib
|
return c_lib
|
||||||
raise Exception('Archetype definition contains elements that does not exist in the library')
|
raise Exception('Archetype definition contains elements that does not exist in the library')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def search_construction_in_archetype(archetype, construction_type):
|
def _search_construction_in_archetype(archetype, construction_type):
|
||||||
for construction in archetype['constructions']['construction']:
|
for construction in archetype['constructions']['construction']:
|
||||||
if construction['@type'] == construction_type:
|
if construction['@type'] == construction_type:
|
||||||
return construction
|
return construction
|
||||||
|
|
|
@ -8,6 +8,9 @@ from physics.physics_feeders.helpers.us_pluto_to_function import UsPlutoToFuncti
|
||||||
|
|
||||||
|
|
||||||
class UsNewYorkCityPhysicsParameters(UsBasePhysicsParameters):
|
class UsNewYorkCityPhysicsParameters(UsBasePhysicsParameters):
|
||||||
|
"""
|
||||||
|
UsNewYorkCityPhysicsParameters class
|
||||||
|
"""
|
||||||
def __init__(self, city, base_path):
|
def __init__(self, city, base_path):
|
||||||
self._city = city
|
self._city = city
|
||||||
climate_zone = 'ASHRAE_2004:4A'
|
climate_zone = 'ASHRAE_2004:4A'
|
||||||
|
|
|
@ -8,6 +8,9 @@ from physics.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes
|
||||||
|
|
||||||
|
|
||||||
class UsPhysicsParameters(UsBasePhysicsParameters):
|
class UsPhysicsParameters(UsBasePhysicsParameters):
|
||||||
|
"""
|
||||||
|
UsPhysicsParameters class
|
||||||
|
"""
|
||||||
def __init__(self, city, base_path):
|
def __init__(self, city, base_path):
|
||||||
self._city = city
|
self._city = city
|
||||||
self._climate_zone = UsToLibraryTypes.city_to_climate_zone(city.name)
|
self._climate_zone = UsToLibraryTypes.city_to_climate_zone(city.name)
|
||||||
|
|
3
pylintrc
3
pylintrc
|
@ -140,6 +140,9 @@ disable=print-statement,
|
||||||
exception-escape,
|
exception-escape,
|
||||||
comprehension-escape,
|
comprehension-escape,
|
||||||
import-error,
|
import-error,
|
||||||
|
parse-error,
|
||||||
|
syntax-error,
|
||||||
|
bad-continuation,
|
||||||
no-name-in-module
|
no-name-in-module
|
||||||
|
|
||||||
# Enable the message, report, category or checker with the given id(s). You can
|
# Enable the message, report, category or checker with the given id(s). You can
|
||||||
|
|
|
@ -7,15 +7,25 @@ from unittest import TestCase
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from geometry.geometry_factory import GeometryFactory
|
from geometry.geometry_factory import GeometryFactory
|
||||||
import os
|
import os
|
||||||
from city_model_structure.surface import Surface
|
|
||||||
|
|
||||||
|
|
||||||
class TestGeometryFactory(TestCase):
|
class TestGeometryFactory(TestCase):
|
||||||
|
"""
|
||||||
|
TestGeometryFactory TestCase
|
||||||
|
"""
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
|
"""
|
||||||
|
Test setup
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
self._city_gml = None
|
self._city_gml = None
|
||||||
self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve()
|
self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve()
|
||||||
|
|
||||||
def get_citygml(self):
|
def get_citygml(self):
|
||||||
|
"""
|
||||||
|
Retrieve the test city gml
|
||||||
|
:return: City
|
||||||
|
"""
|
||||||
if self._city_gml is None:
|
if self._city_gml is None:
|
||||||
file_path = (self._example_path / 'buildings.gml').resolve()
|
file_path = (self._example_path / 'buildings.gml').resolve()
|
||||||
self._city_gml = GeometryFactory('citygml', file_path).city
|
self._city_gml = GeometryFactory('citygml', file_path).city
|
||||||
|
@ -23,6 +33,10 @@ class TestGeometryFactory(TestCase):
|
||||||
return self._city_gml
|
return self._city_gml
|
||||||
|
|
||||||
def test_citygml_city(self):
|
def test_citygml_city(self):
|
||||||
|
"""
|
||||||
|
Test the City parsing
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
city = self.get_citygml()
|
city = self.get_citygml()
|
||||||
self.assertIsNotNone(city.city_objects, 'city_objects is none')
|
self.assertIsNotNone(city.city_objects, 'city_objects is none')
|
||||||
for city_object in city.city_objects:
|
for city_object in city.city_objects:
|
||||||
|
@ -34,6 +48,10 @@ class TestGeometryFactory(TestCase):
|
||||||
self.assertIsNotNone(city.country_code, 'country code is none')
|
self.assertIsNotNone(city.country_code, 'country code is none')
|
||||||
|
|
||||||
def test_citygml_city_objects(self):
|
def test_citygml_city_objects(self):
|
||||||
|
"""
|
||||||
|
Test city objects in the city
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
city = self.get_citygml()
|
city = self.get_citygml()
|
||||||
for city_object in city.city_objects:
|
for city_object in city.city_objects:
|
||||||
self.assertIsNotNone(city_object.name, 'city_object name is none')
|
self.assertIsNotNone(city_object.name, 'city_object name is none')
|
||||||
|
@ -58,6 +76,10 @@ class TestGeometryFactory(TestCase):
|
||||||
os.remove(Path(self._example_path, city_object.name + '.stl').resolve())
|
os.remove(Path(self._example_path, city_object.name + '.stl').resolve())
|
||||||
|
|
||||||
def test_citygml_surfaces(self):
|
def test_citygml_surfaces(self):
|
||||||
|
"""
|
||||||
|
Test surfaces in city objects
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
city = self.get_citygml()
|
city = self.get_citygml()
|
||||||
for city_object in city.city_objects:
|
for city_object in city.city_objects:
|
||||||
for surface in city_object.surfaces:
|
for surface in city_object.surfaces:
|
||||||
|
@ -85,6 +107,10 @@ class TestGeometryFactory(TestCase):
|
||||||
self.assertIsNotNone(surface.intersect(surface), 'self intersection is none')
|
self.assertIsNotNone(surface.intersect(surface), 'self intersection is none')
|
||||||
|
|
||||||
def test_citygml_thermal_zone(self):
|
def test_citygml_thermal_zone(self):
|
||||||
|
"""
|
||||||
|
Test thermal zones in city objects
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
city = self.get_citygml()
|
city = self.get_citygml()
|
||||||
for city_object in city.city_objects:
|
for city_object in city.city_objects:
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in city_object.thermal_zones:
|
||||||
|
@ -97,8 +123,8 @@ class TestGeometryFactory(TestCase):
|
||||||
'thermal_zone additional_thermal_bridge_u_value is not none')
|
'thermal_zone additional_thermal_bridge_u_value is not none')
|
||||||
self.assertIsNone(thermal_zone.effective_thermal_capacity,
|
self.assertIsNone(thermal_zone.effective_thermal_capacity,
|
||||||
'thermal_zone effective_thermal_capacity is not none')
|
'thermal_zone effective_thermal_capacity is not none')
|
||||||
self.assertIsNone(thermal_zone.indirectly_heated_area_ratio
|
self.assertIsNone(thermal_zone.indirectly_heated_area_ratio,
|
||||||
, 'thermal_zone indirectly_heated_area_ratio is not none')
|
'thermal_zone indirectly_heated_area_ratio is not none')
|
||||||
self.assertIsNone(thermal_zone.infiltration_rate_system_off,
|
self.assertIsNone(thermal_zone.infiltration_rate_system_off,
|
||||||
'thermal_zone infiltration_rate_system_off is not none')
|
'thermal_zone infiltration_rate_system_off is not none')
|
||||||
self.assertIsNone(thermal_zone.infiltration_rate_system_on,
|
self.assertIsNone(thermal_zone.infiltration_rate_system_on,
|
||||||
|
@ -107,6 +133,10 @@ class TestGeometryFactory(TestCase):
|
||||||
'thermal_zone usage_zones are not none')
|
'thermal_zone usage_zones are not none')
|
||||||
|
|
||||||
def test_citygml_thermal_boundary(self):
|
def test_citygml_thermal_boundary(self):
|
||||||
|
"""
|
||||||
|
Test thermal boundaries in thermal zones
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
city = self.get_citygml()
|
city = self.get_citygml()
|
||||||
for city_object in city.city_objects:
|
for city_object in city.city_objects:
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in city_object.thermal_zones:
|
||||||
|
@ -133,6 +163,10 @@ class TestGeometryFactory(TestCase):
|
||||||
self.assertIsNone(thermal_boundary.window_ratio, 'thermal_boundary window_ratio was initialized')
|
self.assertIsNone(thermal_boundary.window_ratio, 'thermal_boundary window_ratio was initialized')
|
||||||
|
|
||||||
def test_citygml_thermal_opening(self):
|
def test_citygml_thermal_opening(self):
|
||||||
|
"""
|
||||||
|
Test thermal openings in thermal zones
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
city = self.get_citygml()
|
city = self.get_citygml()
|
||||||
for city_object in city.city_objects:
|
for city_object in city.city_objects:
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in city_object.thermal_zones:
|
||||||
|
@ -141,11 +175,11 @@ class TestGeometryFactory(TestCase):
|
||||||
self.assertIsNone(thermal_opening.area, 'thermal_opening area was initialized')
|
self.assertIsNone(thermal_opening.area, 'thermal_opening area was initialized')
|
||||||
self.assertTrue(thermal_opening.frame_ratio == 0, 'thermal_opening frame_ratio was not 0')
|
self.assertTrue(thermal_opening.frame_ratio == 0, 'thermal_opening frame_ratio was not 0')
|
||||||
self.assertIsNone(thermal_opening.g_value, 'thermal_opening g_value was initialized')
|
self.assertIsNone(thermal_opening.g_value, 'thermal_opening g_value was initialized')
|
||||||
self.assertIsNone(thermal_opening.conductivity_w_mk, 'thermal_opening conductivity_w_mk was initialized')
|
self.assertIsNone(thermal_opening.conductivity, 'thermal_opening conductivity_w_mk was initialized')
|
||||||
self.assertIsNone(thermal_opening.inside_reflectance, 'thermal_opening inside_reflectance was initialized')
|
self.assertIsNone(thermal_opening.inside_reflectance, 'thermal_opening inside_reflectance was initialized')
|
||||||
self.assertRaises(Exception, lambda: thermal_opening.openable_ratio,
|
self.assertRaises(Exception, lambda: thermal_opening.openable_ratio,
|
||||||
'thermal_opening openable_ratio is not raising an exception')
|
'thermal_opening openable_ratio is not raising an exception')
|
||||||
self.assertIsNone(thermal_opening.outside_reflectance,
|
self.assertIsNone(thermal_opening.outside_reflectance,
|
||||||
'thermal_opening outside_reflectance was initialized')
|
'thermal_opening outside_reflectance was initialized')
|
||||||
self.assertIsNone(thermal_opening.thickness_m, 'thermal_opening thickness_m was initialized')
|
self.assertIsNone(thermal_opening.thickness, 'thermal_opening thickness_m was initialized')
|
||||||
self.assertRaises(Exception, lambda: thermal_opening.u_value, 'thermal_opening u_value was initialized')
|
self.assertRaises(Exception, lambda: thermal_opening.u_value, 'thermal_opening u_value was initialized')
|
||||||
|
|
|
@ -10,7 +10,10 @@ from physics.physics_factory import PhysicsFactory
|
||||||
|
|
||||||
|
|
||||||
class TestPhysicsFactory(TestCase):
|
class TestPhysicsFactory(TestCase):
|
||||||
def setUp(self) -> None:
|
"""
|
||||||
|
TestPhysicsFactory TestCase
|
||||||
|
"""
|
||||||
|
def setup(self) -> None:
|
||||||
self._city_gml = None
|
self._city_gml = None
|
||||||
self._nyc_with_physics = None
|
self._nyc_with_physics = None
|
||||||
self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve()
|
self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user