Merge branch 'a_bug_in_internal_gains' into 'master'

erased not_detailed_source_mean_annual_internal_gains parameter and changed by internal_gains. During the import, for those catalogs that don't provide that information, the internal_gains are calc...

See merge request Guille/hub!20
This commit is contained in:
Guillermo Gutierrez Morote 2022-05-18 19:40:03 +00:00
commit 543b42b0e2
8 changed files with 203 additions and 315 deletions

View File

@ -110,8 +110,10 @@ class InternalGain:
@property @property
def schedules(self) -> Union[None, List[Schedule]]: def schedules(self) -> Union[None, List[Schedule]]:
""" """
Get internal gain schedule Get internal gain schedules
dataType = fraction data type = any number
time step = 1 hour
time range = 1 day
:return: [Schedule] :return: [Schedule]
""" """
return self._schedules return self._schedules
@ -119,8 +121,10 @@ class InternalGain:
@schedules.setter @schedules.setter
def schedules(self, value): def schedules(self, value):
""" """
Set internal gain schedule Set internal gain schedules
dataType = fraction data type = any number
time step = 1 hour
time range = 1 day
:param value: [Schedule] :param value: [Schedule]
""" """
self._schedules = value self._schedules = value

View File

@ -7,8 +7,8 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
""" """
import uuid import uuid
import sys
import copy import copy
import numpy
from typing import List, Union, TypeVar from typing import List, Union, TypeVar
from city_model_structure.building_demand.occupancy import Occupancy from city_model_structure.building_demand.occupancy import Occupancy
from city_model_structure.building_demand.appliances import Appliances from city_model_structure.building_demand.appliances import Appliances
@ -16,6 +16,7 @@ from city_model_structure.building_demand.lighting import Lighting
from city_model_structure.building_demand.internal_gain import InternalGain from city_model_structure.building_demand.internal_gain import InternalGain
from city_model_structure.building_demand.thermal_control import ThermalControl from city_model_structure.building_demand.thermal_control import ThermalControl
from city_model_structure.energy_systems.hvac_system import HvacSystem from city_model_structure.energy_systems.hvac_system import HvacSystem
from city_model_structure.attributes.schedule import Schedule
import helpers.constants as cte import helpers.constants as cte
ThermalBoundary = TypeVar('ThermalBoundary') ThermalBoundary = TypeVar('ThermalBoundary')
@ -26,7 +27,7 @@ class ThermalZone:
""" """
ThermalZone class ThermalZone class
""" """
def __init__(self, thermal_boundaries, parent_internal_zone, volume, footprint_area): def __init__(self, thermal_boundaries, parent_internal_zone, volume, footprint_area, usage=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
@ -41,8 +42,7 @@ class ThermalZone:
self._view_factors_matrix = None self._view_factors_matrix = None
self._total_floor_area = None self._total_floor_area = None
self._usage = None self._usage = usage
self._not_detailed_source_mean_annual_internal_gains = None
self._hours_day = None self._hours_day = None
self._days_year = None self._days_year = None
self._mechanical_air_change = None self._mechanical_air_change = None
@ -51,6 +51,21 @@ class ThermalZone:
self._appliances = None self._appliances = None
self._internal_gains = None self._internal_gains = None
self._thermal_control = None self._thermal_control = None
# example 70-office_30-residential
if usage is None:
self._usage_zones = copy.deepcopy(parent_internal_zone.usage_zones)
else:
values = usage.split('_')
usages = []
for value in values:
usages.append(value.split('-'))
self._usage_zones = []
for parent_usage_zone in parent_internal_zone.usage_zones:
for value in usages:
if parent_usage_zone.usage == value[1]:
new_usage_zone = copy.deepcopy(parent_usage_zone)
new_usage_zone.percentage = float(value[0])/100
self._usage_zones.append(new_usage_zone)
@property @property
def id(self): def id(self):
@ -217,24 +232,15 @@ class ThermalZone:
Get thermal zone usage Get thermal zone usage
:return: None or str :return: None or str
""" """
if self._usage is None:
if self._parent_internal_zone.usage_zones is None: if self._parent_internal_zone.usage_zones is None:
return None return None
if self._usage is None:
self._usage = '' self._usage = ''
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._parent_internal_zone.usage_zones:
self._usage += str(round(usage_zone.percentage) * 100) + '_' + usage_zone.usage + '_' self._usage += str(round(usage_zone.percentage) * 100) + '-' + usage_zone.usage + '_'
self._usage = self._usage[:-1] self._usage = self._usage[:-1]
return self._usage 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 @staticmethod
def _get_schedule_of_day(requested_day_type, schedules): def _get_schedule_of_day(requested_day_type, schedules):
for schedule in schedules: for schedule in schedules:
@ -243,158 +249,57 @@ class ThermalZone:
return schedule return schedule
return None return None
@property
def not_detailed_source_mean_annual_internal_gains(self) -> Union[None, List[InternalGain]]:
"""
Get thermal zone internal gains with unknown energy source
:return: [InternalGain]
"""
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 = InternalGain()
_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: [InternalGain]
"""
self._not_detailed_source_mean_annual_internal_gains = value
@property @property
def hours_day(self) -> Union[None, float]: def hours_day(self) -> Union[None, float]:
""" """
Get thermal zone usage hours per day Get thermal zone usage hours per day
:return: None or float :return: None or float
""" """
if self._parent_internal_zone.usage_zones is None: if self._usage_zones is None:
return None return None
if self._hours_day is None: if self._hours_day is None:
self._hours_day = 0 self._hours_day = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
self._hours_day += usage_zone.percentage * usage_zone.hours_day self._hours_day += usage_zone.percentage * usage_zone.hours_day
return self._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 @property
def days_year(self) -> Union[None, float]: def days_year(self) -> Union[None, float]:
""" """
Get thermal zone usage days per year Get thermal zone usage days per year
:return: None or float :return: None or float
""" """
if self._parent_internal_zone.usage_zones is None: if self._usage_zones is None:
return None return None
if self._days_year is None: if self._days_year is None:
self._days_year = 0 self._days_year = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
self._days_year += usage_zone.percentage * usage_zone.days_year self._days_year += usage_zone.percentage * usage_zone.days_year
return self._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 @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 hour (ACH)
:return: None or float :return: None or float
""" """
if self._parent_internal_zone.usage_zones is None: if self._usage_zones is None:
return None return None
if self._mechanical_air_change is None: if self._mechanical_air_change is None:
self._mechanical_air_change = 0 self._mechanical_air_change = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
if usage_zone.mechanical_air_change is None: if usage_zone.mechanical_air_change is None:
return None return None
self._mechanical_air_change += usage_zone.percentage * usage_zone.mechanical_air_change self._mechanical_air_change += usage_zone.percentage * usage_zone.mechanical_air_change
return self._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 @property
def occupancy(self) -> Union[None, Occupancy]: def occupancy(self) -> Union[None, Occupancy]:
""" """
Get occupancy in the thermal zone Get occupancy in the thermal zone
:return: None or Occupancy :return: None or Occupancy
""" """
if self._parent_internal_zone.usage_zones is None: if self._usage_zones is None:
return None return None
if self._occupancy is None: if self._occupancy is None:
self._occupancy = Occupancy() self._occupancy = Occupancy()
@ -402,7 +307,7 @@ class ThermalZone:
_convective_part = 0 _convective_part = 0
_radiative_part = 0 _radiative_part = 0
_latent_part = 0 _latent_part = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
if usage_zone.occupancy is None: if usage_zone.occupancy is None:
return None return None
_occupancy_density += usage_zone.percentage * usage_zone.occupancy.occupancy_density _occupancy_density += usage_zone.percentage * usage_zone.occupancy.occupancy_density
@ -415,7 +320,7 @@ class ThermalZone:
self._occupancy.sensible_radiative_internal_gain = _radiative_part self._occupancy.sensible_radiative_internal_gain = _radiative_part
self._occupancy.latent_internal_gain = _latent_part self._occupancy.latent_internal_gain = _latent_part
_occupancy_reference = self._parent_internal_zone.usage_zones[0].occupancy _occupancy_reference = self._usage_zones[0].occupancy
if _occupancy_reference.occupancy_schedules is not None: if _occupancy_reference.occupancy_schedules is not None:
_schedules = [] _schedules = []
for i_schedule in range(0, len(_occupancy_reference.occupancy_schedules)): for i_schedule in range(0, len(_occupancy_reference.occupancy_schedules)):
@ -423,7 +328,7 @@ class ThermalZone:
new_values = [] new_values = []
for i_value in range(0, len(_occupancy_reference.occupancy_schedules[i_schedule].values)): for i_value in range(0, len(_occupancy_reference.occupancy_schedules[i_schedule].values)):
_new_value = 0 _new_value = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
_new_value += usage_zone.percentage * usage_zone.occupancy.occupancy_schedules[i_schedule].values[i_value] _new_value += usage_zone.percentage * usage_zone.occupancy.occupancy_schedules[i_schedule].values[i_value]
new_values.append(_new_value) new_values.append(_new_value)
schedule.values = new_values schedule.values = new_values
@ -431,21 +336,13 @@ class ThermalZone:
self._occupancy.occupancy_schedules = _schedules self._occupancy.occupancy_schedules = _schedules
return self._occupancy return self._occupancy
@occupancy.setter
def occupancy(self, value):
"""
Set occupancy in the thermal zone
:param value: Occupancy
"""
self._occupancy = value
@property @property
def lighting(self) -> Union[None, Lighting]: def lighting(self) -> Union[None, Lighting]:
""" """
Get lighting information Get lighting information
:return: None or Lighting :return: None or Lighting
""" """
if self._parent_internal_zone.usage_zones is None: if self._usage_zones is None:
return None return None
if self._lighting is None: if self._lighting is None:
self._lighting = Lighting() self._lighting = Lighting()
@ -453,7 +350,7 @@ class ThermalZone:
_convective_part = 0 _convective_part = 0
_radiative_part = 0 _radiative_part = 0
_latent_part = 0 _latent_part = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
if usage_zone.lighting is None: if usage_zone.lighting is None:
return None return None
_lighting_density += usage_zone.percentage * usage_zone.lighting.density _lighting_density += usage_zone.percentage * usage_zone.lighting.density
@ -474,7 +371,7 @@ class ThermalZone:
self._lighting.radiative_fraction = 0 self._lighting.radiative_fraction = 0
self._lighting.latent_fraction = 0 self._lighting.latent_fraction = 0
_lighting_reference = self._parent_internal_zone.usage_zones[0].lighting _lighting_reference = self._usage_zones[0].lighting
if _lighting_reference.schedules is not None: if _lighting_reference.schedules is not None:
_schedules = [] _schedules = []
for i_schedule in range(0, len(_lighting_reference.schedules)): for i_schedule in range(0, len(_lighting_reference.schedules)):
@ -482,7 +379,7 @@ class ThermalZone:
new_values = [] new_values = []
for i_value in range(0, len(_lighting_reference.schedules[i_schedule].values)): for i_value in range(0, len(_lighting_reference.schedules[i_schedule].values)):
_new_value = 0 _new_value = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
_new_value += usage_zone.percentage * usage_zone.lighting.schedules[i_schedule].values[i_value] _new_value += usage_zone.percentage * usage_zone.lighting.schedules[i_schedule].values[i_value]
new_values.append(_new_value) new_values.append(_new_value)
schedule.values = new_values schedule.values = new_values
@ -490,21 +387,13 @@ class ThermalZone:
self._lighting.schedules = _schedules self._lighting.schedules = _schedules
return self._lighting return self._lighting
@lighting.setter
def lighting(self, value):
"""
Set lighting information
:param value: Lighting
"""
self._lighting = value
@property @property
def appliances(self) -> Union[None, Appliances]: def appliances(self) -> Union[None, Appliances]:
""" """
Get appliances information Get appliances information
:return: None or Appliances :return: None or Appliances
""" """
if self._parent_internal_zone.usage_zones is None: if self._usage_zones is None:
return None return None
if self._appliances is None: if self._appliances is None:
self._appliances = Appliances() self._appliances = Appliances()
@ -512,7 +401,7 @@ class ThermalZone:
_convective_part = 0 _convective_part = 0
_radiative_part = 0 _radiative_part = 0
_latent_part = 0 _latent_part = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
if usage_zone.appliances is None: if usage_zone.appliances is None:
return None return None
_appliances_density += usage_zone.percentage * usage_zone.appliances.density _appliances_density += usage_zone.percentage * usage_zone.appliances.density
@ -533,7 +422,7 @@ class ThermalZone:
self._appliances.radiative_fraction = 0 self._appliances.radiative_fraction = 0
self._appliances.latent_fraction = 0 self._appliances.latent_fraction = 0
_appliances_reference = self._parent_internal_zone.usage_zones[0].appliances _appliances_reference = self._usage_zones[0].appliances
if _appliances_reference.schedules is not None: if _appliances_reference.schedules is not None:
_schedules = [] _schedules = []
for i_schedule in range(0, len(_appliances_reference.schedules)): for i_schedule in range(0, len(_appliances_reference.schedules)):
@ -541,7 +430,7 @@ class ThermalZone:
new_values = [] new_values = []
for i_value in range(0, len(_appliances_reference.schedules[i_schedule].values)): for i_value in range(0, len(_appliances_reference.schedules[i_schedule].values)):
_new_value = 0 _new_value = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
_new_value += usage_zone.percentage * usage_zone.appliances.schedules[i_schedule].values[i_value] _new_value += usage_zone.percentage * usage_zone.appliances.schedules[i_schedule].values[i_value]
new_values.append(_new_value) new_values.append(_new_value)
schedule.values = new_values schedule.values = new_values
@ -549,72 +438,62 @@ class ThermalZone:
self._appliances.schedules = _schedules self._appliances.schedules = _schedules
return self._appliances return self._appliances
@appliances.setter @property
def appliances(self, value): def internal_gains(self) -> Union[None, List[InternalGain]]:
"""
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) -> List[InternalGain]:
""" """
Calculates and returns the list of all internal gains defined Calculates and returns the list of all internal gains defined
:return: [InternalGain] :return: [InternalGain]
""" """
if self.not_detailed_source_mean_annual_internal_gains is not None: if self._usage_zones is None:
self._internal_gains = [] return None
for _internal_gain in self.not_detailed_source_mean_annual_internal_gains: if self._internal_gains is None:
self._internal_gains.append(_internal_gain)
if self.occupancy is not None:
if self.occupancy.latent_internal_gain is not None:
_internal_gain = InternalGain() _internal_gain = InternalGain()
_internal_gain.type = cte.OCCUPANCY _days = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY, cte.SUNDAY, cte.HOLIDAY]
_total_heat_gain = (self.occupancy.sensible_convective_internal_gain _average_internal_gain = 0
+ self.occupancy.sensible_radiative_internal_gain _convective_fraction = 0
+ self.occupancy.latent_internal_gain) _radiative_fraction = 0
_internal_gain.average_internal_gain = _total_heat_gain _latent_fraction = 0
if _total_heat_gain > 0: _schedules = None
_internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain _base_schedule = Schedule()
_internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain _base_schedule.type = cte.INTERNAL_GAINS
_internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain _base_schedule.time_range = cte.DAY
else: _base_schedule.time_step = cte.HOUR
_internal_gain.latent_fraction = 0 _base_schedule.data_type = cte.ANY_NUMBER
_internal_gain.radiative_fraction = 0 _schedules_defined = True
_internal_gain.convective_fraction = 0 values = numpy.zeros(24, 8)
_internal_gain.schedules = self.occupancy.occupancy_schedules for usage_zone in self._usage_zones:
if self._internal_gains is not None: for internal_gain in usage_zone.internal_gains:
self._internal_gains.append(_internal_gain) _average_internal_gain += internal_gain.average_internal_gain * usage_zone.percentage
else: _convective_fraction += internal_gain.average_internal_gain * usage_zone.percentage \
self._internal_gains = [_internal_gain] * internal_gain.convective_fraction
_radiative_fraction += internal_gain.average_internal_gain * usage_zone.percentage \
* internal_gain.radiative_fraction
_latent_fraction += internal_gain.average_internal_gain * usage_zone.percentage \
* internal_gain.latent_fraction
for usage_zone in self._usage_zones:
for internal_gain in usage_zone.internal_gains:
if len(internal_gain.schedules) == 0:
_schedules_defined = False
break
for day, _schedule in enumerate(internal_gain.schedules):
for v, value in enumerate(_schedule.values):
values[v, day] += value * usage_zone.percentage
if self.lighting is not None: if _schedules_defined:
_internal_gain = InternalGain() _schedules = []
_internal_gain.type = cte.LIGHTING for day in range(0, len(_days)):
self._add_internal_gain(self.lighting, _internal_gain) _schedule = copy.deepcopy(_base_schedule)
if self._internal_gains is not None: _schedule.day_types = [_days[day]]
self._internal_gains.append(_internal_gain) _schedule.values = values[:day]
else: _schedules.append(_schedule)
self._internal_gains = [_internal_gain]
if self.appliances is not None: _internal_gain.convective_fraction = _convective_fraction / _average_internal_gain
_internal_gain = InternalGain() _internal_gain.radiative_fraction = _radiative_fraction / _average_internal_gain
_internal_gain.type = cte.APPLIANCES _internal_gain.latent_fraction = _latent_fraction / _average_internal_gain
self._add_internal_gain(self.appliances, _internal_gain) _internal_gain.average_internal_gain = _average_internal_gain
if self._internal_gains is not None: _internal_gain.type = 'mean_value'
self._internal_gains.append(_internal_gain) _internal_gain.schedules = _schedules
else:
self._internal_gains = [_internal_gain] self._internal_gains = [_internal_gain]
return self._internal_gains return self._internal_gains
@property @property
@ -623,14 +502,14 @@ class ThermalZone:
Get thermal control of this thermal zone Get thermal control of this thermal zone
:return: None or ThermalControl :return: None or ThermalControl
""" """
if self._parent_internal_zone.usage_zones is None: if self._usage_zones is None:
return None return None
if self._thermal_control is None: if self._thermal_control is None:
self._thermal_control = ThermalControl() self._thermal_control = ThermalControl()
_mean_heating_set_point = 0 _mean_heating_set_point = 0
_heating_set_back = 0 _heating_set_back = 0
_mean_cooling_set_point = 0 _mean_cooling_set_point = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
_mean_heating_set_point += usage_zone.percentage * usage_zone.thermal_control.mean_heating_set_point _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 _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 _mean_cooling_set_point += usage_zone.percentage * usage_zone.thermal_control.mean_cooling_set_point
@ -638,7 +517,7 @@ class ThermalZone:
self._thermal_control.heating_set_back = _heating_set_back self._thermal_control.heating_set_back = _heating_set_back
self._thermal_control.mean_cooling_set_point = _mean_cooling_set_point self._thermal_control.mean_cooling_set_point = _mean_cooling_set_point
_thermal_control_reference = self._parent_internal_zone.usage_zones[0].thermal_control _thermal_control_reference = self._usage_zones[0].thermal_control
_types_reference = [] _types_reference = []
if _thermal_control_reference.hvac_availability_schedules is not None: if _thermal_control_reference.hvac_availability_schedules is not None:
_types_reference.append([cte.HVAC_AVAILABILITY, _thermal_control_reference.hvac_availability_schedules]) _types_reference.append([cte.HVAC_AVAILABILITY, _thermal_control_reference.hvac_availability_schedules])
@ -655,7 +534,7 @@ class ThermalZone:
new_values = [] new_values = []
for i_value in range(0, len(_schedule_type[i_schedule].values)): for i_value in range(0, len(_schedule_type[i_schedule].values)):
_new_value = 0 _new_value = 0
for usage_zone in self._parent_internal_zone.usage_zones: for usage_zone in self._usage_zones:
if _types_reference[i_type][0] == cte.HVAC_AVAILABILITY: if _types_reference[i_type][0] == cte.HVAC_AVAILABILITY:
_new_value += usage_zone.percentage * \ _new_value += usage_zone.percentage * \
usage_zone.thermal_control.hvac_availability_schedules[i_schedule].values[i_value] usage_zone.thermal_control.hvac_availability_schedules[i_schedule].values[i_value]
@ -677,14 +556,6 @@ class ThermalZone:
return self._thermal_control 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
@property @property
def total_floor_area(self): def total_floor_area(self):
""" """

