forked from s_ranjbar/city_retrofit
Merge remote-tracking branch 'origin/master'
# Conflicts: # exports/formats/idf.py
This commit is contained in:
commit
0592f2ce04
|
@ -31,7 +31,6 @@ class Building(CityObject):
|
|||
self._storeys_above_ground = None
|
||||
self._floor_area = None
|
||||
self._roof_type = None
|
||||
self._storeys = None
|
||||
self._internal_zones = None
|
||||
self._shell = None
|
||||
self._type = 'building'
|
||||
|
|
|
@ -13,28 +13,28 @@ class Appliances:
|
|||
Appliances class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._appliances_density = None
|
||||
self._density = None
|
||||
self._convective_fraction = None
|
||||
self._radiative_fraction = None
|
||||
self._latent_fraction = None
|
||||
self._schedules = None
|
||||
|
||||
@property
|
||||
def appliances_density(self) -> Union[None, float]:
|
||||
def density(self) -> Union[None, float]:
|
||||
"""
|
||||
Get appliances density in Watts per m2
|
||||
:return: None or float
|
||||
"""
|
||||
return self._appliances_density
|
||||
return self._density
|
||||
|
||||
@appliances_density.setter
|
||||
def appliances_density(self, value):
|
||||
@density.setter
|
||||
def density(self, value):
|
||||
"""
|
||||
Set appliances density in Watts per m2
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._appliances_density = float(value)
|
||||
self._density = float(value)
|
||||
|
||||
@property
|
||||
def convective_fraction(self) -> Union[None, float]:
|
||||
|
@ -91,6 +91,7 @@ class Appliances:
|
|||
def schedules(self) -> Union[None, List[Schedule]]:
|
||||
"""
|
||||
Get schedules
|
||||
dataType = fraction
|
||||
:return: None or [Schedule]
|
||||
"""
|
||||
return self._schedules
|
||||
|
@ -99,6 +100,7 @@ class Appliances:
|
|||
def schedules(self, value):
|
||||
"""
|
||||
Set schedules
|
||||
dataType = fraction
|
||||
:param value: [Schedule]
|
||||
"""
|
||||
self._schedules = value
|
||||
|
|
|
@ -111,6 +111,7 @@ class InternalGains:
|
|||
def schedules(self) -> Union[None, List[Schedule]]:
|
||||
"""
|
||||
Get internal gain schedule
|
||||
dataType = fraction
|
||||
:return: [Schedule]
|
||||
"""
|
||||
return self._schedules
|
||||
|
@ -119,6 +120,7 @@ class InternalGains:
|
|||
def schedules(self, value):
|
||||
"""
|
||||
Set internal gain schedule
|
||||
dataType = fraction
|
||||
:param value: [Schedule]
|
||||
"""
|
||||
self._schedules = value
|
||||
|
|
|
@ -121,4 +121,3 @@ class InternalZone:
|
|||
:param value: [ThermalZone]
|
||||
"""
|
||||
self._thermal_zones = value
|
||||
|
||||
|
|
|
@ -13,28 +13,28 @@ class Lighting:
|
|||
Lighting class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._lighting_density = None
|
||||
self._density = None
|
||||
self._convective_fraction = None
|
||||
self._radiative_fraction = None
|
||||
self._latent_fraction = None
|
||||
self._schedules = None
|
||||
|
||||
@property
|
||||
def lighting_density(self) -> Union[None, float]:
|
||||
def density(self) -> Union[None, float]:
|
||||
"""
|
||||
Get lighting density in Watts per m2
|
||||
:return: None or float
|
||||
"""
|
||||
return self._lighting_density
|
||||
return self._density
|
||||
|
||||
@lighting_density.setter
|
||||
def lighting_density(self, value):
|
||||
@density.setter
|
||||
def density(self, value):
|
||||
"""
|
||||
Set lighting density in Watts per m2
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._lighting_density = float(value)
|
||||
self._density = float(value)
|
||||
|
||||
@property
|
||||
def convective_fraction(self) -> Union[None, float]:
|
||||
|
@ -91,6 +91,7 @@ class Lighting:
|
|||
def schedules(self) -> Union[None, List[Schedule]]:
|
||||
"""
|
||||
Get schedules
|
||||
dataType = fraction
|
||||
:return: None or [Schedule]
|
||||
"""
|
||||
return self._schedules
|
||||
|
@ -99,6 +100,7 @@ class Lighting:
|
|||
def schedules(self, value):
|
||||
"""
|
||||
Set schedules
|
||||
dataType = fraction
|
||||
:param value: [Schedule]
|
||||
"""
|
||||
self._schedules = value
|
||||
|
|
|
@ -24,7 +24,7 @@ class Occupancy:
|
|||
@property
|
||||
def occupancy_density(self) -> Union[None, float]:
|
||||
"""
|
||||
Get density in m2 per person
|
||||
Get density in persons per m2
|
||||
:return: None or float
|
||||
"""
|
||||
return self._occupancy_density
|
||||
|
@ -32,7 +32,7 @@ class Occupancy:
|
|||
@occupancy_density.setter
|
||||
def occupancy_density(self, value):
|
||||
"""
|
||||
Set density in m2 per persons
|
||||
Set density in persons per m2
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
|
@ -93,6 +93,7 @@ class Occupancy:
|
|||
def occupancy_schedules(self) -> Union[None, List[Schedule]]:
|
||||
"""
|
||||
Get occupancy schedules
|
||||
dataType = fraction
|
||||
:return: None or [Schedule]
|
||||
"""
|
||||
return self._occupancy_schedules
|
||||
|
@ -101,6 +102,7 @@ class Occupancy:
|
|||
def occupancy_schedules(self, value):
|
||||
"""
|
||||
Set occupancy schedules
|
||||
dataType = fraction
|
||||
:param value: [Schedule]
|
||||
"""
|
||||
self._occupancy_schedules = value
|
||||
|
|
|
@ -16,7 +16,7 @@ class Storey:
|
|||
"""
|
||||
Storey class
|
||||
"""
|
||||
def __init__(self, name, storey_surfaces, neighbours, volume, floor_area):
|
||||
def __init__(self, name, storey_surfaces, neighbours, volume, internal_zone, floor_area):
|
||||
self._name = name
|
||||
self._storey_surfaces = storey_surfaces
|
||||
self._thermal_boundaries = None
|
||||
|
@ -24,6 +24,7 @@ class Storey:
|
|||
self._thermal_zone = None
|
||||
self._neighbours = neighbours
|
||||
self._volume = volume
|
||||
self._internal_zone = internal_zone
|
||||
self._floor_area = floor_area
|
||||
|
||||
@property
|
||||
|
@ -87,7 +88,7 @@ class Storey:
|
|||
:return: ThermalZone
|
||||
"""
|
||||
if self._thermal_zone is None:
|
||||
self._thermal_zone = ThermalZone(self.thermal_boundaries, self.volume, self.floor_area)
|
||||
self._thermal_zone = ThermalZone(self.thermal_boundaries, self._internal_zone, self.volume, self.floor_area)
|
||||
return self._thermal_zone
|
||||
|
||||
@property
|
||||
|
|
|
@ -55,7 +55,7 @@ class ThermalControl:
|
|||
Set heating set point defined for a thermal zone in Celsius
|
||||
:param value: float
|
||||
"""
|
||||
self._mean_heating_set_point = value
|
||||
self._mean_heating_set_point = float(value)
|
||||
|
||||
@property
|
||||
def heating_set_back(self) -> Union[None, float]:
|
||||
|
@ -94,12 +94,13 @@ class ThermalControl:
|
|||
Set cooling set point defined for a thermal zone in Celsius
|
||||
:param value: float
|
||||
"""
|
||||
self._mean_cooling_set_point = value
|
||||
self._mean_cooling_set_point = float(value)
|
||||
|
||||
@property
|
||||
def hvac_availability_schedules(self) -> Union[None, List[Schedule]]:
|
||||
"""
|
||||
Get the availability of the conditioning system defined for a thermal zone
|
||||
dataType = on/off
|
||||
:return: None or [Schedule]
|
||||
"""
|
||||
return self._hvac_availability_schedules
|
||||
|
@ -108,6 +109,7 @@ class ThermalControl:
|
|||
def hvac_availability_schedules(self, value):
|
||||
"""
|
||||
Set the availability of the conditioning system defined for a thermal zone
|
||||
dataType = on/off
|
||||
:param value: [Schedule]
|
||||
"""
|
||||
self._hvac_availability_schedules = value
|
||||
|
@ -116,6 +118,7 @@ class ThermalControl:
|
|||
def heating_set_point_schedules(self) -> Union[None, List[Schedule]]:
|
||||
"""
|
||||
Get heating set point schedule defined for a thermal zone in Celsius
|
||||
dataType = temperature
|
||||
:return: None or [Schedule]
|
||||
"""
|
||||
return self._heating_set_point_schedules
|
||||
|
@ -124,6 +127,7 @@ class ThermalControl:
|
|||
def heating_set_point_schedules(self, value):
|
||||
"""
|
||||
Set heating set point schedule defined for a thermal zone in Celsius
|
||||
dataType = temperature
|
||||
:param value: [Schedule]
|
||||
"""
|
||||
self._heating_set_point_schedules = value
|
||||
|
@ -132,6 +136,7 @@ class ThermalControl:
|
|||
def cooling_set_point_schedules(self) -> Union[None, List[Schedule]]:
|
||||
"""
|
||||
Get cooling set point schedule defined for a thermal zone in Celsius
|
||||
dataType = temperature
|
||||
:return: None or [Schedule]
|
||||
"""
|
||||
return self._cooling_set_point_schedules
|
||||
|
@ -140,6 +145,7 @@ class ThermalControl:
|
|||
def cooling_set_point_schedules(self, value):
|
||||
"""
|
||||
Set cooling set point schedule defined for a thermal zone in Celsius
|
||||
dataType = temperature
|
||||
:param value: [Schedule]
|
||||
"""
|
||||
self._cooling_set_point_schedules = value
|
||||
|
|
|
@ -5,22 +5,29 @@ Copyright © 2022 Concordia CERC group
|
|||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
import uuid
|
||||
import uuid, sys
|
||||
import copy
|
||||
from typing import List, Union, TypeVar
|
||||
from city_model_structure.building_demand.usage_zone import UsageZone
|
||||
from city_model_structure.building_demand.occupancy import Occupancy
|
||||
from city_model_structure.building_demand.appliances import Appliances
|
||||
from city_model_structure.building_demand.lighting import Lighting
|
||||
from city_model_structure.building_demand.internal_gains import InternalGains
|
||||
from city_model_structure.attributes.schedule import Schedule
|
||||
from city_model_structure.building_demand.thermal_control import ThermalControl
|
||||
from city_model_structure.energy_systems.hvac_system import HvacSystem
|
||||
import helpers.constants as cte
|
||||
|
||||
ThermalBoundary = TypeVar('ThermalBoundary')
|
||||
InternalZone = TypeVar('InternalZone')
|
||||
|
||||
|
||||
class ThermalZone:
|
||||
"""
|
||||
ThermalZone class
|
||||
"""
|
||||
def __init__(self, thermal_boundaries, volume, floor_area):
|
||||
def __init__(self, thermal_boundaries, parent_internal_zone, volume, floor_area):
|
||||
self._id = None
|
||||
self._parent_internal_zone = parent_internal_zone
|
||||
self._floor_area = floor_area
|
||||
self._thermal_boundaries = thermal_boundaries
|
||||
self._additional_thermal_bridge_u_value = None
|
||||
|
@ -30,11 +37,19 @@ class ThermalZone:
|
|||
self._infiltration_rate_system_off = None
|
||||
self._volume = volume
|
||||
self._ordinate_number = None
|
||||
self._usage_zones = None
|
||||
self._thermal_control = None
|
||||
self._hvac_system = None
|
||||
self._view_factors_matrix = None
|
||||
|
||||
self._usage = None
|
||||
self._not_detailed_source_mean_annual_internal_gains = None
|
||||
self._hours_day = None
|
||||
self._days_year = None
|
||||
self._mechanical_air_change = None
|
||||
self._occupancy = None
|
||||
self._lighting = None
|
||||
self._appliances = None
|
||||
self._internal_gains = None
|
||||
self._thermal_control = None
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
|
@ -169,42 +184,6 @@ class ThermalZone:
|
|||
if value is not None:
|
||||
self._ordinate_number = int(value)
|
||||
|
||||
@property
|
||||
def usage_zones(self) -> [UsageZone]:
|
||||
"""
|
||||
Get list of usage zones and the percentage of thermal zone's volume affected by that usage
|
||||
From internal_zone
|
||||
:return: [UsageZone]
|
||||
"""
|
||||
return self._usage_zones
|
||||
|
||||
@usage_zones.setter
|
||||
def usage_zones(self, values):
|
||||
"""
|
||||
Set list of usage zones and the percentage of thermal zone's volume affected by that usage
|
||||
From internal_zone
|
||||
:param values: [UsageZone]
|
||||
"""
|
||||
self._usage_zones = values
|
||||
|
||||
@property
|
||||
def thermal_control(self) -> Union[None, ThermalControl]:
|
||||
"""
|
||||
Get thermal control of this thermal zone
|
||||
From internal_zone
|
||||
:return: None or ThermalControl
|
||||
"""
|
||||
return self._thermal_control
|
||||
|
||||
@thermal_control.setter
|
||||
def thermal_control(self, value):
|
||||
"""
|
||||
Set thermal control for this thermal zone
|
||||
From internal_zone
|
||||
:param value: ThermalControl
|
||||
"""
|
||||
self._thermal_control = value
|
||||
|
||||
@property
|
||||
def hvac_system(self) -> Union[None, HvacSystem]:
|
||||
"""
|
||||
|
@ -212,16 +191,7 @@ class ThermalZone:
|
|||
From internal_zone
|
||||
:return: None or HvacSystem
|
||||
"""
|
||||
return self._hvac_system
|
||||
|
||||
@hvac_system.setter
|
||||
def hvac_system(self, value):
|
||||
"""
|
||||
Set HVAC system installed for this thermal zone
|
||||
From internal_zone
|
||||
:param value: HvacSystem
|
||||
"""
|
||||
self._hvac_system = value
|
||||
return self._parent_internal_zone.hvac_system
|
||||
|
||||
@property
|
||||
def view_factors_matrix(self):
|
||||
|
@ -238,3 +208,477 @@ class ThermalZone:
|
|||
:param value: [[float]]
|
||||
"""
|
||||
self._view_factors_matrix = value
|
||||
|
||||
@property
|
||||
def usage(self) -> Union[None, str]:
|
||||
"""
|
||||
Get thermal zone usage
|
||||
:return: None or str
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._usage is None:
|
||||
self._usage = ''
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
self._usage += str(round(usage_zone.percentage) * 100) + '_' + usage_zone.usage + '_'
|
||||
self._usage = self._usage[:-1]
|
||||
return self._usage
|
||||
|
||||
@usage.setter
|
||||
def usage(self, value):
|
||||
"""
|
||||
Set thermal zone usage
|
||||
:param value: str
|
||||
"""
|
||||
if value is not None:
|
||||
self._usage = str(value)
|
||||
|
||||
@staticmethod
|
||||
def _get_schedule_of_day(requested_day_type, schedules):
|
||||
for schedule in schedules:
|
||||
for day_type in schedule.day_types:
|
||||
if day_type == requested_day_type:
|
||||
return schedule
|
||||
return None
|
||||
|
||||
@property
|
||||
def not_detailed_source_mean_annual_internal_gains(self) -> Union[None, List[InternalGains]]:
|
||||
"""
|
||||
Get thermal zone internal gains with unknown energy source
|
||||
:return: [InternalGains]
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._not_detailed_source_mean_annual_internal_gains is None:
|
||||
_grouped_internal_gain = InternalGains()
|
||||
_grouped_internal_gain.type = 'grouped internal gains for thermal zone'
|
||||
_average_internal_gain = 0
|
||||
_convective_part = 0
|
||||
_radiative_part = 0
|
||||
_latent_part = 0
|
||||
for _usage_zone in self._parent_internal_zone.usage_zones:
|
||||
if _usage_zone.not_detailed_source_mean_annual_internal_gains is None:
|
||||
return None
|
||||
for _internal_gain in _usage_zone.not_detailed_source_mean_annual_internal_gains:
|
||||
_average_internal_gain += _internal_gain.average_internal_gain
|
||||
_convective_part += _internal_gain.average_internal_gain * _internal_gain.convective_fraction
|
||||
_radiative_part += _internal_gain.average_internal_gain * _internal_gain.radiative_fraction
|
||||
_latent_part += _internal_gain.average_internal_gain * _internal_gain.latent_fraction
|
||||
|
||||
_grouped_internal_gain.average_internal_gain = _average_internal_gain
|
||||
if _average_internal_gain > 0:
|
||||
_grouped_internal_gain.convective_fraction = _convective_part / _average_internal_gain
|
||||
_grouped_internal_gain.radiative_fraction = _radiative_part / _average_internal_gain
|
||||
_grouped_internal_gain.latent_fraction = _latent_part / _average_internal_gain
|
||||
|
||||
_internal_gains_reference = \
|
||||
self._parent_internal_zone.usage_zones[0].not_detailed_source_mean_annual_internal_gains[0]
|
||||
if _internal_gains_reference.schedules is not None:
|
||||
day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY, cte.SUNDAY]
|
||||
schedule_of_days = []
|
||||
for i_day in range(0, 7):
|
||||
schedule_of_day = \
|
||||
copy.deepcopy(self._get_schedule_of_day(day_types[i_day], _internal_gains_reference.schedules))
|
||||
if schedule_of_day is None:
|
||||
sys.stderr.write(f'Error. Not found requested day type when generating internal gains schedules '
|
||||
f'in thermal_zone.\n')
|
||||
schedule_of_day.day_types = [day_types[i_day]]
|
||||
new_values = []
|
||||
for i_value in range(0, len(_internal_gains_reference.schedules[0].values)):
|
||||
_new_value = 0
|
||||
for _usage_zone in self._parent_internal_zone.usage_zones:
|
||||
for _internal_gain in _usage_zone.not_detailed_source_mean_annual_internal_gains:
|
||||
_value = self._get_schedule_of_day(day_types[i_day], _internal_gain.schedules)
|
||||
if _value is None:
|
||||
sys.stderr.write(f'Error. Not found requested day type when generating internal gains schedules '
|
||||
f'in thermal_zone.\n')
|
||||
_value = _value.values[i_value]
|
||||
_new_value += _usage_zone.percentage * _value \
|
||||
/ len(_usage_zone.not_detailed_source_mean_annual_internal_gains)
|
||||
new_values.append(_new_value)
|
||||
schedule_of_day.values = new_values
|
||||
schedule_of_days.append(schedule_of_day)
|
||||
_grouped_internal_gain.schedules = schedule_of_days
|
||||
else:
|
||||
_grouped_internal_gain.convective_fraction = 0
|
||||
_grouped_internal_gain.radiative_fraction = 0
|
||||
_grouped_internal_gain.latent_fraction = 0
|
||||
|
||||
self._not_detailed_source_mean_annual_internal_gains = [_grouped_internal_gain]
|
||||
return self._not_detailed_source_mean_annual_internal_gains
|
||||
|
||||
@not_detailed_source_mean_annual_internal_gains.setter
|
||||
def not_detailed_source_mean_annual_internal_gains(self, value):
|
||||
"""
|
||||
Set thermal zone internal gains with unknown energy source
|
||||
:param value: [InternalGains]
|
||||
"""
|
||||
self._not_detailed_source_mean_annual_internal_gains = value
|
||||
|
||||
@property
|
||||
def hours_day(self) -> Union[None, float]:
|
||||
"""
|
||||
Get thermal zone usage hours per day
|
||||
:return: None or float
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._hours_day is None:
|
||||
self._hours_day = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
self._hours_day += usage_zone.percentage * usage_zone.hours_day
|
||||
return self._hours_day
|
||||
|
||||
@hours_day.setter
|
||||
def hours_day(self, value):
|
||||
"""
|
||||
Set thermal zone usage hours per day
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._hours_day = float(value)
|
||||
|
||||
@property
|
||||
def days_year(self) -> Union[None, float]:
|
||||
"""
|
||||
Get thermal zone usage days per year
|
||||
:return: None or float
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._days_year is None:
|
||||
self._days_year = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
self._days_year += usage_zone.percentage * usage_zone.days_year
|
||||
return self._days_year
|
||||
|
||||
@days_year.setter
|
||||
def days_year(self, value):
|
||||
"""
|
||||
Set thermal zone usage days per year
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._days_year = float(value)
|
||||
|
||||
@property
|
||||
def mechanical_air_change(self) -> Union[None, float]:
|
||||
"""
|
||||
Get thermal zone mechanical air change in air change per hour (ACH)
|
||||
:return: None or float
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._mechanical_air_change is None:
|
||||
self._mechanical_air_change = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
if usage_zone.mechanical_air_change is None:
|
||||
return None
|
||||
self._mechanical_air_change += usage_zone.percentage * usage_zone.mechanical_air_change
|
||||
return self._mechanical_air_change
|
||||
|
||||
@mechanical_air_change.setter
|
||||
def mechanical_air_change(self, value):
|
||||
"""
|
||||
Set thermal zone mechanical air change in air change per hour (ACH)
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._mechanical_air_change = float(value)
|
||||
|
||||
@property
|
||||
def occupancy(self) -> Union[None, Occupancy]:
|
||||
"""
|
||||
Get occupancy in the thermal zone
|
||||
:return: None or Occupancy
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._occupancy is None:
|
||||
self._occupancy = Occupancy()
|
||||
_occupancy_density = 0
|
||||
_convective_part = 0
|
||||
_radiative_part = 0
|
||||
_latent_part = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
if usage_zone.occupancy is None:
|
||||
return None
|
||||
_occupancy_density += usage_zone.percentage * usage_zone.occupancy.occupancy_density
|
||||
if usage_zone.occupancy.sensible_convective_internal_gain is not None:
|
||||
_convective_part += usage_zone.percentage * usage_zone.occupancy.sensible_convective_internal_gain
|
||||
_radiative_part += usage_zone.percentage * usage_zone.occupancy.sensible_radiative_internal_gain
|
||||
_latent_part += usage_zone.percentage * usage_zone.occupancy.latent_internal_gain
|
||||
self._occupancy.occupancy_density = _occupancy_density
|
||||
self._occupancy.sensible_convective_internal_gain = _convective_part
|
||||
self._occupancy.sensible_radiative_internal_gain = _radiative_part
|
||||
self._occupancy.latent_internal_gain = _latent_part
|
||||
|
||||
_occupancy_reference = self._parent_internal_zone.usage_zones[0].occupancy
|
||||
if _occupancy_reference.occupancy_schedules is not None:
|
||||
_schedules = []
|
||||
for i_schedule in range(0, len(_occupancy_reference.occupancy_schedules)):
|
||||
schedule = copy.deepcopy(_occupancy_reference.occupancy_schedules[i_schedule])
|
||||
new_values = []
|
||||
for i_value in range(0, len(_occupancy_reference.occupancy_schedules[i_schedule].values)):
|
||||
_new_value = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
_new_value += usage_zone.percentage * usage_zone.occupancy.occupancy_schedules[i_schedule].values[i_value]
|
||||
new_values.append(_new_value)
|
||||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
self._occupancy.occupancy_schedules = _schedules
|
||||
return self._occupancy
|
||||
|
||||
@occupancy.setter
|
||||
def occupancy(self, value):
|
||||
"""
|
||||
Set occupancy in the thermal zone
|
||||
:param value: Occupancy
|
||||
"""
|
||||
self._occupancy = value
|
||||
|
||||
@property
|
||||
def lighting(self) -> Union[None, Lighting]:
|
||||
"""
|
||||
Get lighting information
|
||||
:return: None or Lighting
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._lighting is None:
|
||||
self._lighting = Lighting()
|
||||
_lighting_density = 0
|
||||
_convective_part = 0
|
||||
_radiative_part = 0
|
||||
_latent_part = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
if usage_zone.lighting is None:
|
||||
return None
|
||||
_lighting_density += usage_zone.percentage * usage_zone.lighting.density
|
||||
if usage_zone.lighting.convective_fraction is not None:
|
||||
_convective_part += usage_zone.percentage * usage_zone.lighting.density \
|
||||
* usage_zone.lighting.convective_fraction
|
||||
_radiative_part += usage_zone.percentage * usage_zone.lighting.density \
|
||||
* usage_zone.lighting.radiative_fraction
|
||||
_latent_part += usage_zone.percentage * usage_zone.lighting.density \
|
||||
* usage_zone.lighting.latent_fraction
|
||||
self._lighting.density = _lighting_density
|
||||
if _lighting_density > 0:
|
||||
self._lighting.convective_fraction = _convective_part / _lighting_density
|
||||
self._lighting.radiative_fraction = _radiative_part / _lighting_density
|
||||
self._lighting.latent_fraction = _latent_part / _lighting_density
|
||||
else:
|
||||
self._lighting.convective_fraction = 0
|
||||
self._lighting.radiative_fraction = 0
|
||||
self._lighting.latent_fraction = 0
|
||||
|
||||
_lighting_reference = self._parent_internal_zone.usage_zones[0].lighting
|
||||
if _lighting_reference.schedules is not None:
|
||||
_schedules = []
|
||||
for i_schedule in range(0, len(_lighting_reference.schedules)):
|
||||
schedule = copy.deepcopy(_lighting_reference.schedules[i_schedule])
|
||||
new_values = []
|
||||
for i_value in range(0, len(_lighting_reference.schedules[i_schedule].values)):
|
||||
_new_value = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
_new_value += usage_zone.percentage * usage_zone.lighting.schedules[i_schedule].values[i_value]
|
||||
new_values.append(_new_value)
|
||||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
self._lighting.schedules = _schedules
|
||||
return self._lighting
|
||||
|
||||
@lighting.setter
|
||||
def lighting(self, value):
|
||||
"""
|
||||
Set lighting information
|
||||
:param value: Lighting
|
||||
"""
|
||||
self._lighting = value
|
||||
|
||||
@property
|
||||
def appliances(self) -> Union[None, Appliances]:
|
||||
"""
|
||||
Get appliances information
|
||||
:return: None or Appliances
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._appliances is None:
|
||||
self._appliances = Appliances()
|
||||
_appliances_density = 0
|
||||
_convective_part = 0
|
||||
_radiative_part = 0
|
||||
_latent_part = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
if usage_zone.appliances is None:
|
||||
return None
|
||||
_appliances_density += usage_zone.percentage * usage_zone.appliances.density
|
||||
if usage_zone.appliances.convective_fraction is not None:
|
||||
_convective_part += usage_zone.percentage * usage_zone.appliances.density \
|
||||
* usage_zone.appliances.convective_fraction
|
||||
_radiative_part += usage_zone.percentage * usage_zone.appliances.density \
|
||||
* usage_zone.appliances.radiative_fraction
|
||||
_latent_part += usage_zone.percentage * usage_zone.appliances.density \
|
||||
* usage_zone.appliances.latent_fraction
|
||||
self._appliances.density = _appliances_density
|
||||
if _appliances_density > 0:
|
||||
self._appliances.convective_fraction = _convective_part / _appliances_density
|
||||
self._appliances.radiative_fraction = _radiative_part / _appliances_density
|
||||
self._appliances.latent_fraction = _latent_part / _appliances_density
|
||||
else:
|
||||
self._appliances.convective_fraction = 0
|
||||
self._appliances.radiative_fraction = 0
|
||||
self._appliances.latent_fraction = 0
|
||||
|
||||
_appliances_reference = self._parent_internal_zone.usage_zones[0].appliances
|
||||
if _appliances_reference.schedules is not None:
|
||||
_schedules = []
|
||||
for i_schedule in range(0, len(_appliances_reference.schedules)):
|
||||
schedule = copy.deepcopy(_appliances_reference.schedules[i_schedule])
|
||||
new_values = []
|
||||
for i_value in range(0, len(_appliances_reference.schedules[i_schedule].values)):
|
||||
_new_value = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
_new_value += usage_zone.percentage * usage_zone.appliances.schedules[i_schedule].values[i_value]
|
||||
new_values.append(_new_value)
|
||||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
self._appliances.schedules = _schedules
|
||||
return self._appliances
|
||||
|
||||
@appliances.setter
|
||||
def appliances(self, value):
|
||||
"""
|
||||
Set appliances information
|
||||
:param value: Appliances
|
||||
"""
|
||||
self._appliances = value
|
||||
|
||||
@staticmethod
|
||||
def _add_internal_gain(internal_gain_type, _internal_gain):
|
||||
_internal_gain.average_internal_gain = internal_gain_type.density
|
||||
_internal_gain.latent_fraction = internal_gain_type.latent_fraction
|
||||
_internal_gain.radiative_fraction = internal_gain_type.radiative_fraction
|
||||
_internal_gain.convective_fraction = internal_gain_type.convective_fraction
|
||||
_internal_gain.schedules = internal_gain_type.schedules
|
||||
|
||||
def get_internal_gains(self) -> [InternalGains]:
|
||||
"""
|
||||
Calculates and returns the list of all internal gains defined
|
||||
:return: InternalGains
|
||||
"""
|
||||
if self.not_detailed_source_mean_annual_internal_gains is not None:
|
||||
self._internal_gains = []
|
||||
for _internal_gain in self.not_detailed_source_mean_annual_internal_gains:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
|
||||
if self.occupancy is not None:
|
||||
if self.occupancy.latent_internal_gain is not None:
|
||||
_internal_gain = InternalGains()
|
||||
_internal_gain.type = cte.OCCUPANCY
|
||||
_total_heat_gain = (self.occupancy.sensible_convective_internal_gain
|
||||
+ self.occupancy.sensible_radiative_internal_gain
|
||||
+ self.occupancy.latent_internal_gain)
|
||||
_internal_gain.average_internal_gain = _total_heat_gain
|
||||
if _total_heat_gain > 0:
|
||||
_internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain
|
||||
_internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain
|
||||
_internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain
|
||||
else:
|
||||
_internal_gain.latent_fraction = 0
|
||||
_internal_gain.radiative_fraction = 0
|
||||
_internal_gain.convective_fraction = 0
|
||||
_internal_gain.schedules = self.occupancy.occupancy_schedules
|
||||
if self._internal_gains is not None:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
else:
|
||||
self._internal_gains = [_internal_gain]
|
||||
|
||||
if self.lighting is not None:
|
||||
_internal_gain = InternalGains()
|
||||
_internal_gain.type = cte.LIGHTING
|
||||
self._add_internal_gain(self.lighting, _internal_gain)
|
||||
if self._internal_gains is not None:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
else:
|
||||
self._internal_gains = [_internal_gain]
|
||||
|
||||
if self.appliances is not None:
|
||||
_internal_gain = InternalGains()
|
||||
_internal_gain.type = cte.APPLIANCES
|
||||
self._add_internal_gain(self.appliances, _internal_gain)
|
||||
if self._internal_gains is not None:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
else:
|
||||
self._internal_gains = [_internal_gain]
|
||||
|
||||
return self._internal_gains
|
||||
|
||||
@property
|
||||
def thermal_control(self) -> Union[None, ThermalControl]:
|
||||
"""
|
||||
Get thermal control of this thermal zone
|
||||
:return: None or ThermalControl
|
||||
"""
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
return None
|
||||
if self._thermal_control is None:
|
||||
self._thermal_control = ThermalControl()
|
||||
_mean_heating_set_point = 0
|
||||
_heating_set_back = 0
|
||||
_mean_cooling_set_point = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
_mean_heating_set_point += usage_zone.percentage * usage_zone.thermal_control.mean_heating_set_point
|
||||
_heating_set_back += usage_zone.percentage * usage_zone.thermal_control.heating_set_back
|
||||
_mean_cooling_set_point += usage_zone.percentage * usage_zone.thermal_control.mean_cooling_set_point
|
||||
self._thermal_control.mean_heating_set_point = _mean_heating_set_point
|
||||
self._thermal_control.heating_set_back = _heating_set_back
|
||||
self._thermal_control.mean_cooling_set_point = _mean_cooling_set_point
|
||||
|
||||
_thermal_control_reference = self._parent_internal_zone.usage_zones[0].thermal_control
|
||||
_types_reference = []
|
||||
if _thermal_control_reference.hvac_availability_schedules is not None:
|
||||
_types_reference.append([cte.HVAC_AVAILABILITY, _thermal_control_reference.hvac_availability_schedules])
|
||||
if _thermal_control_reference.heating_set_point_schedules is not None:
|
||||
_types_reference.append([cte.HEATING_SET_POINT, _thermal_control_reference.heating_set_point_schedules])
|
||||
if _thermal_control_reference.cooling_set_point_schedules is not None:
|
||||
_types_reference.append([cte.COOLING_SET_POINT, _thermal_control_reference.cooling_set_point_schedules])
|
||||
|
||||
for i_type in range(0, len(_types_reference)):
|
||||
_schedules = []
|
||||
_schedule_type = _types_reference[i_type][1]
|
||||
for i_schedule in range(0, len(_schedule_type)):
|
||||
schedule = copy.deepcopy(_schedule_type[i_schedule])
|
||||
new_values = []
|
||||
for i_value in range(0, len(_schedule_type[i_schedule].values)):
|
||||
_new_value = 0
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
if _types_reference[i_type][0] == cte.HVAC_AVAILABILITY:
|
||||
_new_value += usage_zone.percentage * \
|
||||
usage_zone.thermal_control.hvac_availability_schedules[i_schedule].values[i_value]
|
||||
elif _types_reference[i_type][0] == cte.HEATING_SET_POINT:
|
||||
_new_value += usage_zone.percentage * \
|
||||
usage_zone.thermal_control.heating_set_point_schedules[i_schedule].values[i_value]
|
||||
elif _types_reference[i_type][0] == cte.COOLING_SET_POINT:
|
||||
_new_value += usage_zone.percentage * \
|
||||
usage_zone.thermal_control.cooling_set_point_schedules[i_schedule].values[i_value]
|
||||
new_values.append(_new_value)
|
||||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
if i_type == 0:
|
||||
self._thermal_control.hvac_availability_schedules = _schedules
|
||||
elif i_type == 1:
|
||||
self._thermal_control.heating_set_point_schedules = _schedules
|
||||
elif i_type == 2:
|
||||
self._thermal_control.cooling_set_point_schedules = _schedules
|
||||
|
||||
return self._thermal_control
|
||||
|
||||
@thermal_control.setter
|
||||
def thermal_control(self, value):
|
||||
"""
|
||||
Set thermal control for this thermal zone
|
||||
:param value: ThermalControl
|
||||
"""
|
||||
self._thermal_control = value
|
||||
|
|
|
@ -7,7 +7,6 @@ Code contributors: Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
"""
|
||||
import uuid
|
||||
from typing import List, Union
|
||||
import helpers.constants as cte
|
||||
from city_model_structure.building_demand.internal_gains import InternalGains
|
||||
from city_model_structure.building_demand.occupancy import Occupancy
|
||||
from city_model_structure.building_demand.lighting import Lighting
|
||||
|
@ -31,7 +30,6 @@ class UsageZone:
|
|||
self._occupancy = None
|
||||
self._lighting = None
|
||||
self._appliances = None
|
||||
self._internal_gains = None
|
||||
self._thermal_control = None
|
||||
|
||||
@property
|
||||
|
@ -210,51 +208,6 @@ class UsageZone:
|
|||
"""
|
||||
self._appliances = value
|
||||
|
||||
@property
|
||||
def internal_gains(self) -> [InternalGains]:
|
||||
"""
|
||||
Calculates and returns the list of all internal gains defined
|
||||
:return: InternalGains
|
||||
"""
|
||||
if self.occupancy is not None:
|
||||
if self.occupancy.latent_internal_gain is not None:
|
||||
_internal_gain = InternalGains()
|
||||
_internal_gain.type = cte.OCCUPANCY
|
||||
_total_heat_gain = (self.occupancy.sensible_convective_internal_gain
|
||||
+ self.occupancy.sensible_radiative_internal_gain
|
||||
+ self.occupancy.latent_internal_gain)
|
||||
_internal_gain.average_internal_gain = _total_heat_gain
|
||||
_internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain
|
||||
_internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain
|
||||
_internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain
|
||||
_internal_gain.schedules = self.occupancy.occupancy_schedules
|
||||
self._internal_gains = [_internal_gain]
|
||||
if self.lighting is not None:
|
||||
_internal_gain = InternalGains()
|
||||
_internal_gain.type = cte.LIGHTING
|
||||
_internal_gain.average_internal_gain = self.lighting.lighting_density
|
||||
_internal_gain.latent_fraction = self.lighting.latent_fraction
|
||||
_internal_gain.radiative_fraction = self.lighting.radiative_fraction
|
||||
_internal_gain.convective_fraction = self.lighting.convective_fraction
|
||||
_internal_gain.schedules = self.lighting.schedules
|
||||
if self._internal_gains is not None:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
else:
|
||||
self._internal_gains = [_internal_gain]
|
||||
if self.appliances is not None:
|
||||
_internal_gain = InternalGains()
|
||||
_internal_gain.type = cte.APPLIANCES
|
||||
_internal_gain.average_internal_gain = self.appliances.appliances_density
|
||||
_internal_gain.latent_fraction = self.appliances.latent_fraction
|
||||
_internal_gain.radiative_fraction = self.appliances.radiative_fraction
|
||||
_internal_gain.convective_fraction = self.appliances.convective_fraction
|
||||
_internal_gain.schedules = self.appliances.schedules
|
||||
if self._internal_gains is not None:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
else:
|
||||
self._internal_gains = [_internal_gain]
|
||||
return self._internal_gains
|
||||
|
||||
@property
|
||||
def thermal_control(self) -> Union[None, ThermalControl]:
|
||||
"""
|
||||
|
|
|
@ -20,6 +20,8 @@ class ExportsFactory:
|
|||
def __init__(self, export_type, city, path, target_buildings=None):
|
||||
self._city = city
|
||||
self._export_type = '_' + export_type.lower()
|
||||
if isinstance(path, str):
|
||||
path = Path(path)
|
||||
self._path = path
|
||||
self._target_buildings = target_buildings
|
||||
|
||||
|
@ -93,3 +95,10 @@ class ExportsFactory:
|
|||
:return: None
|
||||
"""
|
||||
return getattr(self, self._export_type, lambda: None)
|
||||
|
||||
def export_debug(self):
|
||||
"""
|
||||
Export the city given to the class using the given export type handler
|
||||
:return: None
|
||||
"""
|
||||
return getattr(self, self._export_type)
|
||||
|
|
|
@ -8,6 +8,7 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
|||
"""
|
||||
|
||||
from geomeppy import IDF
|
||||
import helpers.constants as cte
|
||||
|
||||
|
||||
class Idf:
|
||||
|
@ -38,19 +39,19 @@ class Idf:
|
|||
|
||||
idf_surfaces = {
|
||||
# todo: make an enum for all the surface types
|
||||
'Wall': 'wall',
|
||||
'Ground': 'floor',
|
||||
'Roof': 'roof'
|
||||
cte.WALL: 'wall',
|
||||
cte.GROUND: 'floor',
|
||||
cte.ROOF: 'roof'
|
||||
}
|
||||
idf_usage = {
|
||||
# todo: make an enum for all the usage types
|
||||
'residential': 'residential_building'
|
||||
cte.RESIDENTIAL: 'residential_building'
|
||||
}
|
||||
|
||||
idf_type_limits = {
|
||||
'on_off': 'on/off',
|
||||
'fraction': 'Fraction',
|
||||
'any_number': 'Any Number',
|
||||
cte.ON_OFF: 'on/off',
|
||||
cte.FRACTION: 'Fraction',
|
||||
cte.ANY_NUMBER: 'Any Number',
|
||||
'continuous': 'Continuous',
|
||||
'discrete': 'Discrete'
|
||||
}
|
||||
|
@ -120,8 +121,8 @@ class Idf:
|
|||
Visible_Absorptance=layer.material.visible_absorptance
|
||||
)
|
||||
|
||||
def _add_daily_schedule(self, usage_zone, schedule):
|
||||
_schedule = self._idf.newidfobject(self._COMPACT_SCHEDULE, Name=f'{schedule.type} schedules {usage_zone.usage}')
|
||||
def _add_daily_schedule(self, usage, schedule):
|
||||
_schedule = self._idf.newidfobject(self._COMPACT_SCHEDULE, Name=f'{schedule.type} schedules {usage}')
|
||||
_val = schedule.values
|
||||
_schedule.Schedule_Type_Limits_Name = self.idf_type_limits[schedule.data_type.lower()]
|
||||
_schedule.Field_1 = "Through: 12/31"
|
||||
|
@ -175,14 +176,12 @@ class Idf:
|
|||
_schedule.Field_49 = "Until: 24:00"
|
||||
_schedule.Field_50 = _val[23]
|
||||
|
||||
def _add_schedule(self, usage_zone, schedule_type):
|
||||
def _add_schedule(self, usage, new_schedule):
|
||||
for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
||||
if schedule.Name == f'{schedule_type} schedules {usage_zone.usage}':
|
||||
if schedule.Name == f'{new_schedule.type} schedules {usage}':
|
||||
return
|
||||
for schedule in usage_zone.schedules:
|
||||
if schedule.type == schedule_type:
|
||||
if schedule.time_range == "day":
|
||||
return self._add_daily_schedule(usage_zone, schedule)
|
||||
if new_schedule.time_range == "day":
|
||||
return self._add_daily_schedule(usage, new_schedule)
|
||||
return
|
||||
|
||||
def _add_construction(self, thermal_boundary):
|
||||
|
@ -205,12 +204,12 @@ class Idf:
|
|||
_kwargs[f'Layer_{i + 1}'] = layers[1].material.name
|
||||
self._idf.newidfobject(self._CONSTRUCTION, **_kwargs)
|
||||
|
||||
def _add_zone(self, usage_zone):
|
||||
def _add_zone(self, usage_zone, thermal_zone_volume):
|
||||
for zone in self._idf.idfobjects['ZONE']:
|
||||
if zone.Name == usage_zone.id:
|
||||
return
|
||||
# todo: what does we need to define a zone in energy plus?
|
||||
self._idf.newidfobject(self._ZONE, Name=usage_zone.id, Volume=usage_zone.volume)
|
||||
# todo: what do we need to define a zone in energy plus?
|
||||
self._idf.newidfobject(self._ZONE, Name=usage_zone.id, Volume=thermal_zone_volume * usage_zone.percentage)
|
||||
self._add_heating_system(usage_zone)
|
||||
|
||||
def _add_thermostat(self, usage_zone):
|
||||
|
@ -220,8 +219,8 @@ class Idf:
|
|||
return thermostat
|
||||
return self._idf.newidfobject(self._THERMOSTAT,
|
||||
Name=thermostat_name,
|
||||
Constant_Heating_Setpoint=usage_zone.heating_setpoint,
|
||||
Constant_Cooling_Setpoint=usage_zone.cooling_setpoint)
|
||||
Constant_Heating_Setpoint=usage_zone.thermal_control.mean_heating_set_point,
|
||||
Constant_Cooling_Setpoint=usage_zone.thermal_control.mean_cooling_set_point)
|
||||
|
||||
def _add_heating_system(self, usage_zone):
|
||||
for air_system in self._idf.idfobjects[self._IDEAL_LOAD_AIR_SYSTEM]:
|
||||
|
@ -235,14 +234,19 @@ class Idf:
|
|||
Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {usage_zone.usage}',
|
||||
Template_Thermostat_Name=thermostat.Name)
|
||||
|
||||
def _add_occupancy(self, usage_zone):
|
||||
def _add_occupancy(self, usage_zone, area):
|
||||
number_of_people = area * usage_zone.occupancy.occupancy_density
|
||||
fraction_radiant = usage_zone.occupancy.sensible_radiative_internal_gain / \
|
||||
(usage_zone.occupancy.sensible_radiative_internal_gain +
|
||||
usage_zone.occupancy.sensible_convective_internal_gain +
|
||||
usage_zone.occupancy.latent_internal_gain)
|
||||
self._idf.newidfobject(self._PEOPLE,
|
||||
Name=f'{usage_zone.id}_occupancy',
|
||||
Zone_or_ZoneList_Name=usage_zone.id,
|
||||
Number_of_People_Schedule_Name=f'Occupancy schedules {usage_zone.usage}',
|
||||
Number_of_People_Calculation_Method="People",
|
||||
Number_of_People=500, # todo: get people from where?
|
||||
Fraction_Radiant=0.3, # todo: howto get this from InternalGains
|
||||
Number_of_People=number_of_people,
|
||||
Fraction_Radiant=fraction_radiant,
|
||||
Activity_Level_Schedule_Name=f'Occupancy schedules {usage_zone.usage}'
|
||||
)
|
||||
|
||||
|
@ -264,7 +268,7 @@ class Idf:
|
|||
Zone_or_ZoneList_Name=usage_zone.id,
|
||||
Schedule_Name=f'Infiltration schedules {usage_zone.usage}',
|
||||
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
||||
Air_Changes_per_Hour=0.35, # todo: change it from usage catalog
|
||||
Air_Changes_per_Hour=usage_zone.mechanical_air_change,
|
||||
Constant_Term_Coefficient=0.606, # todo: change it from usage catalog
|
||||
Temperature_Term_Coefficient=3.6359996E-02, # todo: change it from usage catalog
|
||||
Velocity_Term_Coefficient=0.1177165, # todo: change it from usage catalog
|
||||
|
@ -278,20 +282,33 @@ class Idf:
|
|||
"""
|
||||
|
||||
for building in self._city.buildings:
|
||||
for usage_zone in building.usage_zones:
|
||||
self._add_schedule(usage_zone, "Infiltration")
|
||||
self._add_schedule(usage_zone, "Lights")
|
||||
self._add_schedule(usage_zone, "Occupancy")
|
||||
self._add_schedule(usage_zone, "Refrigeration")
|
||||
self._add_schedule(usage_zone, "HVAC Avail")
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self._add_construction(thermal_boundary)
|
||||
for usage_zone in thermal_zone.usage_zones:
|
||||
usage = usage_zone.usage
|
||||
usage_zone_area = thermal_zone.floor_area * usage_zone.percentage
|
||||
|
||||
self._add_zone(usage_zone)
|
||||
self._add_heating_system(usage_zone)
|
||||
self._add_infiltration(usage_zone)
|
||||
self._add_occupancy(usage_zone)
|
||||
for thermal_zone in building.thermal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self._add_construction(thermal_boundary)
|
||||
# todo: infiltration can be written with two values (system on and system off) in E+? Or just as schedule?
|
||||
# self._add_schedule(usage, "Infiltration")
|
||||
for schedule in usage_zone.lighting.schedules:
|
||||
for day_type in schedule.day_types:
|
||||
if day_type == cte.MONDAY:
|
||||
self._add_schedule(usage, schedule)
|
||||
for schedule in usage_zone.occupancy.occupancy_schedules:
|
||||
for day_type in schedule.day_types:
|
||||
if day_type == cte.MONDAY:
|
||||
self._add_schedule(usage, usage_zone.occupancy.occupancy_schedules)
|
||||
for schedule in usage_zone.thermal_control.hvac_availability_schedules:
|
||||
for day_type in schedule.day_types:
|
||||
if day_type == cte.MONDAY:
|
||||
self._add_schedule(usage, schedule)
|
||||
|
||||
self._add_zone(usage_zone, thermal_zone.volume)
|
||||
self._add_heating_system(usage_zone)
|
||||
# self._add_infiltration(usage_zone)
|
||||
self._add_occupancy(usage_zone, usage_zone_area)
|
||||
|
||||
if self._export_type == "Surfaces":
|
||||
self._add_surfaces(building)
|
||||
|
@ -338,12 +355,14 @@ class Idf:
|
|||
|
||||
def _add_surfaces(self, building):
|
||||
|
||||
for thermal_zone in building.thermal_zones:
|
||||
for boundary in thermal_zone.thermal_boundaries:
|
||||
idf_surface_type = self.idf_surfaces[boundary.surface.type]
|
||||
for usage_zone in thermal_zone.usage_zones:
|
||||
surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.surface.name}',
|
||||
Surface_Type=idf_surface_type, Zone_Name=usage_zone.id,
|
||||
Construction_Name=boundary.construction_name)
|
||||
coordinates = self._matrix_to_list(boundary.surface.solid_polygon.coordinates, self._city.lower_corner)
|
||||
surface.setcoords(coordinates)
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for boundary in thermal_zone.thermal_boundaries:
|
||||
idf_surface_type = self.idf_surfaces[boundary.parent_surface.type]
|
||||
for usage_zone in thermal_zone.usage_zones:
|
||||
surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.parent_surface.name}',
|
||||
Surface_Type=idf_surface_type, Zone_Name=usage_zone.id,
|
||||
Construction_Name=boundary.construction_name)
|
||||
coordinates = self._matrix_to_list(boundary.parent_surface.solid_polygon.coordinates,
|
||||
self._city.lower_corner)
|
||||
surface.setcoords(coordinates)
|
||||
|
|
|
@ -21,8 +21,9 @@ class StoreysGeneration:
|
|||
"""
|
||||
StoreysGeneration
|
||||
"""
|
||||
def __init__(self, building, divide_in_storeys=False):
|
||||
def __init__(self, building, internal_zone, divide_in_storeys=False):
|
||||
self._building = building
|
||||
self._internal_zone = internal_zone
|
||||
self._thermal_zones = []
|
||||
self._divide_in_storeys = divide_in_storeys
|
||||
self._floor_area = 0
|
||||
|
@ -40,7 +41,8 @@ class StoreysGeneration:
|
|||
self._building.storeys_above_ground)
|
||||
number_of_storeys = 1
|
||||
if not self._divide_in_storeys or number_of_storeys == 1:
|
||||
storey = Storey('storey_0', self._building.surfaces, [None, None], self._building.volume, self._floor_area)
|
||||
storey = Storey('storey_0', self._building.surfaces, [None, None], self._internal_zone.volume,
|
||||
self._internal_zone, self._floor_area)
|
||||
for thermal_boundary in storey.thermal_boundaries:
|
||||
if thermal_boundary.type != cte.INTERIOR_WALL or thermal_boundary.type != cte.INTERIOR_SLAB:
|
||||
# external thermal boundary -> only one thermal zone
|
||||
|
@ -99,13 +101,13 @@ class StoreysGeneration:
|
|||
surfaces_child.append(ceiling)
|
||||
volume = ceiling.area_above_ground * height
|
||||
total_volume += volume
|
||||
storeys.append(Storey(name, surfaces_child, neighbours, volume, self._floor_area))
|
||||
storeys.append(Storey(name, surfaces_child, neighbours, volume, self._internal_zone, self._floor_area))
|
||||
name = 'storey_' + str(number_of_storeys - 1)
|
||||
neighbours = ['storey_' + str(number_of_storeys - 2), None]
|
||||
volume = self._building.volume - total_volume
|
||||
if volume < 0:
|
||||
raise Exception('Error in storeys creation, volume of last storey cannot be lower that 0')
|
||||
storeys.append(Storey(name, surfaces_child_last_storey, neighbours, volume, self._floor_area))
|
||||
storeys.append(Storey(name, surfaces_child_last_storey, neighbours, volume, self._internal_zone, self._floor_area))
|
||||
|
||||
for storey in storeys:
|
||||
for thermal_boundary in storey.thermal_boundaries:
|
||||
|
|
|
@ -238,5 +238,5 @@ class NrelPhysicsInterface:
|
|||
def _create_storeys(building, archetype):
|
||||
building.average_storey_height = archetype.average_storey_height
|
||||
building.storeys_above_ground = archetype.storeys_above_ground
|
||||
thermal_zones = StoreysGeneration(building).thermal_zones
|
||||
thermal_zones = StoreysGeneration(building, building.internal_zones[0]).thermal_zones
|
||||
building.internal_zones[0].thermal_zones = thermal_zones
|
||||
|
|
|
@ -73,8 +73,8 @@ class SanamCustomizedUsageParameters:
|
|||
_occupancy = Occupancy()
|
||||
usage_zone.occupancy = _occupancy
|
||||
usage_zone.occupancy.occupancy_density = archetype.occupancy.occupancy_density
|
||||
archetype_mechanical_air_change = float(archetype.mechanical_air_change) * \
|
||||
float(usage_zone.occupancy.occupancy_density) * cte.METERS_TO_FEET ** 2 \
|
||||
archetype_mechanical_air_change = float(archetype.mechanical_air_change) \
|
||||
* float(archetype.occupancy.occupancy_density) \
|
||||
* cte.HOUR_TO_MINUTES / cte.METERS_TO_FEET ** 3 / volume_per_area
|
||||
usage_zone.mechanical_air_change = archetype_mechanical_air_change
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ from imports.schedules.helpers.schedules_helper import SchedulesHelper
|
|||
from city_model_structure.attributes.schedule import Schedule
|
||||
from city_model_structure.building_demand.occupancy import Occupancy
|
||||
from city_model_structure.building_demand.lighting import Lighting
|
||||
from city_model_structure.building_demand.thermal_control import ThermalControl
|
||||
import helpers.constants as cte
|
||||
|
||||
|
||||
|
@ -142,3 +143,7 @@ class DoeIdf:
|
|||
if usage_zone.lighting is None:
|
||||
usage_zone.lighting = Lighting()
|
||||
usage_zone.lighting.schedules = [schedule]
|
||||
elif schedule.type == cte.HVAC_AVAILABILITY:
|
||||
if usage_zone.thermal_control is None:
|
||||
usage_zone.thermal_control = ThermalControl()
|
||||
usage_zone.thermal_control.hvac_availability_schedules = [schedule]
|
||||
|
|
|
@ -65,7 +65,7 @@ class CaUsageParameters(HftUsageInterface):
|
|||
usage_zone.hours_day = archetype.hours_day
|
||||
usage_zone.days_year = archetype.days_year
|
||||
_appliances = Appliances()
|
||||
_appliances.appliances_density = archetype.appliances.appliances_density
|
||||
_appliances.density = archetype.appliances.density
|
||||
usage_zone.appliances = _appliances
|
||||
_control = ThermalControl()
|
||||
_control.mean_heating_set_point = archetype.thermal_control.mean_heating_set_point
|
||||
|
|
|
@ -79,7 +79,7 @@ class ComnetUsageParameters:
|
|||
_lighting.latent_fraction = ch().comnet_lighting_latent
|
||||
_lighting.convective_fraction = ch().comnet_lighting_convective
|
||||
_lighting.radiative_fraction = ch().comnet_lighting_radiant
|
||||
_lighting.lighting_density = data['lighting'][comnet_usage][4]
|
||||
_lighting.density = data['lighting'][comnet_usage][4]
|
||||
|
||||
# plug loads
|
||||
_appliances = None
|
||||
|
@ -88,21 +88,22 @@ class ComnetUsageParameters:
|
|||
_appliances.latent_fraction = ch().comnet_plugs_latent
|
||||
_appliances.convective_fraction = ch().comnet_plugs_convective
|
||||
_appliances.radiative_fraction = ch().comnet_plugs_radiant
|
||||
_appliances.appliances_density = data['plug loads'][comnet_usage][0]
|
||||
_appliances.density = data['plug loads'][comnet_usage][0]
|
||||
|
||||
# occupancy
|
||||
_occupancy = Occupancy()
|
||||
_occupancy.occupancy_density = data['occupancy'][comnet_usage][0]
|
||||
value = data['occupancy'][comnet_usage][0]
|
||||
if value != 0:
|
||||
_occupancy.occupancy_density = value
|
||||
else:
|
||||
_occupancy.occupancy_density = 0
|
||||
_occupancy.sensible_convective_internal_gain = data['occupancy'][comnet_usage][1] \
|
||||
* ch().comnet_occupancy_sensible_convective
|
||||
_occupancy.sensible_radiative_internal_gain = data['occupancy'][comnet_usage][1] \
|
||||
* ch().comnet_occupancy_sensible_radiant
|
||||
_occupancy.latent_internal_gain = data['occupancy'][comnet_usage][2]
|
||||
|
||||
if _occupancy.occupancy_density <= 0:
|
||||
_usage_zone.mechanical_air_change = 0
|
||||
else:
|
||||
_usage_zone.mechanical_air_change = data['ventilation rate'][comnet_usage][0] / _occupancy.occupancy_density
|
||||
_usage_zone.mechanical_air_change = data['ventilation rate'][comnet_usage][0]
|
||||
|
||||
schedules_usage = UsageHelper.schedules_key(data['schedules_key'][comnet_usage][0])
|
||||
|
||||
|
@ -226,21 +227,27 @@ class ComnetUsageParameters:
|
|||
usage_zone.mechanical_air_change = archetype.mechanical_air_change * cte.METERS_TO_FEET ** 2 \
|
||||
* cte.HOUR_TO_MINUTES / cte.METERS_TO_FEET ** 3 / volume_per_area
|
||||
_occupancy = Occupancy()
|
||||
_occupancy.occupancy_density = archetype.occupancy.occupancy_density * cte.METERS_TO_FEET**2
|
||||
_occupancy.sensible_radiative_internal_gain = archetype.occupancy.sensible_radiative_internal_gain
|
||||
_occupancy.latent_internal_gain = archetype.occupancy.latent_internal_gain
|
||||
_occupancy.sensible_convective_internal_gain = archetype.occupancy.sensible_convective_internal_gain
|
||||
_occupancy.occupancy_density = archetype.occupancy.occupancy_density / cte.METERS_TO_FEET**2
|
||||
_occupancy.sensible_radiative_internal_gain = archetype.occupancy.sensible_radiative_internal_gain \
|
||||
* archetype.occupancy.occupancy_density / cte.METERS_TO_FEET**2 \
|
||||
* cte.BTU_H_TO_WATTS
|
||||
_occupancy.latent_internal_gain = archetype.occupancy.latent_internal_gain \
|
||||
* archetype.occupancy.occupancy_density / cte.METERS_TO_FEET**2 \
|
||||
* cte.BTU_H_TO_WATTS
|
||||
_occupancy.sensible_convective_internal_gain = archetype.occupancy.sensible_convective_internal_gain \
|
||||
* archetype.occupancy.occupancy_density / cte.METERS_TO_FEET**2 \
|
||||
* cte.BTU_H_TO_WATTS
|
||||
_occupancy.occupancy_schedules = archetype.occupancy.occupancy_schedules
|
||||
usage_zone.occupancy = _occupancy
|
||||
_lighting = Lighting()
|
||||
_lighting.lighting_density = archetype.lighting.lighting_density / cte.METERS_TO_FEET**2
|
||||
_lighting.density = archetype.lighting.density / cte.METERS_TO_FEET ** 2
|
||||
_lighting.convective_fraction = archetype.lighting.convective_fraction
|
||||
_lighting.radiative_fraction = archetype.lighting.radiative_fraction
|
||||
_lighting.latent_fraction = archetype.lighting.latent_fraction
|
||||
_lighting.schedules = archetype.lighting.schedules
|
||||
usage_zone.lighting = _lighting
|
||||
_appliances = Appliances()
|
||||
_appliances.appliances_density = archetype.appliances.appliances_density / cte.METERS_TO_FEET**2
|
||||
_appliances.density = archetype.appliances.density / cte.METERS_TO_FEET ** 2
|
||||
_appliances.convective_fraction = archetype.appliances.convective_fraction
|
||||
_appliances.radiative_fraction = archetype.appliances.radiative_fraction
|
||||
_appliances.latent_fraction = archetype.appliances.latent_fraction
|
||||
|
|
|
@ -60,11 +60,16 @@ class HftUsageInterface:
|
|||
_schedule.time_range = cte.DAY
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.data_type = cte.ANY_NUMBER
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY]
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY,
|
||||
cte.SUNDAY]
|
||||
_values = zone_usage_type['occupancy']['internGains']['load']['weekDayProfile']['values']
|
||||
while ' ' in _values:
|
||||
_values = _values.replace(' ', ' ')
|
||||
_schedule.values = _values.split()
|
||||
_values = _values.split()
|
||||
_values_float = []
|
||||
for _value in _values:
|
||||
_values_float.append(float(_value))
|
||||
_schedule.values = _values_float
|
||||
_internal_gain.schedules = [_schedule]
|
||||
|
||||
usage_zone_archetype.not_detailed_source_mean_annual_internal_gains = [_internal_gain]
|
||||
|
@ -81,11 +86,16 @@ class HftUsageInterface:
|
|||
_schedule.time_range = cte.DAY
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.data_type = cte.TEMPERATURE
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY]
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY,
|
||||
cte.SUNDAY]
|
||||
_values = zone_usage_type['endUses']['space_heating']['schedule']['weekDayProfile']['values']
|
||||
while ' ' in _values:
|
||||
_values = _values.replace(' ', ' ')
|
||||
_schedule.values = _values.split()
|
||||
_values = _values.split()
|
||||
_values_float = []
|
||||
for _value in _values:
|
||||
_values_float.append(float(_value))
|
||||
_schedule.values = _values_float
|
||||
_thermal_control.heating_set_point_schedules = [_schedule]
|
||||
|
||||
if 'space_cooling' in zone_usage_type['endUses']:
|
||||
|
@ -97,11 +107,16 @@ class HftUsageInterface:
|
|||
_schedule.time_range = cte.DAY
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.data_type = cte.TEMPERATURE
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY]
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY,
|
||||
cte.SUNDAY]
|
||||
_values = zone_usage_type['endUses']['space_cooling']['schedule']['weekDayProfile']['values']
|
||||
while ' ' in _values:
|
||||
_values = _values.replace(' ', ' ')
|
||||
_schedule.values = _values.split()
|
||||
_values = _values.split()
|
||||
_values_float = []
|
||||
for _value in _values:
|
||||
_values_float.append(float(_value))
|
||||
_schedule.values = _values_float
|
||||
_thermal_control.cooling_set_point_schedules = [_schedule]
|
||||
|
||||
usage_zone_archetype.thermal_control = _thermal_control
|
||||
|
@ -126,7 +141,7 @@ class HftUsageInterface:
|
|||
|
||||
if 'appliance' in zone_usage_type:
|
||||
_appliances = Appliances()
|
||||
_appliances.appliances_density = zone_usage_type['appliance']['#text'] #todo: check units
|
||||
_appliances.density = zone_usage_type['appliance']['#text'] #todo: check units
|
||||
|
||||
usage_zone_archetype.appliances = _appliances
|
||||
|
||||
|
@ -165,11 +180,16 @@ class HftUsageInterface:
|
|||
_schedule.time_range = cte.DAY
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.data_type = cte.ANY_NUMBER
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY]
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY,
|
||||
cte.SUNDAY]
|
||||
_values = usage_zone_variant['occupancy']['internGains']['load']['weekDayProfile']['values']
|
||||
while ' ' in _values:
|
||||
_values = _values.replace(' ', ' ')
|
||||
_schedule.values = _values.split()
|
||||
_values = _values.split()
|
||||
_values_float = []
|
||||
for _value in _values:
|
||||
_values_float.append(float(_value))
|
||||
_schedule.values = _values_float
|
||||
_internal_gain.schedules = [_schedule]
|
||||
|
||||
usage_zone_archetype.not_detailed_source_mean_annual_internal_gains = [_internal_gain]
|
||||
|
@ -188,11 +208,16 @@ class HftUsageInterface:
|
|||
_schedule.time_range = cte.DAY
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.data_type = cte.TEMPERATURE
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY]
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY,
|
||||
cte.SUNDAY]
|
||||
_values = usage_zone_variant['endUses']['space_heating']['schedule']['weekDayProfile']['values']
|
||||
while ' ' in _values:
|
||||
_values = _values.replace(' ', ' ')
|
||||
_schedule.values = _values.split()
|
||||
_values = _values.split()
|
||||
_values_float = []
|
||||
for _value in _values:
|
||||
_values_float.append(float(_value))
|
||||
_schedule.values = _values_float
|
||||
_thermal_control.heating_set_point_schedules = [_schedule]
|
||||
|
||||
if 'space_cooling' in usage_zone_variant['endUses'] and \
|
||||
|
@ -206,11 +231,16 @@ class HftUsageInterface:
|
|||
_schedule.time_range = cte.DAY
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.data_type = cte.TEMPERATURE
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY]
|
||||
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY,
|
||||
cte.SUNDAY]
|
||||
_values = usage_zone_variant['endUses']['space_cooling']['schedule']['weekDayProfile']['values']
|
||||
while ' ' in _values:
|
||||
_values = _values.replace(' ', ' ')
|
||||
_schedule.values = _values.split()
|
||||
_values = _values.split()
|
||||
_values_float = []
|
||||
for _value in _values:
|
||||
_values_float.append(float(_value))
|
||||
_schedule.values = _values_float
|
||||
_thermal_control.cooling_set_point_schedules = [_schedule]
|
||||
|
||||
usage_zone_archetype.thermal_control = _thermal_control
|
||||
|
@ -221,7 +251,7 @@ class HftUsageInterface:
|
|||
|
||||
if 'appliance' in usage_zone_variant:
|
||||
_appliances = Appliances()
|
||||
_appliances.appliances_density = usage_zone_variant['appliance']['#text'] # todo: check units
|
||||
_appliances.density = usage_zone_variant['appliance']['#text'] # todo: check units
|
||||
|
||||
usage_zone_archetype.appliances = _appliances
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ pandas~=1.2.3
|
|||
requests~=2.25.1
|
||||
esoreader~=1.2.3
|
||||
geomeppy~=0.11.8
|
||||
pathlib~=1.0.1
|
||||
PyWavefront~=1.3.3
|
||||
xlrd~=2.0.1
|
||||
openpyxl~=3.0.7
|
||||
|
@ -16,5 +15,4 @@ ply~=3.11
|
|||
rhino3dm~=7.7.0
|
||||
scipy==1.7.1
|
||||
PyYAML==6.0
|
||||
yaml~=0.2.5
|
||||
pyecore~=0.12.2
|
|
@ -85,9 +85,18 @@ class TestConstructionFactory(TestCase):
|
|||
self.assertIsNotNone(thermal_zone.volume, 'thermal_zone volume is none')
|
||||
self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not none')
|
||||
self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none')
|
||||
self.assertIsNone(thermal_zone.usage_zones, 'thermal_zone usage_zones is not none')
|
||||
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal_control is not none')
|
||||
self.assertIsNone(thermal_zone.hvac_system, 'thermal_zone hvac_system is not none')
|
||||
self.assertIsNone(thermal_zone.usage, 'thermal_zone usage is not none')
|
||||
self.assertIsNone(thermal_zone.not_detailed_source_mean_annual_internal_gains,
|
||||
'thermal_zone not detailed source internal gains is not none')
|
||||
self.assertIsNone(thermal_zone.hours_day, 'thermal_zone hours a day is not none')
|
||||
self.assertIsNone(thermal_zone.days_year, 'thermal_zone days a year is not none')
|
||||
self.assertIsNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is not none')
|
||||
self.assertIsNone(thermal_zone.occupancy, 'thermal_zone occupancy is not none')
|
||||
self.assertIsNone(thermal_zone.lighting, 'thermal_zone lighting is not none')
|
||||
self.assertIsNone(thermal_zone.appliances, 'thermal_zone appliances is not none')
|
||||
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal control is not none')
|
||||
self.assertIsNone(thermal_zone.get_internal_gains(), 'thermal_zone internal gains not returns none')
|
||||
|
||||
def _check_thermal_boundaries(self, thermal_zone):
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
|
|
|
@ -30,9 +30,11 @@ class TestBuildings(TestCase):
|
|||
output_path = Path('../unittests/tests_outputs/').resolve()
|
||||
city = GeometryFactory('citygml', city_file).city
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('ca', city).enrich()
|
||||
SchedulesFactory('doe_idf', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
# UsageFactory('ca', city).enrich()
|
||||
# SchedulesFactory('doe_idf', city).enrich()
|
||||
ExportsFactory('idf', city, output_path).export()
|
||||
|
||||
self.assertEqual(10, len(city.buildings))
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
|
|
|
@ -31,6 +31,16 @@ class TestGeometryFactory(TestCase):
|
|||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _check_result(self, city):
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self.assertIsNotNone(usage_zone.id, 'usage id is none')
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zone(thermal_zone)
|
||||
|
||||
def _check_buildings(self, city):
|
||||
for building in city.buildings:
|
||||
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
|
||||
|
@ -43,13 +53,19 @@ class TestGeometryFactory(TestCase):
|
|||
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none')
|
||||
self.assertTrue(building.is_conditioned, 'building is_conditioned is not conditioned')
|
||||
|
||||
def _check_usage_zone(self, usage_zone):
|
||||
self.assertIsNotNone(usage_zone.id, 'usage id is none')
|
||||
|
||||
def _check_thermal_zones(self, thermal_zone):
|
||||
def _check_thermal_zone(self, thermal_zone):
|
||||
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
|
||||
self.assertIsNone(thermal_zone.usage_zones, 'thermal_zone usage_zones is not none')
|
||||
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal_control is not none')
|
||||
self.assertIsNotNone(thermal_zone.usage, 'thermal_zone usage is not none')
|
||||
self.assertIsNotNone(thermal_zone.hours_day, 'thermal_zone hours a day is none')
|
||||
self.assertIsNotNone(thermal_zone.days_year, 'thermal_zone days a year is none')
|
||||
self.assertIsNotNone(thermal_zone.occupancy, 'thermal_zone occupancy is none')
|
||||
self.assertIsNotNone(thermal_zone.thermal_control, 'thermal_zone thermal control is none')
|
||||
self.assertIsNotNone(thermal_zone.get_internal_gains(), 'thermal_zone internal gains returns none')
|
||||
|
||||
def _check_extra_thermal_zone(self, thermal_zone):
|
||||
self.assertIsNotNone(thermal_zone.lighting, 'thermal_zone lighting is none')
|
||||
self.assertIsNotNone(thermal_zone.appliances, 'thermal_zone appliances is none')
|
||||
self.assertIsNotNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is none')
|
||||
|
||||
@staticmethod
|
||||
def _prepare_case_usage_first(city, input_key, construction_key, usage_key):
|
||||
|
@ -73,92 +89,69 @@ class TestGeometryFactory(TestCase):
|
|||
ConstructionFactory(construction_key, city).enrich()
|
||||
UsageFactory(usage_key, city).enrich()
|
||||
|
||||
def _test_hft(self, file):
|
||||
_construction_keys = ['nrel', 'nrcan']
|
||||
_usage_keys = ['ca', 'comnet', 'hft']
|
||||
for construction_key in _construction_keys:
|
||||
for usage_key in _usage_keys:
|
||||
# construction factory called first
|
||||
city = self._get_citygml(file)
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_construction_first(city, 'hft', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
# usage factory called first
|
||||
city = self._get_citygml(file)
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_usage_first(city, 'hft', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
|
||||
def _test_pluto(self, file):
|
||||
_construction_keys = ['nrel']
|
||||
_usage_keys = ['comnet', 'hft']
|
||||
for construction_key in _construction_keys:
|
||||
for usage_key in _usage_keys:
|
||||
# construction factory called first
|
||||
city = self._get_citygml(file)
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_construction_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
# usage factory called first
|
||||
city = self._get_citygml(file)
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_usage_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
|
||||
def test_enrichment(self):
|
||||
"""
|
||||
Test enrichment of the city with different order and all possible combinations
|
||||
:return: None
|
||||
"""
|
||||
file_1 = 'one_building_in_kelowna.gml'
|
||||
print('file 1')
|
||||
self._test_hft(file_1)
|
||||
file_2 = 'pluto_building.gml'
|
||||
print('file 2')
|
||||
self._test_pluto(file_2)
|
||||
file_3 = 'C40_Final.gml'
|
||||
_construction_keys = ['nrel', 'nrcan']
|
||||
_usage_keys = ['ca', 'comnet'] # todo: add 'hft'
|
||||
|
||||
for construction_key in _construction_keys:
|
||||
for usage_key in _usage_keys:
|
||||
city = self._get_citygml(file_1)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_construction_first(city, 'hft', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
|
||||
for construction_key in _construction_keys:
|
||||
for usage_key in _usage_keys:
|
||||
city = self._get_citygml(file_1)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_usage_first(city, 'hft', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
|
||||
for construction_key in _construction_keys:
|
||||
if construction_key != 'nrcan':
|
||||
for usage_key in _usage_keys:
|
||||
if usage_key != 'ca':
|
||||
city = self._get_citygml(file_2)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_construction_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
|
||||
for construction_key in _construction_keys:
|
||||
if construction_key != 'nrcan':
|
||||
for usage_key in _usage_keys:
|
||||
if usage_key != 'ca':
|
||||
city = self._get_citygml(file_2)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_usage_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
|
||||
city = self._get_citygml(file_3)
|
||||
self.assertTrue(len(city.buildings) == 10)
|
||||
|
||||
for construction_key in _construction_keys:
|
||||
if construction_key != 'nrcan':
|
||||
for usage_key in _usage_keys:
|
||||
if usage_key != 'ca':
|
||||
city = self._get_citygml(file_2)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_construction_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
print('file 3')
|
||||
self._test_hft(file_3)
|
||||
|
|
|
@ -10,7 +10,6 @@ from unittest import TestCase
|
|||
from imports.geometry_factory import GeometryFactory
|
||||
from imports.usage_factory import UsageFactory
|
||||
from imports.geometry.helpers.geometry_helper import GeometryHelper
|
||||
from imports.construction_factory import ConstructionFactory
|
||||
|
||||
|
||||
class TestUsageFactory(TestCase):
|
||||
|
@ -73,7 +72,6 @@ class TestUsageFactory(TestCase):
|
|||
def _check_usage_zone(self, usage_zone):
|
||||
self.assertIsNotNone(usage_zone.usage, 'usage is none')
|
||||
self.assertIsNotNone(usage_zone.percentage, 'usage percentage is none')
|
||||
self.assertIsNotNone(usage_zone.internal_gains, 'internal gains is none')
|
||||
self.assertIsNotNone(usage_zone.hours_day, 'hours per day is none')
|
||||
self.assertIsNotNone(usage_zone.days_year, 'days per year is none')
|
||||
self.assertIsNotNone(usage_zone.thermal_control, 'thermal control is none')
|
||||
|
@ -114,14 +112,14 @@ class TestUsageFactory(TestCase):
|
|||
self.assertIsNone(occupancy.occupants, 'occupancy density is not none')
|
||||
self.assertIsNotNone(usage_zone.lighting, 'lighting is none')
|
||||
lighting = usage_zone.lighting
|
||||
self.assertIsNotNone(lighting.lighting_density, 'lighting density is none')
|
||||
self.assertIsNotNone(lighting.density, 'lighting density is none')
|
||||
self.assertIsNotNone(lighting.latent_fraction, 'lighting latent fraction is none')
|
||||
self.assertIsNotNone(lighting.convective_fraction, 'lighting convective fraction is none')
|
||||
self.assertIsNotNone(lighting.radiative_fraction, 'lighting radiant fraction is none')
|
||||
self.assertIsNotNone(lighting.schedules, 'lighting schedule is none')
|
||||
self.assertIsNotNone(usage_zone.appliances, 'appliances is none')
|
||||
appliances = usage_zone.appliances
|
||||
self.assertIsNotNone(appliances.appliances_density, 'appliances density is none')
|
||||
self.assertIsNotNone(appliances.density, 'appliances density is none')
|
||||
self.assertIsNotNone(appliances.latent_fraction, 'appliances latent fraction is none')
|
||||
self.assertIsNotNone(appliances.convective_fraction, 'appliances convective fraction is none')
|
||||
self.assertIsNotNone(appliances.radiative_fraction, 'appliances radiant fraction is none')
|
||||
|
@ -179,4 +177,3 @@ class TestUsageFactory(TestCase):
|
|||
self.assertIsNone(occupancy.occupants, 'occupancy density is not none')
|
||||
self.assertIsNone(usage_zone.lighting, 'lighting is not none')
|
||||
self.assertIsNone(usage_zone.appliances, 'appliances is not none')
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user