from city_model_structure.thermal_opening import ThermalOpening from city_model_structure.surface import Surface from city_model_structure.layer import Layer from helpers.configuration import Configuration 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 = Configuration().h_i h_e = Configuration().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