View File

@ -6,24 +6,23 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Code contributors: Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import uuid import uuid
from typing import List, Union from typing import Union, List
from city_model_structure.building_demand.internal_gain import InternalGain
from city_model_structure.building_demand.occupancy import Occupancy from city_model_structure.building_demand.occupancy import Occupancy
from city_model_structure.building_demand.lighting import Lighting from city_model_structure.building_demand.lighting import Lighting
from city_model_structure.building_demand.appliances import Appliances from city_model_structure.building_demand.appliances import Appliances
from city_model_structure.building_demand.thermal_control import ThermalControl from city_model_structure.building_demand.thermal_control import ThermalControl
import helpers.constants as cte from city_model_structure.building_demand.internal_gain import InternalGain
class UsageZone: class UsageZone:
""" """
UsageZone class UsageZone class
""" """
def __init__(self, not_detailed_source_mean_annual_internal_gains=None): def __init__(self):
self._id = None self._id = None
self._usage = None self._usage = None
self._percentage = None self._percentage = None
self._not_detailed_source_mean_annual_internal_gains = not_detailed_source_mean_annual_internal_gains self._internal_gains = None
self._hours_day = None self._hours_day = None
self._days_year = None self._days_year = None
# self._electrical_app_average_consumption_sqm_year = None # self._electrical_app_average_consumption_sqm_year = None
@ -32,7 +31,6 @@ class UsageZone:
self._lighting = None self._lighting = None
self._appliances = None self._appliances = None
self._thermal_control = None self._thermal_control = None
self._internal_gains = None
@property @property
def id(self): def id(self):
@ -78,6 +76,22 @@ class UsageZone:
if value is not None: if value is not None:
self._percentage = float(value) self._percentage = float(value)
@property
def internal_gains(self) -> List[InternalGain]:
"""
Get usage zone internal gains
:return: [InternalGain]
"""
return self._internal_gains
@internal_gains.setter
def internal_gains(self, value):
"""
Set usage zone internal gains
:param value: [InternalGain]
"""
self._internal_gains = value
@property @property
def hours_day(self) -> Union[None, float]: def hours_day(self) -> Union[None, float]:
""" """
@ -192,64 +206,3 @@ class UsageZone:
:param value: ThermalControl :param value: ThermalControl
""" """
self._thermal_control = value self._thermal_control = value
@property
def internal_gains(self) -> List[InternalGain]:
"""
Calculates and returns the list of all internal gains defined
:return: [InternalGain]
"""
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 = InternalGain()
_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 = InternalGain()
_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 = InternalGain()
_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
@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

