Compare commits
12 Commits
7cf926bc5b
...
ab81edc33d
Author | SHA1 | Date | |
---|---|---|---|
ab81edc33d | |||
04ef636423 | |||
d7e041b686 | |||
90a196465a | |||
83fc351fc7 | |||
1e9afa28a8 | |||
212b4b0621 | |||
fe8c79d7c2 | |||
4b5c037ffa | |||
6b89008698 | |||
a147afe76f | |||
f3208f1735 |
@ -15,6 +15,7 @@ from hub.catalog_factories.data_models.construction.archetype import Archetype
|
|||||||
from hub.catalog_factories.data_models.construction.window import Window
|
from hub.catalog_factories.data_models.construction.window import Window
|
||||||
from hub.catalog_factories.data_models.construction.material import Material
|
from hub.catalog_factories.data_models.construction.material import Material
|
||||||
from hub.catalog_factories.data_models.construction.layer import Layer
|
from hub.catalog_factories.data_models.construction.layer import Layer
|
||||||
|
import hub.helpers.constants as cte
|
||||||
|
|
||||||
|
|
||||||
class EilatCatalog(Catalog):
|
class EilatCatalog(Catalog):
|
||||||
@ -120,8 +121,8 @@ class EilatCatalog(Catalog):
|
|||||||
construction_period = archetype['period_of_construction']
|
construction_period = archetype['period_of_construction']
|
||||||
average_storey_height = archetype['average_storey_height']
|
average_storey_height = archetype['average_storey_height']
|
||||||
extra_loses_due_to_thermal_bridges = archetype['extra_loses_due_thermal_bridges']
|
extra_loses_due_to_thermal_bridges = archetype['extra_loses_due_thermal_bridges']
|
||||||
infiltration_rate_for_ventilation_system_off = archetype['infiltration_rate_for_ventilation_system_off']
|
infiltration_rate_for_ventilation_system_off = archetype['infiltration_rate_for_ventilation_system_off'] / cte.HOUR_TO_SECONDS
|
||||||
infiltration_rate_for_ventilation_system_on = archetype['infiltration_rate_for_ventilation_system_on']
|
infiltration_rate_for_ventilation_system_on = archetype['infiltration_rate_for_ventilation_system_on'] / cte.HOUR_TO_SECONDS
|
||||||
|
|
||||||
archetype_constructions = []
|
archetype_constructions = []
|
||||||
for archetype_construction in archetype['constructions']:
|
for archetype_construction in archetype['constructions']:
|
||||||
|
@ -15,6 +15,7 @@ from hub.catalog_factories.data_models.construction.archetype import Archetype
|
|||||||
from hub.catalog_factories.data_models.construction.window import Window
|
from hub.catalog_factories.data_models.construction.window import Window
|
||||||
from hub.catalog_factories.data_models.construction.material import Material
|
from hub.catalog_factories.data_models.construction.material import Material
|
||||||
from hub.catalog_factories.data_models.construction.layer import Layer
|
from hub.catalog_factories.data_models.construction.layer import Layer
|
||||||
|
import hub.helpers.constants as cte
|
||||||
|
|
||||||
|
|
||||||
class NrcanCatalog(Catalog):
|
class NrcanCatalog(Catalog):
|
||||||
@ -121,8 +122,8 @@ class NrcanCatalog(Catalog):
|
|||||||
average_storey_height = archetype['average_storey_height']
|
average_storey_height = archetype['average_storey_height']
|
||||||
thermal_capacity = float(archetype['thermal_capacity']) * 1000
|
thermal_capacity = float(archetype['thermal_capacity']) * 1000
|
||||||
extra_loses_due_to_thermal_bridges = archetype['extra_loses_due_thermal_bridges']
|
extra_loses_due_to_thermal_bridges = archetype['extra_loses_due_thermal_bridges']
|
||||||
infiltration_rate_for_ventilation_system_off = archetype['infiltration_rate_for_ventilation_system_off']
|
infiltration_rate_for_ventilation_system_off = archetype['infiltration_rate_for_ventilation_system_off'] / cte.HOUR_TO_SECONDS
|
||||||
infiltration_rate_for_ventilation_system_on = archetype['infiltration_rate_for_ventilation_system_on']
|
infiltration_rate_for_ventilation_system_on = archetype['infiltration_rate_for_ventilation_system_on'] / cte.HOUR_TO_SECONDS
|
||||||
|
|
||||||
archetype_constructions = []
|
archetype_constructions = []
|
||||||
for archetype_construction in archetype['constructions']:
|
for archetype_construction in archetype['constructions']:
|
||||||
|
@ -15,6 +15,7 @@ from hub.catalog_factories.data_models.construction.construction import Construc
|
|||||||
from hub.catalog_factories.data_models.construction.content import Content
|
from hub.catalog_factories.data_models.construction.content import Content
|
||||||
from hub.catalog_factories.data_models.construction.archetype import Archetype
|
from hub.catalog_factories.data_models.construction.archetype import Archetype
|
||||||
from hub.catalog_factories.construction.construction_helper import ConstructionHelper
|
from hub.catalog_factories.construction.construction_helper import ConstructionHelper
|
||||||
|
import hub.helpers.constants as cte
|
||||||
|
|
||||||
|
|
||||||
class NrelCatalog(Catalog):
|
class NrelCatalog(Catalog):
|
||||||
@ -124,10 +125,10 @@ class NrelCatalog(Catalog):
|
|||||||
indirect_heated_ratio = float(archetype['indirect_heated_ratio']['#text'])
|
indirect_heated_ratio = float(archetype['indirect_heated_ratio']['#text'])
|
||||||
infiltration_rate_for_ventilation_system_off = float(
|
infiltration_rate_for_ventilation_system_off = float(
|
||||||
archetype['infiltration_rate_for_ventilation_system_off']['#text']
|
archetype['infiltration_rate_for_ventilation_system_off']['#text']
|
||||||
)
|
) / cte.HOUR_TO_SECONDS
|
||||||
infiltration_rate_for_ventilation_system_on = float(
|
infiltration_rate_for_ventilation_system_on = float(
|
||||||
archetype['infiltration_rate_for_ventilation_system_on']['#text']
|
archetype['infiltration_rate_for_ventilation_system_on']['#text']
|
||||||
)
|
) / cte.HOUR_TO_SECONDS
|
||||||
|
|
||||||
archetype_constructions = []
|
archetype_constructions = []
|
||||||
for archetype_construction in archetype['constructions']['construction']:
|
for archetype_construction in archetype['constructions']['construction']:
|
||||||
|
@ -120,7 +120,7 @@ class Archetype:
|
|||||||
@property
|
@property
|
||||||
def infiltration_rate_for_ventilation_system_off(self):
|
def infiltration_rate_for_ventilation_system_off(self):
|
||||||
"""
|
"""
|
||||||
Get archetype infiltration rate for ventilation system off in ACH
|
Get archetype infiltration rate for ventilation system off in 1/s
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
return self._infiltration_rate_for_ventilation_system_off
|
return self._infiltration_rate_for_ventilation_system_off
|
||||||
@ -128,7 +128,7 @@ class Archetype:
|
|||||||
@property
|
@property
|
||||||
def infiltration_rate_for_ventilation_system_on(self):
|
def infiltration_rate_for_ventilation_system_on(self):
|
||||||
"""
|
"""
|
||||||
Get archetype infiltration rate for ventilation system on in ACH
|
Get archetype infiltration rate for ventilation system on in 1/s
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
return self._infiltration_rate_for_ventilation_system_on
|
return self._infiltration_rate_for_ventilation_system_on
|
||||||
@ -147,8 +147,8 @@ class Archetype:
|
|||||||
'thermal capacity [J/m3K]': self.thermal_capacity,
|
'thermal capacity [J/m3K]': self.thermal_capacity,
|
||||||
'extra loses due to thermal bridges [W/m2K]': self.extra_loses_due_to_thermal_bridges,
|
'extra loses due to thermal bridges [W/m2K]': self.extra_loses_due_to_thermal_bridges,
|
||||||
'indirect heated ratio': self.indirect_heated_ratio,
|
'indirect heated ratio': self.indirect_heated_ratio,
|
||||||
'infiltration rate for ventilation off [ACH]': self.infiltration_rate_for_ventilation_system_off,
|
'infiltration rate for ventilation off [1/s]': self.infiltration_rate_for_ventilation_system_off,
|
||||||
'infiltration rate for ventilation on [ACH]': self.infiltration_rate_for_ventilation_system_on,
|
'infiltration rate for ventilation on [1/s]': self.infiltration_rate_for_ventilation_system_on,
|
||||||
'constructions': _constructions
|
'constructions': _constructions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class Income:
|
|||||||
@property
|
@property
|
||||||
def construction_subsidy(self) -> Union[None, float]:
|
def construction_subsidy(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get subsidy for construction in percentage
|
Get subsidy for construction in percentage %
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
return self._construction_subsidy
|
return self._construction_subsidy
|
||||||
@ -35,7 +35,7 @@ class Income:
|
|||||||
@property
|
@property
|
||||||
def hvac_subsidy(self) -> Union[None, float]:
|
def hvac_subsidy(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get subsidy for HVAC system in percentage
|
Get subsidy for HVAC system in percentage %
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
return self._hvac_subsidy
|
return self._hvac_subsidy
|
||||||
|
@ -24,7 +24,7 @@ class Appliances:
|
|||||||
@property
|
@property
|
||||||
def density(self) -> Union[None, float]:
|
def density(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get appliances density in Watts per m2
|
Get appliances density in W/m2
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
return self._density
|
return self._density
|
||||||
|
@ -65,7 +65,7 @@ class Usage:
|
|||||||
@property
|
@property
|
||||||
def mechanical_air_change(self) -> Union[None, float]:
|
def mechanical_air_change(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get usage zone mechanical air change in air change per hour (ACH)
|
Get usage zone mechanical air change in air change per second (1/s)
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
return self._mechanical_air_change
|
return self._mechanical_air_change
|
||||||
|
@ -134,8 +134,8 @@ class NrcanCatalog(Catalog):
|
|||||||
hvac_availability = self._get_schedules(hvac_schedule_name)
|
hvac_availability = self._get_schedules(hvac_schedule_name)
|
||||||
domestic_hot_water_load_schedule = self._get_schedules(domestic_hot_water_schedule_name)
|
domestic_hot_water_load_schedule = self._get_schedules(domestic_hot_water_schedule_name)
|
||||||
|
|
||||||
# ACH
|
# ACH -> 1/s
|
||||||
mechanical_air_change = space_type['ventilation_air_changes']
|
mechanical_air_change = space_type['ventilation_air_changes'] / cte.HOUR_TO_SECONDS
|
||||||
# cfm/ft2 to m3/m2.s
|
# cfm/ft2 to m3/m2.s
|
||||||
ventilation_rate = space_type['ventilation_per_area'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
|
ventilation_rate = space_type['ventilation_per_area'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
|
||||||
# cfm/person to m3/m2.s
|
# cfm/person to m3/m2.s
|
||||||
|
@ -41,7 +41,7 @@ class Building(CityObject):
|
|||||||
self._floor_area = None
|
self._floor_area = None
|
||||||
self._roof_type = None
|
self._roof_type = None
|
||||||
self._internal_zones = None
|
self._internal_zones = None
|
||||||
self._thermal_zones = None
|
self._thermal_zones_from_internal_zones = None
|
||||||
self._shell = None
|
self._shell = None
|
||||||
self._aliases = []
|
self._aliases = []
|
||||||
self._type = 'building'
|
self._type = 'building'
|
||||||
@ -114,26 +114,24 @@ class Building(CityObject):
|
|||||||
:return: [InternalZone]
|
:return: [InternalZone]
|
||||||
"""
|
"""
|
||||||
if self._internal_zones is None:
|
if self._internal_zones is None:
|
||||||
self._internal_zones = [InternalZone(self.surfaces, self.floor_area)]
|
_number_of_storeys = self.eave_height * self.volume / self.floor_area
|
||||||
|
self._internal_zones = [InternalZone(self.surfaces, self.floor_area, self.volume, _number_of_storeys)]
|
||||||
return self._internal_zones
|
return self._internal_zones
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thermal_zones(self) -> Union[None, List[ThermalZone]]:
|
def thermal_zones_from_internal_zones(self) -> Union[None, List[ThermalZone]]:
|
||||||
"""
|
"""
|
||||||
Get building thermal zones
|
Get building thermal zones
|
||||||
For Lod up to 3, there can be more than one thermal zone per internal zone.
|
|
||||||
In LoD 4, there can be more than one internal zone, and therefore, only one thermal zone per internal zone
|
|
||||||
:return: [ThermalZone]
|
:return: [ThermalZone]
|
||||||
"""
|
"""
|
||||||
if self._thermal_zones is None:
|
if self._thermal_zones_from_internal_zones is None:
|
||||||
self._thermal_zones = []
|
self._thermal_zones_from_internal_zones = []
|
||||||
for internal_zone in self.internal_zones:
|
for internal_zone in self.internal_zones:
|
||||||
if internal_zone.thermal_zones is None:
|
if internal_zone.thermal_zones_from_internal_zones is None:
|
||||||
self._thermal_zones = None
|
self._thermal_zones_from_internal_zones = None
|
||||||
return self._thermal_zones
|
return self._thermal_zones_from_internal_zones
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
self._thermal_zones_from_internal_zones.append(internal_zone.thermal_zones_from_internal_zones[0])
|
||||||
self._thermal_zones.append(thermal_zone)
|
return self._thermal_zones_from_internal_zones
|
||||||
return self._thermal_zones
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def grounds(self) -> List[Surface]:
|
def grounds(self) -> List[Surface]:
|
||||||
@ -261,6 +259,15 @@ class Building(CityObject):
|
|||||||
Get building average storey height in meters
|
Get building average storey height in meters
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
|
if len(self.internal_zones) > 1:
|
||||||
|
self._average_storey_height = 0
|
||||||
|
for internal_zone in self.internal_zones:
|
||||||
|
self._average_storey_height += internal_zone.mean_height / len(self.internal_zones)
|
||||||
|
else:
|
||||||
|
if self.internal_zones[0].thermal_archetype is None:
|
||||||
|
self._average_storey_height = None
|
||||||
|
else:
|
||||||
|
self._average_storey_height = self.internal_zones[0].thermal_archetype.average_storey_height
|
||||||
return self._average_storey_height
|
return self._average_storey_height
|
||||||
|
|
||||||
@average_storey_height.setter
|
@average_storey_height.setter
|
||||||
@ -311,7 +318,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def heating_demand(self) -> dict:
|
def heating_demand(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get heating demand in Wh
|
Get heating demand in J
|
||||||
:return: dict{[float]}
|
:return: dict{[float]}
|
||||||
"""
|
"""
|
||||||
return self._heating_demand
|
return self._heating_demand
|
||||||
@ -319,7 +326,7 @@ class Building(CityObject):
|
|||||||
@heating_demand.setter
|
@heating_demand.setter
|
||||||
def heating_demand(self, value):
|
def heating_demand(self, value):
|
||||||
"""
|
"""
|
||||||
Set heating demand in Wh
|
Set heating demand in J
|
||||||
:param value: dict{[float]}
|
:param value: dict{[float]}
|
||||||
"""
|
"""
|
||||||
self._heating_demand = value
|
self._heating_demand = value
|
||||||
@ -327,7 +334,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def cooling_demand(self) -> dict:
|
def cooling_demand(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get cooling demand in Wh
|
Get cooling demand in J
|
||||||
:return: dict{[float]}
|
:return: dict{[float]}
|
||||||
"""
|
"""
|
||||||
return self._cooling_demand
|
return self._cooling_demand
|
||||||
@ -335,7 +342,7 @@ class Building(CityObject):
|
|||||||
@cooling_demand.setter
|
@cooling_demand.setter
|
||||||
def cooling_demand(self, value):
|
def cooling_demand(self, value):
|
||||||
"""
|
"""
|
||||||
Set cooling demand in Wh
|
Set cooling demand in J
|
||||||
:param value: dict{[float]}
|
:param value: dict{[float]}
|
||||||
"""
|
"""
|
||||||
self._cooling_demand = value
|
self._cooling_demand = value
|
||||||
@ -343,7 +350,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def lighting_electrical_demand(self) -> dict:
|
def lighting_electrical_demand(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get lighting electrical demand in Wh
|
Get lighting electrical demand in J
|
||||||
:return: dict{[float]}
|
:return: dict{[float]}
|
||||||
"""
|
"""
|
||||||
return self._lighting_electrical_demand
|
return self._lighting_electrical_demand
|
||||||
@ -351,7 +358,7 @@ class Building(CityObject):
|
|||||||
@lighting_electrical_demand.setter
|
@lighting_electrical_demand.setter
|
||||||
def lighting_electrical_demand(self, value):
|
def lighting_electrical_demand(self, value):
|
||||||
"""
|
"""
|
||||||
Set lighting electrical demand in Wh
|
Set lighting electrical demand in J
|
||||||
:param value: dict{[float]}
|
:param value: dict{[float]}
|
||||||
"""
|
"""
|
||||||
self._lighting_electrical_demand = value
|
self._lighting_electrical_demand = value
|
||||||
@ -359,7 +366,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def appliances_electrical_demand(self) -> dict:
|
def appliances_electrical_demand(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get appliances electrical demand in Wh
|
Get appliances electrical demand in J
|
||||||
:return: dict{[float]}
|
:return: dict{[float]}
|
||||||
"""
|
"""
|
||||||
return self._appliances_electrical_demand
|
return self._appliances_electrical_demand
|
||||||
@ -367,7 +374,7 @@ class Building(CityObject):
|
|||||||
@appliances_electrical_demand.setter
|
@appliances_electrical_demand.setter
|
||||||
def appliances_electrical_demand(self, value):
|
def appliances_electrical_demand(self, value):
|
||||||
"""
|
"""
|
||||||
Set appliances electrical demand in Wh
|
Set appliances electrical demand in J
|
||||||
:param value: dict{[float]}
|
:param value: dict{[float]}
|
||||||
"""
|
"""
|
||||||
self._appliances_electrical_demand = value
|
self._appliances_electrical_demand = value
|
||||||
@ -375,7 +382,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def domestic_hot_water_heat_demand(self) -> dict:
|
def domestic_hot_water_heat_demand(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get domestic hot water heat demand in Wh
|
Get domestic hot water heat demand in J
|
||||||
:return: dict{[float]}
|
:return: dict{[float]}
|
||||||
"""
|
"""
|
||||||
return self._domestic_hot_water_heat_demand
|
return self._domestic_hot_water_heat_demand
|
||||||
@ -383,7 +390,7 @@ class Building(CityObject):
|
|||||||
@domestic_hot_water_heat_demand.setter
|
@domestic_hot_water_heat_demand.setter
|
||||||
def domestic_hot_water_heat_demand(self, value):
|
def domestic_hot_water_heat_demand(self, value):
|
||||||
"""
|
"""
|
||||||
Set domestic hot water heat demand in Wh
|
Set domestic hot water heat demand in J
|
||||||
:param value: dict{[float]}
|
:param value: dict{[float]}
|
||||||
"""
|
"""
|
||||||
self._domestic_hot_water_heat_demand = value
|
self._domestic_hot_water_heat_demand = value
|
||||||
@ -396,7 +403,8 @@ class Building(CityObject):
|
|||||||
"""
|
"""
|
||||||
results = {}
|
results = {}
|
||||||
peak_lighting = 0
|
peak_lighting = 0
|
||||||
for thermal_zone in self.thermal_zones:
|
peak = 0
|
||||||
|
for thermal_zone in self.thermal_zones_from_internal_zones:
|
||||||
lighting = thermal_zone.lighting
|
lighting = thermal_zone.lighting
|
||||||
for schedule in lighting.schedules:
|
for schedule in lighting.schedules:
|
||||||
peak = max(schedule.values) * lighting.density * thermal_zone.total_floor_area
|
peak = max(schedule.values) * lighting.density * thermal_zone.total_floor_area
|
||||||
@ -414,7 +422,8 @@ class Building(CityObject):
|
|||||||
"""
|
"""
|
||||||
results = {}
|
results = {}
|
||||||
peak_appliances = 0
|
peak_appliances = 0
|
||||||
for thermal_zone in self.thermal_zones:
|
peak = 0
|
||||||
|
for thermal_zone in self.thermal_zones_from_internal_zones:
|
||||||
appliances = thermal_zone.appliances
|
appliances = thermal_zone.appliances
|
||||||
for schedule in appliances.schedules:
|
for schedule in appliances.schedules:
|
||||||
peak = max(schedule.values) * appliances.density * thermal_zone.total_floor_area
|
peak = max(schedule.values) * appliances.density * thermal_zone.total_floor_area
|
||||||
@ -438,7 +447,8 @@ class Building(CityObject):
|
|||||||
monthly_values = PeakLoads(self).heating_peak_loads_from_methodology
|
monthly_values = PeakLoads(self).heating_peak_loads_from_methodology
|
||||||
if monthly_values is None:
|
if monthly_values is None:
|
||||||
return None
|
return None
|
||||||
results[cte.MONTH] = monthly_values
|
# todo: @Pilar!!!!
|
||||||
|
results[cte.MONTH] = monthly_values * cte.WATTS_HOUR_TO_JULES
|
||||||
results[cte.YEAR] = [max(monthly_values)]
|
results[cte.YEAR] = [max(monthly_values)]
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@ -455,7 +465,8 @@ class Building(CityObject):
|
|||||||
monthly_values = PeakLoads(self).cooling_peak_loads_from_methodology
|
monthly_values = PeakLoads(self).cooling_peak_loads_from_methodology
|
||||||
if monthly_values is None:
|
if monthly_values is None:
|
||||||
return None
|
return None
|
||||||
results[cte.MONTH] = monthly_values
|
# todo: @Pilar!!!!
|
||||||
|
results[cte.MONTH] = monthly_values * cte.WATTS_HOUR_TO_JULES
|
||||||
results[cte.YEAR] = [max(monthly_values)]
|
results[cte.YEAR] = [max(monthly_values)]
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@ -609,7 +620,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def heating_consumption(self):
|
def heating_consumption(self):
|
||||||
"""
|
"""
|
||||||
Get energy consumption for heating according to the heating system installed in Wh
|
Get energy consumption for heating according to the heating system installed in J
|
||||||
return: dict
|
return: dict
|
||||||
"""
|
"""
|
||||||
if len(self._heating_consumption) == 0:
|
if len(self._heating_consumption) == 0:
|
||||||
@ -625,7 +636,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def cooling_consumption(self):
|
def cooling_consumption(self):
|
||||||
"""
|
"""
|
||||||
Get energy consumption for cooling according to the cooling system installed in Wh
|
Get energy consumption for cooling according to the cooling system installed in J
|
||||||
return: dict
|
return: dict
|
||||||
"""
|
"""
|
||||||
if len(self._cooling_consumption) == 0:
|
if len(self._cooling_consumption) == 0:
|
||||||
@ -641,7 +652,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def domestic_hot_water_consumption(self):
|
def domestic_hot_water_consumption(self):
|
||||||
"""
|
"""
|
||||||
Get energy consumption for domestic according to the domestic hot water system installed in Wh
|
Get energy consumption for domestic according to the domestic hot water system installed in J
|
||||||
return: dict
|
return: dict
|
||||||
"""
|
"""
|
||||||
if len(self._domestic_hot_water_consumption) == 0:
|
if len(self._domestic_hot_water_consumption) == 0:
|
||||||
@ -657,7 +668,7 @@ class Building(CityObject):
|
|||||||
def _calculate_working_hours(self):
|
def _calculate_working_hours(self):
|
||||||
_working_hours = {}
|
_working_hours = {}
|
||||||
for internal_zone in self.internal_zones:
|
for internal_zone in self.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
_working_hours_per_thermal_zone = {}
|
_working_hours_per_thermal_zone = {}
|
||||||
for schedule in thermal_zone.thermal_control.hvac_availability_schedules:
|
for schedule in thermal_zone.thermal_control.hvac_availability_schedules:
|
||||||
_working_hours_per_schedule = [0] * len(schedule.values)
|
_working_hours_per_schedule = [0] * len(schedule.values)
|
||||||
@ -683,7 +694,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def distribution_systems_electrical_consumption(self):
|
def distribution_systems_electrical_consumption(self):
|
||||||
"""
|
"""
|
||||||
Get total electricity consumption for distribution and emission systems in Wh
|
Get total electricity consumption for distribution and emission systems in J
|
||||||
return: dict
|
return: dict
|
||||||
"""
|
"""
|
||||||
if len(self._distribution_systems_electrical_consumption) != 0:
|
if len(self._distribution_systems_electrical_consumption) != 0:
|
||||||
@ -758,7 +769,7 @@ class Building(CityObject):
|
|||||||
@property
|
@property
|
||||||
def onsite_electrical_production(self):
|
def onsite_electrical_production(self):
|
||||||
"""
|
"""
|
||||||
Get total electricity produced onsite in Wh
|
Get total electricity produced onsite in J
|
||||||
return: dict
|
return: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
134
hub/city_model_structure/building_demand/construction.py
Normal file
134
hub/city_model_structure/building_demand/construction.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
"""
|
||||||
|
Construction thermal parameters
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2023 Concordia CERC group
|
||||||
|
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
from hub.city_model_structure.building_demand.layer import Layer
|
||||||
|
|
||||||
|
|
||||||
|
class Construction:
|
||||||
|
"""
|
||||||
|
Construction class
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._type = None
|
||||||
|
self._layers = None
|
||||||
|
self._window_ratio = None
|
||||||
|
self._window_frame_ratio = None
|
||||||
|
self._window_g_value = None
|
||||||
|
self._window_overall_u_value = None
|
||||||
|
self._window_type = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
"""
|
||||||
|
Get construction type
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
@type.setter
|
||||||
|
def type(self, value):
|
||||||
|
"""
|
||||||
|
Set construction type
|
||||||
|
:param value: str
|
||||||
|
"""
|
||||||
|
self._type = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def layers(self) -> [Layer]:
|
||||||
|
"""
|
||||||
|
Get layers
|
||||||
|
:return: [layer]
|
||||||
|
"""
|
||||||
|
return self._layers
|
||||||
|
|
||||||
|
@layers.setter
|
||||||
|
def layers(self, value):
|
||||||
|
"""
|
||||||
|
Set layers
|
||||||
|
:param value: [layer]
|
||||||
|
"""
|
||||||
|
self._layers = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def window_ratio(self):
|
||||||
|
"""
|
||||||
|
Get window ratio
|
||||||
|
:return: dict
|
||||||
|
"""
|
||||||
|
return self._window_ratio
|
||||||
|
|
||||||
|
@window_ratio.setter
|
||||||
|
def window_ratio(self, value):
|
||||||
|
"""
|
||||||
|
Set window ratio
|
||||||
|
:param value: dict
|
||||||
|
"""
|
||||||
|
self._window_ratio = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def window_frame_ratio(self):
|
||||||
|
"""
|
||||||
|
Get window frame ratio
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._window_frame_ratio
|
||||||
|
|
||||||
|
@window_frame_ratio.setter
|
||||||
|
def window_frame_ratio(self, value):
|
||||||
|
"""
|
||||||
|
Set window frame ratio
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._window_frame_ratio = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def window_g_value(self):
|
||||||
|
"""
|
||||||
|
Get transparent surface g-value
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._window_g_value
|
||||||
|
|
||||||
|
@window_g_value.setter
|
||||||
|
def window_g_value(self, value):
|
||||||
|
"""
|
||||||
|
Set transparent surface g-value
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._window_g_value = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def window_overall_u_value(self):
|
||||||
|
"""
|
||||||
|
Get transparent surface overall U-value in W/m2K
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._window_overall_u_value
|
||||||
|
|
||||||
|
@window_overall_u_value.setter
|
||||||
|
def window_overall_u_value(self, value):
|
||||||
|
"""
|
||||||
|
Set transparent surface overall U-value in W/m2K
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._window_overall_u_value = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def window_type(self):
|
||||||
|
"""
|
||||||
|
Get transparent surface type, 'window' or 'skylight'
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
|
return self._window_type
|
||||||
|
|
||||||
|
@window_type.setter
|
||||||
|
def window_type(self, value):
|
||||||
|
"""
|
||||||
|
Set transparent surface type, 'window' or 'skylight'
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
|
self._window_type = value
|
@ -8,24 +8,26 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|||||||
import uuid
|
import uuid
|
||||||
from typing import Union, List
|
from typing import Union, List
|
||||||
from hub.city_model_structure.building_demand.usage import Usage
|
from hub.city_model_structure.building_demand.usage import Usage
|
||||||
|
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
|
||||||
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
|
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
|
||||||
|
from hub.city_model_structure.building_demand.thermal_boundary import ThermalBoundary
|
||||||
from hub.city_model_structure.attributes.polyhedron import Polyhedron
|
from hub.city_model_structure.attributes.polyhedron import Polyhedron
|
||||||
from hub.city_model_structure.energy_systems.hvac_system import HvacSystem
|
|
||||||
|
|
||||||
|
|
||||||
class InternalZone:
|
class InternalZone:
|
||||||
"""
|
"""
|
||||||
InternalZone class
|
InternalZone class
|
||||||
"""
|
"""
|
||||||
def __init__(self, surfaces, area):
|
def __init__(self, surfaces, area, volume, number_of_storeys=None):
|
||||||
self._surfaces = surfaces
|
self._surfaces = surfaces
|
||||||
self._id = None
|
self._id = None
|
||||||
self._geometry = None
|
self._geometry = None
|
||||||
self._volume = None
|
self._volume = volume
|
||||||
self._area = area
|
self._area = area
|
||||||
self._thermal_zones = None
|
self._number_of_storeys = number_of_storeys
|
||||||
|
self._thermal_zones_from_internal_zones = None
|
||||||
self._usages = None
|
self._usages = None
|
||||||
self._hvac_system = None
|
self._thermal_archetype = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
@ -64,7 +66,7 @@ class InternalZone:
|
|||||||
Get internal zone volume in cubic meters
|
Get internal zone volume in cubic meters
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
return self.geometry.volume
|
return self._volume
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def area(self):
|
def area(self):
|
||||||
@ -74,10 +76,18 @@ class InternalZone:
|
|||||||
"""
|
"""
|
||||||
return self._area
|
return self._area
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mean_height(self):
|
||||||
|
"""
|
||||||
|
Get internal zone mean height in meters
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self.volume / self.area
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def usages(self) -> [Usage]:
|
def usages(self) -> [Usage]:
|
||||||
"""
|
"""
|
||||||
Get internal zone usage zones
|
Get usage archetypes
|
||||||
:return: [Usage]
|
:return: [Usage]
|
||||||
"""
|
"""
|
||||||
return self._usages
|
return self._usages
|
||||||
@ -85,39 +95,53 @@ class InternalZone:
|
|||||||
@usages.setter
|
@usages.setter
|
||||||
def usages(self, value):
|
def usages(self, value):
|
||||||
"""
|
"""
|
||||||
Set internal zone usage zones
|
Set usage archetypes
|
||||||
:param value: [Usage]
|
:param value: [Usage]
|
||||||
"""
|
"""
|
||||||
self._usages = value
|
self._usages = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_system(self) -> Union[None, HvacSystem]:
|
def thermal_archetype(self) -> ThermalArchetype:
|
||||||
"""
|
"""
|
||||||
Get HVAC system installed for this thermal zone
|
Get thermal archetype parameters
|
||||||
:return: None or HvacSystem
|
:return: ThermalArchetype
|
||||||
"""
|
"""
|
||||||
return self._hvac_system
|
return self._thermal_archetype
|
||||||
|
|
||||||
@hvac_system.setter
|
@thermal_archetype.setter
|
||||||
def hvac_system(self, value):
|
def thermal_archetype(self, value):
|
||||||
"""
|
"""
|
||||||
Set HVAC system installed for this thermal zone
|
Set thermal archetype parameters
|
||||||
:param value: HvacSystem
|
:param value: ThermalArchetype
|
||||||
"""
|
"""
|
||||||
self._hvac_system = value
|
self._thermal_archetype = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thermal_zones(self) -> Union[None, List[ThermalZone]]:
|
def thermal_zones_from_internal_zones(self) -> Union[None, List[ThermalZone]]:
|
||||||
"""
|
"""
|
||||||
Get building thermal zones
|
Get building thermal zones as one per internal zone
|
||||||
:return: [ThermalZone]
|
:return: [ThermalZone]
|
||||||
"""
|
"""
|
||||||
return self._thermal_zones
|
_thermal_boundaries = []
|
||||||
|
for surface in self.surfaces:
|
||||||
|
if surface.holes_polygons is None:
|
||||||
|
windows_areas = None
|
||||||
|
else:
|
||||||
|
windows_areas = []
|
||||||
|
for hole in surface.holes_polygons:
|
||||||
|
windows_areas.append(hole.area)
|
||||||
|
_thermal_boundary = ThermalBoundary(surface, surface.solid_polygon.area, windows_areas)
|
||||||
|
_thermal_boundaries.append(_thermal_boundary)
|
||||||
|
_thermal_zone = ThermalZone(_thermal_boundaries, self, self.volume, self.area, self._number_of_storeys)
|
||||||
|
for thermal_boundary in _thermal_zone.thermal_boundaries:
|
||||||
|
thermal_boundary.thermal_zones = [_thermal_zone]
|
||||||
|
self._thermal_zones_from_internal_zones = [_thermal_zone]
|
||||||
|
return self._thermal_zones_from_internal_zones
|
||||||
|
|
||||||
@thermal_zones.setter
|
@thermal_zones_from_internal_zones.setter
|
||||||
def thermal_zones(self, value):
|
def thermal_zones_from_internal_zones(self, value):
|
||||||
"""
|
"""
|
||||||
Set city object thermal zones
|
Set city object thermal zones as one per internal zone
|
||||||
:param value: [ThermalZone]
|
:param value: [ThermalZone]
|
||||||
"""
|
"""
|
||||||
self._thermal_zones = value
|
self._thermal_zones_from_internal_zones = value
|
||||||
|
@ -4,9 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from hub.city_model_structure.building_demand.material import Material
|
|
||||||
|
|
||||||
|
|
||||||
class Layer:
|
class Layer:
|
||||||
@ -14,9 +14,17 @@ class Layer:
|
|||||||
Layer class
|
Layer class
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._material = None
|
|
||||||
self._thickness = None
|
self._thickness = None
|
||||||
self._id = None
|
self._id = None
|
||||||
|
self._name = None
|
||||||
|
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
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
@ -28,22 +36,6 @@ class Layer:
|
|||||||
self._id = uuid.uuid4()
|
self._id = uuid.uuid4()
|
||||||
return self._id
|
return self._id
|
||||||
|
|
||||||
@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
|
|
||||||
"""
|
|
||||||
self._material = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thickness(self) -> Union[None, float]:
|
def thickness(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
@ -60,3 +52,155 @@ class Layer:
|
|||||||
"""
|
"""
|
||||||
if value is not None:
|
if value is not None:
|
||||||
self._thickness = float(value)
|
self._thickness = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""
|
||||||
|
Get material name
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, value):
|
||||||
|
"""
|
||||||
|
Set material name
|
||||||
|
:param value: string
|
||||||
|
"""
|
||||||
|
self._name = str(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def conductivity(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get material conductivity in W/mK
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._conductivity
|
||||||
|
|
||||||
|
@conductivity.setter
|
||||||
|
def conductivity(self, value):
|
||||||
|
"""
|
||||||
|
Set material conductivity in W/mK
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._conductivity = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def specific_heat(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get material conductivity in J/kgK
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._specific_heat
|
||||||
|
|
||||||
|
@specific_heat.setter
|
||||||
|
def specific_heat(self, value):
|
||||||
|
"""
|
||||||
|
Get material conductivity in J/kgK
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._specific_heat = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def density(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get material density in kg/m3
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._density
|
||||||
|
|
||||||
|
@density.setter
|
||||||
|
def density(self, value):
|
||||||
|
"""
|
||||||
|
Set material density
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._density = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def solar_absorptance(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get material solar absorptance
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._solar_absorptance
|
||||||
|
|
||||||
|
@solar_absorptance.setter
|
||||||
|
def solar_absorptance(self, value):
|
||||||
|
"""
|
||||||
|
Set material solar absorptance
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._solar_absorptance = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def thermal_absorptance(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get material thermal absorptance
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._thermal_absorptance
|
||||||
|
|
||||||
|
@thermal_absorptance.setter
|
||||||
|
def thermal_absorptance(self, value):
|
||||||
|
"""
|
||||||
|
Set material thermal absorptance
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._thermal_absorptance = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def visible_absorptance(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get material visible absorptance
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._visible_absorptance
|
||||||
|
|
||||||
|
@visible_absorptance.setter
|
||||||
|
def visible_absorptance(self, value):
|
||||||
|
"""
|
||||||
|
Set material visible absorptance
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._visible_absorptance = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def no_mass(self) -> Union[None, bool]:
|
||||||
|
"""
|
||||||
|
Get material no mass flag
|
||||||
|
:return: None or Boolean
|
||||||
|
"""
|
||||||
|
return self._no_mass
|
||||||
|
|
||||||
|
@no_mass.setter
|
||||||
|
def no_mass(self, value):
|
||||||
|
"""
|
||||||
|
Set material no mass flag
|
||||||
|
:param value: Boolean
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._no_mass = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def thermal_resistance(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get material thermal resistance in m2K/W
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._thermal_resistance
|
||||||
|
|
||||||
|
@thermal_resistance.setter
|
||||||
|
def thermal_resistance(self, value):
|
||||||
|
"""
|
||||||
|
Set material thermal resistance in m2K/W
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
self._thermal_resistance = float(value)
|
||||||
|
@ -1,193 +0,0 @@
|
|||||||
"""
|
|
||||||
Material module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
|
|
||||||
class Material:
|
|
||||||
"""
|
|
||||||
Material class
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
self._id = None
|
|
||||||
self._name = None
|
|
||||||
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 id(self):
|
|
||||||
"""
|
|
||||||
Get material id
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._id
|
|
||||||
|
|
||||||
@id.setter
|
|
||||||
def id(self, value):
|
|
||||||
"""
|
|
||||||
Set material id
|
|
||||||
:param value: str
|
|
||||||
"""
|
|
||||||
self._id = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""
|
|
||||||
Get material name
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@name.setter
|
|
||||||
def name(self, value):
|
|
||||||
"""
|
|
||||||
Set material name
|
|
||||||
:param value: string
|
|
||||||
"""
|
|
||||||
self._name = str(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def conductivity(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get material conductivity in W/mK
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._conductivity
|
|
||||||
|
|
||||||
@conductivity.setter
|
|
||||||
def conductivity(self, value):
|
|
||||||
"""
|
|
||||||
Set material conductivity in W/mK
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._conductivity = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def specific_heat(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get material conductivity in J/kgK
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._specific_heat
|
|
||||||
|
|
||||||
@specific_heat.setter
|
|
||||||
def specific_heat(self, value):
|
|
||||||
"""
|
|
||||||
Get material conductivity in J/kgK
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._specific_heat = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def density(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get material density in kg/m3
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._density
|
|
||||||
|
|
||||||
@density.setter
|
|
||||||
def density(self, value):
|
|
||||||
"""
|
|
||||||
Set material density
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._density = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def solar_absorptance(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get material solar absorptance
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._solar_absorptance
|
|
||||||
|
|
||||||
@solar_absorptance.setter
|
|
||||||
def solar_absorptance(self, value):
|
|
||||||
"""
|
|
||||||
Set material solar absorptance
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._solar_absorptance = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def thermal_absorptance(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get material thermal absorptance
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._thermal_absorptance
|
|
||||||
|
|
||||||
@thermal_absorptance.setter
|
|
||||||
def thermal_absorptance(self, value):
|
|
||||||
"""
|
|
||||||
Set material thermal absorptance
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._thermal_absorptance = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def visible_absorptance(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get material visible absorptance
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._visible_absorptance
|
|
||||||
|
|
||||||
@visible_absorptance.setter
|
|
||||||
def visible_absorptance(self, value):
|
|
||||||
"""
|
|
||||||
Set material visible absorptance
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._visible_absorptance = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def no_mass(self) -> Union[None, bool]:
|
|
||||||
"""
|
|
||||||
Get material no mass flag
|
|
||||||
:return: None or Boolean
|
|
||||||
"""
|
|
||||||
return self._no_mass
|
|
||||||
|
|
||||||
@no_mass.setter
|
|
||||||
def no_mass(self, value):
|
|
||||||
"""
|
|
||||||
Set material no mass flag
|
|
||||||
:param value: Boolean
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._no_mass = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def thermal_resistance(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get material thermal resistance in m2K/W
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._thermal_resistance
|
|
||||||
|
|
||||||
@thermal_resistance.setter
|
|
||||||
def thermal_resistance(self, value):
|
|
||||||
"""
|
|
||||||
Set material thermal resistance in m2K/W
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._thermal_resistance = float(value)
|
|
@ -178,7 +178,7 @@ class Surface:
|
|||||||
@property
|
@property
|
||||||
def global_irradiance(self) -> dict:
|
def global_irradiance(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get global irradiance on surface in Wh/m2
|
Get global irradiance on surface in J/m2
|
||||||
:return: dict
|
:return: dict
|
||||||
"""
|
"""
|
||||||
return self._global_irradiance
|
return self._global_irradiance
|
||||||
@ -186,7 +186,7 @@ class Surface:
|
|||||||
@global_irradiance.setter
|
@global_irradiance.setter
|
||||||
def global_irradiance(self, value):
|
def global_irradiance(self, value):
|
||||||
"""
|
"""
|
||||||
Set global irradiance on surface in Wh/m2
|
Set global irradiance on surface in J/m2
|
||||||
:param value: dict
|
:param value: dict
|
||||||
"""
|
"""
|
||||||
self._global_irradiance = value
|
self._global_irradiance = value
|
||||||
|
134
hub/city_model_structure/building_demand/thermal_archetype.py
Normal file
134
hub/city_model_structure/building_demand/thermal_archetype.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
"""
|
||||||
|
Thermal archetype module
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2022 Concordia CERC group
|
||||||
|
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
from hub.city_model_structure.building_demand.construction import Construction
|
||||||
|
|
||||||
|
|
||||||
|
class ThermalArchetype:
|
||||||
|
"""
|
||||||
|
ThermalArchetype class
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._constructions = None
|
||||||
|
self._average_storey_height = None
|
||||||
|
self._thermal_capacity = None
|
||||||
|
self._extra_loses_due_to_thermal_bridges = None
|
||||||
|
self._indirect_heated_ratio = None
|
||||||
|
self._infiltration_rate_for_ventilation_system_off = None
|
||||||
|
self._infiltration_rate_for_ventilation_system_on = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def constructions(self) -> [Construction]:
|
||||||
|
"""
|
||||||
|
Get archetype constructions
|
||||||
|
:return: [Construction]
|
||||||
|
"""
|
||||||
|
return self._constructions
|
||||||
|
|
||||||
|
@constructions.setter
|
||||||
|
def constructions(self, value):
|
||||||
|
"""
|
||||||
|
Set archetype constructions
|
||||||
|
:param value: [Construction]
|
||||||
|
"""
|
||||||
|
self._constructions = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def average_storey_height(self):
|
||||||
|
"""
|
||||||
|
Get average storey height in m
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._average_storey_height
|
||||||
|
|
||||||
|
@average_storey_height.setter
|
||||||
|
def average_storey_height(self, value):
|
||||||
|
"""
|
||||||
|
Set average storey height in m
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._average_storey_height = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def thermal_capacity(self):
|
||||||
|
"""
|
||||||
|
Get thermal capacity in J/m3K
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._thermal_capacity
|
||||||
|
|
||||||
|
@thermal_capacity.setter
|
||||||
|
def thermal_capacity(self, value):
|
||||||
|
"""
|
||||||
|
Set thermal capacity in J/m3K
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._thermal_capacity = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extra_loses_due_to_thermal_bridges(self):
|
||||||
|
"""
|
||||||
|
Get extra loses due to thermal bridges in W/m2K
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._extra_loses_due_to_thermal_bridges
|
||||||
|
|
||||||
|
@extra_loses_due_to_thermal_bridges.setter
|
||||||
|
def extra_loses_due_to_thermal_bridges(self, value):
|
||||||
|
"""
|
||||||
|
Set extra loses due to thermal bridges in W/m2K
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._extra_loses_due_to_thermal_bridges = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def indirect_heated_ratio(self):
|
||||||
|
"""
|
||||||
|
Get indirect heated area ratio
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._indirect_heated_ratio
|
||||||
|
|
||||||
|
@indirect_heated_ratio.setter
|
||||||
|
def indirect_heated_ratio(self, value):
|
||||||
|
"""
|
||||||
|
Set indirect heated area ratio
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._indirect_heated_ratio = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def infiltration_rate_for_ventilation_system_off(self):
|
||||||
|
"""
|
||||||
|
Get infiltration rate for ventilation system off in ACH
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._infiltration_rate_for_ventilation_system_off
|
||||||
|
|
||||||
|
@infiltration_rate_for_ventilation_system_off.setter
|
||||||
|
def infiltration_rate_for_ventilation_system_off(self, value):
|
||||||
|
"""
|
||||||
|
Set infiltration rate for ventilation system off in ACH
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._infiltration_rate_for_ventilation_system_off = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def infiltration_rate_for_ventilation_system_on(self):
|
||||||
|
"""
|
||||||
|
Get infiltration rate for ventilation system on in ACH
|
||||||
|
:return: float
|
||||||
|
"""
|
||||||
|
return self._infiltration_rate_for_ventilation_system_on
|
||||||
|
|
||||||
|
@infiltration_rate_for_ventilation_system_on.setter
|
||||||
|
def infiltration_rate_for_ventilation_system_on(self, value):
|
||||||
|
"""
|
||||||
|
Set infiltration rate for ventilation system on in ACH
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
|
self._infiltration_rate_for_ventilation_system_on = value
|
@ -7,7 +7,9 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
import math
|
||||||
from typing import List, Union, TypeVar
|
from typing import List, Union, TypeVar
|
||||||
|
import logging
|
||||||
from hub.helpers.configuration_helper import ConfigurationHelper as ch
|
from hub.helpers.configuration_helper import ConfigurationHelper as ch
|
||||||
import hub.helpers.constants as cte
|
import hub.helpers.constants as cte
|
||||||
from hub.city_model_structure.building_demand.layer import Layer
|
from hub.city_model_structure.building_demand.layer import Layer
|
||||||
@ -35,7 +37,8 @@ class ThermalBoundary:
|
|||||||
self._construction_name = None
|
self._construction_name = None
|
||||||
self._thickness = None
|
self._thickness = None
|
||||||
self._internal_surface = None
|
self._internal_surface = None
|
||||||
self._window_ratio = None
|
self._external_surface = None
|
||||||
|
self._window_ratio = 0
|
||||||
self._window_ratio_to_be_calculated = False
|
self._window_ratio_to_be_calculated = False
|
||||||
if self._windows_areas is not None:
|
if self._windows_areas is not None:
|
||||||
self._window_ratio_to_be_calculated = True
|
self._window_ratio_to_be_calculated = True
|
||||||
@ -53,7 +56,7 @@ class ThermalBoundary:
|
|||||||
@property
|
@property
|
||||||
def parent_surface(self) -> Surface:
|
def parent_surface(self) -> Surface:
|
||||||
"""
|
"""
|
||||||
Get the surface that belongs to the thermal boundary
|
Get the surface that belongs to the thermal boundary, considered the external surface of that boundary
|
||||||
:return: Surface
|
:return: Surface
|
||||||
"""
|
"""
|
||||||
return self._parent_surface
|
return self._parent_surface
|
||||||
@ -92,7 +95,7 @@ class ThermalBoundary:
|
|||||||
self._thickness = 0.0
|
self._thickness = 0.0
|
||||||
if self.layers is not None:
|
if self.layers is not None:
|
||||||
for layer in self.layers:
|
for layer in self.layers:
|
||||||
if not layer.material.no_mass:
|
if not layer.no_mass:
|
||||||
self._thickness += layer.thickness
|
self._thickness += layer.thickness
|
||||||
return self._thickness
|
return self._thickness
|
||||||
|
|
||||||
@ -148,24 +151,21 @@ class ThermalBoundary:
|
|||||||
else:
|
else:
|
||||||
_area = self.opaque_area * self.window_ratio / (1-self.window_ratio)
|
_area = self.opaque_area * self.window_ratio / (1-self.window_ratio)
|
||||||
_thermal_opening.area = _area
|
_thermal_opening.area = _area
|
||||||
|
self._thermal_openings = [_thermal_opening]
|
||||||
|
for thermal_opening in self._thermal_openings:
|
||||||
|
thermal_opening.g_value = self._construction_archetype.window_g_value
|
||||||
|
thermal_opening.overall_u_value = self._construction_archetype.window_overall_u_value
|
||||||
|
thermal_opening.frame_ratio = self._construction_archetype.window_frame_ratio
|
||||||
|
thermal_opening.construction_name = self._construction_archetype.window_type
|
||||||
return self._thermal_openings
|
return self._thermal_openings
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def construction_name(self) -> Union[None, str]:
|
def _construction_archetype(self):
|
||||||
"""
|
construction_archetypes = self.thermal_zones[0].parent_internal_zone.thermal_archetype.constructions
|
||||||
Get construction name
|
for construction_archetype in construction_archetypes:
|
||||||
:return: None or str
|
if str(self.type) == str(construction_archetype.type):
|
||||||
"""
|
return construction_archetype
|
||||||
return self._construction_name
|
return None
|
||||||
|
|
||||||
@construction_name.setter
|
|
||||||
def construction_name(self, value):
|
|
||||||
"""
|
|
||||||
Set construction name
|
|
||||||
:param value: str
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._construction_name = str(value)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def layers(self) -> List[Layer]:
|
def layers(self) -> List[Layer]:
|
||||||
@ -173,16 +173,13 @@ class ThermalBoundary:
|
|||||||
Get thermal boundary layers
|
Get thermal boundary layers
|
||||||
:return: [Layers]
|
:return: [Layers]
|
||||||
"""
|
"""
|
||||||
|
if self._construction_archetype is not None:
|
||||||
|
self._layers = self._construction_archetype.layers
|
||||||
|
else:
|
||||||
|
logging.error('Layers not defined\n')
|
||||||
|
raise ValueError('Layers not defined')
|
||||||
return self._layers
|
return self._layers
|
||||||
|
|
||||||
@layers.setter
|
|
||||||
def layers(self, value):
|
|
||||||
"""
|
|
||||||
Set thermal boundary layers
|
|
||||||
:param value: [Layer]
|
|
||||||
"""
|
|
||||||
self._layers = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
"""
|
"""
|
||||||
@ -209,18 +206,23 @@ class ThermalBoundary:
|
|||||||
for window_area in self.windows_areas:
|
for window_area in self.windows_areas:
|
||||||
total_window_area += window_area
|
total_window_area += window_area
|
||||||
self._window_ratio = total_window_area / (self.opaque_area + total_window_area)
|
self._window_ratio = total_window_area / (self.opaque_area + total_window_area)
|
||||||
|
else:
|
||||||
|
if self.type in (cte.WALL, cte.ROOF):
|
||||||
|
if -math.sqrt(2) / 2 < math.sin(self.parent_surface.azimuth) < math.sqrt(2) / 2:
|
||||||
|
if 0 < math.cos(self.parent_surface.azimuth):
|
||||||
|
self._window_ratio = \
|
||||||
|
float(self._construction_archetype.window_ratio['north']) / 100
|
||||||
|
else:
|
||||||
|
self._window_ratio = \
|
||||||
|
float(self._construction_archetype.window_ratio['south']) / 100
|
||||||
|
elif math.sqrt(2) / 2 <= math.sin(self._parent_surface.azimuth):
|
||||||
|
self._window_ratio = \
|
||||||
|
float(self._construction_archetype.window_ratio['east']) / 100
|
||||||
|
else:
|
||||||
|
self._window_ratio = \
|
||||||
|
float(self._construction_archetype.window_ratio['west']) / 100
|
||||||
return self._window_ratio
|
return self._window_ratio
|
||||||
|
|
||||||
@window_ratio.setter
|
|
||||||
def window_ratio(self, value):
|
|
||||||
"""
|
|
||||||
Set thermal boundary window ratio
|
|
||||||
:param value: str
|
|
||||||
"""
|
|
||||||
if self._window_ratio_to_be_calculated:
|
|
||||||
raise ValueError('Window ratio cannot be assigned when the windows are defined in the geometry.')
|
|
||||||
self._window_ratio = float(value)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def windows_areas(self) -> [float]:
|
def windows_areas(self) -> [float]:
|
||||||
"""
|
"""
|
||||||
@ -245,10 +247,10 @@ class ThermalBoundary:
|
|||||||
r_value = 1.0/h_i + 1.0/h_e
|
r_value = 1.0/h_i + 1.0/h_e
|
||||||
try:
|
try:
|
||||||
for layer in self.layers:
|
for layer in self.layers:
|
||||||
if layer.material.no_mass:
|
if layer.no_mass:
|
||||||
r_value += float(layer.material.thermal_resistance)
|
r_value += float(layer.thermal_resistance)
|
||||||
else:
|
else:
|
||||||
r_value += float(layer.thickness) / float(layer.material.conductivity)
|
r_value += float(layer.thickness) / float(layer.conductivity)
|
||||||
self._u_value = 1.0/r_value
|
self._u_value = 1.0/r_value
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise TypeError('Constructions layers are not initialized') from TypeError
|
raise TypeError('Constructions layers are not initialized') from TypeError
|
||||||
@ -305,4 +307,18 @@ class ThermalBoundary:
|
|||||||
"""
|
"""
|
||||||
if self._internal_surface is None:
|
if self._internal_surface is None:
|
||||||
self._internal_surface = self.parent_surface.inverse
|
self._internal_surface = self.parent_surface.inverse
|
||||||
|
# The agreement is that the layers are defined from outside to inside
|
||||||
|
internal_layer = self.layers[len(self.layers) - 1]
|
||||||
|
self._internal_surface.short_wave_reflectance = 1 - internal_layer.solar_absorptance
|
||||||
|
self._internal_surface.long_wave_emittance = 1 - internal_layer.solar_absorptance
|
||||||
|
|
||||||
return self._internal_surface
|
return self._internal_surface
|
||||||
|
|
||||||
|
@property
|
||||||
|
def external_surface(self) -> Surface:
|
||||||
|
if self._external_surface is None:
|
||||||
|
# The agreement is that the layers are defined from outside to inside
|
||||||
|
self._external_surface = self.parent_surface
|
||||||
|
self._external_surface.short_wave_reflectance = 1 - self.layers[0].solar_absorptance
|
||||||
|
self._external_surface.long_wave_emittance = 1 - self.layers[0].solar_absorptance
|
||||||
|
return self._external_surface
|
||||||
|
@ -29,7 +29,12 @@ class ThermalZone:
|
|||||||
ThermalZone class
|
ThermalZone class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, thermal_boundaries, parent_internal_zone, volume, footprint_area, usage_name=None):
|
def __init__(self, thermal_boundaries,
|
||||||
|
parent_internal_zone,
|
||||||
|
volume,
|
||||||
|
footprint_area,
|
||||||
|
number_of_storeys,
|
||||||
|
usage_name=None):
|
||||||
self._id = None
|
self._id = None
|
||||||
self._parent_internal_zone = parent_internal_zone
|
self._parent_internal_zone = parent_internal_zone
|
||||||
self._footprint_area = footprint_area
|
self._footprint_area = footprint_area
|
||||||
@ -43,6 +48,7 @@ class ThermalZone:
|
|||||||
self._ordinate_number = None
|
self._ordinate_number = None
|
||||||
self._view_factors_matrix = None
|
self._view_factors_matrix = None
|
||||||
self._total_floor_area = None
|
self._total_floor_area = None
|
||||||
|
self._number_of_storeys = number_of_storeys
|
||||||
self._usage_name = usage_name
|
self._usage_name = usage_name
|
||||||
self._usage_from_parent = False
|
self._usage_from_parent = False
|
||||||
if usage_name is None:
|
if usage_name is None:
|
||||||
@ -58,6 +64,14 @@ class ThermalZone:
|
|||||||
self._domestic_hot_water = None
|
self._domestic_hot_water = None
|
||||||
self._usages = None
|
self._usages = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parent_internal_zone(self) -> InternalZone:
|
||||||
|
"""
|
||||||
|
Get the internal zone to which this thermal zone belongs
|
||||||
|
:return: InternalZone
|
||||||
|
"""
|
||||||
|
return self._parent_internal_zone
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def usages(self):
|
def usages(self):
|
||||||
"""
|
"""
|
||||||
@ -113,83 +127,45 @@ class ThermalZone:
|
|||||||
Get thermal zone additional thermal bridge u value per footprint area W/m2K
|
Get thermal zone additional thermal bridge u value per footprint area W/m2K
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
|
self._additional_thermal_bridge_u_value = self.parent_internal_zone.thermal_archetype.extra_loses_due_to_thermal_bridges
|
||||||
return self._additional_thermal_bridge_u_value
|
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 per footprint area W/m2K
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._additional_thermal_bridge_u_value = float(value)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def effective_thermal_capacity(self) -> Union[None, float]:
|
def effective_thermal_capacity(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get thermal zone effective thermal capacity in J/m3K
|
Get thermal zone effective thermal capacity in J/m3K
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
|
self._effective_thermal_capacity = self._parent_internal_zone.thermal_archetype.thermal_capacity
|
||||||
return self._effective_thermal_capacity
|
return self._effective_thermal_capacity
|
||||||
|
|
||||||
@effective_thermal_capacity.setter
|
|
||||||
def effective_thermal_capacity(self, value):
|
|
||||||
"""
|
|
||||||
Set thermal zone effective thermal capacity in J/m3K
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._effective_thermal_capacity = float(value)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def indirectly_heated_area_ratio(self) -> Union[None, float]:
|
def indirectly_heated_area_ratio(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get thermal zone indirectly heated area ratio
|
Get thermal zone indirectly heated area ratio
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
|
self._indirectly_heated_area_ratio = self._parent_internal_zone.thermal_archetype.indirect_heated_ratio
|
||||||
return self._indirectly_heated_area_ratio
|
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
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._indirectly_heated_area_ratio = float(value)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def infiltration_rate_system_on(self):
|
def infiltration_rate_system_on(self):
|
||||||
"""
|
"""
|
||||||
Get thermal zone infiltration rate system on in air changes per hour (ACH)
|
Get thermal zone infiltration rate system on in air changes per second (1/s)
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
|
self._infiltration_rate_system_on = self._parent_internal_zone.thermal_archetype.infiltration_rate_for_ventilation_system_on
|
||||||
return self._infiltration_rate_system_on
|
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 (ACH)
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
self._infiltration_rate_system_on = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def infiltration_rate_system_off(self):
|
def infiltration_rate_system_off(self):
|
||||||
"""
|
"""
|
||||||
Get thermal zone infiltration rate system off in air changes per hour (ACH)
|
Get thermal zone infiltration rate system off in air changes per second (1/s)
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
|
self._infiltration_rate_system_off = self._parent_internal_zone.thermal_archetype.infiltration_rate_for_ventilation_system_off
|
||||||
return self._infiltration_rate_system_off
|
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 (ACH)
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
self._infiltration_rate_system_off = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def volume(self):
|
def volume(self):
|
||||||
"""
|
"""
|
||||||
@ -221,15 +197,43 @@ class ThermalZone:
|
|||||||
Get thermal zone view factors matrix
|
Get thermal zone view factors matrix
|
||||||
:return: [[float]]
|
:return: [[float]]
|
||||||
"""
|
"""
|
||||||
return self._view_factors_matrix
|
# todo: review method if windows not in window_ratio but in geometry
|
||||||
|
if self._view_factors_matrix is None:
|
||||||
|
total_area = 0
|
||||||
|
for thermal_boundary in self.thermal_boundaries:
|
||||||
|
total_area += thermal_boundary.opaque_area
|
||||||
|
for thermal_opening in thermal_boundary.thermal_openings:
|
||||||
|
total_area += thermal_opening.area
|
||||||
|
|
||||||
@view_factors_matrix.setter
|
view_factors_matrix = []
|
||||||
def view_factors_matrix(self, value):
|
for thermal_boundary_1 in self.thermal_boundaries:
|
||||||
"""
|
values = []
|
||||||
Set thermal zone view factors matrix
|
for thermal_boundary_2 in self.thermal_boundaries:
|
||||||
:param value: [[float]]
|
value = 0
|
||||||
"""
|
if thermal_boundary_1.id != thermal_boundary_2.id:
|
||||||
self._view_factors_matrix = value
|
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
|
||||||
|
values.append(value)
|
||||||
|
for thermal_boundary in self.thermal_boundaries:
|
||||||
|
for thermal_opening in thermal_boundary.thermal_openings:
|
||||||
|
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
|
||||||
|
values.append(value)
|
||||||
|
view_factors_matrix.append(values)
|
||||||
|
|
||||||
|
for thermal_boundary_1 in self.thermal_boundaries:
|
||||||
|
values = []
|
||||||
|
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
|
||||||
|
for thermal_boundary_2 in self.thermal_boundaries:
|
||||||
|
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
|
||||||
|
values.append(value)
|
||||||
|
for thermal_boundary in self.thermal_boundaries:
|
||||||
|
for thermal_opening_2 in thermal_boundary.thermal_openings:
|
||||||
|
value = 0
|
||||||
|
if thermal_opening_1.id != thermal_opening_2.id:
|
||||||
|
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
|
||||||
|
values.append(value)
|
||||||
|
view_factors_matrix.append(values)
|
||||||
|
self._view_factors_matrix = view_factors_matrix
|
||||||
|
return self._view_factors_matrix
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def usage_name(self) -> Union[None, str]:
|
def usage_name(self) -> Union[None, str]:
|
||||||
@ -285,7 +289,7 @@ class ThermalZone:
|
|||||||
@property
|
@property
|
||||||
def mechanical_air_change(self) -> Union[None, float]:
|
def mechanical_air_change(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get thermal zone mechanical air change in air change per hour (ACH)
|
Get thermal zone mechanical air change in air change per second (1/s)
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
if self.usages is None:
|
if self.usages is None:
|
||||||
@ -653,15 +657,8 @@ class ThermalZone:
|
|||||||
@property
|
@property
|
||||||
def total_floor_area(self):
|
def total_floor_area(self):
|
||||||
"""
|
"""
|
||||||
Get the total floor area of this thermal zone
|
Get the total floor area of this thermal zone in m2
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
|
self._total_floor_area = self.footprint_area * self._number_of_storeys
|
||||||
return self._total_floor_area
|
return self._total_floor_area
|
||||||
|
|
||||||
@total_floor_area.setter
|
|
||||||
def total_floor_area(self, value):
|
|
||||||
"""
|
|
||||||
Set the total floor area of this thermal zone
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
self._total_floor_area = value
|
|
||||||
|
@ -173,7 +173,7 @@ class Usage:
|
|||||||
@property
|
@property
|
||||||
def mechanical_air_change(self) -> Union[None, float]:
|
def mechanical_air_change(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
Get usage zone mechanical air change in air change per hour (ACH)
|
Get usage zone mechanical air change in air change per second (1/s)
|
||||||
:return: None or float
|
:return: None or float
|
||||||
"""
|
"""
|
||||||
return self._mechanical_air_change
|
return self._mechanical_air_change
|
||||||
@ -181,7 +181,7 @@ class Usage:
|
|||||||
@mechanical_air_change.setter
|
@mechanical_air_change.setter
|
||||||
def mechanical_air_change(self, value):
|
def mechanical_air_change(self, value):
|
||||||
"""
|
"""
|
||||||
Set usage zone mechanical air change in air change per hour (ACH)
|
Set usage zone mechanical air change in air change per second (1/s)
|
||||||
:param value: float
|
:param value: float
|
||||||
"""
|
"""
|
||||||
if value is not None:
|
if value is not None:
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
"""
|
|
||||||
Bus system module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List
|
|
||||||
from hub.city_model_structure.city_object import CityObject
|
|
||||||
from hub.city_model_structure.attributes.polygon import Polygon
|
|
||||||
from hub.city_model_structure.transport.bus_network import BusNetwork
|
|
||||||
from hub.city_model_structure.transport.bus_node import BusNode
|
|
||||||
from hub.city_model_structure.transport.bus import Bus
|
|
||||||
|
|
||||||
|
|
||||||
class BusSystem(CityObject):
|
|
||||||
"""
|
|
||||||
BusSystem(CityObject) class
|
|
||||||
"""
|
|
||||||
def __init__(self, name, surfaces):
|
|
||||||
super().__init__(name, surfaces)
|
|
||||||
self._bus_routes = None
|
|
||||||
self._bus_network = None
|
|
||||||
self._buses = None
|
|
||||||
self._restricted_polygons = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bus_routes(self) -> List[BusNode]:
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: [BusNode]
|
|
||||||
"""
|
|
||||||
return self._bus_routes
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bus_network(self) -> BusNetwork:
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: BusNetwork
|
|
||||||
"""
|
|
||||||
return self._bus_network
|
|
||||||
|
|
||||||
@property
|
|
||||||
def buses(self) -> List[Bus]:
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: [Bus]
|
|
||||||
"""
|
|
||||||
return self._buses
|
|
||||||
|
|
||||||
@property
|
|
||||||
def restricted_polygons(self) -> List[Polygon]:
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: [Polygon]
|
|
||||||
"""
|
|
||||||
return self._restricted_polygons
|
|
@ -81,6 +81,10 @@ class CityObject:
|
|||||||
|
|
||||||
@volume.setter
|
@volume.setter
|
||||||
def volume(self, value):
|
def volume(self, value):
|
||||||
|
"""
|
||||||
|
Set city object volume in cubic meters
|
||||||
|
:param value: float
|
||||||
|
"""
|
||||||
self._volume = value
|
self._volume = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -204,7 +208,7 @@ class CityObject:
|
|||||||
@property
|
@property
|
||||||
def global_horizontal(self) -> dict:
|
def global_horizontal(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get global horizontal radiation surrounding the city object in W/m2
|
Get global horizontal radiation surrounding the city object in J/m2
|
||||||
:return: dict{dict{[float]}}
|
:return: dict{dict{[float]}}
|
||||||
"""
|
"""
|
||||||
return self._global_horizontal
|
return self._global_horizontal
|
||||||
@ -212,7 +216,7 @@ class CityObject:
|
|||||||
@global_horizontal.setter
|
@global_horizontal.setter
|
||||||
def global_horizontal(self, value):
|
def global_horizontal(self, value):
|
||||||
"""
|
"""
|
||||||
Set global horizontal radiation surrounding the city object in W/m2
|
Set global horizontal radiation surrounding the city object in J/m2
|
||||||
:param value: dict{dict{[float]}}
|
:param value: dict{dict{[float]}}
|
||||||
"""
|
"""
|
||||||
self._global_horizontal = value
|
self._global_horizontal = value
|
||||||
@ -220,7 +224,7 @@ class CityObject:
|
|||||||
@property
|
@property
|
||||||
def diffuse(self) -> dict:
|
def diffuse(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get diffuse radiation surrounding the city object in W/m2
|
Get diffuse radiation surrounding the city object in J/m2
|
||||||
:return: dict{dict{[float]}}
|
:return: dict{dict{[float]}}
|
||||||
"""
|
"""
|
||||||
return self._diffuse
|
return self._diffuse
|
||||||
@ -228,7 +232,7 @@ class CityObject:
|
|||||||
@diffuse.setter
|
@diffuse.setter
|
||||||
def diffuse(self, value):
|
def diffuse(self, value):
|
||||||
"""
|
"""
|
||||||
Set diffuse radiation surrounding the city object in W/m2
|
Set diffuse radiation surrounding the city object in J/m2
|
||||||
:param value: dict{dict{[float]}}
|
:param value: dict{dict{[float]}}
|
||||||
"""
|
"""
|
||||||
self._diffuse = value
|
self._diffuse = value
|
||||||
@ -236,7 +240,7 @@ class CityObject:
|
|||||||
@property
|
@property
|
||||||
def beam(self) -> dict:
|
def beam(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Get beam radiation surrounding the city object in W/m2
|
Get beam radiation surrounding the city object in J/m2
|
||||||
:return: dict{dict{[float]}}
|
:return: dict{dict{[float]}}
|
||||||
"""
|
"""
|
||||||
return self._beam
|
return self._beam
|
||||||
@ -244,7 +248,7 @@ class CityObject:
|
|||||||
@beam.setter
|
@beam.setter
|
||||||
def beam(self, value):
|
def beam(self, value):
|
||||||
"""
|
"""
|
||||||
Set beam radiation surrounding the city object in W/m2
|
Set beam radiation surrounding the city object in J/m2
|
||||||
:param value: dict{dict{[float]}}
|
:param value: dict{dict{[float]}}
|
||||||
"""
|
"""
|
||||||
self._beam = value
|
self._beam = value
|
||||||
|
@ -69,7 +69,7 @@ class GenericDistributionSystem:
|
|||||||
def distribution_consumption_variable_flow(self):
|
def distribution_consumption_variable_flow(self):
|
||||||
"""
|
"""
|
||||||
Get distribution_consumption if the pump or fan work at variable mass or volume flow in ratio
|
Get distribution_consumption if the pump or fan work at variable mass or volume flow in ratio
|
||||||
over energy produced (Wh/Wh)
|
over energy produced (J/J)
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
return self._distribution_consumption_variable_flow
|
return self._distribution_consumption_variable_flow
|
||||||
@ -78,7 +78,7 @@ class GenericDistributionSystem:
|
|||||||
def distribution_consumption_variable_flow(self, value):
|
def distribution_consumption_variable_flow(self, value):
|
||||||
"""
|
"""
|
||||||
Set distribution_consumption if the pump or fan work at variable mass or volume flow in ratio
|
Set distribution_consumption if the pump or fan work at variable mass or volume flow in ratio
|
||||||
over energy produced (Wh/Wh)
|
over energy produced (J/J)
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
self._distribution_consumption_variable_flow = value
|
self._distribution_consumption_variable_flow = value
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
"""
|
|
||||||
HvacSystem module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
from typing import Union, List
|
|
||||||
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
|
|
||||||
|
|
||||||
|
|
||||||
class HvacSystem:
|
|
||||||
"""
|
|
||||||
HvacSystem class
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
self._type = None
|
|
||||||
self._thermal_zones = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def type(self) -> Union[None, str]:
|
|
||||||
"""
|
|
||||||
Get hvac system type
|
|
||||||
:return: None or str
|
|
||||||
"""
|
|
||||||
return self._type
|
|
||||||
|
|
||||||
@type.setter
|
|
||||||
def type(self, value):
|
|
||||||
"""
|
|
||||||
Set hvac system type
|
|
||||||
:param value: str
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._type = str(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def thermal_zones(self) -> Union[None, List[ThermalZone]]:
|
|
||||||
"""
|
|
||||||
Get list of zones that this unit serves
|
|
||||||
:return: None or [ThermalZone]
|
|
||||||
"""
|
|
||||||
return self._thermal_zones
|
|
||||||
|
|
||||||
@thermal_zones.setter
|
|
||||||
def thermal_zones(self, value):
|
|
||||||
"""
|
|
||||||
Set list of zones that this unit serves
|
|
||||||
:param value: [ThermalZone]
|
|
||||||
"""
|
|
||||||
self._thermal_zones = value
|
|
@ -1,115 +0,0 @@
|
|||||||
"""
|
|
||||||
Bus module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from hub.city_model_structure.attributes.schedule import Schedule
|
|
||||||
|
|
||||||
|
|
||||||
class Bus:
|
|
||||||
"""
|
|
||||||
Bus class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._maintenance_time = None
|
|
||||||
self._charging_time = None
|
|
||||||
self._recovery_time = None
|
|
||||||
self._vehicle_type = None
|
|
||||||
self._energy_consumption = None
|
|
||||||
self._trips_schedule = None
|
|
||||||
self._capacity = None
|
|
||||||
self._maintenance_cost = None
|
|
||||||
self._investment_cost = None
|
|
||||||
self._charging_range = None
|
|
||||||
self._maximum_travel_range = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def maintenance_time(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._maintenance_time
|
|
||||||
|
|
||||||
@property
|
|
||||||
def charging_time(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._charging_time
|
|
||||||
|
|
||||||
@property
|
|
||||||
def recovery_time(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self.maintenance_time + self.charging_time
|
|
||||||
|
|
||||||
@property
|
|
||||||
def vehicle_type(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._vehicle_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def energy_consumption(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._energy_consumption
|
|
||||||
|
|
||||||
@property
|
|
||||||
def trips_schedule(self) -> Schedule:
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._trips_schedule
|
|
||||||
|
|
||||||
@property
|
|
||||||
def capacity(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._capacity
|
|
||||||
|
|
||||||
@property
|
|
||||||
def maintenance_cost(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._maintenance_cost
|
|
||||||
|
|
||||||
@property
|
|
||||||
def investment_cost(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._investment_cost
|
|
||||||
|
|
||||||
@property
|
|
||||||
def charging_range(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._charging_range
|
|
||||||
|
|
||||||
@property
|
|
||||||
def maximum_travel_range(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._maximum_travel_range
|
|
@ -1,35 +0,0 @@
|
|||||||
"""
|
|
||||||
Bus depot module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from hub.city_model_structure.transport.bus_node import BusNode
|
|
||||||
|
|
||||||
|
|
||||||
class BusDepot(BusNode):
|
|
||||||
"""
|
|
||||||
BusDepot class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, edges=None):
|
|
||||||
super().__init__(name, coordinates, edges=edges, node_type='BusDepot')
|
|
||||||
self._number_of_charging_poles = None
|
|
||||||
self._number_of_available_buses = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def number_of_charging_poles(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._number_of_charging_poles
|
|
||||||
|
|
||||||
@property
|
|
||||||
def number_of_available_buses(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._number_of_available_buses
|
|
@ -1,47 +0,0 @@
|
|||||||
"""
|
|
||||||
Bus edge module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, TypeVar
|
|
||||||
from hub.city_model_structure.attributes.edge import Edge
|
|
||||||
|
|
||||||
BusNode = TypeVar('BusNode')
|
|
||||||
|
|
||||||
|
|
||||||
class BusEdge(Edge):
|
|
||||||
"""
|
|
||||||
BusEdge class
|
|
||||||
Each edge is unidirectional and starts at the "from" node and ends at the "to" node
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, nodes, edge_type='BusEdge'):
|
|
||||||
super().__init__(name, nodes)
|
|
||||||
self._edge_type = edge_type
|
|
||||||
self._average_travel_time = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edge_type(self):
|
|
||||||
"""
|
|
||||||
Get the edge type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._edge_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nodes(self) -> List[BusNode]:
|
|
||||||
"""
|
|
||||||
Get delimiting nodes for the edge
|
|
||||||
:return: [BusNode]
|
|
||||||
"""
|
|
||||||
return self._nodes
|
|
||||||
|
|
||||||
@property
|
|
||||||
def average_travel_time(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._average_travel_time
|
|
@ -1,44 +0,0 @@
|
|||||||
"""
|
|
||||||
Bus network module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List
|
|
||||||
from hub.city_model_structure.network import Network
|
|
||||||
from hub.city_model_structure.transport.bus_edge import BusEdge
|
|
||||||
from hub.city_model_structure.transport.bus_node import BusNode
|
|
||||||
|
|
||||||
|
|
||||||
class BusNetwork(Network):
|
|
||||||
"""
|
|
||||||
BusNetwork(Network) class
|
|
||||||
"""
|
|
||||||
def __init__(self, name, edges=None, nodes=None):
|
|
||||||
super().__init__(name, edges, nodes)
|
|
||||||
self._type = "BusNetwork"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def type(self):
|
|
||||||
"""
|
|
||||||
Get network type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edges(self) -> List[BusEdge]:
|
|
||||||
"""
|
|
||||||
Get network edges
|
|
||||||
:return: [BusEdge]
|
|
||||||
"""
|
|
||||||
return self._edges
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nodes(self) -> List[BusNode]:
|
|
||||||
"""
|
|
||||||
Get network nodes
|
|
||||||
:return: [BusNode]
|
|
||||||
"""
|
|
||||||
return self._nodes
|
|
@ -1,56 +0,0 @@
|
|||||||
"""
|
|
||||||
Bus node module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, TypeVar
|
|
||||||
|
|
||||||
from hub.city_model_structure.attributes.node import Node
|
|
||||||
from hub.city_model_structure.attributes.point import Point
|
|
||||||
|
|
||||||
BusEdge = TypeVar('BusEdge')
|
|
||||||
|
|
||||||
|
|
||||||
class BusNode(Node):
|
|
||||||
"""
|
|
||||||
BusNode class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, node_type='BusNode', edges=None):
|
|
||||||
super().__init__(name, edges)
|
|
||||||
self._coordinates = coordinates
|
|
||||||
self._node_type = node_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def node_type(self):
|
|
||||||
"""
|
|
||||||
Get node type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._node_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coordinates(self) -> Point:
|
|
||||||
"""
|
|
||||||
Get node coordinates
|
|
||||||
:return: Point
|
|
||||||
"""
|
|
||||||
return self._coordinates
|
|
||||||
|
|
||||||
@coordinates.setter
|
|
||||||
def coordinates(self, value):
|
|
||||||
"""
|
|
||||||
Set node coordinates
|
|
||||||
:param value: Point
|
|
||||||
"""
|
|
||||||
self._coordinates = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edges(self) -> List[BusEdge]:
|
|
||||||
"""
|
|
||||||
get edges delimited by the node
|
|
||||||
:return: [BusEdge]
|
|
||||||
"""
|
|
||||||
return self._edges
|
|
@ -1,56 +0,0 @@
|
|||||||
"""
|
|
||||||
Bus stop module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Union
|
|
||||||
from hub.city_model_structure.transport.bus_node import BusNode
|
|
||||||
from hub.city_model_structure.transport.fast_charging_infrastructure import FastChargingInfrastructure
|
|
||||||
from hub.city_model_structure.attributes.schedule import Schedule
|
|
||||||
|
|
||||||
|
|
||||||
class BusStop(BusNode):
|
|
||||||
"""
|
|
||||||
BusStop class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, edges=None):
|
|
||||||
super().__init__(name, coordinates, edges=edges, node_type='BusStop')
|
|
||||||
self._time_table = None
|
|
||||||
self._average_hourly_passengers_demand = None
|
|
||||||
self._fast_charging_infrastructure = None
|
|
||||||
self._waiting_time = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def time_table(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._time_table
|
|
||||||
|
|
||||||
@property
|
|
||||||
def average_hourly_passengers_demand(self) -> Schedule:
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: Schedule
|
|
||||||
"""
|
|
||||||
return self._average_hourly_passengers_demand
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fast_charging_infrastructure(self) -> Union[None, FastChargingInfrastructure]:
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: FastChargingInfrastructure
|
|
||||||
"""
|
|
||||||
return self._fast_charging_infrastructure
|
|
||||||
|
|
||||||
@property
|
|
||||||
def waiting_time(self):
|
|
||||||
"""
|
|
||||||
Add explanation here
|
|
||||||
:return: add type of variable here
|
|
||||||
"""
|
|
||||||
return self._waiting_time
|
|
@ -1,125 +0,0 @@
|
|||||||
"""
|
|
||||||
Connection module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
from hub.city_model_structure.attributes.edge import Edge
|
|
||||||
from hub.city_model_structure.transport.lane import Lane
|
|
||||||
|
|
||||||
|
|
||||||
class Connection:
|
|
||||||
"""
|
|
||||||
Connection class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._from_edge = None
|
|
||||||
self._to_edge = None
|
|
||||||
self._from_lane = None
|
|
||||||
self._to_lane = None
|
|
||||||
self._pass = None
|
|
||||||
self._keep_clear = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def from_edge(self) -> Edge:
|
|
||||||
"""
|
|
||||||
Get "from" edge
|
|
||||||
:return: Edge
|
|
||||||
"""
|
|
||||||
return self._from_edge
|
|
||||||
|
|
||||||
@from_edge.setter
|
|
||||||
def from_edge(self, value):
|
|
||||||
"""
|
|
||||||
Set "from" edge
|
|
||||||
:param value: Edge
|
|
||||||
"""
|
|
||||||
self._from_edge = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def to_edge(self) -> Edge:
|
|
||||||
"""
|
|
||||||
Get "to" edge
|
|
||||||
:return: Edge
|
|
||||||
"""
|
|
||||||
return self._to_edge
|
|
||||||
|
|
||||||
@to_edge.setter
|
|
||||||
def to_edge(self, value):
|
|
||||||
"""
|
|
||||||
Set "to" edge
|
|
||||||
:param value: Edge
|
|
||||||
"""
|
|
||||||
self._to_edge = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def from_lane(self) -> Lane:
|
|
||||||
"""
|
|
||||||
Get "from" lane
|
|
||||||
:return: Lane
|
|
||||||
"""
|
|
||||||
return self._to_lane
|
|
||||||
|
|
||||||
@from_lane.setter
|
|
||||||
def from_lane(self, value):
|
|
||||||
"""
|
|
||||||
Set "from" lane
|
|
||||||
:param value: Lane
|
|
||||||
"""
|
|
||||||
self._from_lane = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def to_lane(self) -> Lane:
|
|
||||||
"""
|
|
||||||
Get "to" lane
|
|
||||||
:return: Lane
|
|
||||||
"""
|
|
||||||
return self._to_lane
|
|
||||||
|
|
||||||
@to_lane.setter
|
|
||||||
def to_lane(self, value):
|
|
||||||
"""
|
|
||||||
Set "to" lane
|
|
||||||
:param value: Lane
|
|
||||||
"""
|
|
||||||
self._to_lane = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def pass_not_wait(self) -> Union[None, bool]:
|
|
||||||
"""
|
|
||||||
Get if the vehicles which pass this (lane to lane) connection will not wait
|
|
||||||
:return: None or Boolean
|
|
||||||
"""
|
|
||||||
return self._pass
|
|
||||||
|
|
||||||
@pass_not_wait.setter
|
|
||||||
def pass_not_wait(self, value):
|
|
||||||
"""
|
|
||||||
Set if the vehicles which pass this (lane to lane) connection will not wait
|
|
||||||
:param value: Boolean
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._pass = ast.literal_eval(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def keep_clear(self) -> Union[None, bool]:
|
|
||||||
"""
|
|
||||||
Get if vehicles which pass this (lane to lane) connection should keep the intersection clear
|
|
||||||
:return: None or Boolean
|
|
||||||
"""
|
|
||||||
return self._keep_clear
|
|
||||||
|
|
||||||
@keep_clear.setter
|
|
||||||
def keep_clear(self, value):
|
|
||||||
"""
|
|
||||||
Set if vehicles which pass this (lane to lane) connection should keep the intersection clear
|
|
||||||
:param value: Boolean
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._keep_clear = ast.literal_eval(value)
|
|
@ -1,74 +0,0 @@
|
|||||||
"""
|
|
||||||
Crossing module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
from typing import List, Union
|
|
||||||
from hub.city_model_structure.transport.traffic_node import TrafficNode
|
|
||||||
|
|
||||||
|
|
||||||
class Crossing(TrafficNode):
|
|
||||||
"""
|
|
||||||
Crossing class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, priority, width, shape=None, edges=None):
|
|
||||||
super().__init__(name, coordinates, edges=edges, node_type='Crossing')
|
|
||||||
self._priority = priority
|
|
||||||
self._width = width
|
|
||||||
self._shape = shape
|
|
||||||
|
|
||||||
@property
|
|
||||||
def priority(self) -> Union[None, bool]:
|
|
||||||
"""
|
|
||||||
Get whether the pedestrians have priority over the vehicles
|
|
||||||
:return: None or bool
|
|
||||||
"""
|
|
||||||
return self._priority
|
|
||||||
|
|
||||||
@priority.setter
|
|
||||||
def priority(self, value):
|
|
||||||
"""
|
|
||||||
Set whether the pedestrians have priority over the vehicles
|
|
||||||
:param value: bool
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._priority = ast.literal_eval(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def width(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get crossing width in meters
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._width
|
|
||||||
|
|
||||||
@width.setter
|
|
||||||
def width(self, value):
|
|
||||||
"""
|
|
||||||
Set crossing width in meters
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._width = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def shape(self) -> Union[None, List[List[float]]]:
|
|
||||||
"""
|
|
||||||
Get the list of positions
|
|
||||||
:return: None or [[x, y, (z)]]
|
|
||||||
"""
|
|
||||||
return self._shape
|
|
||||||
|
|
||||||
@shape.setter
|
|
||||||
def shape(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of positions
|
|
||||||
:param value: [[x, y, (z)]]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._shape = [[float(i) for i in value]]
|
|
@ -1,27 +0,0 @@
|
|||||||
"""
|
|
||||||
Join module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from hub.city_model_structure.transport.traffic_node import TrafficNode
|
|
||||||
|
|
||||||
|
|
||||||
class Join(TrafficNode):
|
|
||||||
"""
|
|
||||||
Join class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, nodes):
|
|
||||||
self._nodes = nodes
|
|
||||||
edges = []
|
|
||||||
prohibitions = []
|
|
||||||
connections = []
|
|
||||||
for node in self._nodes:
|
|
||||||
edges = edges + node.edges
|
|
||||||
prohibitions = prohibitions + node.prohibitions
|
|
||||||
connections = connections + node.connections
|
|
||||||
super().__init__(name, coordinates, edges=edges, prohibitions=prohibitions, connections=connections,
|
|
||||||
node_type='Join')
|
|
@ -1,144 +0,0 @@
|
|||||||
"""
|
|
||||||
Lane module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, Union
|
|
||||||
|
|
||||||
|
|
||||||
class Lane:
|
|
||||||
"""
|
|
||||||
Lane class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._index = None
|
|
||||||
self._allow = None
|
|
||||||
self._disallow = None
|
|
||||||
self._change_left = None
|
|
||||||
self._change_right = None
|
|
||||||
self._speed = None
|
|
||||||
self._width = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def index(self) -> Union[None, int]:
|
|
||||||
"""
|
|
||||||
Get lane index
|
|
||||||
The enumeration index of the lane (0 is the rightmost lane, <NUMBER_LANES>-1 is the leftmost one)
|
|
||||||
:return: None or int
|
|
||||||
"""
|
|
||||||
return self._index
|
|
||||||
|
|
||||||
@index.setter
|
|
||||||
def index(self, value):
|
|
||||||
"""
|
|
||||||
Set lane index
|
|
||||||
The enumeration index of the lane (0 is the rightmost lane, <NUMBER_LANES>-1 is the leftmost one)
|
|
||||||
:param value: int
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._index = int(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def allow(self) -> Union[None, List[str]]:
|
|
||||||
"""
|
|
||||||
Get the list of allowed vehicle classes
|
|
||||||
:return: None or [str]
|
|
||||||
"""
|
|
||||||
return self._allow
|
|
||||||
|
|
||||||
@allow.setter
|
|
||||||
def allow(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of allowed vehicle classes setter
|
|
||||||
:param value: [str]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._allow = [str(i) for i in value]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def disallow(self) -> Union[None, List[str]]:
|
|
||||||
"""
|
|
||||||
Get the list of not allowed vehicle classes
|
|
||||||
:return: None or [str]
|
|
||||||
"""
|
|
||||||
return self._disallow
|
|
||||||
|
|
||||||
@disallow.setter
|
|
||||||
def disallow(self, value):
|
|
||||||
"""
|
|
||||||
Get the list of not allowed vehicle classes setter
|
|
||||||
:param value: [str]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._disallow = [str(i) for i in value]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def change_left(self) -> Union[None, List[str]]:
|
|
||||||
"""
|
|
||||||
Get the list of vehicle classes that may change left from this lane
|
|
||||||
:return: None or [str]
|
|
||||||
"""
|
|
||||||
return self._change_left
|
|
||||||
|
|
||||||
@change_left.setter
|
|
||||||
def change_left(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of vehicle classes that may change left from this lane
|
|
||||||
:param value: [str]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._change_left = [str(i) for i in value]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def change_right(self) -> Union[None, List[str]]:
|
|
||||||
"""
|
|
||||||
Get the list of vehicle classes that may change right from this lane
|
|
||||||
:return: None or [str]
|
|
||||||
"""
|
|
||||||
return self._change_right
|
|
||||||
|
|
||||||
@change_right.setter
|
|
||||||
def change_right(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of vehicle classes that may change right from this lane
|
|
||||||
:param value: [str]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._change_right = [str(i) for i in value]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def speed(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get the lane speed in m/s
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._speed
|
|
||||||
|
|
||||||
@speed.setter
|
|
||||||
def speed(self, value):
|
|
||||||
"""
|
|
||||||
Set the lane speed in m/s
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._speed = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def width(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get the lane width in meters
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._width
|
|
||||||
|
|
||||||
@width.setter
|
|
||||||
def width(self, value):
|
|
||||||
"""
|
|
||||||
Set the lane width in meters
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._width = float(value)
|
|
@ -1,48 +0,0 @@
|
|||||||
"""
|
|
||||||
Origin-Destination edge module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, TypeVar
|
|
||||||
from hub.city_model_structure.attributes.edge import Edge
|
|
||||||
from hub.city_model_structure.attributes.schedule import Schedule
|
|
||||||
|
|
||||||
OriginDestinationNode = TypeVar('OriginDestinationNode')
|
|
||||||
|
|
||||||
|
|
||||||
class OriginDestinationEdge(Edge):
|
|
||||||
"""
|
|
||||||
OriginDestinationEdge class
|
|
||||||
Each edge is unidirectional and starts at the "from" node and ends at the "to" node
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, nodes, edge_type='OriginDestinationEdge'):
|
|
||||||
super().__init__(name, nodes)
|
|
||||||
self._edge_type = edge_type
|
|
||||||
self._movement_schedule = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edge_type(self):
|
|
||||||
"""
|
|
||||||
Get the edge type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._edge_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nodes(self) -> List[OriginDestinationNode]:
|
|
||||||
"""
|
|
||||||
Get delimiting nodes for the edge
|
|
||||||
:return: [OriginDestinationNode]
|
|
||||||
"""
|
|
||||||
return self._nodes
|
|
||||||
|
|
||||||
@property
|
|
||||||
def movement_schedule(self) -> Schedule:
|
|
||||||
"""
|
|
||||||
Get the schedule of the movement of people along this edge
|
|
||||||
:return: Schedule
|
|
||||||
"""
|
|
||||||
return self._movement_schedule
|
|
@ -1,44 +0,0 @@
|
|||||||
"""
|
|
||||||
Origin-Destination network module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List
|
|
||||||
from hub.city_model_structure.network import Network
|
|
||||||
from hub.city_model_structure.transport.origin_destination_edge import OriginDestinationEdge
|
|
||||||
from hub.city_model_structure.transport.origin_destination_node import OriginDestinationNode
|
|
||||||
|
|
||||||
|
|
||||||
class OriginDestinationNetwork(Network):
|
|
||||||
"""
|
|
||||||
OriginDestinationNetwork(Network) class
|
|
||||||
"""
|
|
||||||
def __init__(self, name, edges=None, nodes=None):
|
|
||||||
super().__init__(name, edges, nodes)
|
|
||||||
self._type = "OriginDestinationNetwork"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def type(self):
|
|
||||||
"""
|
|
||||||
Get network type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edges(self) -> List[OriginDestinationEdge]:
|
|
||||||
"""
|
|
||||||
Get network edges
|
|
||||||
:return: [OriginDestinationEdge]
|
|
||||||
"""
|
|
||||||
return self._edges
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nodes(self) -> List[OriginDestinationNode]:
|
|
||||||
"""
|
|
||||||
Get network nodes
|
|
||||||
:return: [OriginDestinationNode]
|
|
||||||
"""
|
|
||||||
return self._nodes
|
|
@ -1,85 +0,0 @@
|
|||||||
"""
|
|
||||||
Origin-Destination node module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
from typing import List, TypeVar
|
|
||||||
|
|
||||||
from hub.city_model_structure.attributes.node import Node
|
|
||||||
from hub.city_model_structure.attributes.point import Point
|
|
||||||
from hub.city_model_structure.attributes.polygon import Polygon
|
|
||||||
from hub.city_model_structure.city_object import CityObject
|
|
||||||
|
|
||||||
OriginDestinationEdge = TypeVar('OriginDestinationEdge')
|
|
||||||
|
|
||||||
|
|
||||||
class OriginDestinationNode(Node):
|
|
||||||
"""
|
|
||||||
OriginDestinationNode class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, node_type='OriginDestinationNode', edges=None, polygon=None):
|
|
||||||
super().__init__(name, edges)
|
|
||||||
self._coordinates = coordinates
|
|
||||||
self._node_type = node_type
|
|
||||||
self._polygon = polygon
|
|
||||||
self._land_use_types = None
|
|
||||||
self._city_objects = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def node_type(self):
|
|
||||||
"""
|
|
||||||
Get node type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._node_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coordinates(self) -> Point:
|
|
||||||
"""
|
|
||||||
Get node coordinates
|
|
||||||
:return: Point
|
|
||||||
"""
|
|
||||||
return self._coordinates
|
|
||||||
|
|
||||||
@coordinates.setter
|
|
||||||
def coordinates(self, value):
|
|
||||||
"""
|
|
||||||
Set node coordinates
|
|
||||||
:param value: Point
|
|
||||||
"""
|
|
||||||
self._coordinates = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edges(self) -> List[OriginDestinationEdge]:
|
|
||||||
"""
|
|
||||||
get edges delimited by the node
|
|
||||||
:return: [OriginDestinationEdge]
|
|
||||||
"""
|
|
||||||
return self._edges
|
|
||||||
|
|
||||||
@property
|
|
||||||
def polygon(self) -> Polygon:
|
|
||||||
"""
|
|
||||||
Get node polygon that defines the zone represented by the node
|
|
||||||
:return: Polygon
|
|
||||||
"""
|
|
||||||
return self._polygon
|
|
||||||
|
|
||||||
@property
|
|
||||||
def land_use_types(self) -> dict:
|
|
||||||
"""
|
|
||||||
Get land use types inside the node polygon. It returns a dictionary with the types of land use together with the
|
|
||||||
percentage of the land that corresponds to each type
|
|
||||||
:return: {string : float}
|
|
||||||
"""
|
|
||||||
return self._land_use_types
|
|
||||||
|
|
||||||
@property
|
|
||||||
def city_objects(self) -> List[CityObject]:
|
|
||||||
"""
|
|
||||||
Get the list of city objects place inside the zone
|
|
||||||
:return: List[CityObject]
|
|
||||||
"""
|
|
||||||
return self._city_objects
|
|
@ -1,134 +0,0 @@
|
|||||||
"""
|
|
||||||
Phase module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, Union
|
|
||||||
|
|
||||||
|
|
||||||
class Phase:
|
|
||||||
"""
|
|
||||||
Phase class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._duration = None
|
|
||||||
self._state = None
|
|
||||||
self._min_duration = None
|
|
||||||
self._max_duration = None
|
|
||||||
self._name = None
|
|
||||||
self._next = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def duration(self) -> Union[None, int]:
|
|
||||||
"""
|
|
||||||
Get phase duration in seconds
|
|
||||||
:return: None or int
|
|
||||||
"""
|
|
||||||
return self._duration
|
|
||||||
|
|
||||||
@duration.setter
|
|
||||||
def duration(self, value):
|
|
||||||
"""
|
|
||||||
Set phase duration in seconds
|
|
||||||
:param value: int
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._duration = int(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state(self) -> Union[None, List[str]]:
|
|
||||||
"""
|
|
||||||
Get the list of signal states
|
|
||||||
:return: None or [str]
|
|
||||||
"""
|
|
||||||
return self._state
|
|
||||||
|
|
||||||
@state.setter
|
|
||||||
def state(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of signal states
|
|
||||||
:param value: [str]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._state = [str(i) for i in value]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def min_duration(self) -> Union[None, int]:
|
|
||||||
"""
|
|
||||||
Get phase minimum duration in seconds
|
|
||||||
:return: None or int
|
|
||||||
"""
|
|
||||||
if self._min_duration is None:
|
|
||||||
self._min_duration = self._duration
|
|
||||||
return self._min_duration
|
|
||||||
|
|
||||||
@min_duration.setter
|
|
||||||
def min_duration(self, value):
|
|
||||||
"""
|
|
||||||
Set phase minimum duration in seconds
|
|
||||||
:param value: int
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._min_duration = int(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def max_duration(self) -> Union[None, int]:
|
|
||||||
"""
|
|
||||||
Get phase maximum duration in seconds
|
|
||||||
:return: None or int
|
|
||||||
"""
|
|
||||||
if self._max_duration is None:
|
|
||||||
self._max_duration = self._duration
|
|
||||||
return self._max_duration
|
|
||||||
|
|
||||||
@max_duration.setter
|
|
||||||
def max_duration(self, value):
|
|
||||||
"""
|
|
||||||
Set phase maximum duration in seconds
|
|
||||||
:param value: int
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._max_duration = int(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self) -> Union[None, str]:
|
|
||||||
"""
|
|
||||||
Get phase name
|
|
||||||
:return: None or str
|
|
||||||
"""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@name.setter
|
|
||||||
def name(self, value):
|
|
||||||
"""
|
|
||||||
Set phase name
|
|
||||||
:param value: str
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._name = str(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def next(self) -> Union[None, List[int]]:
|
|
||||||
"""
|
|
||||||
Get the next phase in the cycle after the current.
|
|
||||||
This is useful when adding extra transition phases to a traffic light plan which are not part of every cycle.
|
|
||||||
Traffic lights of type 'actuated' can make use of a list of indices for selecting among alternative
|
|
||||||
successor phases.
|
|
||||||
:return: None or [int]
|
|
||||||
"""
|
|
||||||
return self._next
|
|
||||||
|
|
||||||
@next.setter
|
|
||||||
def next(self, value):
|
|
||||||
"""
|
|
||||||
Get the next phase in the cycle after the current.
|
|
||||||
This is useful when adding extra transition phases to a traffic light plan which are not part of every cycle.
|
|
||||||
Traffic lights of type 'actuated' can make use of a list of indices for selecting among alternative
|
|
||||||
successor phases.
|
|
||||||
:param value: [int]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._next = [int(i) for i in value]
|
|
@ -1,150 +0,0 @@
|
|||||||
"""
|
|
||||||
Traffic edge module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, Union
|
|
||||||
from hub.city_model_structure.attributes.edge import Edge
|
|
||||||
from hub.city_model_structure.transport.traffic_node import TrafficNode
|
|
||||||
from hub.city_model_structure.transport.lane import Lane
|
|
||||||
|
|
||||||
|
|
||||||
class TrafficEdge(Edge):
|
|
||||||
"""
|
|
||||||
TrafficEdge class
|
|
||||||
Each edge is unidirectional and starts at the "from" node and ends at the "to" node
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, nodes, priority, speed, lanes, length, allows=None, disallows=None, sidewalk_width=None,
|
|
||||||
edge_type='TrafficEdge'):
|
|
||||||
super().__init__(name, nodes)
|
|
||||||
self._edge_type = edge_type
|
|
||||||
self._lanes = lanes
|
|
||||||
self._priority = priority
|
|
||||||
self._speed = speed
|
|
||||||
self._length = length
|
|
||||||
self._allows = allows
|
|
||||||
self._disallows = disallows
|
|
||||||
self._sidewalk_width = sidewalk_width
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edge_type(self):
|
|
||||||
"""
|
|
||||||
Get the edge type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._edge_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nodes(self) -> List[TrafficNode]:
|
|
||||||
"""
|
|
||||||
Get delimiting nodes for the edge
|
|
||||||
:return: [TrafficNode]
|
|
||||||
"""
|
|
||||||
return self._nodes
|
|
||||||
|
|
||||||
@property
|
|
||||||
def lanes(self) -> List[Lane]:
|
|
||||||
"""
|
|
||||||
Get the lanes on an edge
|
|
||||||
:return: List[Lane]
|
|
||||||
"""
|
|
||||||
return self._lanes
|
|
||||||
|
|
||||||
@lanes.setter
|
|
||||||
def lanes(self, value):
|
|
||||||
"""
|
|
||||||
Set the lanes on an edge
|
|
||||||
:param value: List[Lane]
|
|
||||||
"""
|
|
||||||
self._lanes = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def priority(self) -> Union[None, int]:
|
|
||||||
"""
|
|
||||||
Get the priority between different road types.
|
|
||||||
It starts with one; higher numbers represent more important roads.
|
|
||||||
:return: None or int
|
|
||||||
"""
|
|
||||||
return self._priority
|
|
||||||
|
|
||||||
@priority.setter
|
|
||||||
def priority(self, value):
|
|
||||||
"""
|
|
||||||
Set the priority between different road types.
|
|
||||||
It starts with one; higher numbers represent more important roads.
|
|
||||||
:param value: int
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._priority = int(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def speed(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get he speed limit in m/s
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._speed
|
|
||||||
|
|
||||||
@speed.setter
|
|
||||||
def speed(self, value):
|
|
||||||
"""
|
|
||||||
Set the speed limit in m/s
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._speed = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def length(self) -> Union[None, float]:
|
|
||||||
"""
|
|
||||||
Get the lane length in meters
|
|
||||||
:return: None or float
|
|
||||||
"""
|
|
||||||
return self._length
|
|
||||||
|
|
||||||
@length.setter
|
|
||||||
def length(self, value):
|
|
||||||
"""
|
|
||||||
Set the lane length in meters
|
|
||||||
:param value: float
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._length = float(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def allows(self) -> Union[None, List[str]]:
|
|
||||||
"""
|
|
||||||
Get the list of allowed vehicle classes
|
|
||||||
:return: None or [str]
|
|
||||||
"""
|
|
||||||
return self._allows
|
|
||||||
|
|
||||||
@allows.setter
|
|
||||||
def allows(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of allowed vehicle classes
|
|
||||||
:param value: [str]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._allows = [str(i) for i in value]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def disallows(self) -> Union[None, List[str]]:
|
|
||||||
"""
|
|
||||||
Get the list of not allowed vehicle classes
|
|
||||||
:return: None or [str]
|
|
||||||
"""
|
|
||||||
return self._disallows
|
|
||||||
|
|
||||||
@disallows.setter
|
|
||||||
def disallows(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of not allowed vehicle classes
|
|
||||||
:param value: [str]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._disallows = [str(i) for i in value]
|
|
@ -1,75 +0,0 @@
|
|||||||
"""
|
|
||||||
Traffic light module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
from typing import List, Union
|
|
||||||
from hub.city_model_structure.transport.phase import Phase
|
|
||||||
from hub.city_model_structure.transport.traffic_node import TrafficNode
|
|
||||||
|
|
||||||
|
|
||||||
class TrafficLight(TrafficNode):
|
|
||||||
"""
|
|
||||||
Traffic light class
|
|
||||||
"""
|
|
||||||
def __init__(self, name, coordinates, offset, phases=None, edges=None, right_on_red=False):
|
|
||||||
super().__init__(name, coordinates, edges=edges, node_type='TrafficLight')
|
|
||||||
if phases is None:
|
|
||||||
phases = []
|
|
||||||
self._right_on_red = right_on_red
|
|
||||||
self._offset = offset
|
|
||||||
self._phases = phases
|
|
||||||
|
|
||||||
@property
|
|
||||||
def right_on_red(self) -> Union[None, bool]:
|
|
||||||
"""
|
|
||||||
Get if is possible to turn right when the traffic light is red
|
|
||||||
:return: None or Boolean
|
|
||||||
"""
|
|
||||||
return self._right_on_red
|
|
||||||
|
|
||||||
@right_on_red.setter
|
|
||||||
def right_on_red(self, value):
|
|
||||||
"""
|
|
||||||
Get if is possible to turn right when the traffic light is red
|
|
||||||
:param value: Boolean
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._right_on_red = ast.literal_eval(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def offset(self) -> Union[None, int]:
|
|
||||||
"""
|
|
||||||
Get program initial time offset
|
|
||||||
:return: None or int
|
|
||||||
"""
|
|
||||||
return self._offset
|
|
||||||
|
|
||||||
@offset.setter
|
|
||||||
def offset(self, value):
|
|
||||||
"""
|
|
||||||
Set program initial time offset
|
|
||||||
:param value: int
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._offset = int(value)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def phases(self) -> List[Phase]:
|
|
||||||
"""
|
|
||||||
Get traffic light logic phases
|
|
||||||
:return: [Phase]
|
|
||||||
"""
|
|
||||||
return self._phases
|
|
||||||
|
|
||||||
@phases.setter
|
|
||||||
def phases(self, value):
|
|
||||||
"""
|
|
||||||
Set traffic light logic phases
|
|
||||||
:param value: [Phase]
|
|
||||||
"""
|
|
||||||
self._phases = value
|
|
@ -1,45 +0,0 @@
|
|||||||
"""
|
|
||||||
Traffic network module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List
|
|
||||||
from hub.city_model_structure.network import Network
|
|
||||||
from hub.city_model_structure.transport.traffic_edge import TrafficEdge
|
|
||||||
from hub.city_model_structure.transport.traffic_node import TrafficNode
|
|
||||||
|
|
||||||
|
|
||||||
class TrafficNetwork(Network):
|
|
||||||
"""
|
|
||||||
TrafficNetwork(Network) class
|
|
||||||
"""
|
|
||||||
def __init__(self, name, edges=None, nodes=None):
|
|
||||||
super().__init__(name, edges, nodes)
|
|
||||||
self._type = "TrafficNetwork"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def type(self):
|
|
||||||
"""
|
|
||||||
Get network type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edges(self) -> List[TrafficEdge]:
|
|
||||||
"""
|
|
||||||
Get network edges
|
|
||||||
:return: [TrafficEdge]
|
|
||||||
"""
|
|
||||||
return self._edges
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nodes(self) -> List[TrafficNode]:
|
|
||||||
"""
|
|
||||||
Get network nodes
|
|
||||||
:return: [TrafficNode]
|
|
||||||
"""
|
|
||||||
return self._nodes
|
|
@ -1,97 +0,0 @@
|
|||||||
"""
|
|
||||||
TrafficNode module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, TypeVar
|
|
||||||
|
|
||||||
from hub.city_model_structure.attributes.edge import Edge
|
|
||||||
from hub.city_model_structure.attributes.node import Node
|
|
||||||
from hub.city_model_structure.attributes.point import Point
|
|
||||||
|
|
||||||
Connection = TypeVar('Connection')
|
|
||||||
TrafficEdge = TypeVar('TrafficEdge')
|
|
||||||
|
|
||||||
|
|
||||||
class TrafficNode(Node):
|
|
||||||
"""
|
|
||||||
TrafficNode class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, node_type='TrafficNode', edges=None, prohibitions=None, connections=None):
|
|
||||||
super().__init__(name, edges)
|
|
||||||
if connections is None:
|
|
||||||
connections = []
|
|
||||||
if prohibitions is None:
|
|
||||||
prohibitions = []
|
|
||||||
self._coordinates = coordinates
|
|
||||||
self._prohibitions = prohibitions
|
|
||||||
self._connections = connections
|
|
||||||
self._node_type = node_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def node_type(self):
|
|
||||||
"""
|
|
||||||
Get node type
|
|
||||||
:return: str
|
|
||||||
"""
|
|
||||||
return self._node_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coordinates(self) -> Point:
|
|
||||||
"""
|
|
||||||
Get node coordinates
|
|
||||||
:return: Point
|
|
||||||
"""
|
|
||||||
return self._coordinates
|
|
||||||
|
|
||||||
@coordinates.setter
|
|
||||||
def coordinates(self, value):
|
|
||||||
"""
|
|
||||||
Set node coordinates
|
|
||||||
:param value: Point
|
|
||||||
"""
|
|
||||||
self._coordinates = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def edges(self) -> List[TrafficEdge]:
|
|
||||||
"""
|
|
||||||
get edges delimited by the node
|
|
||||||
:return: [TrafficEdge]
|
|
||||||
"""
|
|
||||||
return self._edges
|
|
||||||
|
|
||||||
@property
|
|
||||||
def prohibitions(self) -> [(Edge, Edge)]:
|
|
||||||
"""
|
|
||||||
Get node prohibitions
|
|
||||||
:return: [(Edge, Edge)]
|
|
||||||
"""
|
|
||||||
return self._prohibitions
|
|
||||||
|
|
||||||
@prohibitions.setter
|
|
||||||
def prohibitions(self, value):
|
|
||||||
"""
|
|
||||||
Set node prohibitions
|
|
||||||
:param value: [(Edge, Edge)]
|
|
||||||
"""
|
|
||||||
self._prohibitions = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def connections(self) -> List[Connection]:
|
|
||||||
"""
|
|
||||||
Get node connections
|
|
||||||
:return: [Connection]
|
|
||||||
"""
|
|
||||||
return self._connections
|
|
||||||
|
|
||||||
@connections.setter
|
|
||||||
def connections(self, value):
|
|
||||||
"""
|
|
||||||
Set node connections
|
|
||||||
:param value: [Connection]
|
|
||||||
"""
|
|
||||||
self._connections = value
|
|
@ -1,37 +0,0 @@
|
|||||||
"""
|
|
||||||
Walkway node module
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|
||||||
Code contributors: Guille guille.gutierrezmorote@concordia.ca
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import List, Union
|
|
||||||
from hub.city_model_structure.transport.traffic_node import TrafficNode
|
|
||||||
|
|
||||||
|
|
||||||
class WalkwayNode(TrafficNode):
|
|
||||||
"""
|
|
||||||
WalkwayNode class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, coordinates, edges=None, shape=None):
|
|
||||||
super().__init__(name, coordinates, edges=edges, node_type='WalkwayNode')
|
|
||||||
self._shape = shape
|
|
||||||
|
|
||||||
@property
|
|
||||||
def shape(self) -> Union[None, List[List[float]]]:
|
|
||||||
"""
|
|
||||||
Get the list of positions
|
|
||||||
:return: None or [[x, y, (z)]]
|
|
||||||
"""
|
|
||||||
return self._shape
|
|
||||||
|
|
||||||
@shape.setter
|
|
||||||
def shape(self, value):
|
|
||||||
"""
|
|
||||||
Set the list of positions
|
|
||||||
:param value: [[x, y, (z)]]
|
|
||||||
"""
|
|
||||||
if value is not None:
|
|
||||||
self._shape = [[float(i) for i in value]]
|
|
@ -335,7 +335,7 @@ class EnergyAde:
|
|||||||
def _thermal_zones(self, building, city):
|
def _thermal_zones(self, building, city):
|
||||||
thermal_zones = []
|
thermal_zones = []
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for index, thermal_zone in enumerate(internal_zone.thermal_zones):
|
for index, thermal_zone in enumerate(internal_zone.thermal_zones_from_internal_zones):
|
||||||
usages = []
|
usages = []
|
||||||
for usage in internal_zone.usages:
|
for usage in internal_zone.usages:
|
||||||
usages.append({'@xlink:href': f'#GML_{usage.id}'})
|
usages.append({'@xlink:href': f'#GML_{usage.id}'})
|
||||||
|
@ -448,22 +448,24 @@ class Idf:
|
|||||||
|
|
||||||
def _add_infiltration(self, thermal_zone, zone_name):
|
def _add_infiltration(self, thermal_zone, zone_name):
|
||||||
schedule = f'Infiltration schedules {thermal_zone.usage_name}'
|
schedule = f'Infiltration schedules {thermal_zone.usage_name}'
|
||||||
|
_infiltration = thermal_zone.infiltration_rate_system_off * cte.HOUR_TO_SECONDS
|
||||||
self._idf.newidfobject(self._INFILTRATION,
|
self._idf.newidfobject(self._INFILTRATION,
|
||||||
Name=f'{zone_name}_infiltration',
|
Name=f'{zone_name}_infiltration',
|
||||||
Zone_or_ZoneList_Name=zone_name,
|
Zone_or_ZoneList_Name=zone_name,
|
||||||
Schedule_Name=schedule,
|
Schedule_Name=schedule,
|
||||||
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
||||||
Air_Changes_per_Hour=thermal_zone.infiltration_rate_system_off
|
Air_Changes_per_Hour=_infiltration
|
||||||
)
|
)
|
||||||
|
|
||||||
def _add_ventilation(self, thermal_zone, zone_name):
|
def _add_ventilation(self, thermal_zone, zone_name):
|
||||||
schedule = f'Ventilation schedules {thermal_zone.usage_name}'
|
schedule = f'Ventilation schedules {thermal_zone.usage_name}'
|
||||||
|
_air_change = thermal_zone.mechanical_air_change * cte.HOUR_TO_SECONDS
|
||||||
self._idf.newidfobject(self._VENTILATION,
|
self._idf.newidfobject(self._VENTILATION,
|
||||||
Name=f'{zone_name}_ventilation',
|
Name=f'{zone_name}_ventilation',
|
||||||
Zone_or_ZoneList_Name=zone_name,
|
Zone_or_ZoneList_Name=zone_name,
|
||||||
Schedule_Name=schedule,
|
Schedule_Name=schedule,
|
||||||
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
||||||
Air_Changes_per_Hour=thermal_zone.mechanical_air_change
|
Air_Changes_per_Hour=_air_change
|
||||||
)
|
)
|
||||||
|
|
||||||
def _add_dhw(self, thermal_zone, zone_name):
|
def _add_dhw(self, thermal_zone, zone_name):
|
||||||
@ -510,9 +512,9 @@ class Idf:
|
|||||||
for building in self._city.buildings:
|
for building in self._city.buildings:
|
||||||
print('building name', building.name)
|
print('building name', building.name)
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
if internal_zone.thermal_zones is None:
|
if internal_zone.thermal_zones_from_internal_zones is None:
|
||||||
continue
|
continue
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self._add_construction(thermal_boundary)
|
self._add_construction(thermal_boundary)
|
||||||
if thermal_boundary.parent_surface.vegetation is not None:
|
if thermal_boundary.parent_surface.vegetation is not None:
|
||||||
@ -556,7 +558,7 @@ class Idf:
|
|||||||
self._add_dhw(thermal_zone, building.name)
|
self._add_dhw(thermal_zone, building.name)
|
||||||
if self._export_type == "Surfaces":
|
if self._export_type == "Surfaces":
|
||||||
if building.name in self._target_buildings or building.name in self._adjacent_buildings:
|
if building.name in self._target_buildings or building.name in self._adjacent_buildings:
|
||||||
if building.internal_zones[0].thermal_zones is not None:
|
if building.internal_zones[0].thermal_zones_from_internal_zones is not None:
|
||||||
self._add_surfaces(building, building.name)
|
self._add_surfaces(building, building.name)
|
||||||
else:
|
else:
|
||||||
self._add_pure_geometry(building, building.name)
|
self._add_pure_geometry(building, building.name)
|
||||||
@ -611,7 +613,7 @@ class Idf:
|
|||||||
num_stories=int(building.storeys_above_ground))
|
num_stories=int(building.storeys_above_ground))
|
||||||
|
|
||||||
for surface in self._idf.idfobjects[self._SURFACE]:
|
for surface in self._idf.idfobjects[self._SURFACE]:
|
||||||
for thermal_zone in building.thermal_zones:
|
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||||
for boundary in thermal_zone.thermal_boundaries:
|
for boundary in thermal_zone.thermal_boundaries:
|
||||||
if surface.Type == self.idf_surfaces[boundary.surface.type]:
|
if surface.Type == self.idf_surfaces[boundary.surface.type]:
|
||||||
surface.Construction_Name = boundary.construction_name
|
surface.Construction_Name = boundary.construction_name
|
||||||
@ -664,7 +666,7 @@ class Idf:
|
|||||||
idf_surface.setcoords(coordinates)
|
idf_surface.setcoords(coordinates)
|
||||||
if self._lod >= 3:
|
if self._lod >= 3:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
for boundary in thermal_zone.thermal_boundaries:
|
for boundary in thermal_zone.thermal_boundaries:
|
||||||
self._add_windows_by_vertices(boundary)
|
self._add_windows_by_vertices(boundary)
|
||||||
else:
|
else:
|
||||||
@ -674,7 +676,7 @@ class Idf:
|
|||||||
|
|
||||||
def _add_surfaces(self, building, zone_name):
|
def _add_surfaces(self, building, zone_name):
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
for boundary in thermal_zone.thermal_boundaries:
|
for boundary in thermal_zone.thermal_boundaries:
|
||||||
idf_surface_type = self.idf_surfaces[boundary.parent_surface.type]
|
idf_surface_type = self.idf_surfaces[boundary.parent_surface.type]
|
||||||
outside_boundary_condition = 'Outdoors'
|
outside_boundary_condition = 'Outdoors'
|
||||||
@ -711,7 +713,7 @@ class Idf:
|
|||||||
|
|
||||||
if self._lod >= 3:
|
if self._lod >= 3:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
for boundary in thermal_zone.thermal_boundaries:
|
for boundary in thermal_zone.thermal_boundaries:
|
||||||
self._add_windows_by_vertices(boundary)
|
self._add_windows_by_vertices(boundary)
|
||||||
else:
|
else:
|
||||||
|
@ -42,7 +42,7 @@ class InselMonthlyEnergyBalance:
|
|||||||
self._insel_files_paths.append(building.name + '.insel')
|
self._insel_files_paths.append(building.name + '.insel')
|
||||||
file_name_out = building.name + '.out'
|
file_name_out = building.name + '.out'
|
||||||
output_path = Path(self._path / file_name_out).resolve()
|
output_path = Path(self._path / file_name_out).resolve()
|
||||||
if building.thermal_zones is None:
|
if building.thermal_zones_from_internal_zones is None:
|
||||||
logging.warning('Building %s has missing values. Monthly Energy Balance cannot be processed', building.name)
|
logging.warning('Building %s has missing values. Monthly Energy Balance cannot be processed', building.name)
|
||||||
|
|
||||||
self._contents.append(
|
self._contents.append(
|
||||||
@ -124,7 +124,7 @@ class InselMonthlyEnergyBalance:
|
|||||||
|
|
||||||
# todo: this method and the insel model have to be reviewed for more than one internal zone
|
# todo: this method and the insel model have to be reviewed for more than one internal zone
|
||||||
internal_zone = building.internal_zones[0]
|
internal_zone = building.internal_zones[0]
|
||||||
thermal_zone = internal_zone.thermal_zones[0]
|
thermal_zone = internal_zone.thermal_zones_from_internal_zones[0]
|
||||||
parameters.append(f'{thermal_zone.indirectly_heated_area_ratio} % BP(6) Indirectly heated area ratio')
|
parameters.append(f'{thermal_zone.indirectly_heated_area_ratio} % BP(6) Indirectly heated area ratio')
|
||||||
parameters.append(f'{thermal_zone.effective_thermal_capacity / 3600 / building.average_storey_height}'
|
parameters.append(f'{thermal_zone.effective_thermal_capacity / 3600 / building.average_storey_height}'
|
||||||
f' % BP(7) Effective heat capacity (Wh/m2K)')
|
f' % BP(7) Effective heat capacity (Wh/m2K)')
|
||||||
@ -137,7 +137,7 @@ class InselMonthlyEnergyBalance:
|
|||||||
|
|
||||||
for i, usage in enumerate(internal_zone.usages):
|
for i, usage in enumerate(internal_zone.usages):
|
||||||
percentage_usage = usage.percentage
|
percentage_usage = usage.percentage
|
||||||
parameters.append(f'{internal_zone.thermal_zones[0].total_floor_area * percentage_usage} '
|
parameters.append(f'{internal_zone.thermal_zones_from_internal_zones[0].total_floor_area * percentage_usage} '
|
||||||
f'% BP(11) #1 Area of zone {i + 1} (m2)')
|
f'% BP(11) #1 Area of zone {i + 1} (m2)')
|
||||||
total_internal_gain = 0
|
total_internal_gain = 0
|
||||||
for i_gain in usage.internal_gains:
|
for i_gain in usage.internal_gains:
|
||||||
@ -167,11 +167,11 @@ class InselMonthlyEnergyBalance:
|
|||||||
infiltration_day = 0
|
infiltration_day = 0
|
||||||
for value in schedule.values:
|
for value in schedule.values:
|
||||||
if value == 0:
|
if value == 0:
|
||||||
infiltration_day += internal_zone.thermal_zones[0].infiltration_rate_system_off / 24
|
infiltration_day += internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_system_off / 24 * cte.HOUR_TO_SECONDS
|
||||||
ventilation_day += 0
|
ventilation_day += 0
|
||||||
else:
|
else:
|
||||||
ventilation_value = usage.mechanical_air_change * value
|
ventilation_value = usage.mechanical_air_change * value * cte.HOUR_TO_SECONDS
|
||||||
infiltration_value = internal_zone.thermal_zones[0].infiltration_rate_system_off * value
|
infiltration_value = internal_zone.thermal_zones_from_internal_zones[0].infiltration_rate_system_off * value * cte.HOUR_TO_SECONDS
|
||||||
if ventilation_value >= infiltration_value:
|
if ventilation_value >= infiltration_value:
|
||||||
ventilation_day += ventilation_value / 24
|
ventilation_day += ventilation_value / 24
|
||||||
infiltration_day += 0
|
infiltration_day += 0
|
||||||
@ -259,7 +259,7 @@ class InselMonthlyEnergyBalance:
|
|||||||
if cte.MONTH not in surface.global_irradiance:
|
if cte.MONTH not in surface.global_irradiance:
|
||||||
raise ValueError(f'surface: {surface.name} from building {building.name} has no global irradiance!')
|
raise ValueError(f'surface: {surface.name} from building {building.name} has no global irradiance!')
|
||||||
|
|
||||||
global_irradiance = surface.global_irradiance[cte.MONTH]
|
global_irradiance = surface.global_irradiance[cte.MONTH] * cte.WATTS_HOUR_TO_JULES
|
||||||
for j in range(0, len(global_irradiance)):
|
for j in range(0, len(global_irradiance)):
|
||||||
parameters.append(f'{j + 1} '
|
parameters.append(f'{j + 1} '
|
||||||
f'{global_irradiance[j] / 24 / _NUMBER_DAYS_PER_MONTH[j]}')
|
f'{global_irradiance[j] / 24 / _NUMBER_DAYS_PER_MONTH[j]}')
|
||||||
|
@ -66,8 +66,9 @@ class SimplifiedRadiosityAlgorithm:
|
|||||||
else:
|
else:
|
||||||
i = (total_days + day - 1) * 24 + hour - 1
|
i = (total_days + day - 1) * 24 + hour - 1
|
||||||
representative_building = self._city.buildings[0]
|
representative_building = self._city.buildings[0]
|
||||||
content += f'{day} {month} {hour} {representative_building.global_horizontal[cte.HOUR][i]} ' \
|
_global = representative_building.global_horizontal[cte.HOUR][i] * cte.WATTS_HOUR_TO_JULES
|
||||||
f'{representative_building.beam[cte.HOUR][i]}\n'
|
_beam = representative_building.beam[cte.HOUR][i] * cte.WATTS_HOUR_TO_JULES
|
||||||
|
content += f'{day} {month} {hour} {_global} {_beam}\n'
|
||||||
with open(file, 'w', encoding='utf-8') as file:
|
with open(file, 'w', encoding='utf-8') as file:
|
||||||
file.write(content)
|
file.write(content)
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ HOUR_TO_SECONDS = 3600
|
|||||||
METERS_TO_FEET = 3.28084
|
METERS_TO_FEET = 3.28084
|
||||||
BTU_H_TO_WATTS = 0.29307107
|
BTU_H_TO_WATTS = 0.29307107
|
||||||
KILO_WATTS_HOUR_TO_JULES = 3600000
|
KILO_WATTS_HOUR_TO_JULES = 3600000
|
||||||
|
WATTS_HOUR_TO_JULES = 3600
|
||||||
GALLONS_TO_QUBIC_METERS = 0.0037854117954011185
|
GALLONS_TO_QUBIC_METERS = 0.0037854117954011185
|
||||||
|
|
||||||
# time
|
# time
|
||||||
|
@ -46,12 +46,11 @@ class LoadsCalculation:
|
|||||||
load_renovation_sensible = 0
|
load_renovation_sensible = 0
|
||||||
for usage in thermal_zone.usages:
|
for usage in thermal_zone.usages:
|
||||||
load_renovation_sensible += cte.AIR_DENSITY * cte.AIR_HEAT_CAPACITY * usage.mechanical_air_change \
|
load_renovation_sensible += cte.AIR_DENSITY * cte.AIR_HEAT_CAPACITY * usage.mechanical_air_change \
|
||||||
* thermal_zone.volume / cte.HOUR_TO_MINUTES / cte.MINUTES_TO_SECONDS \
|
* thermal_zone.volume * (internal_temperature - ambient_temperature)
|
||||||
* (internal_temperature - ambient_temperature)
|
|
||||||
|
|
||||||
load_infiltration_sensible = (
|
load_infiltration_sensible = (
|
||||||
cte.AIR_DENSITY * cte.AIR_HEAT_CAPACITY * thermal_zone.infiltration_rate_system_off * thermal_zone.volume /
|
cte.AIR_DENSITY * cte.AIR_HEAT_CAPACITY * thermal_zone.infiltration_rate_system_off * thermal_zone.volume
|
||||||
cte.HOUR_TO_MINUTES / cte.MINUTES_TO_SECONDS * (internal_temperature - ambient_temperature)
|
* (internal_temperature - ambient_temperature)
|
||||||
)
|
)
|
||||||
|
|
||||||
load_ventilation = load_renovation_sensible + load_infiltration_sensible
|
load_ventilation = load_renovation_sensible + load_infiltration_sensible
|
||||||
@ -65,7 +64,7 @@ class LoadsCalculation:
|
|||||||
"""
|
"""
|
||||||
heating_load_transmitted = 0
|
heating_load_transmitted = 0
|
||||||
for internal_zone in self._building.internal_zones:
|
for internal_zone in self._building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
|
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
|
||||||
heating_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
|
heating_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
|
||||||
ground_temperature)
|
ground_temperature)
|
||||||
@ -78,7 +77,7 @@ class LoadsCalculation:
|
|||||||
"""
|
"""
|
||||||
cooling_load_transmitted = 0
|
cooling_load_transmitted = 0
|
||||||
for internal_zone in self._building.internal_zones:
|
for internal_zone in self._building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
|
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
|
||||||
cooling_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
|
cooling_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
|
||||||
ground_temperature)
|
ground_temperature)
|
||||||
@ -91,7 +90,7 @@ class LoadsCalculation:
|
|||||||
"""
|
"""
|
||||||
heating_ventilation_load = 0
|
heating_ventilation_load = 0
|
||||||
for internal_zone in self._building.internal_zones:
|
for internal_zone in self._building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
|
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
|
||||||
heating_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
|
heating_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
|
||||||
return heating_ventilation_load
|
return heating_ventilation_load
|
||||||
@ -103,7 +102,7 @@ class LoadsCalculation:
|
|||||||
"""
|
"""
|
||||||
cooling_ventilation_load = 0
|
cooling_ventilation_load = 0
|
||||||
for internal_zone in self._building.internal_zones:
|
for internal_zone in self._building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
|
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
|
||||||
cooling_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
|
cooling_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
|
||||||
return cooling_ventilation_load
|
return cooling_ventilation_load
|
||||||
@ -117,7 +116,7 @@ class LoadsCalculation:
|
|||||||
cooling_load_lighting = 0
|
cooling_load_lighting = 0
|
||||||
cooling_load_equipment_sensible = 0
|
cooling_load_equipment_sensible = 0
|
||||||
for internal_zone in self._building.internal_zones:
|
for internal_zone in self._building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
cooling_load_occupancy_sensible += (thermal_zone.occupancy.sensible_convective_internal_gain
|
cooling_load_occupancy_sensible += (thermal_zone.occupancy.sensible_convective_internal_gain
|
||||||
+ thermal_zone.occupancy.sensible_radiative_internal_gain) \
|
+ thermal_zone.occupancy.sensible_radiative_internal_gain) \
|
||||||
* thermal_zone.footprint_area
|
* thermal_zone.footprint_area
|
||||||
@ -139,10 +138,10 @@ class LoadsCalculation:
|
|||||||
"""
|
"""
|
||||||
cooling_load_radiation = 0
|
cooling_load_radiation = 0
|
||||||
for internal_zone in self._building.internal_zones:
|
for internal_zone in self._building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
for thermal_opening in thermal_boundary.thermal_openings:
|
||||||
radiation = thermal_boundary.parent_surface.global_irradiance[cte.HOUR][hour]
|
radiation = thermal_boundary.parent_surface.global_irradiance[cte.HOUR][hour] * cte.WATTS_HOUR_TO_JULES
|
||||||
cooling_load_radiation += (
|
cooling_load_radiation += (
|
||||||
thermal_opening.area * (1 - thermal_opening.frame_ratio) * thermal_opening.g_value * radiation
|
thermal_opening.area * (1 - thermal_opening.frame_ratio) * thermal_opening.g_value * radiation
|
||||||
)
|
)
|
||||||
|
41
hub/helpers/thermal_zones_creation.py
Normal file
41
hub/helpers/thermal_zones_creation.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
"""
|
||||||
|
Thermal zones creation module
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2023 Concordia CERC group
|
||||||
|
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
|
||||||
|
|
||||||
|
|
||||||
|
class ThermalZonesCreation:
|
||||||
|
"""
|
||||||
|
PeakLoads class
|
||||||
|
"""
|
||||||
|
def __init__(self, building=None):
|
||||||
|
self._building = building
|
||||||
|
|
||||||
|
# # The agreement is that the layers are defined from outside to inside
|
||||||
|
# external_layer = catalog_construction.layers[0]
|
||||||
|
# external_surface = thermal_boundary.parent_surface
|
||||||
|
# external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
|
||||||
|
# external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
|
||||||
|
# internal_layer = catalog_construction.layers[len(catalog_construction.layers) - 1]
|
||||||
|
# internal_surface = thermal_boundary.internal_surface
|
||||||
|
# internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
|
||||||
|
# internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
|
||||||
|
|
||||||
|
@property
|
||||||
|
def thermal_zones_from_storeys(self):
|
||||||
|
"""
|
||||||
|
Create and get thermal zones as 1 per each storey
|
||||||
|
:return: [ThermalZone]
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _create_storeys(building, archetype, divide_in_storeys):
|
||||||
|
building.average_storey_height = archetype.average_storey_height
|
||||||
|
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
|
||||||
|
divide_in_storeys=divide_in_storeys).thermal_zones
|
||||||
|
building.internal_zones[0].thermal_zones_from_internal_zones = thermal_zones
|
@ -6,15 +6,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
|
||||||
|
|
||||||
import hub.helpers.constants as cte
|
|
||||||
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
||||||
|
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
|
||||||
|
from hub.city_model_structure.building_demand.construction import Construction
|
||||||
from hub.city_model_structure.building_demand.layer import Layer
|
from hub.city_model_structure.building_demand.layer import Layer
|
||||||
from hub.city_model_structure.building_demand.material import Material
|
|
||||||
from hub.helpers.dictionaries import Dictionaries
|
from hub.helpers.dictionaries import Dictionaries
|
||||||
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
||||||
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
|
|
||||||
|
|
||||||
|
|
||||||
class EilatPhysicsParameters:
|
class EilatPhysicsParameters:
|
||||||
@ -35,7 +33,7 @@ class EilatPhysicsParameters:
|
|||||||
eilat_catalog = ConstructionCatalogFactory('eilat').catalog
|
eilat_catalog = ConstructionCatalogFactory('eilat').catalog
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
if building.function not in Dictionaries().hub_function_to_eilat_construction_function.keys():
|
if building.function not in Dictionaries().hub_function_to_eilat_construction_function.keys():
|
||||||
logging.error(f'Building %s has an unknown building function %s', building.name, building.function )
|
logging.error(f'Building %s has an unknown building function %s', building.name, building.function)
|
||||||
continue
|
continue
|
||||||
function = Dictionaries().hub_function_to_eilat_construction_function[building.function]
|
function = Dictionaries().hub_function_to_eilat_construction_function[building.function]
|
||||||
try:
|
try:
|
||||||
@ -46,29 +44,10 @@ class EilatPhysicsParameters:
|
|||||||
f'[%s], building year of construction: %s and climate zone %s', building.name, function,
|
f'[%s], building year of construction: %s and climate zone %s', building.name, function,
|
||||||
building.function, building.year_of_construction, self._climate_zone)
|
building.function, building.year_of_construction, self._climate_zone)
|
||||||
continue
|
continue
|
||||||
|
thermal_archetype = ThermalArchetype()
|
||||||
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
|
self._assign_values(thermal_archetype, archetype)
|
||||||
# one thermal zone per storey is assigned
|
|
||||||
|
|
||||||
if len(building.internal_zones) == 1:
|
|
||||||
if building.internal_zones[0].thermal_zones is None:
|
|
||||||
self._create_storeys(building, archetype, self._divide_in_storeys)
|
|
||||||
if self._divide_in_storeys:
|
|
||||||
for internal_zone in building.internal_zones:
|
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
|
||||||
else:
|
|
||||||
number_of_storeys = int(building.eave_height / building.average_storey_height)
|
|
||||||
thermal_zone = building.internal_zones[0].thermal_zones[0]
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys
|
|
||||||
else:
|
|
||||||
for internal_zone in building.internal_zones:
|
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._assign_values(internal_zone.thermal_zones, archetype)
|
internal_zone.thermal_archetype = thermal_archetype
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
self._calculate_view_factors(thermal_zone)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone):
|
def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone):
|
||||||
@ -81,133 +60,51 @@ class EilatPhysicsParameters:
|
|||||||
raise KeyError('archetype not found')
|
raise KeyError('archetype not found')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _search_construction_in_archetype(archetype, construction_type):
|
def _assign_values(thermal_archetype, catalog_archetype):
|
||||||
construction_archetypes = archetype.constructions
|
thermal_archetype.average_storey_height = catalog_archetype.average_storey_height
|
||||||
for construction_archetype in construction_archetypes:
|
thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
|
||||||
if str(construction_type) == str(construction_archetype.type):
|
thermal_archetype.indirect_heated_ratio = 0
|
||||||
return construction_archetype
|
thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
|
||||||
return None
|
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
|
||||||
|
effective_thermal_capacity = 0
|
||||||
|
_constructions = []
|
||||||
|
for catalog_construction in catalog_archetype.constructions:
|
||||||
|
construction = Construction()
|
||||||
|
construction.type = catalog_construction.type
|
||||||
|
if catalog_construction.window_ratio is not None:
|
||||||
|
for _orientation in catalog_construction.window_ratio:
|
||||||
|
if catalog_construction.window_ratio[_orientation] is None:
|
||||||
|
catalog_construction.window_ratio[_orientation] = 0
|
||||||
|
construction.window_ratio = catalog_construction.window_ratio
|
||||||
|
_layers = []
|
||||||
|
total_thickness = 0
|
||||||
|
for layer_archetype in catalog_construction.layers:
|
||||||
|
layer = Layer()
|
||||||
|
layer.thickness = layer_archetype.thickness
|
||||||
|
total_thickness += layer_archetype.thickness
|
||||||
|
archetype_material = layer_archetype.material
|
||||||
|
layer.name = archetype_material.name
|
||||||
|
layer.no_mass = archetype_material.no_mass
|
||||||
|
if archetype_material.no_mass:
|
||||||
|
layer.thermal_resistance = archetype_material.thermal_resistance
|
||||||
|
else:
|
||||||
|
layer.density = archetype_material.density
|
||||||
|
layer.conductivity = archetype_material.conductivity
|
||||||
|
layer.specific_heat = archetype_material.specific_heat
|
||||||
|
effective_thermal_capacity += archetype_material.specific_heat \
|
||||||
|
* archetype_material.density * layer_archetype.thickness
|
||||||
|
layer.solar_absorptance = archetype_material.solar_absorptance
|
||||||
|
layer.thermal_absorptance = archetype_material.thermal_absorptance
|
||||||
|
layer.visible_absorptance = archetype_material.visible_absorptance
|
||||||
|
_layers.append(layer)
|
||||||
|
construction.layers = _layers
|
||||||
|
effective_thermal_capacity = effective_thermal_capacity / total_thickness
|
||||||
|
|
||||||
def _assign_values(self, thermal_zones, archetype):
|
if catalog_construction.window is not None:
|
||||||
for thermal_zone in thermal_zones:
|
window_archetype = catalog_construction.window
|
||||||
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges
|
construction.window_frame_ratio = window_archetype.frame_ratio
|
||||||
effective_thermal_capacity = 0
|
construction.window_g_value = window_archetype.g_value
|
||||||
thermal_zone.indirectly_heated_area_ratio = 0
|
construction.window_overall_u_value = window_archetype.overall_u_value
|
||||||
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on
|
_constructions.append(construction)
|
||||||
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off
|
thermal_archetype.constructions = _constructions
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
thermal_archetype.thermal_capacity = effective_thermal_capacity
|
||||||
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
|
|
||||||
thermal_boundary.construction_name = f'{thermal_boundary.type}_{construction_archetype.name}'
|
|
||||||
try:
|
|
||||||
thermal_boundary.window_ratio = 0
|
|
||||||
if thermal_boundary.type in (cte.WALL, cte.ROOF):
|
|
||||||
if construction_archetype.window is not None:
|
|
||||||
if -math.sqrt(2) / 2 < math.sin(thermal_boundary.parent_surface.azimuth) < math.sqrt(2) / 2:
|
|
||||||
if 0 < math.cos(thermal_boundary.parent_surface.azimuth):
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['north']) / 100
|
|
||||||
else:
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['south']) / 100
|
|
||||||
elif math.sqrt(2) / 2 <= math.sin(thermal_boundary.parent_surface.azimuth):
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['east']) / 100
|
|
||||||
else:
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['west']) / 100
|
|
||||||
except ValueError:
|
|
||||||
# This is the normal operation way when the windows are defined in the geometry
|
|
||||||
continue
|
|
||||||
thermal_boundary.layers = []
|
|
||||||
total_thickness = 0
|
|
||||||
for layer_archetype in construction_archetype.layers:
|
|
||||||
layer = Layer()
|
|
||||||
layer.thickness = layer_archetype.thickness
|
|
||||||
total_thickness += layer_archetype.thickness
|
|
||||||
material = Material()
|
|
||||||
archetype_material = layer_archetype.material
|
|
||||||
material.name = archetype_material.name
|
|
||||||
material.id = archetype_material.id
|
|
||||||
material.no_mass = archetype_material.no_mass
|
|
||||||
if archetype_material.no_mass:
|
|
||||||
material.thermal_resistance = archetype_material.thermal_resistance
|
|
||||||
else:
|
|
||||||
material.density = archetype_material.density
|
|
||||||
material.conductivity = archetype_material.conductivity
|
|
||||||
material.specific_heat = archetype_material.specific_heat
|
|
||||||
effective_thermal_capacity += archetype_material.specific_heat \
|
|
||||||
* archetype_material.density * layer_archetype.thickness
|
|
||||||
material.solar_absorptance = archetype_material.solar_absorptance
|
|
||||||
material.thermal_absorptance = archetype_material.thermal_absorptance
|
|
||||||
material.visible_absorptance = archetype_material.visible_absorptance
|
|
||||||
layer.material = material
|
|
||||||
thermal_boundary.layers.append(layer)
|
|
||||||
|
|
||||||
effective_thermal_capacity = effective_thermal_capacity / total_thickness
|
|
||||||
# The agreement is that the layers are defined from outside to inside
|
|
||||||
external_layer = construction_archetype.layers[0]
|
|
||||||
external_surface = thermal_boundary.parent_surface
|
|
||||||
external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
|
|
||||||
external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
|
|
||||||
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
|
|
||||||
internal_surface = thermal_boundary.internal_surface
|
|
||||||
internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
|
|
||||||
internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
|
|
||||||
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
if construction_archetype.window is not None:
|
|
||||||
window_archetype = construction_archetype.window
|
|
||||||
thermal_opening.construction_name = window_archetype.name
|
|
||||||
thermal_opening.frame_ratio = window_archetype.frame_ratio
|
|
||||||
thermal_opening.g_value = window_archetype.g_value
|
|
||||||
thermal_opening.overall_u_value = window_archetype.overall_u_value
|
|
||||||
|
|
||||||
thermal_zone.effective_thermal_capacity = effective_thermal_capacity
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _calculate_view_factors(thermal_zone):
|
|
||||||
"""
|
|
||||||
Get thermal zone view factors matrix
|
|
||||||
:return: [[float]]
|
|
||||||
"""
|
|
||||||
total_area = 0
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
total_area += thermal_boundary.opaque_area
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
total_area += thermal_opening.area
|
|
||||||
|
|
||||||
view_factors_matrix = []
|
|
||||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
|
||||||
values = []
|
|
||||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
|
||||||
value = 0
|
|
||||||
if thermal_boundary_1.id != thermal_boundary_2.id:
|
|
||||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
|
|
||||||
values.append(value)
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
|
|
||||||
values.append(value)
|
|
||||||
view_factors_matrix.append(values)
|
|
||||||
|
|
||||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
|
||||||
values = []
|
|
||||||
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
|
|
||||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
|
||||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
|
|
||||||
values.append(value)
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
for thermal_opening_2 in thermal_boundary.thermal_openings:
|
|
||||||
value = 0
|
|
||||||
if thermal_opening_1.id != thermal_opening_2.id:
|
|
||||||
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
|
|
||||||
values.append(value)
|
|
||||||
view_factors_matrix.append(values)
|
|
||||||
thermal_zone.view_factors_matrix = view_factors_matrix
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _create_storeys(building, archetype, divide_in_storeys):
|
|
||||||
building.average_storey_height = archetype.average_storey_height
|
|
||||||
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
|
|
||||||
divide_in_storeys=divide_in_storeys).thermal_zones
|
|
||||||
building.internal_zones[0].thermal_zones = thermal_zones
|
|
||||||
|
@ -5,8 +5,6 @@ Copyright © 2022 Concordia CERC group
|
|||||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from hub.helpers import constants as cte
|
|
||||||
|
|
||||||
|
|
||||||
class ConstructionHelper:
|
class ConstructionHelper:
|
||||||
"""
|
"""
|
||||||
|
@ -6,15 +6,13 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
|
||||||
|
|
||||||
import hub.helpers.constants as cte
|
|
||||||
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
||||||
|
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
|
||||||
|
from hub.city_model_structure.building_demand.construction import Construction
|
||||||
from hub.city_model_structure.building_demand.layer import Layer
|
from hub.city_model_structure.building_demand.layer import Layer
|
||||||
from hub.city_model_structure.building_demand.material import Material
|
|
||||||
from hub.helpers.dictionaries import Dictionaries
|
from hub.helpers.dictionaries import Dictionaries
|
||||||
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
||||||
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
|
|
||||||
|
|
||||||
|
|
||||||
class NrcanPhysicsParameters:
|
class NrcanPhysicsParameters:
|
||||||
@ -35,7 +33,7 @@ class NrcanPhysicsParameters:
|
|||||||
nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog
|
nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
if building.function not in Dictionaries().hub_function_to_nrcan_construction_function.keys():
|
if building.function not in Dictionaries().hub_function_to_nrcan_construction_function.keys():
|
||||||
logging.error(f'Building %s has an unknown building function %s', building.name, building.function )
|
logging.error(f'Building %s has an unknown building function %s', building.name, building.function)
|
||||||
continue
|
continue
|
||||||
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
|
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
|
||||||
try:
|
try:
|
||||||
@ -46,29 +44,10 @@ class NrcanPhysicsParameters:
|
|||||||
f'[%s], building year of construction: %s and climate zone %s', building.name, function,
|
f'[%s], building year of construction: %s and climate zone %s', building.name, function,
|
||||||
building.function, building.year_of_construction, self._climate_zone)
|
building.function, building.year_of_construction, self._climate_zone)
|
||||||
continue
|
continue
|
||||||
|
thermal_archetype = ThermalArchetype()
|
||||||
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
|
self._assign_values(thermal_archetype, archetype)
|
||||||
# one thermal zone per storey is assigned
|
|
||||||
|
|
||||||
if len(building.internal_zones) == 1:
|
|
||||||
if building.internal_zones[0].thermal_zones is None:
|
|
||||||
self._create_storeys(building, archetype, self._divide_in_storeys)
|
|
||||||
if self._divide_in_storeys:
|
|
||||||
for internal_zone in building.internal_zones:
|
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
|
||||||
else:
|
|
||||||
number_of_storeys = int(building.eave_height / building.average_storey_height)
|
|
||||||
thermal_zone = building.internal_zones[0].thermal_zones[0]
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys
|
|
||||||
else:
|
|
||||||
for internal_zone in building.internal_zones:
|
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._assign_values(internal_zone.thermal_zones, archetype)
|
internal_zone.thermal_archetype = thermal_archetype
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
self._calculate_view_factors(thermal_zone)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone):
|
def _search_archetype(nrcan_catalog, function, year_of_construction, climate_zone):
|
||||||
@ -81,126 +60,45 @@ class NrcanPhysicsParameters:
|
|||||||
raise KeyError('archetype not found')
|
raise KeyError('archetype not found')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _search_construction_in_archetype(archetype, construction_type):
|
def _assign_values(thermal_archetype, catalog_archetype):
|
||||||
construction_archetypes = archetype.constructions
|
thermal_archetype.average_storey_height = catalog_archetype.average_storey_height
|
||||||
for construction_archetype in construction_archetypes:
|
thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
|
||||||
if str(construction_type) == str(construction_archetype.type):
|
thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity
|
||||||
return construction_archetype
|
thermal_archetype.indirect_heated_ratio = 0
|
||||||
return None
|
thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
|
||||||
|
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
|
||||||
|
_constructions = []
|
||||||
|
for catalog_construction in catalog_archetype.constructions:
|
||||||
|
construction = Construction()
|
||||||
|
construction.type = catalog_construction.type
|
||||||
|
if catalog_construction.window_ratio is not None:
|
||||||
|
for _orientation in catalog_construction.window_ratio:
|
||||||
|
if catalog_construction.window_ratio[_orientation] is None:
|
||||||
|
catalog_construction.window_ratio[_orientation] = 0
|
||||||
|
construction.window_ratio = catalog_construction.window_ratio
|
||||||
|
_layers = []
|
||||||
|
for layer_archetype in catalog_construction.layers:
|
||||||
|
layer = Layer()
|
||||||
|
layer.thickness = layer_archetype.thickness
|
||||||
|
archetype_material = layer_archetype.material
|
||||||
|
layer.name = archetype_material.name
|
||||||
|
layer.no_mass = archetype_material.no_mass
|
||||||
|
if archetype_material.no_mass:
|
||||||
|
layer.thermal_resistance = archetype_material.thermal_resistance
|
||||||
|
else:
|
||||||
|
layer.density = archetype_material.density
|
||||||
|
layer.conductivity = archetype_material.conductivity
|
||||||
|
layer.specific_heat = archetype_material.specific_heat
|
||||||
|
layer.solar_absorptance = archetype_material.solar_absorptance
|
||||||
|
layer.thermal_absorptance = archetype_material.thermal_absorptance
|
||||||
|
layer.visible_absorptance = archetype_material.visible_absorptance
|
||||||
|
_layers.append(layer)
|
||||||
|
construction.layers = _layers
|
||||||
|
|
||||||
def _assign_values(self, thermal_zones, archetype):
|
if catalog_construction.window is not None:
|
||||||
for thermal_zone in thermal_zones:
|
window_archetype = catalog_construction.window
|
||||||
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges
|
construction.window_frame_ratio = window_archetype.frame_ratio
|
||||||
thermal_zone.effective_thermal_capacity = archetype.thermal_capacity
|
construction.window_g_value = window_archetype.g_value
|
||||||
thermal_zone.indirectly_heated_area_ratio = 0
|
construction.window_overall_u_value = window_archetype.overall_u_value
|
||||||
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on
|
_constructions.append(construction)
|
||||||
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off
|
thermal_archetype.constructions = _constructions
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
|
|
||||||
thermal_boundary.construction_name = f'{thermal_boundary.type}_{construction_archetype.name}'
|
|
||||||
try:
|
|
||||||
thermal_boundary.window_ratio = 0
|
|
||||||
if thermal_boundary.type in ( cte.WALL, cte.ROOF):
|
|
||||||
if construction_archetype.window is not None:
|
|
||||||
if -math.sqrt(2) / 2 < math.sin(thermal_boundary.parent_surface.azimuth) < math.sqrt(2) / 2:
|
|
||||||
if 0 < math.cos(thermal_boundary.parent_surface.azimuth):
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['north']) / 100
|
|
||||||
else:
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['south']) / 100
|
|
||||||
elif math.sqrt(2) / 2 <= math.sin(thermal_boundary.parent_surface.azimuth):
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['east']) / 100
|
|
||||||
else:
|
|
||||||
thermal_boundary.window_ratio = \
|
|
||||||
float(construction_archetype.window_ratio['west']) / 100
|
|
||||||
except ValueError:
|
|
||||||
# This is the normal operation way when the windows are defined in the geometry
|
|
||||||
continue
|
|
||||||
thermal_boundary.layers = []
|
|
||||||
for layer_archetype in construction_archetype.layers:
|
|
||||||
layer = Layer()
|
|
||||||
layer.thickness = layer_archetype.thickness
|
|
||||||
material = Material()
|
|
||||||
archetype_material = layer_archetype.material
|
|
||||||
material.name = archetype_material.name
|
|
||||||
material.id = archetype_material.id
|
|
||||||
material.no_mass = archetype_material.no_mass
|
|
||||||
if archetype_material.no_mass:
|
|
||||||
material.thermal_resistance = archetype_material.thermal_resistance
|
|
||||||
else:
|
|
||||||
material.density = archetype_material.density
|
|
||||||
material.conductivity = archetype_material.conductivity
|
|
||||||
material.specific_heat = archetype_material.specific_heat
|
|
||||||
material.solar_absorptance = archetype_material.solar_absorptance
|
|
||||||
material.thermal_absorptance = archetype_material.thermal_absorptance
|
|
||||||
material.visible_absorptance = archetype_material.visible_absorptance
|
|
||||||
layer.material = material
|
|
||||||
thermal_boundary.layers.append(layer)
|
|
||||||
# The agreement is that the layers are defined from outside to inside
|
|
||||||
external_layer = construction_archetype.layers[0]
|
|
||||||
external_surface = thermal_boundary.parent_surface
|
|
||||||
external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
|
|
||||||
external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
|
|
||||||
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
|
|
||||||
internal_surface = thermal_boundary.internal_surface
|
|
||||||
internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
|
|
||||||
internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
|
|
||||||
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
if construction_archetype.window is not None:
|
|
||||||
window_archetype = construction_archetype.window
|
|
||||||
thermal_opening.construction_name = window_archetype.name
|
|
||||||
thermal_opening.frame_ratio = window_archetype.frame_ratio
|
|
||||||
thermal_opening.g_value = window_archetype.g_value
|
|
||||||
thermal_opening.overall_u_value = window_archetype.overall_u_value
|
|
||||||
|
|
||||||
# todo: verify windows
|
|
||||||
@staticmethod
|
|
||||||
def _calculate_view_factors(thermal_zone):
|
|
||||||
"""
|
|
||||||
Get thermal zone view factors matrix
|
|
||||||
:return: [[float]]
|
|
||||||
"""
|
|
||||||
total_area = 0
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
total_area += thermal_boundary.opaque_area
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
total_area += thermal_opening.area
|
|
||||||
|
|
||||||
view_factors_matrix = []
|
|
||||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
|
||||||
values = []
|
|
||||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
|
||||||
value = 0
|
|
||||||
if thermal_boundary_1.id != thermal_boundary_2.id:
|
|
||||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
|
|
||||||
values.append(value)
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
|
|
||||||
values.append(value)
|
|
||||||
view_factors_matrix.append(values)
|
|
||||||
|
|
||||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
|
||||||
values = []
|
|
||||||
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
|
|
||||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
|
||||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
|
|
||||||
values.append(value)
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
for thermal_opening_2 in thermal_boundary.thermal_openings:
|
|
||||||
value = 0
|
|
||||||
if thermal_opening_1.id != thermal_opening_2.id:
|
|
||||||
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
|
|
||||||
values.append(value)
|
|
||||||
view_factors_matrix.append(values)
|
|
||||||
thermal_zone.view_factors_matrix = view_factors_matrix
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _create_storeys(building, archetype, divide_in_storeys):
|
|
||||||
building.average_storey_height = archetype.average_storey_height
|
|
||||||
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
|
|
||||||
divide_in_storeys=divide_in_storeys).thermal_zones
|
|
||||||
building.internal_zones[0].thermal_zones = thermal_zones
|
|
||||||
|
@ -8,11 +8,11 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
||||||
|
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
|
||||||
|
from hub.city_model_structure.building_demand.construction import Construction
|
||||||
from hub.city_model_structure.building_demand.layer import Layer
|
from hub.city_model_structure.building_demand.layer import Layer
|
||||||
from hub.city_model_structure.building_demand.material import Material
|
|
||||||
from hub.helpers.dictionaries import Dictionaries
|
from hub.helpers.dictionaries import Dictionaries
|
||||||
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
||||||
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
|
|
||||||
|
|
||||||
|
|
||||||
class NrelPhysicsParameters:
|
class NrelPhysicsParameters:
|
||||||
@ -44,28 +44,10 @@ class NrelPhysicsParameters:
|
|||||||
f' and climate zone {self._climate_zone}\n')
|
f' and climate zone {self._climate_zone}\n')
|
||||||
|
|
||||||
continue
|
continue
|
||||||
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
|
thermal_archetype = ThermalArchetype()
|
||||||
# one thermal zone per storey is assigned
|
self._assign_values(thermal_archetype, archetype)
|
||||||
if len(building.internal_zones) == 1:
|
|
||||||
if building.internal_zones[0].thermal_zones is None:
|
|
||||||
self._create_storeys(building, archetype, self._divide_in_storeys)
|
|
||||||
if self._divide_in_storeys:
|
|
||||||
for internal_zone in building.internal_zones:
|
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
|
||||||
else:
|
|
||||||
number_of_storeys = int(building.eave_height / building.average_storey_height)
|
|
||||||
thermal_zone = building.internal_zones[0].thermal_zones[0]
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys
|
|
||||||
else:
|
|
||||||
for internal_zone in building.internal_zones:
|
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
|
||||||
|
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._assign_values(internal_zone.thermal_zones, archetype)
|
internal_zone.thermal_archetype = thermal_archetype
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
self._calculate_view_factors(thermal_zone)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone):
|
def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone):
|
||||||
@ -80,111 +62,46 @@ class NrelPhysicsParameters:
|
|||||||
raise KeyError('archetype not found')
|
raise KeyError('archetype not found')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _search_construction_in_archetype(archetype, construction_type):
|
def _assign_values(thermal_archetype, catalog_archetype):
|
||||||
construction_archetypes = archetype.constructions
|
thermal_archetype.average_storey_height = catalog_archetype.average_storey_height
|
||||||
for construction_archetype in construction_archetypes:
|
thermal_archetype.extra_loses_due_to_thermal_bridges = catalog_archetype.extra_loses_due_to_thermal_bridges
|
||||||
if str(construction_type) == str(construction_archetype.type):
|
thermal_archetype.thermal_capacity = catalog_archetype.thermal_capacity
|
||||||
return construction_archetype
|
thermal_archetype.indirect_heated_ratio = catalog_archetype.indirect_heated_ratio
|
||||||
return None
|
thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
|
||||||
|
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
|
||||||
|
_constructions = []
|
||||||
|
for catalog_construction in catalog_archetype.constructions:
|
||||||
|
construction = Construction()
|
||||||
|
construction.type = catalog_construction.type
|
||||||
|
if catalog_construction.window_ratio is not None:
|
||||||
|
construction.window_ratio = {'north': catalog_construction.window_ratio,
|
||||||
|
'east': catalog_construction.window_ratio,
|
||||||
|
'south': catalog_construction.window_ratio,
|
||||||
|
'west': catalog_construction.window_ratio
|
||||||
|
}
|
||||||
|
_layers = []
|
||||||
|
for layer_archetype in catalog_construction.layers:
|
||||||
|
layer = Layer()
|
||||||
|
layer.thickness = layer_archetype.thickness
|
||||||
|
archetype_material = layer_archetype.material
|
||||||
|
layer.name = archetype_material.name
|
||||||
|
layer.no_mass = archetype_material.no_mass
|
||||||
|
if archetype_material.no_mass:
|
||||||
|
layer.thermal_resistance = archetype_material.thermal_resistance
|
||||||
|
else:
|
||||||
|
layer.density = archetype_material.density
|
||||||
|
layer.conductivity = archetype_material.conductivity
|
||||||
|
layer.specific_heat = archetype_material.specific_heat
|
||||||
|
layer.solar_absorptance = archetype_material.solar_absorptance
|
||||||
|
layer.thermal_absorptance = archetype_material.thermal_absorptance
|
||||||
|
layer.visible_absorptance = archetype_material.visible_absorptance
|
||||||
|
_layers.append(layer)
|
||||||
|
construction.layers = _layers
|
||||||
|
|
||||||
def _assign_values(self, thermal_zones, archetype):
|
if catalog_construction.window is not None:
|
||||||
for thermal_zone in thermal_zones:
|
window_archetype = catalog_construction.window
|
||||||
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges
|
construction.window_frame_ratio = window_archetype.frame_ratio
|
||||||
thermal_zone.effective_thermal_capacity = archetype.thermal_capacity
|
construction.window_g_value = window_archetype.g_value
|
||||||
thermal_zone.indirectly_heated_area_ratio = archetype.indirect_heated_ratio
|
construction.window_overall_u_value = window_archetype.overall_u_value
|
||||||
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on
|
_constructions.append(construction)
|
||||||
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off
|
thermal_archetype.constructions = _constructions
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
|
|
||||||
thermal_boundary.construction_name = construction_archetype.name
|
|
||||||
try:
|
|
||||||
thermal_boundary.window_ratio = construction_archetype.window_ratio
|
|
||||||
except ValueError:
|
|
||||||
# This is the normal operation way when the windows are defined in the geometry
|
|
||||||
continue
|
|
||||||
thermal_boundary.layers = []
|
|
||||||
for layer_archetype in construction_archetype.layers:
|
|
||||||
layer = Layer()
|
|
||||||
layer.thickness = layer_archetype.thickness
|
|
||||||
material = Material()
|
|
||||||
archetype_material = layer_archetype.material
|
|
||||||
material.name = archetype_material.name
|
|
||||||
material.id = archetype_material.id
|
|
||||||
material.no_mass = archetype_material.no_mass
|
|
||||||
if archetype_material.no_mass:
|
|
||||||
material.thermal_resistance = archetype_material.thermal_resistance
|
|
||||||
else:
|
|
||||||
material.density = archetype_material.density
|
|
||||||
material.conductivity = archetype_material.conductivity
|
|
||||||
material.specific_heat = archetype_material.specific_heat
|
|
||||||
material.solar_absorptance = archetype_material.solar_absorptance
|
|
||||||
material.thermal_absorptance = archetype_material.thermal_absorptance
|
|
||||||
material.visible_absorptance = archetype_material.visible_absorptance
|
|
||||||
layer.material = material
|
|
||||||
thermal_boundary.layers.append(layer)
|
|
||||||
# The agreement is that the layers are defined from outside to inside
|
|
||||||
external_layer = construction_archetype.layers[0]
|
|
||||||
external_surface = thermal_boundary.parent_surface
|
|
||||||
external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance
|
|
||||||
external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance
|
|
||||||
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
|
|
||||||
internal_surface = thermal_boundary.internal_surface
|
|
||||||
internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance
|
|
||||||
internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance
|
|
||||||
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
if construction_archetype.window is not None:
|
|
||||||
window_archetype = construction_archetype.window
|
|
||||||
thermal_opening.construction_name = window_archetype.name
|
|
||||||
thermal_opening.frame_ratio = window_archetype.frame_ratio
|
|
||||||
thermal_opening.g_value = window_archetype.g_value
|
|
||||||
thermal_opening.overall_u_value = window_archetype.overall_u_value
|
|
||||||
|
|
||||||
# todo: verify windows
|
|
||||||
@staticmethod
|
|
||||||
def _calculate_view_factors(thermal_zone):
|
|
||||||
"""
|
|
||||||
Get thermal zone view factors matrix
|
|
||||||
:return: [[float]]
|
|
||||||
"""
|
|
||||||
total_area = 0
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
total_area += thermal_boundary.opaque_area
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
total_area += thermal_opening.area
|
|
||||||
|
|
||||||
view_factors_matrix = []
|
|
||||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
|
||||||
values = []
|
|
||||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
|
||||||
value = 0
|
|
||||||
if thermal_boundary_1.id != thermal_boundary_2.id:
|
|
||||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
|
|
||||||
values.append(value)
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
|
||||||
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
|
|
||||||
values.append(value)
|
|
||||||
view_factors_matrix.append(values)
|
|
||||||
|
|
||||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
|
||||||
values = []
|
|
||||||
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
|
|
||||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
|
||||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
|
|
||||||
values.append(value)
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
for thermal_opening_2 in thermal_boundary.thermal_openings:
|
|
||||||
value = 0
|
|
||||||
if thermal_opening_1.id != thermal_opening_2.id:
|
|
||||||
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
|
|
||||||
values.append(value)
|
|
||||||
view_factors_matrix.append(values)
|
|
||||||
thermal_zone.view_factors_matrix = view_factors_matrix
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _create_storeys(building, archetype, divide_in_storeys):
|
|
||||||
building.average_storey_height = archetype.average_storey_height
|
|
||||||
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
|
|
||||||
divide_in_storeys=divide_in_storeys).thermal_zones
|
|
||||||
building.internal_zones[0].thermal_zones = thermal_zones
|
|
@ -30,7 +30,7 @@ class InselMonthlyEnergyBalance:
|
|||||||
demand = str(line).replace("['", '').replace("']", '').split()
|
demand = str(line).replace("['", '').replace("']", '').split()
|
||||||
for i in range(0, 2):
|
for i in range(0, 2):
|
||||||
if demand[i] != 'NaN':
|
if demand[i] != 'NaN':
|
||||||
aux = float(demand[i]) * 1000 # kWh to Wh
|
aux = float(demand[i]) * cte.WATTS_HOUR_TO_JULES * 1000 # kWh to J
|
||||||
demand[i] = str(aux)
|
demand[i] = str(aux)
|
||||||
else:
|
else:
|
||||||
demand[i] = '0'
|
demand[i] = '0'
|
||||||
@ -43,12 +43,12 @@ class InselMonthlyEnergyBalance:
|
|||||||
domestic_hot_water_demand = []
|
domestic_hot_water_demand = []
|
||||||
lighting_demand = []
|
lighting_demand = []
|
||||||
appliances_demand = []
|
appliances_demand = []
|
||||||
if building.internal_zones[0].thermal_zones is None:
|
if building.internal_zones[0].thermal_zones_from_internal_zones is None:
|
||||||
domestic_hot_water_demand = [0] * 12
|
domestic_hot_water_demand = [0] * 12
|
||||||
lighting_demand = [0] * 12
|
lighting_demand = [0] * 12
|
||||||
appliances_demand = [0] * 12
|
appliances_demand = [0] * 12
|
||||||
else:
|
else:
|
||||||
thermal_zone = building.internal_zones[0].thermal_zones[0]
|
thermal_zone = building.internal_zones[0].thermal_zones_from_internal_zones[0]
|
||||||
area = thermal_zone.total_floor_area
|
area = thermal_zone.total_floor_area
|
||||||
cold_water = building.cold_water_temperature[cte.MONTH]
|
cold_water = building.cold_water_temperature[cte.MONTH]
|
||||||
peak_flow = thermal_zone.domestic_hot_water.peak_flow
|
peak_flow = thermal_zone.domestic_hot_water.peak_flow
|
||||||
@ -66,7 +66,8 @@ class InselMonthlyEnergyBalance:
|
|||||||
for value in schedule.values:
|
for value in schedule.values:
|
||||||
total_day += value
|
total_day += value
|
||||||
for day_type in schedule.day_types:
|
for day_type in schedule.day_types:
|
||||||
total_lighting += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] * lighting_density
|
total_lighting += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] \
|
||||||
|
* lighting_density / cte.WATTS_HOUR_TO_JULES
|
||||||
lighting_demand.append(total_lighting * area)
|
lighting_demand.append(total_lighting * area)
|
||||||
|
|
||||||
for schedule in thermal_zone.appliances.schedules:
|
for schedule in thermal_zone.appliances.schedules:
|
||||||
@ -74,7 +75,8 @@ class InselMonthlyEnergyBalance:
|
|||||||
for value in schedule.values:
|
for value in schedule.values:
|
||||||
total_day += value
|
total_day += value
|
||||||
for day_type in schedule.day_types:
|
for day_type in schedule.day_types:
|
||||||
total_appliances += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] * appliances_density
|
total_appliances += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] \
|
||||||
|
* appliances_density / cte.WATTS_HOUR_TO_JULES
|
||||||
appliances_demand.append(total_appliances * area)
|
appliances_demand.append(total_appliances * area)
|
||||||
|
|
||||||
for schedule in thermal_zone.domestic_hot_water.schedules:
|
for schedule in thermal_zone.domestic_hot_water.schedules:
|
||||||
@ -83,7 +85,8 @@ class InselMonthlyEnergyBalance:
|
|||||||
total_day += value
|
total_day += value
|
||||||
for day_type in schedule.day_types:
|
for day_type in schedule.day_types:
|
||||||
demand = (
|
demand = (
|
||||||
peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * (service_temperature - cold_water[month])
|
peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY
|
||||||
|
* (service_temperature - cold_water[month]) / cte.WATTS_HOUR_TO_JULES
|
||||||
)
|
)
|
||||||
total_dhw_demand += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] * demand
|
total_dhw_demand += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] * demand
|
||||||
domestic_hot_water_demand.append(total_dhw_demand * area)
|
domestic_hot_water_demand.append(total_dhw_demand * area)
|
||||||
@ -97,14 +100,15 @@ class InselMonthlyEnergyBalance:
|
|||||||
|
|
||||||
def enrich(self):
|
def enrich(self):
|
||||||
"""
|
"""
|
||||||
Enrich the city by using the insel monthly energy balance output files
|
Enrich the city by using the insel monthly energy balance output files (J)
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
for building in self._city.buildings:
|
for building in self._city.buildings:
|
||||||
file_name = building.name + '.out'
|
file_name = building.name + '.out'
|
||||||
insel_output_file_path = Path(self._base_path / file_name).resolve()
|
insel_output_file_path = Path(self._base_path / file_name).resolve()
|
||||||
if insel_output_file_path.is_file():
|
if insel_output_file_path.is_file():
|
||||||
building.heating_demand[cte.MONTH], building.cooling_demand[cte.MONTH] = self._conditioning_demand(insel_output_file_path)
|
building.heating_demand[cte.MONTH], building.cooling_demand[cte.MONTH] \
|
||||||
|
= self._conditioning_demand(insel_output_file_path)
|
||||||
building.heating_demand[cte.YEAR] = [sum(building.heating_demand[cte.MONTH])]
|
building.heating_demand[cte.YEAR] = [sum(building.heating_demand[cte.MONTH])]
|
||||||
building.cooling_demand[cte.YEAR] = [sum(building.cooling_demand[cte.MONTH])]
|
building.cooling_demand[cte.YEAR] = [sum(building.cooling_demand[cte.MONTH])]
|
||||||
self._dhw_and_electric_demand()
|
self._dhw_and_electric_demand()
|
||||||
|
@ -34,7 +34,8 @@ class SimplifiedRadiosityAlgorithm:
|
|||||||
for key in self._results:
|
for key in self._results:
|
||||||
_irradiance = {}
|
_irradiance = {}
|
||||||
header_name = key.split(':')
|
header_name = key.split(':')
|
||||||
result = self._results[key]
|
# todo: @Pilar!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
result = self._results[key] / cte.WATTS_HOUR_TO_JULES
|
||||||
city_object_name = header_name[1]
|
city_object_name = header_name[1]
|
||||||
building = self._city.city_object(city_object_name)
|
building = self._city.city_object(city_object_name)
|
||||||
surface_id = header_name[2]
|
surface_id = header_name[2]
|
||||||
|
@ -71,8 +71,7 @@ class ComnetUsageParameters:
|
|||||||
# Due to the fact that python is not a typed language, the wrong object type is assigned to
|
# Due to the fact that python is not a typed language, the wrong object type is assigned to
|
||||||
# usage.occupancy when writing usage.occupancy = archetype.occupancy.
|
# usage.occupancy when writing usage.occupancy = archetype.occupancy.
|
||||||
# Same happens for lighting and appliances. Therefore, this walk around has been done.
|
# Same happens for lighting and appliances. Therefore, this walk around has been done.
|
||||||
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area \
|
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area
|
||||||
* cte.HOUR_TO_SECONDS
|
|
||||||
_occupancy = Occupancy()
|
_occupancy = Occupancy()
|
||||||
_occupancy.occupancy_density = archetype.occupancy.occupancy_density
|
_occupancy.occupancy_density = archetype.occupancy.occupancy_density
|
||||||
_occupancy.sensible_radiative_internal_gain = archetype.occupancy.sensible_radiative_internal_gain
|
_occupancy.sensible_radiative_internal_gain = archetype.occupancy.sensible_radiative_internal_gain
|
||||||
|
@ -71,8 +71,7 @@ class EilatUsageParameters:
|
|||||||
# Due to the fact that python is not a typed language, the wrong object type is assigned to
|
# Due to the fact that python is not a typed language, the wrong object type is assigned to
|
||||||
# usage.occupancy when writing usage.occupancy = archetype.occupancy.
|
# usage.occupancy when writing usage.occupancy = archetype.occupancy.
|
||||||
# Same happens for lighting and appliances. Therefore, this walk around has been done.
|
# Same happens for lighting and appliances. Therefore, this walk around has been done.
|
||||||
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area \
|
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area
|
||||||
* cte.HOUR_TO_SECONDS
|
|
||||||
_occupancy = Occupancy()
|
_occupancy = Occupancy()
|
||||||
_occupancy.occupancy_density = archetype.occupancy.occupancy_density
|
_occupancy.occupancy_density = archetype.occupancy.occupancy_density
|
||||||
_occupancy.sensible_radiative_internal_gain = archetype.occupancy.sensible_radiative_internal_gain
|
_occupancy.sensible_radiative_internal_gain = archetype.occupancy.sensible_radiative_internal_gain
|
||||||
|
@ -92,11 +92,11 @@ class NrcanUsageParameters:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _assign_values(usage, archetype, volume_per_area, cold_water_temperature):
|
def _assign_values(usage, archetype, volume_per_area, cold_water_temperature):
|
||||||
if archetype.mechanical_air_change > 0:
|
if archetype.mechanical_air_change > 0:
|
||||||
# ACH
|
# 1/s
|
||||||
usage.mechanical_air_change = archetype.mechanical_air_change
|
usage.mechanical_air_change = archetype.mechanical_air_change
|
||||||
elif archetype.ventilation_rate > 0:
|
elif archetype.ventilation_rate > 0:
|
||||||
# m3/m2.s to ACH
|
# m3/m2.s to 1/s
|
||||||
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area * cte.HOUR_TO_SECONDS
|
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area
|
||||||
else:
|
else:
|
||||||
usage.mechanical_air_change = 0
|
usage.mechanical_air_change = 0
|
||||||
_occupancy = Occupancy()
|
_occupancy = Occupancy()
|
||||||
|
@ -110,9 +110,10 @@ class EpwWeatherParameters:
|
|||||||
# new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
|
# new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
|
||||||
# number_invalid_records = new_value[new_value.epw == 99.9].count().epw
|
# number_invalid_records = new_value[new_value.epw == 99.9].count().epw
|
||||||
building.external_temperature[cte.HOUR] = self._weather_values['dry_bulb_temperature_c']
|
building.external_temperature[cte.HOUR] = self._weather_values['dry_bulb_temperature_c']
|
||||||
building.global_horizontal[cte.HOUR] = self._weather_values['global_horizontal_radiation_wh_m2']
|
building.global_horizontal[cte.HOUR] = self._weather_values[
|
||||||
building.diffuse[cte.HOUR] = self._weather_values['diffuse_horizontal_radiation_wh_m2']
|
'global_horizontal_radiation_wh_m2'] / cte.WATTS_HOUR_TO_JULES
|
||||||
building.beam[cte.HOUR] = self._weather_values['direct_normal_radiation_wh_m2']
|
building.diffuse[cte.HOUR] = self._weather_values['diffuse_horizontal_radiation_wh_m2'] / cte.WATTS_HOUR_TO_JULES
|
||||||
|
building.beam[cte.HOUR] = self._weather_values['direct_normal_radiation_wh_m2'] / cte.WATTS_HOUR_TO_JULES
|
||||||
building.cold_water_temperature[cte.HOUR] = wh().cold_water_temperature(building.external_temperature[cte.HOUR])
|
building.cold_water_temperature[cte.HOUR] = wh().cold_water_temperature(building.external_temperature[cte.HOUR])
|
||||||
|
|
||||||
# create the monthly and yearly values out of the hourly
|
# create the monthly and yearly values out of the hourly
|
||||||
|
@ -60,7 +60,7 @@ class CityObject(Models):
|
|||||||
self.wall_area = wall_area
|
self.wall_area = wall_area
|
||||||
window_ratio = 0
|
window_ratio = 0
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
window_ratio = thermal_boundary.window_ratio
|
window_ratio = thermal_boundary.window_ratio
|
||||||
break
|
break
|
||||||
|
@ -106,7 +106,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
self.assertIsNotNone(building.shell, 'building shell is none')
|
self.assertIsNotNone(building.shell, 'building shell is none')
|
||||||
|
|
||||||
def _check_thermal_zones(self, internal_zone):
|
def _check_thermal_zones(self, internal_zone):
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
|
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
|
||||||
self.assertIsNotNone(thermal_zone.footprint_area, 'thermal_zone floor area is none')
|
self.assertIsNotNone(thermal_zone.footprint_area, 'thermal_zone floor area is none')
|
||||||
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
|
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
|
||||||
@ -138,7 +138,6 @@ class TestConstructionFactory(TestCase):
|
|||||||
self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none')
|
self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none')
|
||||||
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
|
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
|
||||||
self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none')
|
self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none')
|
||||||
self.assertIsNotNone(thermal_boundary.construction_name, 'construction_name is none')
|
|
||||||
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')
|
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')
|
||||||
self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none')
|
self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none')
|
||||||
self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none')
|
self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none')
|
||||||
@ -150,17 +149,15 @@ class TestConstructionFactory(TestCase):
|
|||||||
def _check_thermal_openings(self, thermal_boundary):
|
def _check_thermal_openings(self, thermal_boundary):
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
for thermal_opening in thermal_boundary.thermal_openings:
|
||||||
self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none')
|
self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none')
|
||||||
self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction is none')
|
|
||||||
self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none')
|
self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none')
|
||||||
self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none')
|
self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none')
|
||||||
self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none')
|
self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none')
|
||||||
self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none')
|
self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none')
|
||||||
self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none')
|
self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none')
|
||||||
self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none')
|
self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none')
|
||||||
self.assertIsNotNone(thermal_opening.construction_name, 'thermal opening construction_name is none')
|
|
||||||
|
|
||||||
def _check_surfaces(self, thermal_boundary):
|
def _check_surfaces(self, thermal_boundary):
|
||||||
external_surface = thermal_boundary.parent_surface
|
external_surface = thermal_boundary.external_surface
|
||||||
internal_surface = thermal_boundary.internal_surface
|
internal_surface = thermal_boundary.internal_surface
|
||||||
self.assertIsNotNone(external_surface.short_wave_reflectance,
|
self.assertIsNotNone(external_surface.short_wave_reflectance,
|
||||||
'external surface short_wave_reflectance id is not none')
|
'external surface short_wave_reflectance id is not none')
|
||||||
@ -184,7 +181,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._check_thermal_zones(internal_zone)
|
self._check_thermal_zones(internal_zone)
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
self._check_thermal_boundaries(thermal_zone)
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||||
@ -202,25 +199,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._check_thermal_zones(internal_zone)
|
self._check_thermal_zones(internal_zone)
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
|
||||||
self._check_thermal_openings(thermal_boundary)
|
|
||||||
self._check_surfaces(thermal_boundary)
|
|
||||||
|
|
||||||
file = 'one_building_in_kelowna.gml'
|
|
||||||
city = self._get_citygml(file)
|
|
||||||
for building in city.buildings:
|
|
||||||
building.year_of_construction = 2006
|
|
||||||
building.function = self._internal_function('hft', building.function)
|
|
||||||
ConstructionFactory('nrel', city).enrich()
|
|
||||||
|
|
||||||
self._check_buildings(city)
|
|
||||||
for building in city.buildings:
|
|
||||||
for internal_zone in building.internal_zones:
|
|
||||||
self._check_thermal_zones(internal_zone)
|
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
self._check_thermal_boundaries(thermal_zone)
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||||
@ -238,7 +217,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._check_thermal_zones(internal_zone)
|
self._check_thermal_zones(internal_zone)
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
self._check_thermal_boundaries(thermal_zone)
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||||
@ -256,7 +235,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._check_thermal_zones(internal_zone)
|
self._check_thermal_zones(internal_zone)
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
self._check_thermal_boundaries(thermal_zone)
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||||
@ -277,7 +256,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._check_thermal_zones(internal_zone)
|
self._check_thermal_zones(internal_zone)
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
self._check_thermal_boundaries(thermal_zone)
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||||
@ -299,7 +278,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._check_thermal_zones(internal_zone)
|
self._check_thermal_zones(internal_zone)
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
self._check_thermal_boundaries(thermal_zone)
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||||
@ -321,7 +300,7 @@ class TestConstructionFactory(TestCase):
|
|||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self._check_thermal_zones(internal_zone)
|
self._check_thermal_zones(internal_zone)
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_boundaries(thermal_zone)
|
self._check_thermal_boundaries(thermal_zone)
|
||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||||
|
@ -51,7 +51,8 @@ class TestExports(TestCase):
|
|||||||
_irradiance = {}
|
_irradiance = {}
|
||||||
for key in self._results:
|
for key in self._results:
|
||||||
header_name = key.split(':')
|
header_name = key.split(':')
|
||||||
result = self._results[key]
|
# todo: @Pilar!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
result = self._results[key] / cte.WATTS_HOUR_TO_JULES
|
||||||
city_object_name = header_name[1]
|
city_object_name = header_name[1]
|
||||||
building = self._city.city_object(city_object_name)
|
building = self._city.city_object(city_object_name)
|
||||||
surface_id = header_name[2]
|
surface_id = header_name[2]
|
||||||
@ -100,7 +101,7 @@ class TestExports(TestCase):
|
|||||||
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
|
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
|
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
|
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
|
||||||
f'indirectly_heated_area_ratio is none')
|
f'indirectly_heated_area_ratio is none')
|
||||||
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
|
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
|
||||||
@ -113,11 +114,12 @@ class TestExports(TestCase):
|
|||||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||||
self.assertIsNotNone(thermal_boundary.type)
|
self.assertIsNotNone(thermal_boundary.type)
|
||||||
self.assertIsNotNone(thermal_boundary.opaque_area)
|
self.assertIsNotNone(thermal_boundary.opaque_area)
|
||||||
self.assertIsNotNone(thermal_boundary.window_ratio)
|
if thermal_boundary.type in (cte.WALL, cte.ROOF):
|
||||||
|
self.assertIsNotNone(thermal_boundary.window_ratio)
|
||||||
self.assertIsNotNone(thermal_boundary.u_value)
|
self.assertIsNotNone(thermal_boundary.u_value)
|
||||||
self.assertIsNotNone(thermal_boundary.thermal_openings)
|
self.assertIsNotNone(thermal_boundary.thermal_openings)
|
||||||
if thermal_boundary.type is not cte.GROUND:
|
if thermal_boundary.type is not cte.GROUND:
|
||||||
self.assertIsNotNone(thermal_boundary.parent_surface.short_wave_reflectance)
|
self.assertIsNotNone(thermal_boundary.external_surface.short_wave_reflectance)
|
||||||
|
|
||||||
for usage in internal_zone.usages:
|
for usage in internal_zone.usages:
|
||||||
self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none')
|
self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none')
|
||||||
|
@ -274,8 +274,8 @@ TestDBFactory
|
|||||||
{'yearly_domestic_hot_water_consumption': yearly_domestic_hot_water_consumption},
|
{'yearly_domestic_hot_water_consumption': yearly_domestic_hot_water_consumption},
|
||||||
{'monthly_distribution_systems_electrical_consumption': monthly_distribution_systems_electrical_consumption},
|
{'monthly_distribution_systems_electrical_consumption': monthly_distribution_systems_electrical_consumption},
|
||||||
{'yearly_distribution_systems_electrical_consumption': yearly_distribution_systems_electrical_consumption},
|
{'yearly_distribution_systems_electrical_consumption': yearly_distribution_systems_electrical_consumption},
|
||||||
{'monthly_on_site_electrical_production': monthly_on_site_electrical_production},
|
{'monthly_on_site_electrical_production': monthly_on_site_electrical_production * cte.WATTS_HOUR_TO_JULES},
|
||||||
{'yearly_on_site_electrical_production': yearly_on_site_electrical_production}
|
{'yearly_on_site_electrical_production': yearly_on_site_electrical_production * cte.WATTS_HOUR_TO_JULES}
|
||||||
]})
|
]})
|
||||||
|
|
||||||
db_building_id = _building.id
|
db_building_id = _building.id
|
||||||
|
@ -38,7 +38,7 @@ class TestGeometryFactory(TestCase):
|
|||||||
self.assertIsNot(len(internal_zone.usages), 0, 'no building usages defined')
|
self.assertIsNot(len(internal_zone.usages), 0, 'no building usages defined')
|
||||||
for usage in internal_zone.usages:
|
for usage in internal_zone.usages:
|
||||||
self.assertIsNotNone(usage.id, 'usage id is none')
|
self.assertIsNotNone(usage.id, 'usage id is none')
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_thermal_zone(thermal_zone)
|
self._check_thermal_zone(thermal_zone)
|
||||||
|
|
||||||
def _check_buildings(self, city):
|
def _check_buildings(self, city):
|
||||||
@ -46,7 +46,7 @@ class TestGeometryFactory(TestCase):
|
|||||||
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
|
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self.assertIsNotNone(internal_zone.usages, 'usage zones are not defined')
|
self.assertIsNotNone(internal_zone.usages, 'usage zones are not defined')
|
||||||
self.assertIsNotNone(internal_zone.thermal_zones, 'thermal zones are not defined')
|
self.assertIsNotNone(internal_zone.thermal_zones_from_internal_zones, 'thermal zones are not defined')
|
||||||
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
||||||
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
||||||
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
|
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
|
||||||
@ -105,7 +105,7 @@ class TestGeometryFactory(TestCase):
|
|||||||
if usage_key == 'comnet':
|
if usage_key == 'comnet':
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_extra_thermal_zone(thermal_zone)
|
self._check_extra_thermal_zone(thermal_zone)
|
||||||
# usage factory called first
|
# usage factory called first
|
||||||
city = self._get_citygml(file)
|
city = self._get_citygml(file)
|
||||||
@ -117,7 +117,7 @@ class TestGeometryFactory(TestCase):
|
|||||||
if usage_key == 'comnet':
|
if usage_key == 'comnet':
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_extra_thermal_zone(thermal_zone)
|
self._check_extra_thermal_zone(thermal_zone)
|
||||||
|
|
||||||
def _test_pluto(self, file):
|
def _test_pluto(self, file):
|
||||||
@ -135,7 +135,7 @@ class TestGeometryFactory(TestCase):
|
|||||||
if usage_key == 'comnet':
|
if usage_key == 'comnet':
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_extra_thermal_zone(thermal_zone)
|
self._check_extra_thermal_zone(thermal_zone)
|
||||||
# usage factory called first
|
# usage factory called first
|
||||||
city = self._get_citygml(file)
|
city = self._get_citygml(file)
|
||||||
@ -147,7 +147,7 @@ class TestGeometryFactory(TestCase):
|
|||||||
if usage_key == 'comnet':
|
if usage_key == 'comnet':
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self._check_extra_thermal_zone(thermal_zone)
|
self._check_extra_thermal_zone(thermal_zone)
|
||||||
|
|
||||||
def test_enrichment(self):
|
def test_enrichment(self):
|
||||||
|
@ -120,6 +120,7 @@ class TestExports(TestCase):
|
|||||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||||
UsageFactory('nrcan', city).enrich()
|
UsageFactory('nrcan', city).enrich()
|
||||||
WeatherFactory('epw', city).enrich()
|
WeatherFactory('epw', city).enrich()
|
||||||
|
print(self._output_path)
|
||||||
try:
|
try:
|
||||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -62,7 +62,7 @@ class TestGeometryFactory(TestCase):
|
|||||||
self.assertIsNotNone(building.internal_zones, 'building internal zones is none')
|
self.assertIsNotNone(building.internal_zones, 'building internal zones is none')
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self.assertIsNone(internal_zone.usages, 'usage zones are defined')
|
self.assertIsNone(internal_zone.usages, 'usage zones are defined')
|
||||||
self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined')
|
self.assertIsNone(internal_zone.thermal_archetype, 'thermal archetype is defined')
|
||||||
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
||||||
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
||||||
self.assertIsNone(building.terrains, 'building terrains is not none')
|
self.assertIsNone(building.terrains, 'building terrains is not none')
|
||||||
|
@ -51,7 +51,8 @@ class TestExports(TestCase):
|
|||||||
_irradiance = {}
|
_irradiance = {}
|
||||||
for key in self._results:
|
for key in self._results:
|
||||||
header_name = key.split(':')
|
header_name = key.split(':')
|
||||||
result = self._results[key]
|
# todo: @Pilar!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
result = self._results[key] / cte.WATTS_HOUR_TO_JULES
|
||||||
city_object_name = header_name[1]
|
city_object_name = header_name[1]
|
||||||
building = self._city.city_object(city_object_name)
|
building = self._city.city_object(city_object_name)
|
||||||
surface_id = header_name[2]
|
surface_id = header_name[2]
|
||||||
@ -100,7 +101,7 @@ class TestExports(TestCase):
|
|||||||
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
|
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
|
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
|
||||||
for thermal_zone in internal_zone.thermal_zones:
|
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||||
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
|
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
|
||||||
f'indirectly_heated_area_ratio is none')
|
f'indirectly_heated_area_ratio is none')
|
||||||
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
|
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
|
||||||
@ -117,7 +118,7 @@ class TestExports(TestCase):
|
|||||||
self.assertIsNotNone(thermal_boundary.u_value)
|
self.assertIsNotNone(thermal_boundary.u_value)
|
||||||
self.assertIsNotNone(thermal_boundary.thermal_openings)
|
self.assertIsNotNone(thermal_boundary.thermal_openings)
|
||||||
if thermal_boundary.type is not cte.GROUND:
|
if thermal_boundary.type is not cte.GROUND:
|
||||||
self.assertIsNotNone(thermal_boundary.parent_surface.short_wave_reflectance)
|
self.assertIsNotNone(thermal_boundary.external_surface.short_wave_reflectance)
|
||||||
|
|
||||||
for usage in internal_zone.usages:
|
for usage in internal_zone.usages:
|
||||||
self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none')
|
self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none')
|
||||||
|
Loading…
Reference in New Issue
Block a user