forked from s_ranjbar/city_retrofit
133 lines
3.6 KiB
Python
133 lines
3.6 KiB
Python
from city_model_structure.thermal_opening import ThermalOpening
|
|
from city_model_structure.surface import Surface
|
|
from city_model_structure.layer import Layer
|
|
import helpers.assumptions as assumptions
|
|
from typing import List
|
|
|
|
|
|
class ThermalBoundary:
|
|
def __init__(self, surface, delimits):
|
|
self._surface = surface
|
|
self._delimits = delimits
|
|
# ToDo: up to at least LOD2 will be just one thermal opening per Thermal boundary, review for LOD3 and LOD4
|
|
self._thermal_openings = [ThermalOpening()]
|
|
self._layers = None
|
|
self._outside_solar_absorptance = None
|
|
self._outside_thermal_absorptance = None
|
|
self._outside_visible_absorptance = None
|
|
self._window_ratio = None
|
|
self._u_value = None
|
|
self._window_area = None
|
|
self._shortwave_reflectance = None
|
|
|
|
@property
|
|
def delimits(self) -> List[Surface]:
|
|
return self._delimits
|
|
|
|
@property
|
|
def azimuth(self):
|
|
return self._surface.azimuth
|
|
|
|
@property
|
|
def inclination(self):
|
|
return self._surface.inclination
|
|
|
|
@property
|
|
def area(self):
|
|
return self._surface.area
|
|
|
|
@property
|
|
def area_above_ground(self):
|
|
return self._surface.area_above_ground
|
|
|
|
@property
|
|
def area_below_ground(self):
|
|
return self._surface.area_below_ground
|
|
|
|
@property
|
|
def outside_solar_absorptance(self):
|
|
return self._outside_solar_absorptance
|
|
|
|
@outside_solar_absorptance.setter
|
|
def outside_solar_absorptance(self, value):
|
|
self._outside_solar_absorptance = value
|
|
|
|
@property
|
|
def outside_thermal_absorptance(self):
|
|
return self._outside_thermal_absorptance
|
|
|
|
@outside_thermal_absorptance.setter
|
|
def outside_thermal_absorptance(self, value):
|
|
self._outside_thermal_absorptance = value
|
|
|
|
@property
|
|
def outside_visible_absorptance(self):
|
|
return self._outside_visible_absorptance
|
|
|
|
@outside_visible_absorptance.setter
|
|
def outside_visible_absorptance(self, value):
|
|
self._outside_visible_absorptance = value
|
|
|
|
@property
|
|
def thermal_openings(self) -> List[ThermalOpening]:
|
|
return self._thermal_openings
|
|
|
|
@thermal_openings.setter
|
|
def thermal_openings(self, value):
|
|
self._thermal_openings = value
|
|
|
|
@property
|
|
def layers(self) -> List[Layer]:
|
|
return self._layers
|
|
|
|
@layers.setter
|
|
def layers(self, value):
|
|
self._layers = value
|
|
|
|
@property
|
|
def type(self):
|
|
return self._surface.type
|
|
|
|
@property
|
|
def window_ratio(self):
|
|
return self._window_ratio
|
|
|
|
@window_ratio.setter
|
|
def window_ratio(self, value):
|
|
self._window_ratio = value
|
|
|
|
@property
|
|
def window_area(self):
|
|
if self._window_area is None:
|
|
try:
|
|
self._window_area = float(self._surface.area) * float(self.window_ratio)
|
|
except TypeError:
|
|
raise Exception('Window ratio is not defined or invalid surface area')
|
|
return self._window_area
|
|
|
|
@property
|
|
def u_value(self):
|
|
if self._u_value is None:
|
|
h_i = assumptions.h_i
|
|
h_e = assumptions.h_e
|
|
r_value = 1.0/h_i + 1.0/h_e
|
|
try:
|
|
for layer in self.layers:
|
|
if layer.material.no_mass:
|
|
r_value += float(layer.material.thermal_resistance_m2k_w)
|
|
else:
|
|
r_value = r_value + float(layer.material.conductivity_wm_k)/float(layer.thickness_m)
|
|
self._u_value = 1.0/r_value
|
|
except TypeError:
|
|
raise Exception('Constructions layers are not initialized')
|
|
return self._u_value
|
|
|
|
@property
|
|
def shortwave_reflectance(self):
|
|
if self._shortwave_reflectance is None:
|
|
try:
|
|
self._shortwave_reflectance = 1.0 - float(self.outside_solar_absorptance)
|
|
except TypeError:
|
|
raise Exception('Outside solar absorptance is not initialized')
|
|
return self._shortwave_reflectance
|