View File

@ -48,6 +48,7 @@ CONTROL_TYPE = 'control_type'
CONTINUOUS = 'continuous' CONTINUOUS = 'continuous'
DISCRETE = 'discrete' DISCRETE = 'discrete'
CONSTANT = 'constant' CONSTANT = 'constant'
INTERNAL_GAINS = 'internal_gains'
# surface types # surface types
WALL = 'Wall' WALL = 'Wall'

View File

@ -4,10 +4,11 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group 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
""" """
import copy
import sys import sys
from typing import Dict from typing import Dict
import pandas as pd import pandas as pd
import numpy
import helpers.constants as cte import helpers.constants as cte
from helpers.configuration_helper import ConfigurationHelper as ch from helpers.configuration_helper import ConfigurationHelper as ch
@ -20,6 +21,7 @@ from city_model_structure.building_demand.occupancy import Occupancy
from city_model_structure.building_demand.appliances import Appliances from city_model_structure.building_demand.appliances import Appliances
from city_model_structure.building_demand.thermal_control import ThermalControl from city_model_structure.building_demand.thermal_control import ThermalControl
from city_model_structure.attributes.schedule import Schedule from city_model_structure.attributes.schedule import Schedule
from city_model_structure.building_demand.internal_gain import InternalGain
class ComnetUsageParameters: class ComnetUsageParameters:
@ -93,10 +95,10 @@ class ComnetUsageParameters:
# occupancy # occupancy
_occupancy = Occupancy() _occupancy = Occupancy()
value = data['occupancy'][comnet_usage][0] value = data['occupancy'][comnet_usage][0]
if value != 0:
_occupancy.occupancy_density = value
else:
_occupancy.occupancy_density = 0 _occupancy.occupancy_density = 0
if value != 0:
_occupancy.occupancy_density = 1 / value
_occupancy.sensible_convective_internal_gain = data['occupancy'][comnet_usage][1] \ _occupancy.sensible_convective_internal_gain = data['occupancy'][comnet_usage][1] \
* ch().comnet_occupancy_sensible_convective * ch().comnet_occupancy_sensible_convective
_occupancy.sensible_radiative_internal_gain = data['occupancy'][comnet_usage][1] \ _occupancy.sensible_radiative_internal_gain = data['occupancy'][comnet_usage][1] \
@ -276,3 +278,67 @@ class ComnetUsageParameters:
usage_zone.hours_day = total / 365 usage_zone.hours_day = total / 365
usage_zone.days_year = 365 usage_zone.days_year = 365
@staticmethod
def _calculate_internal_gains(archetype):
_DAYS = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY, cte.SUNDAY, cte.HOLIDAY]
_number_of_days_per_type = [51, 50, 50, 50, 50, 52, 52, 10]
_mean_internal_gain = InternalGain()
_mean_internal_gain.type = 'mean_value_of_internal_gains'
_base_schedule = Schedule()
_base_schedule.type = cte.INTERNAL_GAINS
_base_schedule.time_range = cte.DAY
_base_schedule.time_step = cte.HOUR
_base_schedule.data_type = cte.FRACTION
_latent_heat_gain = archetype.occupancy.latent_internal_gain
_convective_heat_gain = archetype.occupancy.sensible_convective_internal_gain
_radiative_heat_gain = archetype.occupancy.sensible_radiative_internal_gain
_total_heat_gain = (_latent_heat_gain + _convective_heat_gain + _radiative_heat_gain)
_schedule_values = numpy.zeros(24, 7)
_sum = 0
for day, _schedule in enumerate(archetype.occupancy.schedules):
for v, value in enumerate(_schedule.values):
_schedule_values[v, day] = value * _total_heat_gain
_sum += value * _total_heat_gain * _number_of_days_per_type[day]
_total_heat_gain += archetype.lighting.density + archetype.appliances.density
_latent_heat_gain += archetype.lighting.latent_fraction * archetype.lighting.density\
+ archetype.appliances.latent_fraction * archetype.appliances.density
_radiative_heat_gain = archetype.lighting.radiative_fraction * archetype.lighting.density \
+ archetype.appliances.radiative_fraction * archetype.appliances.density
_convective_heat_gain = archetype.lighting.convective_fraction * archetype.lighting.density \
+ archetype.appliances.convective_fraction * archetype.appliances.density
for day, _schedule in enumerate(archetype.lighting.schedules):
for v, value in enumerate(_schedule.values):
_schedule_values[v, day] += value * archetype.lighting.density
_sum += value * archetype.lighting.density * _number_of_days_per_type[day]
for day, _schedule in enumerate(archetype.appliances.schedules):
for v, value in enumerate(_schedule.values):
_schedule_values[v, day] += value * archetype.appliances.density
_sum += value * archetype.appliances.density * _number_of_days_per_type[day]
_latent_fraction = _latent_heat_gain / _total_heat_gain
_radiative_fraction = _radiative_heat_gain / _total_heat_gain
_convective_fraction = _convective_heat_gain / _total_heat_gain
_average_internal_gain = _sum / _total_heat_gain
_schedules = []
for day in range(0, len(_DAYS)):
_schedule = copy.deepcopy(_base_schedule)
_schedule.day_types = [_DAYS[day]]
_schedule.values = _schedule_values[:day]
_schedules.append(_schedule)
_mean_internal_gain.average_internal_gain = _average_internal_gain
_mean_internal_gain.latent_fraction = _latent_fraction
_mean_internal_gain.convective_fraction = _convective_fraction
_mean_internal_gain.radiative_fraction = _radiative_fraction
_mean_internal_gain.schedules = _schedules
return [_mean_internal_gain]

