forked from s_ranjbar/city_retrofit
modified structure
This commit is contained in:
parent
94c593b651
commit
b3f8647036
|
@ -0,0 +1,53 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class DomesticHotWaterFacility:
|
||||
"""
|
||||
Domestic Hot Water facilities class
|
||||
"""
|
||||
|
||||
def __init__(self, number_of_baths, number_of_showers, number_of_basin, water_storage_volume):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
|
||||
self._number_of_baths = number_of_baths
|
||||
self._number_of_showers = number_of_showers
|
||||
self._number_of_basin = number_of_basin
|
||||
self._water_storage_volume = water_storage_volume
|
||||
|
||||
@property
|
||||
def number_of_baths(self):
|
||||
"""
|
||||
Get number of baths of a building unit
|
||||
:return: number of baths
|
||||
"""
|
||||
return self._number_of_baths
|
||||
|
||||
@property
|
||||
def number_of_showers(self):
|
||||
"""
|
||||
Get number of showers of a building unit
|
||||
:return: number of showers
|
||||
"""
|
||||
return self._number_of_showers
|
||||
|
||||
@property
|
||||
def number_of_basin(self):
|
||||
"""
|
||||
Get number of wash basins of a building unit
|
||||
:return: number of wash basins
|
||||
"""
|
||||
return self._number_of_basin
|
||||
|
||||
@property
|
||||
def water_storage_volume(self):
|
||||
"""
|
||||
Get the volume of water storage
|
||||
:return: volume of water storage
|
||||
"""
|
||||
return self._water_storage_volume
|
|
@ -0,0 +1,26 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class appliances_facilities:
|
||||
"""
|
||||
Electric appliance facilities class
|
||||
"""
|
||||
|
||||
def __init__(self, appliance_electric_power):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
|
||||
self._appliance_electric_power = appliance_electric_power
|
||||
|
||||
@property
|
||||
def appliance_electric_power(self):
|
||||
"""
|
||||
Get appliances electric power
|
||||
:return: appliances electric power
|
||||
"""
|
||||
return self._appliance_electric_power
|
59
city_model_structure/attributes/facility.py
Normal file
59
city_model_structure/attributes/facility.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Facility:
|
||||
"""
|
||||
facilities class
|
||||
"""
|
||||
|
||||
def __init__(self, operation_schedules, convective_fraction, latent_fraction,
|
||||
radiant_fraction, total_value_of_heat_dissipation):
|
||||
self._operation_schedules = operation_schedules
|
||||
self._convective_fraction = convective_fraction
|
||||
self._latent_fraction = latent_fraction
|
||||
self._radiant_fraction = radiant_fraction
|
||||
self._total_value_of_heat_dissipation = total_value_of_heat_dissipation
|
||||
|
||||
@property
|
||||
def operation_schedules(self):
|
||||
"""
|
||||
Get operation schedules of the facilities
|
||||
:return: operation schedules
|
||||
"""
|
||||
return self._operation_schedules
|
||||
|
||||
@property
|
||||
def convective_fraction(self):
|
||||
"""
|
||||
Get convective fraction value
|
||||
:return: convective fraction
|
||||
"""
|
||||
return self._convective_fraction
|
||||
|
||||
@property
|
||||
def latent_fraction(self):
|
||||
"""
|
||||
Get latent fraction value
|
||||
:return: latent fraction
|
||||
"""
|
||||
return self._latent_fraction
|
||||
|
||||
@property
|
||||
def radiant_fraction(self):
|
||||
"""
|
||||
Get radiant fraction value
|
||||
:return: radiant fraction
|
||||
"""
|
||||
return self._radiant_fraction
|
||||
|
||||
@property
|
||||
def total_value_of_heat_dissipation(self):
|
||||
"""
|
||||
Get heat dissipation value
|
||||
:return: heat dissipation
|
||||
"""
|
||||
return self._total_value_of_heat_dissipation
|
36
city_model_structure/attributes/household.py
Normal file
36
city_model_structure/attributes/household.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class household:
|
||||
"""
|
||||
Household class
|
||||
"""
|
||||
|
||||
def __init__(self, resident_type, household_type):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
|
||||
self._resident_type = resident_type
|
||||
self._household_type = household_type
|
||||
|
||||
|
||||
@property
|
||||
def resident_type(self):
|
||||
"""
|
||||
Get resident type
|
||||
:return: resident type
|
||||
"""
|
||||
return self._resident_type
|
||||
|
||||
@property
|
||||
def household_type(self):
|
||||
"""
|
||||
Get household type
|
||||
:return: household type
|
||||
"""
|
||||
return self._household_type
|
36
city_model_structure/attributes/hvac_facility.py
Normal file
36
city_model_structure/attributes/hvac_facility.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class HvacFacility:
|
||||
"""
|
||||
HVAC facilities class
|
||||
"""
|
||||
|
||||
def __init__(self, temperature_setpoints, hvac_schedules):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
|
||||
self._temperature_setpoints = temperature_setpoints
|
||||
self._hvac_schedules = hvac_schedules
|
||||
|
||||
@property
|
||||
def temperature_setpoints(self):
|
||||
"""
|
||||
Get temperature setpoints
|
||||
:return: temperature setpoints
|
||||
"""
|
||||
return self._temperature_setpoints
|
||||
|
||||
@property
|
||||
def hvac_schedules(self):
|
||||
"""
|
||||
Get HVAC schedules
|
||||
:return: HVAC schedules
|
||||
"""
|
||||
return self._hvac_schedules
|
||||
|
84
city_model_structure/attributes/internal_gains.py
Normal file
84
city_model_structure/attributes/internal_gains.py
Normal file
|
@ -0,0 +1,84 @@
|
|||
"""
|
||||
InternalGains module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class InternalGains:
|
||||
"""
|
||||
InternalGains class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._average_internal_gain = None
|
||||
self._convective_fraction = None
|
||||
self._radiative_fraction = None
|
||||
self._latent_fraction = None
|
||||
|
||||
@property
|
||||
def average_internal_gain(self):
|
||||
"""
|
||||
Get internal gains average internal gain in w/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._average_internal_gain
|
||||
|
||||
@average_internal_gain.setter
|
||||
def average_internal_gain(self, value):
|
||||
"""
|
||||
Set internal gains average internal gain in w/m2
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._average_internal_gain = value
|
||||
|
||||
@property
|
||||
def convective_fraction(self):
|
||||
"""
|
||||
Get internal gains convective fraction
|
||||
:return: float
|
||||
"""
|
||||
return self._convective_fraction
|
||||
|
||||
@convective_fraction.setter
|
||||
def convective_fraction(self, value):
|
||||
"""
|
||||
Set internal gains convective fraction
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._convective_fraction = value
|
||||
|
||||
@property
|
||||
def radiative_fraction(self):
|
||||
"""
|
||||
Get internal gains radiative fraction
|
||||
:return: float
|
||||
"""
|
||||
return self._radiative_fraction
|
||||
|
||||
@radiative_fraction.setter
|
||||
def radiative_fraction(self, value):
|
||||
"""
|
||||
Set internal gains convective fraction
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._radiative_fraction = value
|
||||
|
||||
@property
|
||||
def latent_fraction(self):
|
||||
"""
|
||||
Get internal gains latent fraction
|
||||
:return: float
|
||||
"""
|
||||
return self._latent_fraction
|
||||
|
||||
@latent_fraction.setter
|
||||
def latent_fraction(self, value):
|
||||
"""
|
||||
Set internal gains latent fraction
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._latent_fraction = value
|
49
city_model_structure/attributes/layer.py
Normal file
49
city_model_structure/attributes/layer.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
Layers module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
from city_model_structure.attributes.material import Material
|
||||
|
||||
|
||||
class Layer:
|
||||
"""
|
||||
Layer class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._material = None
|
||||
self._thickness = None
|
||||
|
||||
@property
|
||||
def material(self) -> Material:
|
||||
"""
|
||||
Get layer material
|
||||
:return: Material
|
||||
"""
|
||||
return self._material
|
||||
|
||||
@material.setter
|
||||
def material(self, value):
|
||||
"""
|
||||
Set layer material
|
||||
:param value: Material
|
||||
:return: None
|
||||
"""
|
||||
self._material = value
|
||||
|
||||
@property
|
||||
def thickness(self):
|
||||
"""
|
||||
Get layer thickness in meters
|
||||
:return: float
|
||||
"""
|
||||
return self._thickness
|
||||
|
||||
@thickness.setter
|
||||
def thickness(self, value):
|
||||
"""
|
||||
Get layer thickness in meters
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._thickness = value
|
26
city_model_structure/attributes/lighting_facilities.py
Normal file
26
city_model_structure/attributes/lighting_facilities.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class lighting_facilities:
|
||||
"""
|
||||
Lighting facilities class
|
||||
"""
|
||||
|
||||
def __init__(self, electric_power):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
|
||||
self._electric_power = electric_power
|
||||
|
||||
@property
|
||||
def electric_power(self):
|
||||
"""
|
||||
Get lighting electric power
|
||||
:return: lighting electric power
|
||||
"""
|
||||
return self._electric_power
|
156
city_model_structure/attributes/material.py
Normal file
156
city_model_structure/attributes/material.py
Normal file
|
@ -0,0 +1,156 @@
|
|||
"""
|
||||
Material module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Material:
|
||||
"""
|
||||
Material class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._conductivity = None
|
||||
self._specific_heat = None
|
||||
self._density = None
|
||||
self._solar_absorptance = None
|
||||
self._thermal_absorptance = None
|
||||
self._visible_absorptance = None
|
||||
self._no_mass = False
|
||||
self._thermal_resistance = None
|
||||
|
||||
@property
|
||||
def conductivity(self):
|
||||
"""
|
||||
Get material conductivity in W/mK
|
||||
:return: float
|
||||
"""
|
||||
return self._conductivity
|
||||
|
||||
@conductivity.setter
|
||||
def conductivity(self, value):
|
||||
"""
|
||||
Set material conductivity in W/mK
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._conductivity = value
|
||||
|
||||
@property
|
||||
def specific_heat(self):
|
||||
"""
|
||||
Get material conductivity in J/kgK
|
||||
:return: float
|
||||
"""
|
||||
return self._specific_heat
|
||||
|
||||
@specific_heat.setter
|
||||
def specific_heat(self, value):
|
||||
"""
|
||||
Get material conductivity in J/kgK
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._specific_heat = value
|
||||
|
||||
@property
|
||||
def density(self):
|
||||
"""
|
||||
Get material density in kg/m3
|
||||
:return: float
|
||||
"""
|
||||
return self._density
|
||||
|
||||
@density.setter
|
||||
def density(self, value):
|
||||
"""
|
||||
Set material density in kg/m3
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._density = value
|
||||
|
||||
@property
|
||||
def solar_absorptance(self):
|
||||
"""
|
||||
Get material solar absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._solar_absorptance
|
||||
|
||||
@solar_absorptance.setter
|
||||
def solar_absorptance(self, value):
|
||||
"""
|
||||
Set material solar absorptance
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._solar_absorptance = value
|
||||
|
||||
@property
|
||||
def thermal_absorptance(self):
|
||||
"""
|
||||
Get material thermal absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._thermal_absorptance
|
||||
|
||||
@thermal_absorptance.setter
|
||||
def thermal_absorptance(self, value):
|
||||
"""
|
||||
Set material thermal absorptance
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._thermal_absorptance = value
|
||||
|
||||
@property
|
||||
def visible_absorptance(self):
|
||||
"""
|
||||
Get material visible absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._visible_absorptance
|
||||
|
||||
@visible_absorptance.setter
|
||||
def visible_absorptance(self, value):
|
||||
"""
|
||||
Set material visible absorptance
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._visible_absorptance = value
|
||||
|
||||
@property
|
||||
def no_mass(self):
|
||||
"""
|
||||
Get material no mass flag
|
||||
:return: Boolean
|
||||
"""
|
||||
return self._no_mass
|
||||
|
||||
@no_mass.setter
|
||||
def no_mass(self, value):
|
||||
"""
|
||||
Set material no mass flag
|
||||
:param value: Boolean
|
||||
:return: None
|
||||
"""
|
||||
self._no_mass = value
|
||||
|
||||
@property
|
||||
def thermal_resistance(self):
|
||||
"""
|
||||
Get material thermal resistance in m2K/W
|
||||
:return: float
|
||||
"""
|
||||
return self._thermal_resistance
|
||||
|
||||
@thermal_resistance.setter
|
||||
def thermal_resistance(self, value):
|
||||
"""
|
||||
Set material thermal resistance in m2K/W
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._thermal_resistance = value
|
127
city_model_structure/attributes/occupancy.py
Normal file
127
city_model_structure/attributes/occupancy.py
Normal file
|
@ -0,0 +1,127 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Occupancy:
|
||||
"""
|
||||
Occupancy class
|
||||
"""
|
||||
|
||||
def __init__(self, internal_heat_gain, heat_dissipation, occupant_rate, occupant_type, occupant_zone,
|
||||
number_of_occupants, arrival_time=None, departure_time=None, break_time=None, day_of_week=None,
|
||||
pd_of_meetings_duration=None, occupant_schedule=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
|
||||
self._internal_heat_gain = internal_heat_gain
|
||||
self._heat_dissipation = heat_dissipation
|
||||
self._occupant_rate = occupant_rate
|
||||
self._occupant_type = occupant_type
|
||||
self._occupant_zone = occupant_zone
|
||||
self._occupant_schedule = occupant_schedule
|
||||
self._number_of_occupants = number_of_occupants
|
||||
self._arrival_time = arrival_time
|
||||
self._departure_time = departure_time
|
||||
self._break_time = break_time
|
||||
self._day_of_week = day_of_week
|
||||
self._pd_of_meetings_duration = pd_of_meetings_duration
|
||||
|
||||
@property
|
||||
def internal_heat_gain(self):
|
||||
"""
|
||||
Get internal heat gain of occupants
|
||||
:return: occupant heat gain
|
||||
"""
|
||||
return self._internal_heat_gain
|
||||
|
||||
@property
|
||||
def heat_dissipation(self):
|
||||
"""
|
||||
Get heat dissipation of occupants
|
||||
:return: heat dissipation
|
||||
"""
|
||||
return self._heat_dissipation
|
||||
|
||||
@property
|
||||
def occupant_rate(self):
|
||||
"""
|
||||
Get rate of occupancy
|
||||
:return: rate of occupancy
|
||||
"""
|
||||
return self._occupant_rate
|
||||
|
||||
@property
|
||||
def occupant_type(self):
|
||||
"""
|
||||
Get type of occupancy
|
||||
:return: type of occupancy
|
||||
"""
|
||||
return self._occupant_type
|
||||
|
||||
@property
|
||||
def occupant_zone(self):
|
||||
"""
|
||||
Get the zone that occupant is in it
|
||||
:return: occupant zone
|
||||
"""
|
||||
return self._occupant_zone
|
||||
|
||||
@property
|
||||
def occupant_schedule(self):
|
||||
"""
|
||||
Get the schedule when an occupant is in a zone
|
||||
:return: occupant schedule
|
||||
"""
|
||||
return self._occupant_schedule
|
||||
|
||||
@property
|
||||
def number_of_occupants(self):
|
||||
"""
|
||||
Get the number of occupants
|
||||
:return: number of occupants
|
||||
"""
|
||||
return self._number_of_occupants
|
||||
|
||||
@property
|
||||
def arrival_time(self):
|
||||
"""
|
||||
Get the arrival time of the occupant (for office building)
|
||||
:return: arrival time
|
||||
"""
|
||||
return self._arrival_time
|
||||
|
||||
@property
|
||||
def departure_time(self):
|
||||
"""
|
||||
Get the departure time of the occupant (for office building)
|
||||
:return: departure time
|
||||
"""
|
||||
return self._departure_time
|
||||
|
||||
@property
|
||||
def break_time(self):
|
||||
"""
|
||||
Get the lunch or break time of the occupant (for office building)
|
||||
:return: break time
|
||||
"""
|
||||
return self._break_time
|
||||
|
||||
@property
|
||||
def day_of_week(self):
|
||||
"""
|
||||
Get the day of the week
|
||||
:return: day of the week
|
||||
"""
|
||||
return self._day_of_week
|
||||
|
||||
@property
|
||||
def pd_of_meetings_duration(self):
|
||||
"""
|
||||
Get the probability distribution of the meeting duration
|
||||
:return: probability distribution of the meeting duration
|
||||
"""
|
||||
return self._pd_of_meetings_duration
|
116
city_model_structure/attributes/polyhedron.py
Normal file
116
city_model_structure/attributes/polyhedron.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
"""
|
||||
Polyhedron module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
import numpy as np
|
||||
from trimesh import Trimesh
|
||||
|
||||
from helpers.geometry_helper import GeometryHelper
|
||||
|
||||
|
||||
class Polyhedron:
|
||||
"""
|
||||
Polyhedron class
|
||||
"""
|
||||
def __init__(self, surfaces):
|
||||
self._surfaces = list(surfaces)
|
||||
self._polygons = [s.polygon for s in surfaces]
|
||||
self._polyhedron = None
|
||||
self._volume = None
|
||||
self._faces = None
|
||||
self._vertices = None
|
||||
self._mesh = None
|
||||
self._centroid = None
|
||||
self._max_z = None
|
||||
self._geometry = GeometryHelper()
|
||||
|
||||
def _position_of(self, point):
|
||||
vertices = self.vertices
|
||||
for i in range(len(vertices)):
|
||||
if self._geometry.almost_equal(vertices[i], point):
|
||||
return i
|
||||
return -1
|
||||
|
||||
@property
|
||||
def vertices(self) -> np.ndarray:
|
||||
"""
|
||||
Polyhedron vertices
|
||||
:return: np.ndarray(int)
|
||||
"""
|
||||
if self._vertices is None:
|
||||
vertices, self._vertices = [], []
|
||||
_ = [vertices.extend(s.points) for s in self._surfaces]
|
||||
for vertex_1 in vertices:
|
||||
found = False
|
||||
for vertex_2 in self._vertices:
|
||||
found = False
|
||||
if self._geometry.almost_equal(vertex_1, vertex_2):
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
self._vertices.append(vertex_1)
|
||||
self._vertices = np.asarray(self._vertices)
|
||||
return self._vertices
|
||||
|
||||
@property
|
||||
def faces(self) -> np.ndarray:
|
||||
"""
|
||||
Polyhedron faces
|
||||
:return: np.ndarray([int])
|
||||
"""
|
||||
if self._faces is None:
|
||||
self._faces = []
|
||||
for surface in self._surfaces:
|
||||
face = []
|
||||
points = surface.points
|
||||
for point in points:
|
||||
face.append(self._position_of(point))
|
||||
self._faces.append(face)
|
||||
return self._faces
|
||||
|
||||
@property
|
||||
def _polyhedron_mesh(self):
|
||||
if self._mesh is None:
|
||||
self._mesh = Trimesh(vertices=self.vertices, faces=self.faces)
|
||||
return self._mesh
|
||||
|
||||
@property
|
||||
def volume(self):
|
||||
"""
|
||||
Polyhedron volume in cubic meters
|
||||
:return: float
|
||||
"""
|
||||
if self._volume is None:
|
||||
if not self._polyhedron_mesh.is_volume:
|
||||
print('The geometry is not a closed volume')
|
||||
self._volume = np.inf
|
||||
else:
|
||||
self._volume = self._polyhedron_mesh.volume
|
||||
return self._volume
|
||||
|
||||
@property
|
||||
def max_z(self):
|
||||
"""
|
||||
Polyhedron maximal z value
|
||||
:return: float
|
||||
"""
|
||||
bounds = self._polyhedron_mesh.bounds
|
||||
z_max = max(bounds[:, 2])
|
||||
return z_max
|
||||
|
||||
@property
|
||||
def centroid(self):
|
||||
"""
|
||||
Polyhedron centroid
|
||||
:return: [x,y,z]
|
||||
"""
|
||||
return self._polyhedron_mesh.centroid
|
||||
|
||||
def export(self, full_path):
|
||||
"""
|
||||
Export the polyhedron to stl given file
|
||||
:param full_path: str
|
||||
:return: None
|
||||
"""
|
||||
self._polyhedron_mesh.export(full_path)
|
34
city_model_structure/attributes/schedule_value.py
Normal file
34
city_model_structure/attributes/schedule_value.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
"""
|
||||
Building module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class ScheduleValue:
|
||||
"""
|
||||
Schedule Values class
|
||||
"""
|
||||
|
||||
def __init__(self, hour, probability):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self._hour = hour
|
||||
self._probability = probability
|
||||
|
||||
@property
|
||||
def hour(self):
|
||||
"""
|
||||
Get hours
|
||||
:return: hour of a day
|
||||
"""
|
||||
return self._hour
|
||||
|
||||
@property
|
||||
def probability(self):
|
||||
"""
|
||||
Get probabilities of occupants' presence
|
||||
:return: occupants' presence probabilities
|
||||
"""
|
||||
return self._probability
|
443
city_model_structure/attributes/surface.py
Normal file
443
city_model_structure/attributes/surface.py
Normal file
|
@ -0,0 +1,443 @@
|
|||
"""
|
||||
Surface module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
|
||||
import numpy as np
|
||||
import pyny3d.geoms as pn
|
||||
import pandas as pd
|
||||
import helpers.constants as cte
|
||||
|
||||
from helpers.geometry_helper import GeometryHelper
|
||||
|
||||
|
||||
class Surface:
|
||||
"""
|
||||
Surface class
|
||||
"""
|
||||
def __init__(self, coordinates, surface_type=None, name=None, swr='0.2', remove_last=True, is_projected=False):
|
||||
self._coordinates = coordinates
|
||||
self._type = surface_type
|
||||
self._name = name
|
||||
self._swr = swr
|
||||
self._remove_last = remove_last
|
||||
self._is_projected = is_projected
|
||||
self._geometry_helper = GeometryHelper()
|
||||
self._polygon = None
|
||||
self._ground_polygon = None
|
||||
self._area = None
|
||||
self._points = None
|
||||
self._ground_points = None
|
||||
self._points_list = None
|
||||
self._normal = None
|
||||
self._azimuth = None
|
||||
self._inclination = None
|
||||
self._area_above_ground = None
|
||||
self._area_below_ground = None
|
||||
self._parent = None
|
||||
self._shapely = None
|
||||
self._projected_surface = None
|
||||
self._min_x = None
|
||||
self._min_y = None
|
||||
self._min_z = None
|
||||
self._shared_surfaces = []
|
||||
self._global_irradiance = pd.DataFrame()
|
||||
self._global_irradiance_hour = np.zeros(8760)
|
||||
self._global_irradiance_month = np.zeros(12)
|
||||
self._ground_coordinates = (self.min_x, self.min_y, self.min_z)
|
||||
|
||||
def parent(self, parent, surface_id):
|
||||
"""
|
||||
Assign a city object as surface parent and a surface id
|
||||
:param parent: CityObject
|
||||
:param surface_id: str
|
||||
:return: None
|
||||
"""
|
||||
self._parent = parent
|
||||
self._name = str(surface_id)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Surface name
|
||||
:return: str
|
||||
"""
|
||||
if self._name is None:
|
||||
raise Exception('surface has no name')
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def swr(self):
|
||||
"""
|
||||
Get surface short wave reflectance
|
||||
:return: float
|
||||
"""
|
||||
return self._swr
|
||||
|
||||
@swr.setter
|
||||
def swr(self, value):
|
||||
"""
|
||||
Set surface short wave reflectance
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._swr = value
|
||||
|
||||
@property
|
||||
def points(self) -> np.ndarray:
|
||||
"""
|
||||
Surface point matrix
|
||||
:return: np.ndarray
|
||||
"""
|
||||
if self._points is None:
|
||||
self._points = np.fromstring(self._coordinates, dtype=float, sep=' ')
|
||||
self._points = GeometryHelper.to_points_matrix(self._points, self._remove_last)
|
||||
return self._points
|
||||
|
||||
def _min_coord(self, axis):
|
||||
if axis == 'x':
|
||||
axis = 0
|
||||
elif axis == 'y':
|
||||
axis = 1
|
||||
else:
|
||||
axis = 2
|
||||
min_coordinate = ''
|
||||
for point in self.points:
|
||||
if min_coordinate == '':
|
||||
min_coordinate = point[axis]
|
||||
elif min_coordinate > point[axis]:
|
||||
min_coordinate = point[axis]
|
||||
return min_coordinate
|
||||
|
||||
@property
|
||||
def min_x(self):
|
||||
"""
|
||||
Surface minimal x value
|
||||
:return: float
|
||||
"""
|
||||
if self._min_x is None:
|
||||
self._min_x = self._min_coord('x')
|
||||
return self._min_x
|
||||
|
||||
@property
|
||||
def min_y(self):
|
||||
"""
|
||||
Surface minimal y value
|
||||
:return: float
|
||||
"""
|
||||
if self._min_y is None:
|
||||
self._min_y = self._min_coord('y')
|
||||
return self._min_y
|
||||
|
||||
@property
|
||||
def min_z(self):
|
||||
"""
|
||||
Surface minimal z value
|
||||
:return: float
|
||||
"""
|
||||
if self._min_z is None:
|
||||
self._min_z = self._min_coord('z')
|
||||
return self._min_z
|
||||
|
||||
@property
|
||||
def ground_points(self) -> np.ndarray:
|
||||
"""
|
||||
Surface grounded points matrix
|
||||
:return: np.ndarray
|
||||
"""
|
||||
if self._ground_points is None:
|
||||
coordinates = ''
|
||||
for point in self.points:
|
||||
x = point[0] - self._ground_coordinates[0]
|
||||
y = point[1] - self._ground_coordinates[1]
|
||||
z = point[2] - self._ground_coordinates[2]
|
||||
if coordinates != '':
|
||||
coordinates = coordinates + ' '
|
||||
coordinates = coordinates + str(x) + ' ' + str(y) + ' ' + str(z)
|
||||
self._ground_points = np.fromstring(coordinates, dtype=float, sep=' ')
|
||||
self._ground_points = GeometryHelper.to_points_matrix(self._ground_points, False)
|
||||
return self._ground_points
|
||||
|
||||
@property
|
||||
def points_list(self) -> np.ndarray:
|
||||
"""
|
||||
Surface point list
|
||||
:return: np.ndarray
|
||||
"""
|
||||
if self._points_list is None:
|
||||
s = self.points
|
||||
self._points_list = np.reshape(s, len(s) * 3)
|
||||
return self._points_list
|
||||
|
||||
@property
|
||||
def polygon(self) -> Union[pn.Polygon, None]:
|
||||
"""
|
||||
Surface polygon
|
||||
:return: None or pyny3d.Polygon
|
||||
"""
|
||||
if self._polygon is None:
|
||||
try:
|
||||
self._polygon = pn.Polygon(self.points)
|
||||
except ValueError:
|
||||
# is not really a polygon but a line so just return none
|
||||
self._polygon = None
|
||||
return self._polygon
|
||||
|
||||
@property
|
||||
def ground_polygon(self) -> Union[pn.Polygon, None]:
|
||||
"""
|
||||
Surface grounded polygon
|
||||
:return: None or pyny3d.Polygon
|
||||
"""
|
||||
if self._ground_polygon is None:
|
||||
try:
|
||||
self._ground_polygon = pn.Polygon(self.ground_points)
|
||||
except ValueError:
|
||||
# is not really a polygon but a line so just return none
|
||||
self._ground_polygon = None
|
||||
return self._ground_polygon
|
||||
|
||||
@property
|
||||
def area(self):
|
||||
"""
|
||||
Surface area in square meters
|
||||
:return: float
|
||||
"""
|
||||
if self._area is None:
|
||||
self._area = self.polygon.get_area()
|
||||
return self._area
|
||||
|
||||
def _is_almost_same_terrain(self, terrain_points, ground_points):
|
||||
equal = 0
|
||||
for terrain_point in terrain_points:
|
||||
for ground_point in ground_points:
|
||||
if self._geometry_helper.almost_equal(terrain_point, ground_point):
|
||||
equal += 1
|
||||
return equal == len(terrain_points)
|
||||
|
||||
@property
|
||||
def _is_terrain(self):
|
||||
for t_points in self._parent.terrains:
|
||||
if len(t_points) == len(self.points) and self._is_almost_same_terrain(t_points, self.points):
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def area_above_ground(self):
|
||||
"""
|
||||
Surface area above ground in square meters
|
||||
:return: float
|
||||
"""
|
||||
if self._area_above_ground is None:
|
||||
self._area_above_ground = self.area - self.area_below_ground
|
||||
return self._area_above_ground
|
||||
|
||||
@property
|
||||
def area_below_ground(self):
|
||||
"""
|
||||
Surface area below ground in square meters
|
||||
:return: float
|
||||
"""
|
||||
if self._area_below_ground is None:
|
||||
self._area_below_ground = 0.0
|
||||
if self._is_terrain:
|
||||
self._area_below_ground = self.area
|
||||
return self._area_below_ground
|
||||
|
||||
@property
|
||||
def normal(self) -> np.ndarray:
|
||||
"""
|
||||
Surface normal vector
|
||||
:return: np.ndarray
|
||||
"""
|
||||
if self._normal is None:
|
||||
points = self.points
|
||||
cross_product = np.cross(points[1] - points[0], points[2] - points[0])
|
||||
self._normal = cross_product / np.linalg.norm(cross_product)
|
||||
return self._normal
|
||||
|
||||
@property
|
||||
def azimuth(self):
|
||||
"""
|
||||
Surface azimuth in radians
|
||||
:return: float
|
||||
"""
|
||||
if self._azimuth is None:
|
||||
normal = self.normal
|
||||
self._azimuth = np.arctan2(normal[1], normal[0])
|
||||
return self._azimuth
|
||||
|
||||
@property
|
||||
def inclination(self):
|
||||
"""
|
||||
Surface inclination in radians
|
||||
:return: float
|
||||
"""
|
||||
if self._inclination is None:
|
||||
self._inclination = np.arccos(self.normal[2])
|
||||
return self._inclination
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
"""
|
||||
Surface type Ground, Wall or Roof
|
||||
:return: str
|
||||
"""
|
||||
if self._type is None:
|
||||
grad = np.rad2deg(self.inclination)
|
||||
if grad >= 170:
|
||||
self._type = 'Ground'
|
||||
elif 80 <= grad <= 100:
|
||||
self._type = 'Wall'
|
||||
else:
|
||||
self._type = 'Roof'
|
||||
return self._type
|
||||
|
||||
def add_shared(self, surface, intersection_area):
|
||||
"""
|
||||
Add a given surface and shared area in percent to this surface.
|
||||
:param surface:
|
||||
:param intersection_area:
|
||||
:return:
|
||||
"""
|
||||
percent = intersection_area / self.area
|
||||
self._shared_surfaces.append((percent, surface))
|
||||
|
||||
def shared(self, surface):
|
||||
"""
|
||||
Check if given surface share some area with this surface
|
||||
:param surface: Surface
|
||||
:return: None
|
||||
"""
|
||||
if self.type != 'Wall' or surface.type != 'Wall':
|
||||
return
|
||||
if self._geometry_helper.is_almost_same_surface(self, surface):
|
||||
intersection_area = self.intersect(surface).area
|
||||
self.add_shared(surface, intersection_area)
|
||||
surface.add_shared(self, intersection_area)
|
||||
|
||||
@property
|
||||
def global_irradiance_hour(self):
|
||||
"""
|
||||
Get surface global irradiance hour in Wh/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._global_irradiance_hour
|
||||
|
||||
@global_irradiance_hour.setter
|
||||
def global_irradiance_hour(self, value):
|
||||
"""
|
||||
Set surface global irradiance per hour in Wh/m2
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._global_irradiance_hour = value
|
||||
|
||||
@property
|
||||
def global_irradiance_month(self):
|
||||
"""
|
||||
Get surface global irradiance per month in Wh/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._global_irradiance_month
|
||||
|
||||
@global_irradiance_month.setter
|
||||
def global_irradiance_month(self, value):
|
||||
"""
|
||||
Set surface global irradiance per month in Wh/m2
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._global_irradiance_month = value
|
||||
|
||||
def global_irradiance(self, time_scale):
|
||||
"""
|
||||
Get surface global irradiance in Wh/m2 in a defined time_scale
|
||||
:param time_scale: string.
|
||||
:return: DataFrame(float)
|
||||
"""
|
||||
if time_scale == cte.time_scale['hour']:
|
||||
self._global_irradiance = self.global_irradiance_hour
|
||||
elif time_scale == cte.time_scale['month']:
|
||||
self._global_irradiance = self.global_irradiance_month
|
||||
else:
|
||||
raise NotImplementedError
|
||||
return self._global_irradiance
|
||||
|
||||
@property
|
||||
def shapely(self) -> Union[None, pn.Polygon]:
|
||||
"""
|
||||
Surface shapely (Z projection)
|
||||
:return: None or pyny3d.Polygon
|
||||
"""
|
||||
if self.polygon is None:
|
||||
return None
|
||||
if self._shapely is None:
|
||||
self._shapely = self.polygon.get_shapely()
|
||||
return self._shapely
|
||||
|
||||
@staticmethod
|
||||
def _polygon_to_surface(polygon) -> Surface:
|
||||
coordinates = ''
|
||||
for coordinate in polygon.exterior.coords:
|
||||
if coordinates != '':
|
||||
coordinates = coordinates + ' '
|
||||
coordinates = coordinates + str(coordinate[0]) + ' ' + str(coordinate[1]) + ' 0.0'
|
||||
return Surface(coordinates, remove_last=False)
|
||||
|
||||
@property
|
||||
def projection(self) -> Surface:
|
||||
"""
|
||||
Projected surface (Z projection)
|
||||
:return: Surface
|
||||
"""
|
||||
if self._is_projected:
|
||||
return self
|
||||
if self._projected_surface is None:
|
||||
shapely = self.shapely
|
||||
if shapely is not None:
|
||||
self._projected_surface = self._polygon_to_surface(shapely)
|
||||
return self._projected_surface
|
||||
|
||||
def intersect(self, surface) -> Union[Surface, None]:
|
||||
"""
|
||||
Get the intersection surface, if any, between the given surface and this surface
|
||||
:param surface: Surface
|
||||
:return: None or Surface
|
||||
"""
|
||||
min_x = min(self.min_x, surface.min_x)
|
||||
min_y = min(self.min_y, surface.min_y)
|
||||
min_z = min(self.min_z, surface.min_z)
|
||||
self._ground_coordinates = (min_x, min_y, min_z)
|
||||
surface._ground_coordinates = (min_x, min_y, min_z)
|
||||
origin = (0, 0, 0)
|
||||
azimuth = self.azimuth - (np.pi / 2)
|
||||
while azimuth < 0:
|
||||
azimuth += (np.pi / 2)
|
||||
inclination = self.inclination - np.pi
|
||||
while inclination < 0:
|
||||
inclination += np.pi
|
||||
polygon1 = self.ground_polygon.rotate(azimuth, 'z', origin).rotate(inclination, 'x', origin)
|
||||
polygon2 = surface.ground_polygon.rotate(azimuth, 'z', origin).rotate(inclination, 'x', origin)
|
||||
try:
|
||||
coordinates = ''
|
||||
intersection = pn.Surface([polygon1]).intersect_with(polygon2)
|
||||
if len(intersection) == 0:
|
||||
return None
|
||||
for coordinate in pn.Surface([polygon1]).intersect_with(polygon2)[0]:
|
||||
if coordinates != '':
|
||||
coordinates = coordinates + ' '
|
||||
coordinates = coordinates + str(coordinate[0]) + ' ' + str(coordinate[1]) + ' 0.0'
|
||||
if coordinates == '':
|
||||
return None
|
||||
intersect_surface = Surface(coordinates, remove_last=False)
|
||||
if intersect_surface.polygon is None:
|
||||
return None
|
||||
|
||||
return Surface(coordinates, remove_last=False)
|
||||
except Exception as err:
|
||||
print('Error', err)
|
||||
return None
|
242
city_model_structure/attributes/thermal_boundary.py
Normal file
242
city_model_structure/attributes/thermal_boundary.py
Normal file
|
@ -0,0 +1,242 @@
|
|||
"""
|
||||
ThermalBoundary module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
from typing import List
|
||||
|
||||
from city_model_structure.attributes.layer import Layer
|
||||
from city_model_structure.attributes.thermal_opening import ThermalOpening
|
||||
from city_model_structure.attributes.thermal_zone import ThermalZone
|
||||
from helpers.configuration_helper import ConfigurationHelper
|
||||
|
||||
|
||||
class ThermalBoundary:
|
||||
"""
|
||||
ThermalBoundary class
|
||||
"""
|
||||
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 = ConfigurationHelper().outside_solar_absorptance
|
||||
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 = 1 - self._outside_solar_absorptance
|
||||
|
||||
@property
|
||||
def delimits(self) -> List[ThermalZone]:
|
||||
"""
|
||||
Get the thermal zones delimited by the thermal boundary
|
||||
:return: [ThermalZone]
|
||||
"""
|
||||
return self._delimits
|
||||
|
||||
@property
|
||||
def azimuth(self):
|
||||
"""
|
||||
Thermal boundary azimuth in radians
|
||||
:return: float
|
||||
"""
|
||||
return self._surface.azimuth
|
||||
|
||||
@property
|
||||
def inclination(self):
|
||||
"""
|
||||
Thermal boundary inclination in radians
|
||||
:return: float
|
||||
"""
|
||||
return self._surface.inclination
|
||||
|
||||
@property
|
||||
def area(self):
|
||||
"""
|
||||
Thermal boundary area in square meters
|
||||
:return: float
|
||||
"""
|
||||
return self._surface.area
|
||||
|
||||
@property
|
||||
def area_above_ground(self):
|
||||
"""
|
||||
Thermal boundary area above ground in square meters
|
||||
:return: float
|
||||
"""
|
||||
return self._surface.area_above_ground
|
||||
|
||||
@property
|
||||
def area_below_ground(self):
|
||||
"""
|
||||
Thermal boundary area below ground in square meters
|
||||
:return: float
|
||||
"""
|
||||
return self._surface.area_below_ground
|
||||
|
||||
@property
|
||||
def outside_solar_absorptance(self):
|
||||
"""
|
||||
Get thermal boundary outside solar absorptance
|
||||
:return: 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
|
||||
:return: None
|
||||
"""
|
||||
self._outside_solar_absorptance = value
|
||||
self._shortwave_reflectance = 1.0 - float(value)
|
||||
|
||||
@property
|
||||
def outside_thermal_absorptance(self):
|
||||
"""
|
||||
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
|
||||
:return: None
|
||||
"""
|
||||
self._outside_thermal_absorptance = value
|
||||
|
||||
@property
|
||||
def outside_visible_absorptance(self):
|
||||
"""
|
||||
Get thermal boundary outside visible absorptance
|
||||
:return: 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
|
||||
:return: None
|
||||
"""
|
||||
self._outside_visible_absorptance = value
|
||||
|
||||
@property
|
||||
def thermal_openings(self) -> List[ThermalOpening]:
|
||||
"""
|
||||
Get thermal boundary thermal openings
|
||||
:return: [ThermalOpening]
|
||||
"""
|
||||
return self._thermal_openings
|
||||
|
||||
@thermal_openings.setter
|
||||
def thermal_openings(self, value):
|
||||
"""
|
||||
Set thermal boundary thermal openings
|
||||
:param value: [ThermalOpening]
|
||||
:return: None
|
||||
"""
|
||||
self._thermal_openings = value
|
||||
|
||||
@property
|
||||
def layers(self) -> List[Layer]:
|
||||
"""
|
||||
Get thermal boundary layers
|
||||
:return: [Layers]
|
||||
"""
|
||||
return self._layers
|
||||
|
||||
@layers.setter
|
||||
def layers(self, value):
|
||||
"""
|
||||
Set thermal boundary layers
|
||||
:param value: [Layer]
|
||||
:return: None
|
||||
"""
|
||||
self._layers = value
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
"""
|
||||
Thermal boundary surface type
|
||||
:return: str
|
||||
"""
|
||||
return self._surface.type
|
||||
|
||||
@property
|
||||
def window_ratio(self):
|
||||
"""
|
||||
Get thermal boundary window ratio
|
||||
:return: float
|
||||
"""
|
||||
return self._window_ratio
|
||||
|
||||
@window_ratio.setter
|
||||
def window_ratio(self, value):
|
||||
"""
|
||||
Set thermal boundary window ratio
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._window_ratio = value
|
||||
|
||||
@property
|
||||
def window_area(self):
|
||||
"""
|
||||
Thermal boundary window area in square meters
|
||||
:return: float
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
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:
|
||||
h_i = ConfigurationHelper().h_i
|
||||
h_e = ConfigurationHelper().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)
|
||||
else:
|
||||
r_value = r_value + float(layer.material.conductivity) / float(layer.thickness)
|
||||
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):
|
||||
"""
|
||||
Get thermal boundary shortwave reflectance
|
||||
:return: float
|
||||
"""
|
||||
return self._shortwave_reflectance
|
||||
|
||||
@shortwave_reflectance.setter
|
||||
def shortwave_reflectance(self, value):
|
||||
"""
|
||||
Set thermal boundary shortwave reflectance
|
||||
:param value: float
|
||||
:return:
|
||||
"""
|
||||
self._shortwave_reflectance = value
|
||||
self._outside_solar_absorptance = 1.0 - float(value)
|
171
city_model_structure/attributes/thermal_opening.py
Normal file
171
city_model_structure/attributes/thermal_opening.py
Normal file
|
@ -0,0 +1,171 @@
|
|||
"""
|
||||
ThermalOpening module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
from helpers.configuration_helper import ConfigurationHelper
|
||||
|
||||
|
||||
class ThermalOpening:
|
||||
"""
|
||||
ThermalOpening class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._openable_ratio = None
|
||||
self._conductivity = None
|
||||
self._frame_ratio = ConfigurationHelper().frame_ratio
|
||||
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
|
||||
|
||||
@property
|
||||
def openable_ratio(self):
|
||||
"""
|
||||
Get thermal opening openable ratio, NOT IMPLEMENTED
|
||||
:return: Exception
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@openable_ratio.setter
|
||||
def openable_ratio(self, value):
|
||||
"""
|
||||
Set thermal opening openable ratio, NOT IMPLEMENTED
|
||||
:param value: Any
|
||||
:return: Exception
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def conductivity(self):
|
||||
"""
|
||||
Get thermal opening conductivity in W/mK
|
||||
:return: float
|
||||
"""
|
||||
return self._conductivity
|
||||
|
||||
@conductivity.setter
|
||||
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.
|
||||
# This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read.
|
||||
self._conductivity = value
|
||||
if self._overall_u_value is None and self.thickness is not None:
|
||||
h_i = ConfigurationHelper().h_i
|
||||
h_e = ConfigurationHelper().h_e
|
||||
r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness)
|
||||
self._overall_u_value = 1 / r_value
|
||||
|
||||
@property
|
||||
def frame_ratio(self):
|
||||
"""
|
||||
Get thermal opening frame ratio
|
||||
:return: float
|
||||
"""
|
||||
return self._frame_ratio
|
||||
|
||||
@frame_ratio.setter
|
||||
def frame_ratio(self, value):
|
||||
"""
|
||||
Set thermal opening frame ratio
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._frame_ratio = value
|
||||
|
||||
@property
|
||||
def g_value(self):
|
||||
"""
|
||||
Get thermal opening g value
|
||||
:return: float
|
||||
"""
|
||||
return self._g_value
|
||||
|
||||
@g_value.setter
|
||||
def g_value(self, value):
|
||||
"""
|
||||
Set thermal opening g value
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
self._g_value = value
|
||||
|
||||
@property
|
||||
def thickness(self):
|
||||
"""
|
||||
Get thermal opening thickness in meters
|
||||
:return:
|
||||
"""
|
||||
return self._thickness
|
||||
|
||||
@thickness.setter
|
||||
def thickness(self, value):
|
||||
"""
|
||||
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.
|
||||
self._thickness = value
|
||||
if self._overall_u_value is None and self.conductivity is not None:
|
||||
h_i = ConfigurationHelper().h_i
|
||||
h_e = ConfigurationHelper().h_e
|
||||
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):
|
||||
"""
|
||||
Get thermal opening front side solar transmittance at normal incidence
|
||||
:return: 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
|
||||
:return: None
|
||||
"""
|
||||
self._front_side_solar_transmittance_at_normal_incidence = value
|
||||
|
||||
@property
|
||||
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
|
||||
|
||||
@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
|
||||
:return: None
|
||||
"""
|
||||
self._back_side_solar_transmittance_at_normal_incidence = value
|
||||
|
||||
@property
|
||||
def overall_u_value(self):
|
||||
"""
|
||||
Get thermal opening overall u value in W/m2K
|
||||
:return: float
|
||||
"""
|
||||
return self._overall_u_value
|
||||
|
||||
@overall_u_value.setter
|
||||
def overall_u_value(self, value):
|
||||
"""
|
||||
Get thermal opening overall u value in W/m2K
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._overall_u_value = value
|
187
city_model_structure/attributes/thermal_zone.py
Normal file
187
city_model_structure/attributes/thermal_zone.py
Normal file
|
@ -0,0 +1,187 @@
|
|||
"""
|
||||
ThermalZone module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
from typing import List, TypeVar
|
||||
|
||||
from city_model_structure.attributes.surface import Surface
|
||||
from city_model_structure.attributes.usage_zone import UsageZone
|
||||
from helpers.configuration_helper import ConfigurationHelper
|
||||
|
||||
ThermalBoundary = TypeVar('ThermalBoundary')
|
||||
|
||||
|
||||
class ThermalZone:
|
||||
"""
|
||||
ThermalZone class
|
||||
"""
|
||||
def __init__(self, surfaces):
|
||||
self._surfaces = surfaces
|
||||
self._floor_area = None
|
||||
self._bounded = None
|
||||
self._heated = ConfigurationHelper().heated
|
||||
self._cooled = ConfigurationHelper().cooled
|
||||
self._additional_thermal_bridge_u_value = ConfigurationHelper().additional_thermal_bridge_u_value
|
||||
self._effective_thermal_capacity = None
|
||||
self._indirectly_heated_area_ratio = ConfigurationHelper().indirectly_heated_area_ratio
|
||||
self._infiltration_rate_system_on = ConfigurationHelper().infiltration_rate_system_on
|
||||
self._infiltration_rate_system_off = None
|
||||
self._usage_zones = None
|
||||
|
||||
@property
|
||||
def heated(self):
|
||||
"""
|
||||
Get thermal zone heated flag
|
||||
:return: Boolean
|
||||
"""
|
||||
return self._heated
|
||||
|
||||
@property
|
||||
def cooled(self):
|
||||
"""
|
||||
Get thermal zone cooled flag
|
||||
:return: Boolean
|
||||
"""
|
||||
return self._cooled
|
||||
|
||||
@property
|
||||
def floor_area(self):
|
||||
"""
|
||||
Get thermal zone floor area in square meters
|
||||
:return: float
|
||||
"""
|
||||
if self._floor_area is None:
|
||||
self._floor_area = 0
|
||||
for s in self._surfaces:
|
||||
if s.type == 'Ground':
|
||||
self._floor_area += s.area
|
||||
return self._floor_area
|
||||
|
||||
@property
|
||||
def bounded(self) -> List[ThermalBoundary]:
|
||||
"""
|
||||
Get thermal boundaries bounding with the thermal zone
|
||||
:return: [ThermalBoundary]
|
||||
"""
|
||||
return self._bounded
|
||||
|
||||
@bounded.setter
|
||||
def bounded(self, value):
|
||||
"""
|
||||
Set thermal boundaries bounding with the thermal zone
|
||||
:param value: [ThermalBoundary]
|
||||
:return: None
|
||||
"""
|
||||
self._bounded = value
|
||||
|
||||
@property
|
||||
def surfaces(self) -> List[Surface]:
|
||||
# todo: This property should be erased
|
||||
"""
|
||||
Get thermal zone surfaces
|
||||
:return: [Surface]
|
||||
"""
|
||||
return self._surfaces
|
||||
|
||||
@property
|
||||
def additional_thermal_bridge_u_value(self):
|
||||
"""
|
||||
Get thermal zone additional thermal bridge u value W/m2K
|
||||
:return: float
|
||||
"""
|
||||
return self._additional_thermal_bridge_u_value
|
||||
|
||||
@additional_thermal_bridge_u_value.setter
|
||||
def additional_thermal_bridge_u_value(self, value):
|
||||
"""
|
||||
Set thermal zone additional thermal bridge u value W/m2K
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._additional_thermal_bridge_u_value = value
|
||||
|
||||
@property
|
||||
def effective_thermal_capacity(self):
|
||||
"""
|
||||
Get thermal zone effective thermal capacity
|
||||
:return: float
|
||||
"""
|
||||
return self._effective_thermal_capacity
|
||||
|
||||
@effective_thermal_capacity.setter
|
||||
def effective_thermal_capacity(self, value):
|
||||
"""
|
||||
Set thermal zone effective thermal capacity
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._effective_thermal_capacity = value
|
||||
|
||||
@property
|
||||
def indirectly_heated_area_ratio(self):
|
||||
"""
|
||||
Get thermal zone indirectly heated area ratio
|
||||
:return: float
|
||||
"""
|
||||
return self._indirectly_heated_area_ratio
|
||||
|
||||
@indirectly_heated_area_ratio.setter
|
||||
def indirectly_heated_area_ratio(self, value):
|
||||
"""
|
||||
Set thermal zone indirectly heated area ratio
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._indirectly_heated_area_ratio = value
|
||||
|
||||
@property
|
||||
def infiltration_rate_system_on(self):
|
||||
"""
|
||||
Get thermal zone infiltration rate system on in air changes per hour
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_system_on
|
||||
|
||||
@infiltration_rate_system_on.setter
|
||||
def infiltration_rate_system_on(self, value):
|
||||
"""
|
||||
Set thermal zone infiltration rate system on in air changes per hour
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._infiltration_rate_system_on = value
|
||||
|
||||
@property
|
||||
def infiltration_rate_system_off(self):
|
||||
"""
|
||||
Get thermal zone infiltration rate system off in air changes per hour
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_system_off
|
||||
|
||||
@infiltration_rate_system_off.setter
|
||||
def infiltration_rate_system_off(self, value):
|
||||
"""
|
||||
Set thermal zone infiltration rate system on in air changes per hour
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._infiltration_rate_system_off = value
|
||||
|
||||
@property
|
||||
def usage_zones(self) -> List[UsageZone]:
|
||||
"""
|
||||
Get thermal zone usage zones
|
||||
:return: [UsageZone]
|
||||
"""
|
||||
return self._usage_zones
|
||||
|
||||
@usage_zones.setter
|
||||
def usage_zones(self, values):
|
||||
"""
|
||||
Set thermal zone usage zones
|
||||
:param values: [UsageZone]
|
||||
:return: None
|
||||
"""
|
||||
self._usage_zones = values
|
195
city_model_structure/attributes/usage_zone.py
Normal file
195
city_model_structure/attributes/usage_zone.py
Normal file
|
@ -0,0 +1,195 @@
|
|||
"""
|
||||
UsageZone module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
from typing import List
|
||||
|
||||
from city_model_structure.attributes.internal_gains import InternalGains
|
||||
from helpers.configuration_helper import ConfigurationHelper
|
||||
|
||||
|
||||
class UsageZone:
|
||||
"""
|
||||
UsageZone class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._usage = None
|
||||
self._internal_gains = None
|
||||
self._heating_setpoint = None
|
||||
self._heating_setback = None
|
||||
self._cooling_setpoint = None
|
||||
self._hours_day = None
|
||||
self._days_year = None
|
||||
# todo: this must come from library, talk to Rabeeh
|
||||
self._mechanical_air_change = ConfigurationHelper().min_air_change
|
||||
self._occupancy = None
|
||||
self._schedules = None
|
||||
|
||||
@property
|
||||
def internal_gains(self) -> List[InternalGains]:
|
||||
"""
|
||||
Get usage zone internal gains
|
||||
:return: [InternalGains]
|
||||
"""
|
||||
return self._internal_gains
|
||||
|
||||
@internal_gains.setter
|
||||
def internal_gains(self, value):
|
||||
"""
|
||||
Set usage zone internal gains
|
||||
:param value: [InternalGains]
|
||||
:return: None
|
||||
"""
|
||||
self._internal_gains = value
|
||||
|
||||
@property
|
||||
def heating_setpoint(self):
|
||||
"""
|
||||
Get usage zone heating set point in celsius grads
|
||||
:return: float
|
||||
"""
|
||||
return self._heating_setpoint
|
||||
|
||||
@heating_setpoint.setter
|
||||
def heating_setpoint(self, value):
|
||||
"""
|
||||
Set usage zone heating set point in celsius grads
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._heating_setpoint = value
|
||||
|
||||
@property
|
||||
def heating_setback(self):
|
||||
"""
|
||||
Get usage zone heating setback in celsius grads
|
||||
:return: float
|
||||
"""
|
||||
return self._heating_setback
|
||||
|
||||
@heating_setback.setter
|
||||
def heating_setback(self, value):
|
||||
"""
|
||||
Set usage zone heating setback in celsius grads
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._heating_setback = value
|
||||
|
||||
@property
|
||||
def cooling_setpoint(self):
|
||||
"""
|
||||
Get usage zone cooling setpoint in celsius grads
|
||||
:return: float
|
||||
"""
|
||||
return self._cooling_setpoint
|
||||
|
||||
@cooling_setpoint.setter
|
||||
def cooling_setpoint(self, value):
|
||||
"""
|
||||
Set usage zone cooling setpoint in celsius grads
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._cooling_setpoint = value
|
||||
|
||||
@property
|
||||
def hours_day(self):
|
||||
"""
|
||||
Get usage zone usage hours per day
|
||||
:return: float
|
||||
"""
|
||||
return self._hours_day
|
||||
|
||||
@hours_day.setter
|
||||
def hours_day(self, value):
|
||||
"""
|
||||
Set usage zone usage hours per day
|
||||
:param value: float
|
||||
:return: float
|
||||
"""
|
||||
self._hours_day = value
|
||||
|
||||
@property
|
||||
def days_year(self):
|
||||
"""
|
||||
Get usage zone usage days per year
|
||||
:return: float
|
||||
"""
|
||||
return self._days_year
|
||||
|
||||
@days_year.setter
|
||||
def days_year(self, value):
|
||||
"""
|
||||
Set usage zone usage days per year
|
||||
:param value: float
|
||||
:return: None
|
||||
"""
|
||||
self._days_year = value
|
||||
|
||||
@property
|
||||
def mechanical_air_change(self):
|
||||
"""
|
||||
Set usage zone mechanical air change in air change per hour
|
||||
:return: float
|
||||
"""
|
||||
return self._mechanical_air_change
|
||||
|
||||
@mechanical_air_change.setter
|
||||
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
|
||||
|
||||
@property
|
||||
def usage(self):
|
||||
"""
|
||||
Get usage zone usage
|
||||
:return: str
|
||||
"""
|
||||
return self._usage
|
||||
|
||||
@usage.setter
|
||||
def usage(self, value):
|
||||
"""
|
||||
Get usage zone usage
|
||||
:param value: str
|
||||
:return: None
|
||||
"""
|
||||
self._usage = value
|
||||
|
||||
@property
|
||||
def occupancy(self):
|
||||
"""
|
||||
Get occupancy data
|
||||
:return: [Occupancy]
|
||||
"""
|
||||
return self._occupancy
|
||||
|
||||
@occupancy.setter
|
||||
def occupancy(self, values):
|
||||
"""
|
||||
Set occupancy
|
||||
:param values: [Occupancy]
|
||||
"""
|
||||
self._occupancy = values
|
||||
|
||||
@property
|
||||
def schedules(self):
|
||||
"""
|
||||
Get schedule of Sundays
|
||||
:return: [Sundays Schedule_Values]
|
||||
"""
|
||||
return self._schedules
|
||||
|
||||
@schedules.setter
|
||||
def schedules(self, value):
|
||||
"""
|
||||
occupancy schedules of Sundays
|
||||
:param value: Sunday schedules
|
||||
"""
|
||||
self._schedules = value
|
37
factories/weather/weather_factory.py
Normal file
37
factories/weather/weather_factory.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
WeatherFactory retrieve the specific weather module for the given source format
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
|
||||
"""
|
||||
|
||||
from factories.weather.weather_feeders.cli_weather_parameters import CliWeatherParameters
|
||||
from factories.weather.weather_feeders.dat_weather_parameters import DatWeatherParameters
|
||||
|
||||
|
||||
class WeatherFactory:
|
||||
"""
|
||||
WeatherFactory class
|
||||
"""
|
||||
|
||||
# todo: modify full_path_weather to make it depending on "city"
|
||||
def __init__(self, handler, city, full_path_weather):
|
||||
self._handler = '_' + handler.lower().replace(' ', '_')
|
||||
self._city = city
|
||||
self._full_path_weather = full_path_weather
|
||||
self.factory()
|
||||
|
||||
def _cli(self):
|
||||
CliWeatherParameters(self._full_path_weather)
|
||||
|
||||
def _dat(self):
|
||||
DatWeatherParameters(self._full_path_weather)
|
||||
|
||||
def _tmy(self):
|
||||
raise Exception('Not implemented')
|
||||
|
||||
def factory(self):
|
||||
"""
|
||||
Enrich the city with the usage information
|
||||
:return: None
|
||||
"""
|
||||
getattr(self, self._handler, lambda: None)()
|
13
factories/weather/weather_feeders/cli_weather_parameters.py
Normal file
13
factories/weather/weather_feeders/cli_weather_parameters.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
"""
|
||||
CliWeatherParameters class to extract weather parameters from a defined region in .cli format
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
|
||||
"""
|
||||
|
||||
|
||||
class CliWeatherParameters:
|
||||
"""
|
||||
CliWeatherParameters class
|
||||
"""
|
||||
def __init__(self, full_path_weather):
|
||||
self._full_path_weather = full_path_weather
|
24
factories/weather/weather_feeders/dat_weather_parameters.py
Normal file
24
factories/weather/weather_feeders/dat_weather_parameters.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
"""
|
||||
CliWeatherParameters class to extract weather parameters from a defined region in .dat format
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class DatWeatherParameters:
|
||||
"""
|
||||
DatWeatherParameters class
|
||||
"""
|
||||
def __init__(self, full_path_weather):
|
||||
self._full_path_weather = full_path_weather
|
||||
self._weather_values = None
|
||||
|
||||
def weather_values(self):
|
||||
if self._full_path_weather is not None:
|
||||
# TODO: catch error if file does not exist
|
||||
if self._weather_values is None:
|
||||
self._weather_values = pd.read_csv(self._full_path_weather, sep='\s+', header=None,
|
||||
names=['hour', 'global_horiz', 'temperature', 'diffuse', 'beam', 'empty'])
|
||||
return self._weather_values
|
31
factories/weather/weather_feeders/helpers/weather.py
Normal file
31
factories/weather/weather_feeders/helpers/weather.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
import math
|
||||
import pandas as pd
|
||||
import helpers.constants as cte
|
||||
from helpers import monthly_values as mv
|
||||
|
||||
|
||||
class Weather(object):
|
||||
def __init__(self, weather_values):
|
||||
self._weather_values = pd.concat([mv.MonthlyValues().month_hour, weather_values], axis=1)
|
||||
self._temperatures_hourly = None
|
||||
|
||||
@property
|
||||
def external_and_sky_temperatures(self):
|
||||
if self._temperatures_hourly is None:
|
||||
self._temperatures_hourly = self._weather_values[['month', 'temperature']]
|
||||
sky_temperature = self.sky_temperature(self._temperatures_hourly)
|
||||
self._temperatures_hourly = pd.concat([self._temperatures_hourly, sky_temperature], axis=1)
|
||||
return self._temperatures_hourly
|
||||
|
||||
@staticmethod
|
||||
def sky_temperature(ambient_temperature):
|
||||
# Swinbank - Fuentes sky model approximation(1963) based on cloudiness statistics(32 %) in United States
|
||||
# ambient temperatures( in °C)
|
||||
# sky temperatures( in °C)
|
||||
_ambient_temperature = ambient_temperature[['temperature']].to_numpy()
|
||||
values = []
|
||||
for temperature in _ambient_temperature:
|
||||
value = 0.037536 * math.pow((temperature + cte.celsius_to_kelvin), 1.5) \
|
||||
+ 0.32 * (temperature + cte.celsius_to_kelvin) - cte.celsius_to_kelvin
|
||||
values.append(value)
|
||||
return pd.DataFrame(values, columns=['sky temperature'])
|
Loading…
Reference in New Issue
Block a user