View File

@ -13,11 +13,11 @@ class UsageZoneArchetype:
""" """
UsageZoneArchetype class UsageZoneArchetype class
""" """
def __init__(self, usage=None, not_detailed_source_mean_annual_internal_gains=None, hours_day=None, days_year=None, def __init__(self, usage=None, internal_gains=None, hours_day=None, days_year=None,
electrical_app_average_consumption_sqm_year=None, mechanical_air_change=None, occupancy=None, electrical_app_average_consumption_sqm_year=None, mechanical_air_change=None, occupancy=None,
lighting=None, appliances=None): lighting=None, appliances=None):
self._usage = usage self._usage = usage
self._not_detailed_source_mean_annual_internal_gains = not_detailed_source_mean_annual_internal_gains self._internal_gains = internal_gains
self._hours_day = hours_day self._hours_day = hours_day
self._days_year = days_year self._days_year = days_year
self._electrical_app_average_consumption_sqm_year = electrical_app_average_consumption_sqm_year self._electrical_app_average_consumption_sqm_year = electrical_app_average_consumption_sqm_year
@ -27,12 +27,12 @@ class UsageZoneArchetype:
self._appliances = appliances self._appliances = appliances
@property @property
def not_detailed_source_mean_annual_internal_gains(self) -> List[HftInternalGainsArchetype]: def internal_gains(self) -> List[HftInternalGainsArchetype]:
""" """
Get usage zone internal gains from not detailed heating source in W/m2 Get usage zone internal gains from not detailed heating source in W/m2
:return: [InternalGain] :return: [InternalGain]
""" """
return self._not_detailed_source_mean_annual_internal_gains return self._internal_gains
@property @property
def hours_day(self): def hours_day(self):

View File

@ -39,6 +39,9 @@ class HftUsageInterface:
@staticmethod @staticmethod
def _parse_zone_usage_type(usage, zone_usage_type): def _parse_zone_usage_type(usage, zone_usage_type):
usage_zone_archetype = UsageZone()
usage_zone_archetype.usage = usage
if 'occupancy' in zone_usage_type: if 'occupancy' in zone_usage_type:
_occupancy = Occupancy() _occupancy = Occupancy()
_occupancy.occupancy_density = zone_usage_type['occupancy']['occupancyDensity'] #todo: check units _occupancy.occupancy_density = zone_usage_type['occupancy']['occupancyDensity'] #todo: check units
@ -67,19 +70,12 @@ class HftUsageInterface:
_schedule.values = _values_float _schedule.values = _values_float
_internal_gain.schedules = [_schedule] _internal_gain.schedules = [_schedule]
_not_detailed_source_mean_annual_internal_gains = [_internal_gain] usage_zone_archetype.internal_gains = [_internal_gain]
usage_zone_archetype = UsageZone(_not_detailed_source_mean_annual_internal_gains)
else:
usage_zone_archetype = UsageZone()
usage_zone_archetype.hours_day = zone_usage_type['occupancy']['usageHoursPerDay'] usage_zone_archetype.hours_day = zone_usage_type['occupancy']['usageHoursPerDay']
usage_zone_archetype.days_year = zone_usage_type['occupancy']['usageDaysPerYear'] usage_zone_archetype.days_year = zone_usage_type['occupancy']['usageDaysPerYear']
usage_zone_archetype.occupancy = _occupancy usage_zone_archetype.occupancy = _occupancy
else:
usage_zone_archetype = UsageZone()
usage_zone_archetype.usage = usage
if 'endUses' in zone_usage_type: if 'endUses' in zone_usage_type:
_thermal_control = ThermalControl() _thermal_control = ThermalControl()
if 'space_heating' in zone_usage_type['endUses']: if 'space_heating' in zone_usage_type['endUses']:
@ -198,7 +194,7 @@ class HftUsageInterface:
_schedule.values = _values_float _schedule.values = _values_float
_internal_gain.schedules = [_schedule] _internal_gain.schedules = [_schedule]
usage_zone_archetype.not_detailed_source_mean_annual_internal_gains = [_internal_gain] usage_zone_archetype.internal_gains = [_internal_gain]
if 'endUses' in usage_zone_variant: if 'endUses' in usage_zone_variant:
_thermal_control = ThermalControl() _thermal_control = ThermalControl()
@ -272,10 +268,9 @@ class HftUsageInterface:
@staticmethod @staticmethod
def _assign_values(usage, archetype): def _assign_values(usage, archetype):
_not_detailed_source_mean_annual_internal_gains = \ usage_zone = UsageZone()
copy.deepcopy(archetype.internal_gains)
usage_zone = UsageZone(_not_detailed_source_mean_annual_internal_gains)
usage_zone.usage = usage usage_zone.usage = usage
usage_zone.internal_gains = copy.deepcopy(archetype.internal_gains)
usage_zone.mechanical_air_change = archetype.mechanical_air_change usage_zone.mechanical_air_change = archetype.mechanical_air_change
usage_zone.occupancy = copy.deepcopy(archetype.occupancy) usage_zone.occupancy = copy.deepcopy(archetype.occupancy)
usage_zone.appliances = copy.deepcopy(archetype.appliances) usage_zone.appliances = copy.deepcopy(archetype.appliances)

View File

@ -86,8 +86,6 @@ class TestConstructionFactory(TestCase):
self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none') self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none')
self.assertIsNone(thermal_zone.hvac_system, 'thermal_zone hvac_system 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.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.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.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.mechanical_air_change, 'thermal_zone mechanical air change is not none')