complete modification of the structure of the classes that define the buildig for a better adjustment to the different data sources and the connected tools. NOT finished

This commit is contained in:
Pilar 2022-03-17 18:49:44 -04:00
parent 69169b45b1
commit 77a8969a7e
27 changed files with 1465 additions and 944 deletions

View File

@ -9,131 +9,131 @@ from typing import Union, List
class Schedule: class Schedule:
""" """
Schedule class Schedule class
""" """
def __init__(self): def __init__(self):
self._id = None self._id = None
self._type = None self._type = None
self._values = None self._values = None
self._data_type = None self._data_type = None
self._time_step = None self._time_step = None
self._time_range = None self._time_range = None
self._day_types = None self._day_types = None
@property @property
def id(self): def id(self):
""" """
Get schedule id, an universally unique identifier randomly generated Get schedule id, an universally unique identifier randomly generated
:return: str :return: str
""" """
if self._id is None: if self._id is None:
self._id = uuid.uuid4() self._id = uuid.uuid4()
return self._id return self._id
@property @property
def type(self) -> Union[None, str]: def type(self) -> Union[None, str]:
""" """
Get schedule type Get schedule type
:return: None or str :return: None or str
""" """
return self._type return self._type
@type.setter @type.setter
def type(self, value): def type(self, value):
""" """
Set schedule type Set schedule type
:param: str :param: str
""" """
if value is not None: if value is not None:
self._type = str(value) self._type = str(value)
@property @property
def values(self): def values(self):
""" """
Get schedule values Get schedule values
:return: [Any] :return: [Any]
""" """
return self._values return self._values
@values.setter @values.setter
def values(self, value): def values(self, value):
""" """
Set schedule values Set schedule values
:param: [Any] :param: [Any]
""" """
self._values = value self._values = value
@property @property
def data_type(self) -> Union[None, str]: def data_type(self) -> Union[None, str]:
""" """
Get schedule data type from: Get schedule data type from:
['any_number', 'fraction', 'on_off', 'temperature', 'humidity', 'control_type'] ['any_number', 'fraction', 'on_off', 'temperature', 'humidity', 'control_type']
:return: None or str :return: None or str
""" """
return self._data_type return self._data_type
@data_type.setter @data_type.setter
def data_type(self, value): def data_type(self, value):
""" """
Set schedule data type Set schedule data type
:param: str :param: str
""" """
if value is not None: if value is not None:
self._data_type = str(value) self._data_type = str(value)
@property @property
def time_step(self) -> Union[None, str]: def time_step(self) -> Union[None, str]:
""" """
Get schedule time step from: Get schedule time step from:
['second', 'minute', 'hour', 'day', 'week', 'month'] ['second', 'minute', 'hour', 'day', 'week', 'month']
:return: None or str :return: None or str
""" """
return self._time_step return self._time_step
@time_step.setter @time_step.setter
def time_step(self, value): def time_step(self, value):
""" """
Set schedule time step Set schedule time step
:param: str :param: str
""" """
if value is not None: if value is not None:
self._time_step = str(value) self._time_step = str(value)
@property @property
def time_range(self) -> Union[None, str]: def time_range(self) -> Union[None, str]:
""" """
Get schedule time range from: Get schedule time range from:
['minute', 'hour', 'day', 'week', 'month', 'year'] ['minute', 'hour', 'day', 'week', 'month', 'year']
:return: None or str :return: None or str
""" """
return self._time_range return self._time_range
@time_range.setter @time_range.setter
def time_range(self, value): def time_range(self, value):
""" """
Set schedule time range Set schedule time range
:param: str :param: str
""" """
if value is not None: if value is not None:
self._time_range = str(value) self._time_range = str(value)
@property @property
def day_types(self) -> Union[None, List[str]]: def day_types(self) -> Union[None, List[str]]:
""" """
Get schedule day types, as many as needed from: Get schedule day types, as many as needed from:
['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'holiday', 'winter_design_day', ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'holiday', 'winter_design_day',
'summer_design_day'] 'summer_design_day']
:return: None or [str] :return: None or [str]
""" """
return self._day_types return self._day_types
@day_types.setter @day_types.setter
def day_types(self, value): def day_types(self, value):
""" """
Set schedule day types Set schedule day types
:param: [str] :param: [str]
""" """
if value is not None: if value is not None:
self._day_types = [str(i) for i in value] self._day_types = [str(i) for i in value]

View File

@ -5,18 +5,15 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from typing import List, Union, TypeVar from typing import List, Union
import numpy as np import numpy as np
from city_model_structure.building_demand.surface import Surface from city_model_structure.building_demand.surface import Surface
from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.building_demand.storey import Storey from city_model_structure.building_demand.storey import Storey
from city_model_structure.city_object import CityObject from city_model_structure.city_object import CityObject
from city_model_structure.building_demand.household import Household from city_model_structure.building_demand.household import Household
from city_model_structure.building_demand.internal_zone import InternalZone from city_model_structure.building_demand.internal_zone import InternalZone
from city_model_structure.attributes.polyhedron import Polyhedron from city_model_structure.attributes.polyhedron import Polyhedron
ThermalZone = TypeVar('ThermalZone')
class Building(CityObject): class Building(CityObject):
""" """
@ -36,9 +33,7 @@ class Building(CityObject):
self._roof_type = None self._roof_type = None
self._storeys = None self._storeys = None
self._internal_zones = None self._internal_zones = None
self._shell = None self._shell = None
self._thermal_zones = None
self._usage_zones = None
self._type = 'building' self._type = 'building'
self._heating = dict() self._heating = dict()
self._cooling = dict() self._cooling = dict()
@ -108,22 +103,6 @@ class Building(CityObject):
""" """
return self._walls return self._walls
@property
def usage_zones(self) -> Union[None, List[UsageZone]]:
"""
Get city object usage zones
:return: [UsageZone]
"""
return self._usage_zones
@usage_zones.setter
def usage_zones(self, value):
"""
Set city object usage zones
:param value: [UsageZone]
"""
self._usage_zones = value
@property @property
def terrains(self) -> Union[None, List[Surface]]: def terrains(self) -> Union[None, List[Surface]]:
""" """
@ -166,22 +145,6 @@ class Building(CityObject):
if value is not None: if value is not None:
self._basement_heated = int(value) self._basement_heated = int(value)
@property
def thermal_zones(self) -> Union[None, List[ThermalZone]]:
"""
Get building thermal zones
:return: [ThermalZone]
"""
return self._thermal_zones
@thermal_zones.setter
def thermal_zones(self, value):
"""
Set city object thermal zones
:param value: [ThermalZone]
"""
self._thermal_zones = value
@property @property
def heated_volume(self): def heated_volume(self):
""" """
@ -368,9 +331,11 @@ class Building(CityObject):
Get building heated flag Get building heated flag
:return: Boolean :return: Boolean
""" """
if self.thermal_zones is None: if self.internal_zones is None:
return False return False
for thermal_zone in self.thermal_zones: for internal_zone in self.internal_zones:
if thermal_zone.hvac_system is not None: if internal_zone.usage_zones is not None:
return True for usage_zone in internal_zone.usage_zones:
if usage_zone.thermal_control is not None:
return True
return False return False

View File

@ -3,7 +3,7 @@ Appliances module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from typing import Union from typing import Union, List
from city_model_structure.attributes.schedule import Schedule from city_model_structure.attributes.schedule import Schedule
@ -12,28 +12,28 @@ class Appliances:
Appliances class Appliances class
""" """
def __init__(self): def __init__(self):
self._lighting_density = None self._appliances_density = None
self._convective_fraction = None self._convective_fraction = None
self._radiant_fraction = None self._radiative_fraction = None
self._latent_fraction = None self._latent_fraction = None
self._schedule = None self._schedules = None
@property @property
def lighting_density(self) -> Union[None, float]: def appliances_density(self) -> Union[None, float]:
""" """
Get lighting density in Watts per m2 Get appliances density in Watts per m2
:return: None or float :return: None or float
""" """
return self._lighting_density return self._appliances_density
@lighting_density.setter @appliances_density.setter
def lighting_density(self, value): def appliances_density(self, value):
""" """
Set lighting density in Watts per m2 Set appliances density in Watts per m2
:param value: float :param value: float
""" """
if value is not None: if value is not None:
self._lighting_density = float(value) self._appliances_density = float(value)
@property @property
def convective_fraction(self) -> Union[None, float]: def convective_fraction(self) -> Union[None, float]:
@ -53,21 +53,21 @@ class Appliances:
self._convective_fraction = float(value) self._convective_fraction = float(value)
@property @property
def radiant_fraction(self) -> Union[None, float]: def radiative_fraction(self) -> Union[None, float]:
""" """
Get radiant fraction Get radiant fraction
:return: None or float :return: None or float
""" """
return self._radiant_fraction return self._radiative_fraction
@radiant_fraction.setter @radiative_fraction.setter
def radiant_fraction(self, value): def radiative_fraction(self, value):
""" """
Set radiant fraction Set radiant fraction
:param value: float :param value: float
""" """
if value is not None: if value is not None:
self._radiant_fraction = float(value) self._radiative_fraction = float(value)
@property @property
def latent_fraction(self) -> Union[None, float]: def latent_fraction(self) -> Union[None, float]:
@ -87,17 +87,17 @@ class Appliances:
self._latent_fraction = float(value) self._latent_fraction = float(value)
@property @property
def schedule(self) -> Union[None, Schedule]: def schedules(self) -> Union[None, List[Schedule]]:
""" """
Get schedule Get schedules
:return: None or Schedule :return: None or [Schedule]
""" """
return self._schedule return self._schedules
@schedule.setter @schedules.setter
def schedule(self, value): def schedules(self, value):
""" """
Set schedule Set schedules
:param value: Schedule :param value: [Schedule]
""" """
self._schedule = value self._schedules = value

View File

@ -4,7 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
from typing import Union from typing import Union, List
from city_model_structure.attributes.schedule import Schedule from city_model_structure.attributes.schedule import Schedule
@ -19,7 +19,7 @@ class InternalGains:
self._convective_fraction = None self._convective_fraction = None
self._radiative_fraction = None self._radiative_fraction = None
self._latent_fraction = None self._latent_fraction = None
self._schedule = None self._schedules = None
@property @property
def type(self) -> Union[None, str]: def type(self) -> Union[None, str]:
@ -107,17 +107,17 @@ class InternalGains:
self._latent_fraction = float(value) self._latent_fraction = float(value)
@property @property
def schedule(self) -> Union[None, Schedule]: def schedules(self) -> Union[None, List[Schedule]]:
""" """
Get internal gain schedule Get internal gain schedule
:return: Schedule :return: [Schedule]
""" """
return self._schedule return self._schedules
@schedule.setter @schedules.setter
def schedule(self, value): def schedules(self, value):
""" """
Set internal gain schedule Set internal gain schedule
:param value: Schedule :param value: [Schedule]
""" """
self._schedule = value self._schedules = value

View File

@ -3,9 +3,13 @@ InternalZone module. It saves the original geometrical information from interior
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import uuid import uuid
from typing import Union, List
from city_model_structure.building_demand.usage_zone import UsageZone from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.building_demand.thermal_zone import ThermalZone
from city_model_structure.attributes.polyhedron import Polyhedron from city_model_structure.attributes.polyhedron import Polyhedron
from city_model_structure.energy_systems.hvac_system import HvacSystem
class InternalZone: class InternalZone:
@ -18,7 +22,9 @@ class InternalZone:
self._geometry = None self._geometry = None
self._volume = None self._volume = None
self._area = area self._area = area
self._usage_zones = [] self._thermal_zones = None
self._usage_zones = None
self._hvac_system = None
@property @property
def id(self): def id(self):
@ -82,3 +88,36 @@ class InternalZone:
:param value: [UsageZone] :param value: [UsageZone]
""" """
self._usage_zones = value self._usage_zones = value
@property
def hvac_system(self) -> Union[None, HvacSystem]:
"""
Get HVAC system installed for this thermal 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
:param value: HvacSystem
"""
self._hvac_system = value
@property
def thermal_zones(self) -> Union[None, List[ThermalZone]]:
"""
Get building thermal zones
:return: [ThermalZone]
"""
return self._thermal_zones
@thermal_zones.setter
def thermal_zones(self, value):
"""
Set city object thermal zones
:param value: [ThermalZone]
"""
self._thermal_zones = value

View File

@ -3,7 +3,7 @@ Lighting module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from typing import Union from typing import Union, List
from city_model_structure.attributes.schedule import Schedule from city_model_structure.attributes.schedule import Schedule
@ -14,9 +14,9 @@ class Lighting:
def __init__(self): def __init__(self):
self._lighting_density = None self._lighting_density = None
self._convective_fraction = None self._convective_fraction = None
self._radiant_fraction = None self._radiative_fraction = None
self._latent_fraction = None self._latent_fraction = None
self._schedule = None self._schedules = None
@property @property
def lighting_density(self) -> Union[None, float]: def lighting_density(self) -> Union[None, float]:
@ -53,21 +53,21 @@ class Lighting:
self._convective_fraction = float(value) self._convective_fraction = float(value)
@property @property
def radiant_fraction(self) -> Union[None, float]: def radiative_fraction(self) -> Union[None, float]:
""" """
Get radiant fraction Get radiant fraction
:return: None or float :return: None or float
""" """
return self._radiant_fraction return self._radiative_fraction
@radiant_fraction.setter @radiative_fraction.setter
def radiant_fraction(self, value): def radiative_fraction(self, value):
""" """
Set radiant fraction Set radiant fraction
:param value: float :param value: float
""" """
if value is not None: if value is not None:
self._radiant_fraction = float(value) self._radiative_fraction = float(value)
@property @property
def latent_fraction(self) -> Union[None, float]: def latent_fraction(self) -> Union[None, float]:
@ -87,17 +87,17 @@ class Lighting:
self._latent_fraction = float(value) self._latent_fraction = float(value)
@property @property
def schedule(self) -> Union[None, Schedule]: def schedules(self) -> Union[None, List[Schedule]]:
""" """
Get schedule Get schedules
:return: None or Schedule :return: None or [Schedule]
""" """
return self._schedule return self._schedules
@schedule.setter @schedules.setter
def schedule(self, value): def schedules(self, value):
""" """
Set schedule Set schedules
:param value: Schedule :param value: [Schedule]
""" """
self._schedule = value self._schedules = value

View File

@ -15,9 +15,9 @@ class Occupancy:
def __init__(self): def __init__(self):
self._occupancy_density = None self._occupancy_density = None
self._sensible_convective_internal_gain = None self._sensible_convective_internal_gain = None
self._sensible_radiant_internal_gain = None self._sensible_radiative_internal_gain = None
self._latent_internal_gain = None self._latent_internal_gain = None
self._occupancy_schedule = None self._occupancy_schedules = None
self._occupants = None self._occupants = None
@property @property
@ -55,21 +55,21 @@ class Occupancy:
self._sensible_convective_internal_gain = float(value) self._sensible_convective_internal_gain = float(value)
@property @property
def sensible_radiant_internal_gain(self) -> Union[None, float]: def sensible_radiative_internal_gain(self) -> Union[None, float]:
""" """
Get sensible radiant internal gain in Watts per m2 Get sensible radiant internal gain in Watts per m2
:return: None or float :return: None or float
""" """
return self._sensible_radiant_internal_gain return self._sensible_radiative_internal_gain
@sensible_radiant_internal_gain.setter @sensible_radiative_internal_gain.setter
def sensible_radiant_internal_gain(self, value): def sensible_radiative_internal_gain(self, value):
""" """
Set sensible radiant internal gain in Watts per m2 Set sensible radiant internal gain in Watts per m2
:param value: float :param value: float
""" """
if value is not None: if value is not None:
self._sensible_radiant_internal_gain = float(value) self._sensible_radiative_internal_gain = float(value)
@property @property
def latent_internal_gain(self) -> Union[None, float]: def latent_internal_gain(self) -> Union[None, float]:
@ -89,20 +89,20 @@ class Occupancy:
self._latent_internal_gain = float(value) self._latent_internal_gain = float(value)
@property @property
def occupancy_schedule(self) -> Union[None, Schedule]: def occupancy_schedules(self) -> Union[None, List[Schedule]]:
""" """
Get occupancy schedule Get occupancy schedules
:return: None or Schedule :return: None or [Schedule]
""" """
return self._occupancy_schedule return self._occupancy_schedules
@occupancy_schedule.setter @occupancy_schedules.setter
def occupancy_schedule(self, value): def occupancy_schedules(self, value):
""" """
Set occupancy schedule Set occupancy schedules
:param value: Schedule :param value: [Schedule]
""" """
self._occupancy_schedule = value self._occupancy_schedules = value
@property @property
def occupants(self) -> Union[None, List[Occupant]]: def occupants(self) -> Union[None, List[Occupant]]:

View File

@ -3,7 +3,7 @@ ThermalControl module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from typing import Union from typing import Union, List
from city_model_structure.attributes.schedule import Schedule from city_model_structure.attributes.schedule import Schedule
@ -12,35 +12,59 @@ class ThermalControl:
ThermalControl class ThermalControl class
""" """
def __init__(self): def __init__(self):
self._heating_set_point = None self._mean_heating_set_point = None
self._cooling_set_point = None
self._hvac_availability = None
self._heating_set_back = None self._heating_set_back = None
self._mean_cooling_set_point = None
self._hvac_availability_schedules = None
self._heating_set_point_schedules = None
self._cooling_set_point_schedules = None
@staticmethod
def _maximum_value(schedules):
maximum = -1000
for schedule in schedules:
for value in schedule.values:
if value > maximum:
maximum = value
return maximum
@staticmethod
def _minimum_value(schedules):
minimum = 1000
for schedule in schedules:
for value in schedule.values:
if value < minimum:
minimum = value
return minimum
@property @property
def heating_set_point(self) -> Union[None, Schedule]: def mean_heating_set_point(self) -> Union[None, float]:
""" """
Get heating set point defined for a thermal zone in Celsius Get heating set point defined for a thermal zone in Celsius
:return: None or Schedule :return: None or float
""" """
return self._heating_set_point if self._mean_heating_set_point is None:
if self.heating_set_point_schedules is not None:
self._mean_heating_set_point = self._maximum_value(self.heating_set_point_schedules)
return self._mean_heating_set_point
@heating_set_point.setter @mean_heating_set_point.setter
def heating_set_point(self, value): def mean_heating_set_point(self, value):
""" """
Set heating set point defined for a thermal zone in Celsius Set heating set point defined for a thermal zone in Celsius
:param value: Schedule :param value: float
""" """
self._heating_set_point = value self._mean_heating_set_point = value
@property @property
def heating_set_back(self) -> Union[None, float]: def heating_set_back(self) -> Union[None, float]:
""" """
Get heating set back defined for a thermal zone in Celsius Get heating set back defined for a thermal zone in Celsius
Heating set back is the only parameter which is not a schedule as it is either one value or it is implicit in the
set point schedule
:return: None or float :return: None or float
""" """
if self._heating_set_back is None:
if self.heating_set_point_schedules is not None:
self._heating_set_back = self._minimum_value(self.heating_set_point_schedules)
return self._heating_set_back return self._heating_set_back
@heating_set_back.setter @heating_set_back.setter
@ -53,34 +77,68 @@ class ThermalControl:
self._heating_set_back = float(value) self._heating_set_back = float(value)
@property @property
def cooling_set_point(self) -> Union[None, Schedule]: def mean_cooling_set_point(self) -> Union[None, float]:
""" """
Get cooling set point defined for a thermal zone in Celsius Get cooling set point defined for a thermal zone in Celsius
:return: None or Schedule :return: None or float
""" """
return self._cooling_set_point if self._mean_cooling_set_point is None:
if self.cooling_set_point_schedules is not None:
self._mean_cooling_set_point = self._minimum_value(self.cooling_set_point_schedules)
return self._mean_cooling_set_point
@cooling_set_point.setter @mean_cooling_set_point.setter
def cooling_set_point(self, value): def mean_cooling_set_point(self, value):
""" """
Set cooling set point defined for a thermal zone in Celsius Set cooling set point defined for a thermal zone in Celsius
:param value: Schedule :param value: float
""" """
self._cooling_set_point = value self._mean_cooling_set_point = value
@property @property
def hvac_availability(self) -> Union[None, Schedule]: def hvac_availability_schedules(self) -> Union[None, List[Schedule]]:
""" """
Get the availability of the conditioning system defined for a thermal zone Get the availability of the conditioning system defined for a thermal zone
:return: None or Schedule :return: None or [Schedule]
""" """
return self._hvac_availability return self._hvac_availability_schedules
@hvac_availability.setter @hvac_availability_schedules.setter
def hvac_availability(self, value): def hvac_availability_schedules(self, value):
""" """
Set the availability of the conditioning system defined for a thermal zone Set the availability of the conditioning system defined for a thermal zone
:param value: Schedule :param value: [Schedule]
""" """
self._hvac_availability = value self._hvac_availability_schedules = value
@property
def heating_set_point_schedules(self) -> Union[None, List[Schedule]]:
"""
Get heating set point schedule defined for a thermal zone in Celsius
:return: None or [Schedule]
"""
return self._heating_set_point_schedules
@heating_set_point_schedules.setter
def heating_set_point_schedules(self, value):
"""
Set heating set point schedule defined for a thermal zone in Celsius
:param value: [Schedule]
"""
self._heating_set_point_schedules = value
@property
def cooling_set_point_schedules(self) -> Union[None, List[Schedule]]:
"""
Get cooling set point schedule defined for a thermal zone in Celsius
:return: None or [Schedule]
"""
return self._cooling_set_point_schedules
@cooling_set_point_schedules.setter
def cooling_set_point_schedules(self, value):
"""
Set cooling set point schedule defined for a thermal zone in Celsius
:param value: [Schedule]
"""
self._cooling_set_point_schedules = value

View File

@ -5,11 +5,11 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import uuid import uuid
from typing import List, Union, Tuple, TypeVar from typing import List, Union, TypeVar
from city_model_structure.building_demand.usage_zone import UsageZone from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.attributes.schedule import Schedule
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
ThermalBoundary = TypeVar('ThermalBoundary') ThermalBoundary = TypeVar('ThermalBoundary')
@ -27,11 +27,12 @@ class ThermalZone:
self._indirectly_heated_area_ratio = None self._indirectly_heated_area_ratio = None
self._infiltration_rate_system_on = None self._infiltration_rate_system_on = None
self._infiltration_rate_system_off = None self._infiltration_rate_system_off = None
self._usage_zones = None
self._volume = volume self._volume = volume
self._ordinate_number = None self._ordinate_number = None
self._usage_zones = None
self._thermal_control = None self._thermal_control = None
self._hvac_system = None self._hvac_system = None
self._view_factors_matrix = None
@property @property
def id(self): def id(self):
@ -142,22 +143,6 @@ class ThermalZone:
""" """
self._infiltration_rate_system_off = value self._infiltration_rate_system_off = value
@property
def usage_zones(self) -> Tuple[float, UsageZone]:
"""
Get list of usage zones and the percentage of thermal zone's volume affected by that usage
: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
:param values: Tuple[float, UsageZone]
"""
self._usage_zones = values
@property @property
def volume(self): def volume(self):
""" """
@ -183,10 +168,29 @@ class ThermalZone:
if value is not None: if value is not None:
self._ordinate_number = int(value) 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 @property
def thermal_control(self) -> Union[None, ThermalControl]: def thermal_control(self) -> Union[None, ThermalControl]:
""" """
Get thermal control of this thermal zone Get thermal control of this thermal zone
From internal_zone
:return: None or ThermalControl :return: None or ThermalControl
""" """
return self._thermal_control return self._thermal_control
@ -195,6 +199,7 @@ class ThermalZone:
def thermal_control(self, value): def thermal_control(self, value):
""" """
Set thermal control for this thermal zone Set thermal control for this thermal zone
From internal_zone
:param value: ThermalControl :param value: ThermalControl
""" """
self._thermal_control = value self._thermal_control = value
@ -203,6 +208,7 @@ class ThermalZone:
def hvac_system(self) -> Union[None, HvacSystem]: def hvac_system(self) -> Union[None, HvacSystem]:
""" """
Get HVAC system installed for this thermal zone Get HVAC system installed for this thermal zone
From internal_zone
:return: None or HvacSystem :return: None or HvacSystem
""" """
return self._hvac_system return self._hvac_system
@ -211,6 +217,23 @@ class ThermalZone:
def hvac_system(self, value): def hvac_system(self, value):
""" """
Set HVAC system installed for this thermal zone Set HVAC system installed for this thermal zone
From internal_zone
:param value: HvacSystem :param value: HvacSystem
""" """
self._hvac_system = value self._hvac_system = value
@property
def view_factors_matrix(self):
"""
Get thermal zone view factors matrix
:return: [[float]]
"""
return self._view_factors_matrix
@view_factors_matrix.setter
def view_factors_matrix(self, value):
"""
Set thermal zone view factors matrix
:param value: [[float]]
"""
self._view_factors_matrix = value

View File

@ -11,6 +11,7 @@ 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.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
class UsageZone: class UsageZone:
@ -20,6 +21,7 @@ class UsageZone:
def __init__(self): def __init__(self):
self._id = None self._id = None
self._usage = None self._usage = None
self._percentage = None
self._not_detailed_source_mean_annual_internal_gains = None 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
@ -29,6 +31,7 @@ class UsageZone:
self._lighting = None self._lighting = None
self._appliances = None self._appliances = None
self._internal_gains = None self._internal_gains = None
self._thermal_control = None
@property @property
def id(self): def id(self):
@ -40,6 +43,40 @@ class UsageZone:
self._id = uuid.uuid4() self._id = uuid.uuid4()
return self._id return self._id
@property
def usage(self) -> Union[None, str]:
"""
Get usage zone usage
:return: None or str
"""
return self._usage
@usage.setter
def usage(self, value):
"""
Set usage zone usage
:param value: str
"""
if value is not None:
self._usage = str(value)
@property
def percentage(self):
"""
Get usage zone percentage in range[0,1]
:return: float
"""
return self._percentage
@percentage.setter
def percentage(self, value):
"""
Set usage zone percentage in range[0,1]
:param value: float
"""
if value is not None:
self._percentage = float(value)
@property @property
def not_detailed_source_mean_annual_internal_gains(self) -> List[InternalGains]: def not_detailed_source_mean_annual_internal_gains(self) -> List[InternalGains]:
""" """
@ -107,23 +144,6 @@ class UsageZone:
if value is not None: if value is not None:
self._mechanical_air_change = float(value) self._mechanical_air_change = float(value)
@property
def usage(self) -> Union[None, str]:
"""
Get usage zone usage
:return: None or str
"""
return self._usage
@usage.setter
def usage(self, value):
"""
Set usage zone usage
:param value: str
"""
if value is not None:
self._usage = str(value)
@property @property
def electrical_app_average_consumption_sqm_year(self) -> Union[None, float]: def electrical_app_average_consumption_sqm_year(self) -> Union[None, float]:
""" """
@ -199,22 +219,22 @@ class UsageZone:
_internal_gain = InternalGains() _internal_gain = InternalGains()
_internal_gain.type = cte.OCCUPANCY _internal_gain.type = cte.OCCUPANCY
_total_heat_gain = (self.occupancy.sensible_convective_internal_gain _total_heat_gain = (self.occupancy.sensible_convective_internal_gain
+ self.occupancy.sensible_radiant_internal_gain + self.occupancy.sensible_radiative_internal_gain
+ self.occupancy.latent_internal_gain) + self.occupancy.latent_internal_gain)
_internal_gain.average_internal_gain = _total_heat_gain _internal_gain.average_internal_gain = _total_heat_gain
_internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain _internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain
_internal_gain.radiative_fraction = self.occupancy.sensible_radiant_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.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain
_internal_gain.schedule = self.occupancy.occupancy_schedule _internal_gain.schedules = self.occupancy.occupancy_schedules
self._internal_gains = [_internal_gain] self._internal_gains = [_internal_gain]
if self.lighting is not None: if self.lighting is not None:
_internal_gain = InternalGains() _internal_gain = InternalGains()
_internal_gain.type = cte.LIGHTING _internal_gain.type = cte.LIGHTING
_internal_gain.average_internal_gain = self.lighting.lighting_density _internal_gain.average_internal_gain = self.lighting.lighting_density
_internal_gain.latent_fraction = self.lighting.latent_fraction _internal_gain.latent_fraction = self.lighting.latent_fraction
_internal_gain.radiative_fraction = self.lighting.radiant_fraction _internal_gain.radiative_fraction = self.lighting.radiative_fraction
_internal_gain.convective_fraction = self.lighting.convective_fraction _internal_gain.convective_fraction = self.lighting.convective_fraction
_internal_gain.schedule = self.lighting.schedule _internal_gain.schedules = self.lighting.schedules
if self._internal_gains is not None: if self._internal_gains is not None:
self._internal_gains.append(_internal_gain) self._internal_gains.append(_internal_gain)
else: else:
@ -222,13 +242,29 @@ class UsageZone:
if self.appliances is not None: if self.appliances is not None:
_internal_gain = InternalGains() _internal_gain = InternalGains()
_internal_gain.type = cte.APPLIANCES _internal_gain.type = cte.APPLIANCES
_internal_gain.average_internal_gain = self.appliances.lighting_density _internal_gain.average_internal_gain = self.appliances.appliances_density
_internal_gain.latent_fraction = self.appliances.latent_fraction _internal_gain.latent_fraction = self.appliances.latent_fraction
_internal_gain.radiative_fraction = self.appliances.radiant_fraction _internal_gain.radiative_fraction = self.appliances.radiative_fraction
_internal_gain.convective_fraction = self.appliances.convective_fraction _internal_gain.convective_fraction = self.appliances.convective_fraction
_internal_gain.schedule = self.appliances.schedule _internal_gain.schedules = self.appliances.schedules
if self._internal_gains is not None: if self._internal_gains is not None:
self._internal_gains.append(_internal_gain) self._internal_gains.append(_internal_gain)
else: else:
self._internal_gains = [_internal_gain] self._internal_gains = [_internal_gain]
return self._internal_gains return self._internal_gains
@property
def thermal_control(self) -> Union[None, ThermalControl]:
"""
Get thermal control of this thermal zone
:return: None or ThermalControl
"""
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

Binary file not shown.

View File

@ -84,7 +84,7 @@
<weekDayProfile> <weekDayProfile>
<source>DIN 18599-10</source> <source>DIN 18599-10</source>
<values>16.0 16.0 16.0 16.0 16.0 16.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 <values>16.0 16.0 16.0 16.0 16.0 16.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0
20.0 20.0 20.0 20.0 20.0 20.0 0.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0
</values> </values>
</weekDayProfile> </weekDayProfile>
</schedule> </schedule>
@ -117,7 +117,7 @@
<schedule> <schedule>
<weekDayProfile> <weekDayProfile>
<values>16.0 16.0 16.0 16.0 16.0 16.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 <values>16.0 16.0 16.0 16.0 16.0 16.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0
20.0 20.0 20.0 20.0 20.0 20.0 0.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0
</values> </values>
</weekDayProfile> </weekDayProfile>
</schedule> </schedule>

View File

@ -11,6 +11,7 @@ KELVIN = 273.15
HOUR_TO_MINUTES = 60 HOUR_TO_MINUTES = 60
METERS_TO_FEET = 3.28084 METERS_TO_FEET = 3.28084
BTU_H_TO_WATTS = 0.29307107 BTU_H_TO_WATTS = 0.29307107
KILO_WATTS_HOUR_TO_JULES = 3600000
# time # time
SECOND = 'second' SECOND = 'second'

View File

@ -25,23 +25,25 @@ class CaPhysicsParameters(NrelPhysicsInterface):
city = self._city city = self._city
# it is assumed that all buildings have the same archetypes' keys # it is assumed that all buildings have the same archetypes' keys
for building in city.buildings: for building in city.buildings:
archetype = self._search_archetype(ConstructionHelper.nrcan_from_function(building.function), try:
building.year_of_construction) archetype = self._search_archetype(ConstructionHelper.nrcan_from_function(building.function),
if archetype is None: building.year_of_construction)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: ' sys.stderr.write(f'Building {building.name} has unknown archetype for building function: '
f'{ConstructionHelper.nrcan_from_function(building.function)} ' f'{ConstructionHelper.nrcan_from_function(building.function)} '
f'and building year of construction: {building.year_of_construction}\n') f'and building year of construction: {building.year_of_construction}\n')
continue return
# if building has no thermal zones defined from geometry, one thermal zone per storey is assigned # if building has no thermal zones defined from geometry, one thermal zone per storey is assigned
if building.thermal_zones is None: if len(building.internal_zones) == 1:
self._create_storeys(building, archetype) if building.internal_zones[0].thermal_zones is None:
thermal_zones = [] self._create_storeys(building, archetype)
for storey in building.storeys: thermal_zones = []
thermal_zones.append(storey.thermal_zone) for storey in building.storeys:
building.thermal_zones = thermal_zones thermal_zones.append(storey.thermal_zone)
building.internal_zones[0].thermal_zones = thermal_zones
self._assign_values(building, archetype) self._assign_values(building.internal_zones, archetype)
def _search_archetype(self, function, year_of_construction): def _search_archetype(self, function, year_of_construction):
for building_archetype in self._building_archetypes: for building_archetype in self._building_archetypes:
@ -54,31 +56,32 @@ class CaPhysicsParameters(NrelPhysicsInterface):
return building_archetype return building_archetype
return None return None
def _assign_values(self, building, archetype): def _assign_values(self, internal_zones, archetype):
for thermal_zone in building.thermal_zones: for internal_zone in internal_zones:
thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value for thermal_zone in internal_zone.thermal_zones:
thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value
thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on
for thermal_boundary in thermal_zone.thermal_boundaries: thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off
construction_type = ConstructionHelper.nrcan_construction_types[thermal_boundary.type] for thermal_boundary in thermal_zone.thermal_boundaries:
thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type) construction_type = ConstructionHelper.nrcan_construction_types[thermal_boundary.type]
thermal_boundary.u_value = thermal_boundary_archetype.overall_u_value thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type)
thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance thermal_boundary.u_value = thermal_boundary_archetype.overall_u_value
thermal_boundary.construction_name = thermal_boundary_archetype.construction_name thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance
try: thermal_boundary.construction_name = thermal_boundary_archetype.construction_name
thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio try:
except ValueError: thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio
# This is the normal operation way when the windows are defined in the geometry except ValueError:
continue # This is the normal operation way when the windows are defined in the geometry
if thermal_boundary.thermal_openings is not None: continue
for thermal_opening in thermal_boundary.thermal_openings: if thermal_boundary.thermal_openings is not None:
if thermal_boundary_archetype.thermal_opening_archetype is not None: for thermal_opening in thermal_boundary.thermal_openings:
thermal_opening_archetype = thermal_boundary_archetype.thermal_opening_archetype if thermal_boundary_archetype.thermal_opening_archetype is not None:
thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio thermal_opening_archetype = thermal_boundary_archetype.thermal_opening_archetype
thermal_opening.g_value = thermal_opening_archetype.g_value thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio
thermal_opening.overall_u_value = thermal_opening_archetype.overall_u_value thermal_opening.g_value = thermal_opening_archetype.g_value
thermal_opening.overall_u_value = thermal_opening_archetype.overall_u_value
@staticmethod @staticmethod
def _create_storeys(building, archetype): def _create_storeys(building, archetype):

View File

@ -12,7 +12,7 @@ class ConstructionHelper:
Construction helper Construction helper
""" """
# NREL # NREL
function_to_nrel = { _function_to_nrel = {
cte.RESIDENTIAL: 'residential', cte.RESIDENTIAL: 'residential',
cte.SFH: 'single family house', cte.SFH: 'single family house',
cte.MFH: 'multifamily house', cte.MFH: 'multifamily house',
@ -27,12 +27,12 @@ class ConstructionHelper:
cte.OFFICE: 'office', cte.OFFICE: 'office',
cte.LARGE_OFFICE: 'large office' cte.LARGE_OFFICE: 'large office'
} }
nrel_function_default_value = 'residential'
nrel_standards = { _nrel_standards = {
'ASHRAE Std189': 1, 'ASHRAE Std189': 1,
'ASHRAE 90.1_2004': 2 'ASHRAE 90.1_2004': 2
} }
reference_city_to_nrel_climate_zone = { _reference_city_to_nrel_climate_zone = {
'Miami': 'ASHRAE_2004:1A', 'Miami': 'ASHRAE_2004:1A',
'Houston': 'ASHRAE_2004:2A', 'Houston': 'ASHRAE_2004:2A',
'Phoenix': 'ASHRAE_2004:2B', 'Phoenix': 'ASHRAE_2004:2B',
@ -51,6 +51,7 @@ class ConstructionHelper:
'Fairbanks': 'ASHRAE_2004:8A' 'Fairbanks': 'ASHRAE_2004:8A'
} }
nrel_window_types = [cte.WINDOW, cte.DOOR, cte.SKYLIGHT] nrel_window_types = [cte.WINDOW, cte.DOOR, cte.SKYLIGHT]
nrel_construction_types = { nrel_construction_types = {
cte.WALL: 'exterior wall', cte.WALL: 'exterior wall',
cte.INTERIOR_WALL: 'interior wall', cte.INTERIOR_WALL: 'interior wall',
@ -62,7 +63,7 @@ class ConstructionHelper:
} }
# NRCAN # NRCAN
function_to_nrcan = { _function_to_nrcan = {
cte.RESIDENTIAL: 'residential', cte.RESIDENTIAL: 'residential',
cte.SFH: 'single family house', cte.SFH: 'single family house',
cte.MFH: 'multifamily house', cte.MFH: 'multifamily house',
@ -78,8 +79,9 @@ class ConstructionHelper:
cte.LARGE_OFFICE: 'large office', cte.LARGE_OFFICE: 'large office',
cte.OFFICE_WORKSHOP: 'residential' cte.OFFICE_WORKSHOP: 'residential'
} }
nrcan_function_default_value = 'residential'
nrcan_window_types = [cte.WINDOW] nrcan_window_types = [cte.WINDOW]
nrcan_construction_types = { nrcan_construction_types = {
cte.WALL: 'wall', cte.WALL: 'wall',
cte.GROUND_WALL: 'basement_wall', cte.GROUND_WALL: 'basement_wall',
@ -97,10 +99,9 @@ class ConstructionHelper:
:return: str :return: str
""" """
try: try:
return ConstructionHelper.function_to_nrel[function] return ConstructionHelper._function_to_nrel[function]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default NREL function "residential"\n') sys.stderr.write('Error: keyword not found.\n')
return ConstructionHelper.nrel_function_default_value
@staticmethod @staticmethod
def yoc_to_nrel_standard(year_of_construction): def yoc_to_nrel_standard(year_of_construction):
@ -136,7 +137,7 @@ class ConstructionHelper:
:return: str :return: str
""" """
reference_city = ConstructionHelper.city_to_reference_city(city) reference_city = ConstructionHelper.city_to_reference_city(city)
return ConstructionHelper.reference_city_to_nrel_climate_zone[reference_city] return ConstructionHelper._reference_city_to_nrel_climate_zone[reference_city]
@staticmethod @staticmethod
def nrcan_from_function(function): def nrcan_from_function(function):
@ -146,7 +147,6 @@ class ConstructionHelper:
:return: str :return: str
""" """
try: try:
return ConstructionHelper.function_to_nrcan[function] return ConstructionHelper._function_to_nrcan[function]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default NRCAN function "residential"\n') sys.stderr.write('Error: keyword not found.\n')
return ConstructionHelper.nrcan_function_default_value

View File

@ -33,23 +33,25 @@ class UsPhysicsParameters(NrelPhysicsInterface):
building_type = ConstructionHelper.nrel_from_function(building.function) building_type = ConstructionHelper.nrel_from_function(building.function)
if building_type is None: if building_type is None:
return return
archetype = self._search_archetype(building_type, try:
ConstructionHelper.yoc_to_nrel_standard(building.year_of_construction), archetype = self._search_archetype(building_type,
self._climate_zone) ConstructionHelper.yoc_to_nrel_standard(building.year_of_construction),
if archetype is None: self._climate_zone)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} ' sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} '
f'and building year of construction: {building.year_of_construction}\n') f'and building year of construction: {building.year_of_construction}\n')
continue return
# if building has no thermal zones defined from geometry, one thermal zone per storey is assigned # if building has no thermal zones defined from geometry, one thermal zone per storey is assigned
if building.thermal_zones is None: if len(building.internal_zones) == 1:
self._create_storeys(building, archetype) if building.internal_zones[0].thermal_zones is None:
thermal_zones = [] self._create_storeys(building, archetype)
for storey in building.storeys: thermal_zones = []
thermal_zones.append(storey.thermal_zone) for storey in building.storeys:
building.thermal_zones = thermal_zones thermal_zones.append(storey.thermal_zone)
building.internal_zones[0].thermal_zones = thermal_zones
self._assign_values(building, archetype) self._assign_values(building.internal_zones, archetype)
def _search_archetype(self, building_type, standard, climate_zone): def _search_archetype(self, building_type, standard, climate_zone):
for building_archetype in self._building_archetypes: for building_archetype in self._building_archetypes:
@ -60,52 +62,53 @@ class UsPhysicsParameters(NrelPhysicsInterface):
return building_archetype return building_archetype
return None return None
def _assign_values(self, building, archetype): def _assign_values(self, internal_zones, archetype):
for thermal_zone in building.thermal_zones: for internal_zone in internal_zones:
thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value for thermal_zone in internal_zone.thermal_zones:
thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value
thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on
for thermal_boundary in thermal_zone.thermal_boundaries: thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off
construction_type = ConstructionHelper.nrel_construction_types[thermal_boundary.type] for thermal_boundary in thermal_zone.thermal_boundaries:
thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type) construction_type = ConstructionHelper.nrel_construction_types[thermal_boundary.type]
thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type)
thermal_boundary.outside_thermal_absorptance = thermal_boundary_archetype.outside_thermal_absorptance thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance
thermal_boundary.outside_visible_absorptance = thermal_boundary_archetype.outside_visible_absorptance thermal_boundary.outside_thermal_absorptance = thermal_boundary_archetype.outside_thermal_absorptance
thermal_boundary.construction_name = thermal_boundary_archetype.construction_name thermal_boundary.outside_visible_absorptance = thermal_boundary_archetype.outside_visible_absorptance
try: thermal_boundary.construction_name = thermal_boundary_archetype.construction_name
thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio try:
except ValueError: thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio
# This is the normal operation way when the windows are defined in the geometry except ValueError:
continue # This is the normal operation way when the windows are defined in the geometry
thermal_boundary.layers = [] continue
for layer_archetype in thermal_boundary_archetype.layers: thermal_boundary.layers = []
layer = Layer() for layer_archetype in thermal_boundary_archetype.layers:
layer.thickness = layer_archetype.thickness layer = Layer()
material = Material() layer.thickness = layer_archetype.thickness
material.name = layer_archetype.name material = Material()
material.no_mass = layer_archetype.no_mass material.name = layer_archetype.name
material.density = layer_archetype.density material.no_mass = layer_archetype.no_mass
material.conductivity = layer_archetype.conductivity material.density = layer_archetype.density
material.specific_heat = layer_archetype.specific_heat material.conductivity = layer_archetype.conductivity
material.solar_absorptance = layer_archetype.solar_absorptance material.specific_heat = layer_archetype.specific_heat
material.thermal_absorptance = layer_archetype.thermal_absorptance material.solar_absorptance = layer_archetype.solar_absorptance
material.visible_absorptance = layer_archetype.visible_absorptance material.thermal_absorptance = layer_archetype.thermal_absorptance
material.thermal_resistance = layer_archetype.thermal_resistance material.visible_absorptance = layer_archetype.visible_absorptance
layer.material = material material.thermal_resistance = layer_archetype.thermal_resistance
thermal_boundary.layers.append(layer) layer.material = material
for thermal_opening in thermal_boundary.thermal_openings: thermal_boundary.layers.append(layer)
if thermal_boundary_archetype.thermal_opening_archetype is not None: for thermal_opening in thermal_boundary.thermal_openings:
thermal_opening_archetype = thermal_boundary_archetype.thermal_opening_archetype if thermal_boundary_archetype.thermal_opening_archetype is not None:
thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio thermal_opening_archetype = thermal_boundary_archetype.thermal_opening_archetype
thermal_opening.g_value = thermal_opening_archetype.g_value thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio
thermal_opening.conductivity = thermal_opening_archetype.conductivity thermal_opening.g_value = thermal_opening_archetype.g_value
thermal_opening.thickness = thermal_opening_archetype.thickness thermal_opening.conductivity = thermal_opening_archetype.conductivity
thermal_opening.back_side_solar_transmittance_at_normal_incidence = \ thermal_opening.thickness = thermal_opening_archetype.thickness
thermal_opening_archetype.back_side_solar_transmittance_at_normal_incidence thermal_opening.back_side_solar_transmittance_at_normal_incidence = \
thermal_opening.front_side_solar_transmittance_at_normal_incidence = \ thermal_opening_archetype.back_side_solar_transmittance_at_normal_incidence
thermal_opening_archetype.front_side_solar_transmittance_at_normal_incidence thermal_opening.front_side_solar_transmittance_at_normal_incidence = \
thermal_opening_archetype.front_side_solar_transmittance_at_normal_incidence
@staticmethod @staticmethod
def _create_storeys(building, archetype): def _create_storeys(building, archetype):

View File

@ -12,229 +12,207 @@ class GeometryHelper:
Geometry helper Geometry helper
""" """
# function # function
pluto_to_function = { _pluto_to_function = {
'A0': 'single family house', 'A0': cte.SFH,
'A1': 'single family house', 'A1': cte.SFH,
'A2': 'single family house', 'A2': cte.SFH,
'A3': 'single family house', 'A3': cte.SFH,
'A4': 'single family house', 'A4': cte.SFH,
'A5': 'single family house', 'A5': cte.SFH,
'A6': 'single family house', 'A6': cte.SFH,
'A7': 'single family house', 'A7': cte.SFH,
'A8': 'single family house', 'A8': cte.SFH,
'A9': 'single family house', 'A9': cte.SFH,
'B1': 'multifamily house', 'B1': cte.MFH,
'B2': 'multifamily house', 'B2': cte.MFH,
'B3': 'multifamily house', 'B3': cte.MFH,
'B9': 'multifamily house', 'B9': cte.MFH,
'C0': 'residential', 'C0': cte.RESIDENTIAL,
'C1': 'residential', 'C1': cte.RESIDENTIAL,
'C2': 'residential', 'C2': cte.RESIDENTIAL,
'C3': 'residential', 'C3': cte.RESIDENTIAL,
'C4': 'residential', 'C4': cte.RESIDENTIAL,
'C5': 'residential', 'C5': cte.RESIDENTIAL,
'C6': 'residential', 'C6': cte.RESIDENTIAL,
'C7': 'residential', 'C7': cte.RESIDENTIAL,
'C8': 'residential', 'C8': cte.RESIDENTIAL,
'C9': 'residential', 'C9': cte.RESIDENTIAL,
'D0': 'residential', 'D0': cte.RESIDENTIAL,
'D1': 'residential', 'D1': cte.RESIDENTIAL,
'D2': 'residential', 'D2': cte.RESIDENTIAL,
'D3': 'residential', 'D3': cte.RESIDENTIAL,
'D4': 'residential', 'D4': cte.RESIDENTIAL,
'D5': 'residential', 'D5': cte.RESIDENTIAL,
'D6': 'residential', 'D6': cte.RESIDENTIAL,
'D7': 'residential', 'D7': cte.RESIDENTIAL,
'D8': 'residential', 'D8': cte.RESIDENTIAL,
'D9': 'residential', 'D9': cte.RESIDENTIAL,
'E1': 'warehouse', 'E1': cte.WAREHOUSE,
'E3': 'warehouse', 'E3': cte.WAREHOUSE,
'E4': 'warehouse', 'E4': cte.WAREHOUSE,
'E5': 'warehouse', 'E5': cte.WAREHOUSE,
'E7': 'warehouse', 'E7': cte.WAREHOUSE,
'E9': 'warehouse', 'E9': cte.WAREHOUSE,
'F1': 'warehouse', 'F1': cte.WAREHOUSE,
'F2': 'warehouse', 'F2': cte.WAREHOUSE,
'F4': 'warehouse', 'F4': cte.WAREHOUSE,
'F5': 'warehouse', 'F5': cte.WAREHOUSE,
'F8': 'warehouse', 'F8': cte.WAREHOUSE,
'F9': 'warehouse', 'F9': cte.WAREHOUSE,
'G0': 'office', 'G0': cte.OFFICE,
'G1': 'office', 'G1': cte.OFFICE,
'G2': 'office', 'G2': cte.OFFICE,
'G3': 'office', 'G3': cte.OFFICE,
'G4': 'office', 'G4': cte.OFFICE,
'G5': 'office', 'G5': cte.OFFICE,
'G6': 'office', 'G6': cte.OFFICE,
'G7': 'office', 'G7': cte.OFFICE,
'G8': 'office', 'G8': cte.OFFICE,
'G9': 'office', 'G9': cte.OFFICE,
'H1': 'hotel', 'H1': cte.HOTEL,
'H2': 'hotel', 'H2': cte.HOTEL,
'H3': 'hotel', 'H3': cte.HOTEL,
'H4': 'hotel', 'H4': cte.HOTEL,
'H5': 'hotel', 'H5': cte.HOTEL,
'H6': 'hotel', 'H6': cte.HOTEL,
'H7': 'hotel', 'H7': cte.HOTEL,
'H8': 'hotel', 'H8': cte.HOTEL,
'H9': 'hotel', 'H9': cte.HOTEL,
'HB': 'hotel', 'HB': cte.HOTEL,
'HH': 'hotel', 'HH': cte.HOTEL,
'HR': 'hotel', 'HR': cte.HOTEL,
'HS': 'hotel', 'HS': cte.HOTEL,
'I1': 'hospital', 'I1': cte.HOSPITAL,
'I2': 'outpatient', 'I2': cte.OUTPATIENT,
'I3': 'outpatient', 'I3': cte.OUTPATIENT,
'I4': 'residential', 'I4': cte.RESIDENTIAL,
'I5': 'outpatient', 'I5': cte.OUTPATIENT,
'I6': 'outpatient', 'I6': cte.OUTPATIENT,
'I7': 'outpatient', 'I7': cte.OUTPATIENT,
'I9': 'outpatient', 'I9': cte.OUTPATIENT,
'J1': 'large office', 'J1': cte.LARGE_OFFICE,
'J2': 'large office', 'J2': cte.LARGE_OFFICE,
'J3': 'large office', 'J3': cte.LARGE_OFFICE,
'J4': 'large office', 'J4': cte.LARGE_OFFICE,
'J5': 'large office', 'J5': cte.LARGE_OFFICE,
'J6': 'large office', 'J6': cte.LARGE_OFFICE,
'J7': 'large office', 'J7': cte.LARGE_OFFICE,
'J8': 'large office', 'J8': cte.LARGE_OFFICE,
'J9': 'large office', 'J9': cte.LARGE_OFFICE,
'K1': 'strip mall', 'K1': cte.STRIP_MALL,
'K2': 'strip mall', 'K2': cte.STRIP_MALL,
'K3': 'strip mall', 'K3': cte.STRIP_MALL,
'K4': 'residential', 'K4': cte.RESIDENTIAL,
'K5': 'restaurant', 'K5': cte.RESTAURANT,
'K6': 'commercial', 'K6': cte.COMMERCIAL,
'K7': 'commercial', 'K7': cte.COMMERCIAL,
'K8': 'commercial', 'K8': cte.COMMERCIAL,
'K9': 'commercial', 'K9': cte.COMMERCIAL,
'L1': 'residential', 'L1': cte.RESIDENTIAL,
'L2': 'residential', 'L2': cte.RESIDENTIAL,
'L3': 'residential', 'L3': cte.RESIDENTIAL,
'L8': 'residential', 'L8': cte.RESIDENTIAL,
'L9': 'residential', 'L9': cte.RESIDENTIAL,
'M1': 'large office', 'M1': cte.LARGE_OFFICE,
'M2': 'large office', 'M2': cte.LARGE_OFFICE,
'M3': 'large office', 'M3': cte.LARGE_OFFICE,
'M4': 'large office', 'M4': cte.LARGE_OFFICE,
'M9': 'large office', 'M9': cte.LARGE_OFFICE,
'N1': 'residential', 'N1': cte.RESIDENTIAL,
'N2': 'residential', 'N2': cte.RESIDENTIAL,
'N3': 'residential', 'N3': cte.RESIDENTIAL,
'N4': 'residential', 'N4': cte.RESIDENTIAL,
'N9': 'residential', 'N9': cte.RESIDENTIAL,
'O1': 'office', 'O1': cte.OFFICE,
'O2': 'office', 'O2': cte.OFFICE,
'O3': 'office', 'O3': cte.OFFICE,
'O4': 'office', 'O4': cte.OFFICE,
'O5': 'office', 'O5': cte.OFFICE,
'O6': 'office', 'O6': cte.OFFICE,
'O7': 'office', 'O7': cte.OFFICE,
'O8': 'office', 'O8': cte.OFFICE,
'O9': 'office', 'O9': cte.OFFICE,
'P1': 'large office', 'P1': cte.LARGE_OFFICE,
'P2': 'hotel', 'P2': cte.HOTEL,
'P3': 'office', 'P3': cte.OFFICE,
'P4': 'office', 'P4': cte.OFFICE,
'P5': 'office', 'P5': cte.OFFICE,
'P6': 'office', 'P6': cte.OFFICE,
'P7': 'large office', 'P7': cte.LARGE_OFFICE,
'P8': 'large office', 'P8': cte.LARGE_OFFICE,
'P9': 'office', 'P9': cte.OFFICE,
'Q0': 'office', 'Q0': cte.OFFICE,
'Q1': 'office', 'Q1': cte.OFFICE,
'Q2': 'office', 'Q2': cte.OFFICE,
'Q3': 'office', 'Q3': cte.OFFICE,
'Q4': 'office', 'Q4': cte.OFFICE,
'Q5': 'office', 'Q5': cte.OFFICE,
'Q6': 'office', 'Q6': cte.OFFICE,
'Q7': 'office', 'Q7': cte.OFFICE,
'Q8': 'office', 'Q8': cte.OFFICE,
'Q9': 'office', 'Q9': cte.OFFICE,
'R0': 'residential', 'R0': cte.RESIDENTIAL,
'R1': 'residential', 'R1': cte.RESIDENTIAL,
'R2': 'residential', 'R2': cte.RESIDENTIAL,
'R3': 'residential', 'R3': cte.RESIDENTIAL,
'R4': 'residential', 'R4': cte.RESIDENTIAL,
'R5': 'residential', 'R5': cte.RESIDENTIAL,
'R6': 'residential', 'R6': cte.RESIDENTIAL,
'R7': 'residential', 'R7': cte.RESIDENTIAL,
'R8': 'residential', 'R8': cte.RESIDENTIAL,
'R9': 'residential', 'R9': cte.RESIDENTIAL,
'RA': 'residential', 'RA': cte.RESIDENTIAL,
'RB': 'residential', 'RB': cte.RESIDENTIAL,
'RC': 'residential', 'RC': cte.RESIDENTIAL,
'RD': 'residential', 'RD': cte.RESIDENTIAL,
'RG': 'residential', 'RG': cte.RESIDENTIAL,
'RH': 'residential', 'RH': cte.RESIDENTIAL,
'RI': 'residential', 'RI': cte.RESIDENTIAL,
'RK': 'residential', 'RK': cte.RESIDENTIAL,
'RM': 'residential', 'RM': cte.RESIDENTIAL,
'RR': 'residential', 'RR': cte.RESIDENTIAL,
'RS': 'residential', 'RS': cte.RESIDENTIAL,
'RW': 'residential', 'RW': cte.RESIDENTIAL,
'RX': 'residential', 'RX': cte.RESIDENTIAL,
'RZ': 'residential', 'RZ': cte.RESIDENTIAL,
'S0': 'residential', 'S0': cte.RESIDENTIAL,
'S1': 'residential', 'S1': cte.RESIDENTIAL,
'S2': 'residential', 'S2': cte.RESIDENTIAL,
'S3': 'residential', 'S3': cte.RESIDENTIAL,
'S4': 'residential', 'S4': cte.RESIDENTIAL,
'S5': 'residential', 'S5': cte.RESIDENTIAL,
'S9': 'residential', 'S9': cte.RESIDENTIAL,
'T1': 'na', 'U0': cte.WAREHOUSE,
'T2': 'na', 'U1': cte.WAREHOUSE,
'T9': 'na', 'U2': cte.WAREHOUSE,
'U0': 'warehouse', 'U3': cte.WAREHOUSE,
'U1': 'warehouse', 'U4': cte.WAREHOUSE,
'U2': 'warehouse', 'U5': cte.WAREHOUSE,
'U3': 'warehouse', 'U6': cte.WAREHOUSE,
'U4': 'warehouse', 'U7': cte.WAREHOUSE,
'U5': 'warehouse', 'U8': cte.WAREHOUSE,
'U6': 'warehouse', 'U9': cte.WAREHOUSE,
'U7': 'warehouse', 'W1': cte.PRIMARY_SCHOOL,
'U8': 'warehouse', 'W2': cte.PRIMARY_SCHOOL,
'U9': 'warehouse', 'W3': cte.SECONDARY_SCHOOL,
'V0': 'na', 'W4': cte.SECONDARY_SCHOOL,
'V1': 'na', 'W5': cte.SECONDARY_SCHOOL,
'V2': 'na', 'W6': cte.SECONDARY_SCHOOL,
'V3': 'na', 'W7': cte.SECONDARY_SCHOOL,
'V4': 'na', 'W8': cte.PRIMARY_SCHOOL,
'V5': 'na', 'W9': cte.SECONDARY_SCHOOL,
'V6': 'na', 'Y1': cte.LARGE_OFFICE,
'V7': 'na', 'Y2': cte.LARGE_OFFICE,
'V8': 'na', 'Y3': cte.LARGE_OFFICE,
'V9': 'na', 'Y4': cte.LARGE_OFFICE,
'W1': 'primary school', 'Y5': cte.LARGE_OFFICE,
'W2': 'primary school', 'Y6': cte.LARGE_OFFICE,
'W3': 'secondary school', 'Y7': cte.LARGE_OFFICE,
'W4': 'secondary school', 'Y8': cte.LARGE_OFFICE,
'W5': 'secondary school', 'Y9': cte.LARGE_OFFICE,
'W6': 'secondary school', 'Z1': cte.LARGE_OFFICE
'W7': 'secondary school',
'W8': 'primary school',
'W9': 'secondary school',
'Y1': 'large office',
'Y2': 'large office',
'Y3': 'large office',
'Y4': 'large office',
'Y5': 'large office',
'Y6': 'large office',
'Y7': 'large office',
'Y8': 'large office',
'Y9': 'large office',
'Z0': 'na',
'Z1': 'large office',
'Z2': 'na',
'Z3': 'na',
'Z4': 'na',
'Z5': 'na',
'Z6': 'na',
'Z7': 'na',
'Z8': 'na',
'Z9': 'na'
} }
hft_to_function = { _hft_to_function = {
'residential': cte.RESIDENTIAL, 'residential': cte.RESIDENTIAL,
'single family house': cte.SFH, 'single family house': cte.SFH,
'multifamily house': cte.MFH, 'multifamily house': cte.MFH,
@ -251,25 +229,18 @@ class GeometryHelper:
} }
# usage # usage
function_to_usage = { _function_to_usage = {
'full service restaurant': 'restaurant', cte.RESTAURANT: cte.RESTAURANT,
'highrise apartment': cte.RESIDENTIAL, cte.RESIDENTIAL: cte.RESIDENTIAL,
'hospital': 'health care', cte.HOSPITAL: cte.HEALTH_CARE,
'large hotel': 'hotel', cte.HOTEL: cte.HOTEL,
'large office': 'office and administration', cte.LARGE_OFFICE: cte.OFFICE_ADMINISTRATION,
'medium office': 'office and administration', cte.OFFICE: cte.OFFICE_ADMINISTRATION,
'midrise apartment': cte.RESIDENTIAL, cte.PRIMARY_SCHOOL: cte.EDUCATION,
'outpatient healthcare': 'health care', cte.SECONDARY_SCHOOL: cte.EDUCATION,
'primary school': 'education', cte.RETAIL: cte.RETAIL,
'quick service restaurant': 'restaurant', cte.STRIP_MALL: cte.HALL,
'secondary school': 'education', cte.WAREHOUSE: cte.INDUSTRY
'small hotel': 'hotel',
'small office': 'office and administration',
'stand alone retail': 'retail',
'strip mall': 'hall',
'supermarket': 'retail',
'warehouse': 'industry',
'residential': cte.RESIDENTIAL
} }
@staticmethod @staticmethod
@ -279,7 +250,7 @@ class GeometryHelper:
:param building_hft_function: str :param building_hft_function: str
:return: str :return: str
""" """
return GeometryHelper.hft_to_function[building_hft_function] return GeometryHelper._hft_to_function[building_hft_function]
@staticmethod @staticmethod
def function_from_pluto(building_pluto_function): def function_from_pluto(building_pluto_function):
@ -288,7 +259,7 @@ class GeometryHelper:
:param building_pluto_function: str :param building_pluto_function: str
:return: str :return: str
""" """
return GeometryHelper.pluto_to_function[building_pluto_function] return GeometryHelper._pluto_to_function[building_pluto_function]
@staticmethod @staticmethod
def usage_from_function(building_function): def usage_from_function(building_function):
@ -297,7 +268,7 @@ class GeometryHelper:
:param building_function: str :param building_function: str
:return: str :return: str
""" """
return GeometryHelper.function_to_usage[building_function] return GeometryHelper._function_to_usage[building_function]
@staticmethod @staticmethod
def to_points_matrix(points): def to_points_matrix(points):

View File

@ -12,7 +12,7 @@ class SchedulesHelper:
""" """
Schedules helper Schedules helper
""" """
usage_to_comnet = { _usage_to_comnet = {
cte.RESIDENTIAL: 'C-12 Residential', cte.RESIDENTIAL: 'C-12 Residential',
cte.INDUSTRY: 'C-10 Warehouse', cte.INDUSTRY: 'C-10 Warehouse',
cte.OFFICE_ADMINISTRATION: 'C-5 Office', cte.OFFICE_ADMINISTRATION: 'C-5 Office',
@ -23,16 +23,15 @@ class SchedulesHelper:
cte.RESTAURANT: 'C-7 Restaurant', cte.RESTAURANT: 'C-7 Restaurant',
cte.EDUCATION: 'C-9 School' cte.EDUCATION: 'C-9 School'
} }
comnet_default_value = 'C-12 Residential'
comnet_to_data_type = { _comnet_to_data_type = {
'Fraction': cte.FRACTION, 'Fraction': cte.FRACTION,
'OnOff': cte.ON_OFF, 'OnOff': cte.ON_OFF,
'Temperature': cte.TEMPERATURE 'Temperature': cte.TEMPERATURE
} }
# usage # usage
function_to_usage = { _function_to_usage = {
'full service restaurant': cte.RESTAURANT, 'full service restaurant': cte.RESTAURANT,
'high-rise apartment': cte.RESIDENTIAL, 'high-rise apartment': cte.RESIDENTIAL,
'hospital': cte.HEALTH_CARE, 'hospital': cte.HEALTH_CARE,
@ -61,10 +60,9 @@ class SchedulesHelper:
:return: str :return: str
""" """
try: try:
return SchedulesHelper.usage_to_comnet[usage] return SchedulesHelper._usage_to_comnet[usage]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default Comnet schedules "residential"\n') sys.stderr.write('Error: keyword not found.\n')
return SchedulesHelper.comnet_default_value
@staticmethod @staticmethod
def data_type_from_comnet(comnet_data_type): def data_type_from_comnet(comnet_data_type):
@ -74,7 +72,7 @@ class SchedulesHelper:
:return: str :return: str
""" """
try: try:
return SchedulesHelper.comnet_to_data_type[comnet_data_type] return SchedulesHelper._comnet_to_data_type[comnet_data_type]
except KeyError: except KeyError:
raise ValueError(f"Error: comnet data type keyword not found.") raise ValueError(f"Error: comnet data type keyword not found.")
@ -85,4 +83,4 @@ class SchedulesHelper:
:param building_function: str :param building_function: str
:return: str :return: str
""" """
return SchedulesHelper.function_to_usage[building_function] return SchedulesHelper._function_to_usage[building_function]

View File

@ -5,10 +5,12 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
""" """
import sys import sys
from imports.geometry.helpers.geometry_helper import GeometryHelper as gh
from imports.usage.hft_usage_interface import HftUsageInterface from imports.usage.hft_usage_interface import HftUsageInterface
from city_model_structure.building_demand.usage_zone import UsageZone from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.building_demand.internal_gains import InternalGains 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.appliances import Appliances
from city_model_structure.building_demand.thermal_control import ThermalControl
class CaUsageParameters(HftUsageInterface): class CaUsageParameters(HftUsageInterface):
@ -18,9 +20,6 @@ class CaUsageParameters(HftUsageInterface):
def __init__(self, city, base_path): def __init__(self, city, base_path):
super().__init__(base_path, 'ca_archetypes_reduced.xml') super().__init__(base_path, 'ca_archetypes_reduced.xml')
self._city = city self._city = city
# todo: this is a wrong location for self._min_air_change -> re-think where to place this info
# and where it comes from
self._min_air_change = 0
def enrich_buildings(self): def enrich_buildings(self):
""" """
@ -29,19 +28,20 @@ class CaUsageParameters(HftUsageInterface):
""" """
city = self._city city = self._city
for building in city.buildings: for building in city.buildings:
archetype = self._search_archetype(building.function) try:
if archetype is None: print(building.function)
archetype = self._search_archetype(building.function)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as ' f' {building.function}\n')
f'{gh.usage_from_function(building.function)}\n') return
continue
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
usage_zone = UsageZone() usage_zone = UsageZone()
usage_zone.usage = building.function usage_zone.usage = building.function
self._assign_values(usage_zone, archetype) usage_zone.percentage = 1
usage_zone.percentage = 1 self._assign_values_usage_zone(usage_zone, archetype)
internal_zone.usage_zones = [usage_zone] internal_zone.usage_zones = [usage_zone]
def _search_archetype(self, building_usage): def _search_archetype(self, building_usage):
for building_archetype in self._usage_archetypes: for building_archetype in self._usage_archetypes:
@ -50,26 +50,30 @@ class CaUsageParameters(HftUsageInterface):
return None return None
@staticmethod @staticmethod
def _assign_values(usage_zone, archetype): def _assign_values_usage_zone(usage_zone, archetype):
# Due to the fact that python is not a typed language, the wrong object type is assigned to # Due to the fact that python is not a typed language, the wrong object type is assigned to
# usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains. # usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains.
# Therefore, this walk around has been done. # Therefore, this walk around has been done.
internal_gains = [] usage_zone.mechanical_air_change = archetype.mechanical_air_change
for archetype_internal_gain in archetype.internal_gains: _occupancy = Occupancy()
internal_gain = InternalGains() _occupancy.occupancy_density = archetype.occupancy.occupancy_density
internal_gain.average_internal_gain = archetype_internal_gain.average_internal_gain usage_zone.occupancy = _occupancy
internal_gain.convective_fraction = archetype_internal_gain.convective_fraction
internal_gain.radiative_fraction = archetype_internal_gain.radiative_fraction
internal_gain.latent_fraction = archetype_internal_gain.latent_fraction
internal_gains.append(internal_gain)
usage_zone.internal_gains = internal_gains
usage_zone.heating_setpoint = archetype.heating_setpoint
usage_zone.heating_setback = archetype.heating_setback
usage_zone.cooling_setpoint = archetype.cooling_setpoint
usage_zone.occupancy_density = archetype.occupancy_density
usage_zone.hours_day = archetype.hours_day usage_zone.hours_day = archetype.hours_day
usage_zone.days_year = archetype.days_year usage_zone.days_year = archetype.days_year
usage_zone.dhw_average_volume_pers_day = archetype.dhw_average_volume_pers_day _appliances = Appliances()
usage_zone.dhw_preparation_temperature = archetype.dhw_preparation_temperature _appliances.appliances_density = archetype.appliances.appliances_density
usage_zone.electrical_app_average_consumption_sqm_year = archetype.electrical_app_average_consumption_sqm_year usage_zone.appliances = _appliances
usage_zone.mechanical_air_change = archetype.mechanical_air_change _control = ThermalControl()
_control.mean_heating_set_point = archetype.thermal_control.mean_heating_set_point
_control.heating_set_back = archetype.thermal_control.heating_set_back
_control.mean_cooling_set_point = archetype.thermal_control.mean_cooling_set_point
usage_zone.thermal_control = _control
_internal_gains = []
for archetype_internal_gain in archetype.not_detailed_source_mean_annual_internal_gains:
_internal_gain = InternalGains()
_internal_gain.average_internal_gain = archetype_internal_gain.average_internal_gain
_internal_gain.convective_fraction = archetype_internal_gain.convective_fraction
_internal_gain.radiative_fraction = archetype_internal_gain.radiative_fraction
_internal_gain.latent_fraction = archetype_internal_gain.latent_fraction
_internal_gains.append(_internal_gain)
usage_zone.not_detailed_source_mean_annual_internal_gains = _internal_gains

View File

@ -3,6 +3,7 @@ ComnetUsageParameters model the usage properties
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2021 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2021 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import sys import sys
from typing import Dict from typing import Dict
import pandas as pd import pandas as pd
@ -11,11 +12,13 @@ import helpers.constants as cte
from helpers.configuration_helper import ConfigurationHelper as ch from helpers.configuration_helper import ConfigurationHelper as ch
from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.usage.helpers.usage_helper import UsageHelper from imports.usage.helpers.usage_helper import UsageHelper
from imports.schedules.helpers.schedules_helper import SchedulesHelper
from city_model_structure.building_demand.usage_zone import UsageZone from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.building_demand.lighting import Lighting from city_model_structure.building_demand.lighting import Lighting
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
from city_model_structure.building_demand.internal_gains import InternalGains from city_model_structure.building_demand.thermal_control import ThermalControl
from city_model_structure.attributes.schedule import Schedule
class ComnetUsageParameters: class ComnetUsageParameters:
@ -25,24 +28,19 @@ class ComnetUsageParameters:
def __init__(self, city, base_path): def __init__(self, city, base_path):
self._city = city self._city = city
self._base_path = str(base_path / 'comnet_archetypes.xlsx') self._base_path = str(base_path / 'comnet_archetypes.xlsx')
self._usage_archetypes = [] self._data = self._read_file()
data = self._read_file() self._comnet_schedules_path = str(base_path / 'comnet_schedules_archetypes.xlsx')
for item in data['lighting']: self._xls = pd.ExcelFile(self._comnet_schedules_path)
for usage in UsageHelper.usage_to_comnet:
comnet_usage = UsageHelper.usage_to_comnet[usage]
if comnet_usage == item:
usage_archetype = self._parse_zone_usage_type(comnet_usage, data)
self._usage_archetypes.append(usage_archetype)
def _read_file(self) -> Dict: def _read_file(self) -> Dict:
""" """
reads xlsx file containing usage information into a dictionary reads xlsx files containing usage information into a dictionary
:return : Dict :return : Dict
""" """
number_usage_types = 33 number_usage_types = 33
xl_file = pd.ExcelFile(self._base_path) xl_file = pd.ExcelFile(self._base_path)
file_data = pd.read_excel(xl_file, sheet_name="Modeling Data", skiprows=[0, 1, 2], file_data = pd.read_excel(xl_file, sheet_name="Modeling Data", skiprows=[0, 1, 2],
nrows=number_usage_types, usecols="A:Z") nrows=number_usage_types, usecols="A:AB")
lighting_data = {} lighting_data = {}
plug_loads_data = {} plug_loads_data = {}
@ -50,6 +48,7 @@ class ComnetUsageParameters:
ventilation_rate = {} ventilation_rate = {}
water_heating = {} water_heating = {}
process_data = {} process_data = {}
schedules_key = {}
for j in range(0, number_usage_types): for j in range(0, number_usage_types):
usage_parameters = file_data.iloc[j] usage_parameters = file_data.iloc[j]
@ -60,53 +59,130 @@ class ComnetUsageParameters:
ventilation_rate[usage_type] = usage_parameters[20:21].values.tolist() ventilation_rate[usage_type] = usage_parameters[20:21].values.tolist()
water_heating[usage_type] = usage_parameters[23:24].values.tolist() water_heating[usage_type] = usage_parameters[23:24].values.tolist()
process_data[usage_type] = usage_parameters[24:26].values.tolist() process_data[usage_type] = usage_parameters[24:26].values.tolist()
schedules_key[usage_type] = usage_parameters[27:28].values.tolist()
return {'lighting': lighting_data, return {'lighting': lighting_data,
'plug loads': plug_loads_data, 'plug loads': plug_loads_data,
'occupancy': occupancy_data, 'occupancy': occupancy_data,
'ventilation rate': ventilation_rate, 'ventilation rate': ventilation_rate,
'water heating': water_heating, 'water heating': water_heating,
'process': process_data} 'process': process_data,
'schedules_key': schedules_key}
@staticmethod @staticmethod
def _parse_zone_usage_type(usage, data): def _parse_usage_type(comnet_usage, data, schedules_data):
_usage_zone = UsageZone() _usage_zone = UsageZone()
_usage_zone.usage = usage
# lighting # lighting
_lighting = Lighting() _lighting = Lighting()
_lighting.latent_fraction = ch().comnet_lighting_latent _lighting.latent_fraction = ch().comnet_lighting_latent
_lighting.convective_fraction = ch().comnet_lighting_convective _lighting.convective_fraction = ch().comnet_lighting_convective
_lighting.radiative_fraction = ch().comnet_lighting_radiant _lighting.radiative_fraction = ch().comnet_lighting_radiant
_lighting.average_internal_gain = data['lighting'][usage][4] _lighting.lighting_density = data['lighting'][comnet_usage][4]
# plug loads # plug loads
_appliances = None _appliances = None
if data['plug loads'][usage][0] != 'n.a.': if data['plug loads'][comnet_usage][0] != 'n.a.':
_appliances = Appliances() _appliances = Appliances()
_appliances.latent_fraction = ch().comnet_plugs_latent _appliances.latent_fraction = ch().comnet_plugs_latent
_appliances.convective_fraction = ch().comnet_plugs_convective _appliances.convective_fraction = ch().comnet_plugs_convective
_appliances.radiative_fraction = ch().comnet_plugs_radiant _appliances.radiative_fraction = ch().comnet_plugs_radiant
_appliances.average_internal_gain = data['plug loads'][usage][0] _appliances.appliances_density = data['plug loads'][comnet_usage][0]
# occupancy # occupancy
_occupancy = Occupancy() _occupancy = Occupancy()
_occupancy.occupancy_density = data['occupancy'][usage][0] _occupancy.occupancy_density = data['occupancy'][comnet_usage][0]
_occupancy.sensible_convective_internal_gain = data['occupancy'][usage][1] \ _occupancy.sensible_convective_internal_gain = data['occupancy'][comnet_usage][1] \
* ch().comnet_occupancy_sensible_convective * ch().comnet_occupancy_sensible_convective
_occupancy.sensible_radiant_internal_gain = data['occupancy'][usage][1] * ch().comnet_occupancy_sensible_radiant _occupancy.sensible_radiative_internal_gain = data['occupancy'][comnet_usage][1] \
_occupancy.latent_internal_gain = data['occupancy'][usage][2] * ch().comnet_occupancy_sensible_radiant
_occupancy.latent_internal_gain = data['occupancy'][comnet_usage][2]
if _occupancy.occupancy_density <= 0: if _occupancy.occupancy_density <= 0:
_usage_zone.mechanical_air_change = 0 _usage_zone.mechanical_air_change = 0
else: else:
_usage_zone.mechanical_air_change = data['ventilation rate'][usage][0] / _occupancy.occupancy_density _usage_zone.mechanical_air_change = data['ventilation rate'][comnet_usage][0] / _occupancy.occupancy_density
schedules_usage = UsageHelper.schedules_key(data['schedules_key'][comnet_usage][0])
_extracted_data = pd.read_excel(schedules_data, sheet_name=schedules_usage,
skiprows=[0, 1, 2, 3], nrows=39, usecols="A:AA")
schedules = []
number_of_schedule_types = 13
schedules_per_schedule_type = 3
day_types = dict({'week_day': 0, 'saturday': 1, 'sunday': 2})
for schedule_types in range(0, number_of_schedule_types):
name = ''
data_type = ''
for schedule_day in range(0, schedules_per_schedule_type):
_schedule = Schedule()
_schedule.time_step = cte.HOUR
_schedule.time_range = cte.DAY
row_cells = _extracted_data.iloc[schedules_per_schedule_type * schedule_types + schedule_day]
if schedule_day == day_types['week_day']:
name = row_cells[0]
data_type = row_cells[1]
_schedule.day_types = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY]
elif schedule_day == day_types['saturday']:
_schedule.day_types = [cte.SATURDAY]
else:
_schedule.day_types = [cte.SUNDAY]
_schedule.type = name
_schedule.data_type = SchedulesHelper.data_type_from_comnet(data_type)
if _schedule.data_type == cte.TEMPERATURE:
values = []
for cell in row_cells[schedules_per_schedule_type:].to_numpy():
values.append((float(cell) - 32.) * 5 / 9)
_schedule.values = values
else:
_schedule.values = row_cells[schedules_per_schedule_type:].to_numpy()
schedules.append(_schedule)
schedules_types = dict({'Occupancy': 0, 'Lights': 3, 'Receptacle': 6, 'Infiltration': 9, 'HVAC Avail': 12,
'ClgSetPt': 15, 'HtgSetPt': 18})
_schedules = []
for pointer in range(0, 3):
_schedules.append(schedules[schedules_types['Occupancy']+pointer])
_occupancy.occupancy_schedules = _schedules
_schedules = []
for pointer in range(0, 3):
_schedules.append(schedules[schedules_types['Lights']+pointer])
_lighting.schedules = _schedules
_schedules = []
for pointer in range(0, 3):
_schedules.append(schedules[schedules_types['Receptacle']+pointer])
_appliances.schedules = _schedules
_usage_zone.occupancy = _occupancy _usage_zone.occupancy = _occupancy
_usage_zone.lighting = _lighting _usage_zone.lighting = _lighting
_usage_zone.appliances = _appliances _usage_zone.appliances = _appliances
_control = ThermalControl()
_schedules = []
for pointer in range(0, 3):
_schedules.append(schedules[schedules_types['HtgSetPt']+pointer])
_control.heating_set_point_schedules = _schedules
_schedules = []
for pointer in range(0, 3):
_schedules.append(schedules[schedules_types['ClgSetPt']+pointer])
_control.cooling_set_point_schedules = _schedules
_schedules = []
for pointer in range(0, 3):
_schedules.append(schedules[schedules_types['HVAC Avail']+pointer])
_control.hvac_availability_schedules = _schedules
_usage_zone.thermal_control = _control
return _usage_zone return _usage_zone
def _search_archetypes(self, usage):
for item in self._data['lighting']:
comnet_usage = UsageHelper.comnet_from_usage(usage)
if comnet_usage == item:
usage_archetype = self._parse_usage_type(comnet_usage, self._data, self._xls)
return usage_archetype
return None, None
def enrich_buildings(self): def enrich_buildings(self):
""" """
Returns the city with the usage parameters assigned to the buildings Returns the city with the usage parameters assigned to the buildings
@ -115,41 +191,80 @@ class ComnetUsageParameters:
city = self._city city = self._city
for building in city.buildings: for building in city.buildings:
usage = GeometryHelper.usage_from_function(building.function) usage = GeometryHelper.usage_from_function(building.function)
archetype = self._search_archetype(UsageHelper.comnet_from_usage(usage)) try:
if archetype is None: archetype_usage = self._search_archetypes(usage)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as ' f' {building.function}, that assigns building usage as '
f'{GeometryHelper.usage_from_function(building.function)}\n') f'{GeometryHelper.usage_from_function(building.function)}\n')
continue return
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
if internal_zone.area is None:
raise Exception('Internal zone area not defined, ACH cannot be calculated')
if internal_zone.volume is None:
raise Exception('Internal zone volume not defined, ACH cannot be calculated')
if internal_zone.area <= 0:
raise Exception('Internal zone area is zero, ACH cannot be calculated')
if internal_zone.volume <= 0:
raise Exception('Internal zone volume is zero, ACH cannot be calculated')
volume_per_area = internal_zone.volume / internal_zone.area
usage_zone = UsageZone() usage_zone = UsageZone()
usage_zone.usage = usage usage_zone.usage = usage
self._assign_values(usage_zone, archetype, volume_per_area) self._assign_values_usage_zone(usage_zone, archetype_usage, volume_per_area)
usage_zone.percentage = 1 usage_zone.percentage = 1
self._calculate_reduced_values_from_extended_library(usage_zone, archetype_usage)
internal_zone.usage_zones = [usage_zone] internal_zone.usage_zones = [usage_zone]
def _search_archetype(self, building_usage): @staticmethod
for building_archetype in self._usage_archetypes: def _assign_values_usage_zone(usage_zone, archetype, volume_per_area):
if building_archetype.usage == building_usage: # Due to the fact that python is not a typed language, the wrong object type is assigned to
return building_archetype # usage_zone.occupancy when writing usage_zone.occupancy = archetype.occupancy.
return None # Same happens for lighting and appliances. Therefore, this walk around has been done.
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_schedules = archetype.occupancy.occupancy_schedules
usage_zone.occupancy = _occupancy
_lighting = Lighting()
_lighting.lighting_density = archetype.lighting.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.convective_fraction = archetype.appliances.convective_fraction
_appliances.radiative_fraction = archetype.appliances.radiative_fraction
_appliances.latent_fraction = archetype.appliances.latent_fraction
_appliances.schedules = archetype.appliances.schedules
usage_zone.appliances = _appliances
_control = ThermalControl()
_control.cooling_set_point_schedules = archetype.thermal_control.cooling_set_point_schedules
_control.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules
_control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules
usage_zone.thermal_control = _control
@staticmethod @staticmethod
def _assign_values(usage_zone, archetype, volume_per_area): def _calculate_reduced_values_from_extended_library(usage_zone, archetype):
# Due to the fact that python is not a typed language, the wrong object type is assigned to number_of_days_per_type = {'WD': 251, 'Sat': 52, 'Sun': 62}
# usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains. total = 0
# Therefore, this walk around has been done. for schedule in archetype.thermal_control.hvac_availability_schedules:
internal_gains = [] if schedule.day_types[0] == cte.SATURDAY:
for archetype_internal_gain in archetype.internal_gains: for value in schedule.values:
internal_gain = InternalGains() total += value * number_of_days_per_type['Sat']
internal_gain.type = archetype_internal_gain.type elif schedule.day_types[0] == cte.SUNDAY:
internal_gain.average_internal_gain = archetype_internal_gain.average_internal_gain for value in schedule.values:
internal_gain.convective_fraction = archetype_internal_gain.convective_fraction total += value * number_of_days_per_type['Sun']
internal_gain.radiative_fraction = archetype_internal_gain.radiative_fraction else:
internal_gain.latent_fraction = archetype_internal_gain.latent_fraction for value in schedule.values:
internal_gains.append(internal_gain) total += value * number_of_days_per_type['WD']
usage_zone.internal_gains = internal_gains
usage_zone.occupancy_density = archetype.occupancy_density * cte.METERS_TO_FEET**2 usage_zone.hours_day = total / 365
usage_zone.mechanical_air_change = archetype.mechanical_air_change * cte.METERS_TO_FEET**2 \ usage_zone.days_year = 365
* cte.HOUR_TO_MINUTES / cte.METERS_TO_FEET**3 / volume_per_area

View File

@ -11,7 +11,7 @@ class UsageHelper:
""" """
Usage helper class Usage helper class
""" """
usage_to_hft = { _usage_to_hft = {
cte.RESIDENTIAL: 'residential', cte.RESIDENTIAL: 'residential',
cte.INDUSTRY: 'industry', cte.INDUSTRY: 'industry',
cte.OFFICE_ADMINISTRATION: 'office and administration', cte.OFFICE_ADMINISTRATION: 'office and administration',
@ -20,9 +20,7 @@ class UsageHelper:
cte.RETAIL: 'retail', cte.RETAIL: 'retail',
cte.HALL: 'hall', cte.HALL: 'hall',
cte.RESTAURANT: 'restaurant', cte.RESTAURANT: 'restaurant',
cte.EDUCATION: 'education' cte.EDUCATION: 'education'}
}
hft_default_value = 'residential'
@staticmethod @staticmethod
def hft_from_usage(usage): def hft_from_usage(usage):
@ -32,12 +30,11 @@ class UsageHelper:
:return: str :return: str
""" """
try: try:
return UsageHelper.usage_to_hft[usage] return UsageHelper._usage_to_hft[usage]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default HfT usage "residential"\n') sys.stderr.write('Error: keyword not found.\n')
return UsageHelper.hft_default_value
usage_to_comnet = { _usage_to_comnet = {
cte.RESIDENTIAL: 'BA Multifamily', cte.RESIDENTIAL: 'BA Multifamily',
cte.INDUSTRY: 'BA Manufacturing Facility', cte.INDUSTRY: 'BA Manufacturing Facility',
cte.OFFICE_ADMINISTRATION: 'BA Office', cte.OFFICE_ADMINISTRATION: 'BA Office',
@ -46,9 +43,23 @@ class UsageHelper:
cte.RETAIL: 'BA Retail', cte.RETAIL: 'BA Retail',
cte.HALL: 'BA Town Hall', cte.HALL: 'BA Town Hall',
cte.RESTAURANT: 'BA Dining: Bar Lounge/Leisure', cte.RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
cte.EDUCATION: 'BA School/University' cte.EDUCATION: 'BA School/University'}
}
comnet_default_value = 'BA Multifamily' _comnet_schedules_key_to_comnet_schedules = {
'C-1 Assembly': 'C-1 Assembly',
'C-2 Public': 'C-2 Health',
'C-3 Hotel Motel': 'C-3 Hotel',
'C-4 Manufacturing': 'C-4 Manufacturing',
'C-5 Office': 'C-5 Office',
'C-6 Parking Garage': 'C-6 Parking',
'C-7 Restaurant': 'C-7 Restaurant',
'C-8 Retail': 'C-8 Retail',
'C-9 Schools': 'C-9 School',
'C-10 Warehouse': 'C-10 Warehouse',
'C-11 Laboratory': 'C-11 Lab',
'C-12 Residential': 'C-12 Residential',
'C-13 Data Center': 'C-13 Data',
'C-14 Gymnasium': 'C-14 Gymnasium'}
@staticmethod @staticmethod
def comnet_from_usage(usage): def comnet_from_usage(usage):
@ -58,7 +69,19 @@ class UsageHelper:
:return: str :return: str
""" """
try: try:
return UsageHelper.usage_to_comnet[usage] return UsageHelper._usage_to_comnet[usage]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default Comnet usage "BA Multifamily"\n') sys.stderr.write('Error: keyword not found.\n')
return UsageHelper.comnet_default_value
@staticmethod
def schedules_key(usage):
"""
Get Comnet schedules key from the list found in the Comnet usage file
:param usage: str
:return: str
"""
try:
return UsageHelper._comnet_schedules_key_to_comnet_schedules[usage]
except KeyError:
sys.stderr.write('Error: Comnet keyword not found. An update of the Comnet files might have been '
'done changing the keywords.\n')

View File

@ -1,12 +1,17 @@
""" """
Hft-based interface, it reads format defined within the CERC team based on that one used in SimStadt and developed by Hft-based interface, it reads format defined within the CERC team (based on that one used in SimStadt and developed by
the IAF team at hft-Stuttgart and enriches the city with usage parameters the IAF team at hft-Stuttgart)
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import xmltodict import xmltodict
from imports.usage.data_classes.usage_zone_archetype import UsageZoneArchetype as huza from city_model_structure.building_demand.usage_zone import UsageZone
from imports.usage.data_classes.hft_internal_gains_archetype import HftInternalGainsArchetype as higa 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.appliances import Appliances
from city_model_structure.building_demand.thermal_control import ThermalControl
from city_model_structure.attributes.schedule import Schedule
import helpers.constants as cte
class HftUsageInterface: class HftUsageInterface:
@ -28,116 +33,196 @@ class HftUsageInterface:
usage = usage_zone_variant['id'] usage = usage_zone_variant['id']
usage_archetype_variant = self._parse_zone_usage_variant(usage, usage_archetype, usage_zone_variant) usage_archetype_variant = self._parse_zone_usage_variant(usage, usage_archetype, usage_zone_variant)
self._usage_archetypes.append(usage_archetype_variant) self._usage_archetypes.append(usage_archetype_variant)
for usage in self._usage_archetypes:
print(usage.usage)
@staticmethod @staticmethod
def _parse_zone_usage_type(usage, zone_usage_type): def _parse_zone_usage_type(usage, zone_usage_type):
occupancy_density = zone_usage_type['occupancy']['occupancyDensity'] usage_zone_archetype = UsageZone()
hours_day = zone_usage_type['occupancy']['usageHoursPerDay'] usage_zone_archetype.usage = usage
days_year = zone_usage_type['occupancy']['usageDaysPerYear']
cooling_setpoint = zone_usage_type['endUses']['space_cooling']['coolingSetPointTemperature']
heating_setpoint = zone_usage_type['endUses']['space_heating']['heatingSetPointTemperature']
heating_setback = zone_usage_type['endUses']['space_heating']['heatingSetBackTemperature']
mechanical_air_change = None
if 'ventilation' in zone_usage_type['endUses'] and zone_usage_type['endUses']['ventilation'] is not None:
mechanical_air_change = zone_usage_type['endUses']['ventilation']['mechanicalAirChangeRate']
dhw_average_volume_pers_day = None
dhw_preparation_temperature = None
if 'domestic_hot_water' in zone_usage_type['endUses']:
# liters to cubic meters
dhw_average_volume_pers_day = float(
zone_usage_type['endUses']['domestic_hot_water']['averageVolumePerPersAndDay']) / 1000
dhw_preparation_temperature = zone_usage_type['endUses']['domestic_hot_water']['preparationTemperature']
electrical_app_average_consumption_sqm_year = None
if 'all_electrical_appliances' in zone_usage_type['endUses']:
if 'averageConsumptionPerSqmAndYear' in zone_usage_type['endUses']['all_electrical_appliances']:
# kWh to J
electrical_app_average_consumption_sqm_year = \
float(zone_usage_type['endUses']['all_electrical_appliances']['averageConsumptionPerSqmAndYear']) / 3.6
# todo: for internal_gain in usage_zone_variant['schedules']['internGains']:???????????????? if 'occupancy' in zone_usage_type:
# There are no more internal gains? How is it saved when more than one??? _occupancy = Occupancy()
internal_gains = [] _occupancy.occupancy_density = zone_usage_type['occupancy']['occupancyDensity'] #todo: check units
if 'internGains' in zone_usage_type['occupancy']: usage_zone_archetype.hours_day = zone_usage_type['occupancy']['usageHoursPerDay']
latent_fraction = zone_usage_type['occupancy']['internGains']['latentFraction'] usage_zone_archetype.days_year = zone_usage_type['occupancy']['usageDaysPerYear']
convective_fraction = zone_usage_type['occupancy']['internGains']['convectiveFraction'] usage_zone_archetype.occupancy = _occupancy
average_internal_gain = zone_usage_type['occupancy']['internGains']['averageInternGainPerSqm']
radiative_fraction = zone_usage_type['occupancy']['internGains']['radiantFraction'] if 'internGains' in zone_usage_type['occupancy']:
else: _internal_gain = InternalGains()
latent_fraction = 0 _internal_gain.latent_fraction = zone_usage_type['occupancy']['internGains']['latentFraction']
convective_fraction = 0 _internal_gain.convective_fraction = zone_usage_type['occupancy']['internGains']['convectiveFraction']
average_internal_gain = 0 _internal_gain.average_internal_gain = zone_usage_type['occupancy']['internGains']['averageInternGainPerSqm']
radiative_fraction = 0 _internal_gain.radiative_fraction = zone_usage_type['occupancy']['internGains']['radiantFraction']
if 'load' in zone_usage_type['occupancy']['internGains']:
_schedule = Schedule()
_schedule.type = 'internal gains load'
_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]
_values = zone_usage_type['occupancy']['internGains']['load']['weekDayProfile']['values']
while ' ' in _values:
_values = _values.replace(' ', ' ')
_schedule.values = _values.split()
_internal_gain.schedules = [_schedule]
usage_zone_archetype.not_detailed_source_mean_annual_internal_gains = [_internal_gain]
if 'endUses' in zone_usage_type:
_thermal_control = ThermalControl()
if 'space_heating' in zone_usage_type['endUses']:
_thermal_control.mean_heating_set_point = \
zone_usage_type['endUses']['space_heating']['heatingSetPointTemperature']
_thermal_control.heating_set_back = zone_usage_type['endUses']['space_heating']['heatingSetBackTemperature']
if 'schedule' in zone_usage_type['endUses']['space_heating']:
_schedule = Schedule()
_schedule.type = 'heating temperature'
_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]
_values = zone_usage_type['endUses']['space_heating']['schedule']['weekDayProfile']['values']
while ' ' in _values:
_values = _values.replace(' ', ' ')
_schedule.values = _values.split()
_thermal_control.heating_set_point_schedules = [_schedule]
if 'space_cooling' in zone_usage_type['endUses']:
_thermal_control.mean_cooling_set_point = \
zone_usage_type['endUses']['space_cooling']['coolingSetPointTemperature']
if 'schedule' in zone_usage_type['endUses']['space_cooling']:
_schedule = Schedule()
_schedule.type = 'cooling temperature'
_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]
_values = zone_usage_type['endUses']['space_cooling']['schedule']['weekDayProfile']['values']
while ' ' in _values:
_values = _values.replace(' ', ' ')
_schedule.values = _values.split()
_thermal_control.cooling_set_point_schedules = [_schedule]
usage_zone_archetype.thermal_control = _thermal_control
if 'ventilation' in zone_usage_type['endUses'] and zone_usage_type['endUses']['ventilation'] is not None:
usage_zone_archetype.mechanical_air_change = \
zone_usage_type['endUses']['ventilation']['mechanicalAirChangeRate']
# todo: not used or assigned anywhere
if 'domestic_hot_water' in zone_usage_type['endUses']:
# liters to cubic meters
dhw_average_volume_pers_day = float(
zone_usage_type['endUses']['domestic_hot_water']['averageVolumePerPersAndDay']) / 1000
dhw_preparation_temperature = zone_usage_type['endUses']['domestic_hot_water']['preparationTemperature']
if 'all_electrical_appliances' in zone_usage_type['endUses']:
if 'averageConsumptionPerSqmAndYear' in zone_usage_type['endUses']['all_electrical_appliances']:
# kWh to J
usage_zone_archetype.electrical_app_average_consumption_sqm_year = \
float(zone_usage_type['endUses']['all_electrical_appliances']['averageConsumptionPerSqmAndYear']) \
* cte.KILO_WATTS_HOUR_TO_JULES
if 'appliance' in zone_usage_type:
_appliances = Appliances()
_appliances.appliances_density = zone_usage_type['appliance']['#text'] #todo: check units
usage_zone_archetype.appliances = _appliances
internal_gains.append(higa(average_internal_gain=average_internal_gain, convective_fraction=convective_fraction,
radiative_fraction=radiative_fraction, latent_fraction=latent_fraction))
usage_zone_archetype = huza(usage=usage, internal_gains=internal_gains, heating_set_point=heating_setpoint,
heating_set_back=heating_setback, cooling_set_point=cooling_setpoint,
occupancy_density=occupancy_density, hours_day=hours_day, days_year=days_year,
dhw_average_volume_pers_day=dhw_average_volume_pers_day,
dhw_preparation_temperature=dhw_preparation_temperature,
electrical_app_average_consumption_sqm_year=electrical_app_average_consumption_sqm_year,
mechanical_air_change=mechanical_air_change)
return usage_zone_archetype return usage_zone_archetype
@staticmethod @staticmethod
def _parse_zone_usage_variant(usage, usage_zone, usage_zone_variant): def _parse_zone_usage_variant(usage, usage_zone, usage_zone_variant):
# for the variants all is optional because it mimics the inheritance concept from OOP # the variants mimic the inheritance concept from OOP
occupancy_density = usage_zone.occupancy_density usage_zone_archetype = usage_zone
hours_day = usage_zone.hours_day usage_zone_archetype.usage = usage
days_year = usage_zone.days_year
cooling_setpoint = usage_zone.cooling_setpoint
heating_setpoint = usage_zone.heating_setpoint
heating_setback = usage_zone.heating_setback
mechanical_air_change = usage_zone.mechanical_air_change
dhw_average_volume_pers_day = usage_zone.dhw_average_volume_pers_day
dhw_preparation_temperature = usage_zone.dhw_preparation_temperature
electrical_app_average_consumption_sqm_year = usage_zone.electrical_app_average_consumption_sqm_year
# todo: for internal_gain in usage_zone_variant['schedules']['internGains']:???????????????? if 'occupancy' in usage_zone_variant:
# There are no more internal gains? How is it saved when more than one??? _occupancy = Occupancy()
# for internal_gain in usage_zone.internal_gains: if 'occupancyDensity' in usage_zone_variant['occupancy']:
internal_gains = usage_zone.not_detailed_source_mean_annual_internal_gains[0] _occupancy.occupancy_density = usage_zone_variant['occupancy']['occupancyDensity'] # todo: check units
latent_fraction = internal_gains.latent_fraction if 'usageHoursPerDay' in usage_zone_variant['occupancy']:
convective_fraction = internal_gains.convective_fraction usage_zone_archetype.hours_day = usage_zone_variant['occupancy']['usageHoursPerDay']
average_internal_gain = internal_gains.average_internal_gain if 'usageDaysPerYear' in usage_zone_variant['occupancy']:
radiative_fraction = internal_gains.radiative_fraction usage_zone_archetype.days_year = usage_zone_variant['occupancy']['usageDaysPerYear']
usage_zone_archetype.occupancy = _occupancy
if 'internGains' in usage_zone_variant['occupancy']:
_internal_gain = InternalGains()
if 'latentFraction' in usage_zone_variant['occupancy']['internGains']:
_internal_gain.latent_fraction = usage_zone_variant['occupancy']['internGains']['latentFraction']
if 'convectiveFraction' in usage_zone_variant['occupancy']['internGains']:
_internal_gain.convective_fraction = usage_zone_variant['occupancy']['internGains']['convectiveFraction']
if 'averageInternGainPerSqm' in usage_zone_variant['occupancy']['internGains']:
_internal_gain.average_internal_gain = \
usage_zone_variant['occupancy']['internGains']['averageInternGainPerSqm']
if 'radiantFraction' in usage_zone_variant['occupancy']['internGains']:
_internal_gain.radiative_fraction = usage_zone_variant['occupancy']['internGains']['radiantFraction']
if 'load' in usage_zone_variant['occupancy']['internGains']:
_schedule = Schedule()
_schedule.type = 'internal gains load'
_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]
_values = usage_zone_variant['occupancy']['internGains']['load']['weekDayProfile']['values']
while ' ' in _values:
_values = _values.replace(' ', ' ')
_schedule.values = _values.split()
_internal_gain.schedules = [_schedule]
usage_zone_archetype.not_detailed_source_mean_annual_internal_gains = [_internal_gain]
if 'endUses' in usage_zone_variant:
_thermal_control = ThermalControl()
if 'space_heating' in usage_zone_variant['endUses']:
if 'heatingSetPointTemperature' in usage_zone_variant['endUses']['space_heating']:
_thermal_control.mean_heating_set_point = \
usage_zone_variant['endUses']['space_heating']['heatingSetPointTemperature']
if 'heatingSetBackTemperature' in usage_zone_variant['endUses']['space_heating']:
_thermal_control.heating_set_back = usage_zone_variant['endUses']['space_heating']['heatingSetBackTemperature']
if 'schedule' in usage_zone_variant['endUses']['space_heating']:
_schedule = Schedule()
_schedule.type = 'heating temperature'
_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]
_values = usage_zone_variant['endUses']['space_heating']['schedule']['weekDayProfile']['values']
while ' ' in _values:
_values = _values.replace(' ', ' ')
_schedule.values = _values.split()
_thermal_control.heating_set_point_schedules = [_schedule]
if 'space_cooling' in usage_zone_variant['endUses'] and \
usage_zone_variant['endUses']['space_cooling'] is not None:
if 'coolingSetPointTemperature' in usage_zone_variant['endUses']['space_cooling']:
_thermal_control.mean_cooling_set_point = \
usage_zone_variant['endUses']['space_cooling']['coolingSetPointTemperature']
if 'schedule' in usage_zone_variant['endUses']['space_cooling']:
_schedule = Schedule()
_schedule.type = 'cooling temperature'
_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]
_values = usage_zone_variant['endUses']['space_cooling']['schedule']['weekDayProfile']['values']
while ' ' in _values:
_values = _values.replace(' ', ' ')
_schedule.values = _values.split()
_thermal_control.cooling_set_point_schedules = [_schedule]
usage_zone_archetype.thermal_control = _thermal_control
if 'ventilation' in usage_zone_variant['endUses'] and usage_zone_variant['endUses']['ventilation'] is not None:
usage_zone_archetype.mechanical_air_change = \
usage_zone_variant['endUses']['ventilation']['mechanicalAirChangeRate']
if 'appliance' in usage_zone_variant:
_appliances = Appliances()
_appliances.appliances_density = usage_zone_variant['appliance']['#text'] # todo: check units
usage_zone_archetype.appliances = _appliances
if 'space_cooling' in usage_zone_variant['endUses'] and usage_zone_variant['endUses']['space_cooling'] is not None:
if 'coolingSetPointTemperature' in usage_zone_variant['endUses']['space_cooling']:
cooling_setpoint = usage_zone_variant['endUses']['space_cooling']['coolingSetPointTemperature']
if 'space_heating' in usage_zone_variant['endUses'] and usage_zone_variant['endUses']['space_heating'] is not None:
if 'heatingSetPointTemperature' in usage_zone_variant['endUses']['space_heating']:
heating_setpoint = usage_zone_variant['endUses']['space_heating']['heatingSetPointTemperature']
if 'heatingSetBackTemperature' in usage_zone_variant['endUses']['space_heating']:
heating_setback = usage_zone_variant['endUses']['space_heating']['heatingSetBackTemperature']
if 'ventilation' in usage_zone_variant['endUses'] and usage_zone_variant['endUses']['ventilation'] is not None:
if 'mechanicalAirChangeRate' in usage_zone_variant['endUses']['ventilation']:
mechanical_air_change = usage_zone_variant['endUses']['ventilation']['mechanicalAirChangeRate']
# todo: for internal_gain in usage_zone_variant['schedules']['internGains']:????????????????
# There are no more internal gains? How is it saved when more than one???
if 'schedules' in usage_zone_variant:
if 'usageHoursPerDay' in usage_zone_variant['schedules']:
hours_day = usage_zone_variant['schedules']['usageHoursPerDay']
if 'usageDaysPerYear' in usage_zone_variant['schedules']:
days_year = usage_zone_variant['schedules']['usageDaysPerYear']
if 'internalGains' in usage_zone_variant['schedules'] and usage_zone_variant['schedules'][
'internGains'] is not None:
internal_gains = []
if 'latentFraction' in usage_zone_variant['schedules']['internGains']:
latent_fraction = usage_zone_variant['schedules']['internGains']['latentFraction']
if 'convectiveFraction' in usage_zone_variant['schedules']['internGains']:
convective_fraction = usage_zone_variant['schedules']['internGains']['convectiveFraction']
if 'averageInternGainPerSqm' in usage_zone_variant['schedules']['internGains']:
average_internal_gain = usage_zone_variant['schedules']['internGains']['averageInternGainPerSqm']
if 'radiantFraction' in usage_zone_variant['schedules']['internGains']:
radiative_fraction = usage_zone_variant['schedules']['internGains']['radiantFraction']
internal_gains.append(higa(average_internal_gain=average_internal_gain, convective_fraction=convective_fraction,
radiative_fraction=radiative_fraction, latent_fraction=latent_fraction))
usage_zone_archetype = huza(usage=usage, internal_gains=internal_gains, heating_set_point=heating_setpoint,
heating_set_back=heating_setback, cooling_set_point=cooling_setpoint,
occupancy_density=occupancy_density, hours_day=hours_day, days_year=days_year,
dhw_average_volume_pers_day=dhw_average_volume_pers_day,
dhw_preparation_temperature=dhw_preparation_temperature,
electrical_app_average_consumption_sqm_year=electrical_app_average_consumption_sqm_year,
mechanical_air_change=mechanical_air_change)
return usage_zone_archetype return usage_zone_archetype

View File

@ -9,6 +9,9 @@ from imports.geometry.helpers.geometry_helper import GeometryHelper as gh
from imports.usage.hft_usage_interface import HftUsageInterface from imports.usage.hft_usage_interface import HftUsageInterface
from city_model_structure.building_demand.usage_zone import UsageZone from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.building_demand.internal_gains import InternalGains 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.appliances import Appliances
from city_model_structure.building_demand.thermal_control import ThermalControl
class HftUsageParameters(HftUsageInterface): class HftUsageParameters(HftUsageInterface):
@ -26,19 +29,21 @@ class HftUsageParameters(HftUsageInterface):
""" """
city = self._city city = self._city
for building in city.buildings: for building in city.buildings:
archetype = self._search_archetype(gh.usage_from_function(building.function)) usage = gh.usage_from_function(building.function)
if archetype is None: try:
archetype = self._search_archetype(usage)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as ' f' {building.function}, that assigns building usage as '
f'{gh.usage_from_function(building.function)}\n') f'{gh.usage_from_function(building.function)}\n')
continue return
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
usage_zone = UsageZone() usage_zone = UsageZone()
usage_zone.usage = building.function usage_zone.usage = building.function
self._assign_values(usage_zone, archetype) self._assign_values(usage_zone, archetype)
usage_zone.percentage = 1 usage_zone.percentage = 1
internal_zone.usage_zones = [usage_zone] internal_zone.usage_zones = [usage_zone]
def _search_archetype(self, building_usage): def _search_archetype(self, building_usage):
for building_archetype in self._usage_archetypes: for building_archetype in self._usage_archetypes:
@ -51,22 +56,30 @@ class HftUsageParameters(HftUsageInterface):
# Due to the fact that python is not a typed language, the wrong object type is assigned to # Due to the fact that python is not a typed language, the wrong object type is assigned to
# usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains. # usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains.
# Therefore, this walk around has been done. # Therefore, this walk around has been done.
internal_gains = [] # Due to the fact that python is not a typed language, the wrong object type is assigned to
for archetype_internal_gain in archetype.internal_gains: # usage_zone.occupancy when writing usage_zone.occupancy = archetype.occupancy.
internal_gain = InternalGains() # Same happens for lighting and appliances. Therefore, this walk around has been done.
internal_gain.average_internal_gain = archetype_internal_gain.average_internal_gain
internal_gain.convective_fraction = archetype_internal_gain.convective_fraction
internal_gain.radiative_fraction = archetype_internal_gain.radiative_fraction
internal_gain.latent_fraction = archetype_internal_gain.latent_fraction
internal_gains.append(internal_gain)
usage_zone.internal_gains = internal_gains
usage_zone.heating_setpoint = archetype.heating_setpoint
usage_zone.heating_setback = archetype.heating_setback
usage_zone.cooling_setpoint = archetype.cooling_setpoint
usage_zone.occupancy_density = archetype.occupancy_density
usage_zone.hours_day = archetype.hours_day
usage_zone.days_year = archetype.days_year
usage_zone.dhw_average_volume_pers_day = archetype.dhw_average_volume_pers_day
usage_zone.dhw_preparation_temperature = archetype.dhw_preparation_temperature
usage_zone.electrical_app_average_consumption_sqm_year = archetype.electrical_app_average_consumption_sqm_year
usage_zone.mechanical_air_change = archetype.mechanical_air_change usage_zone.mechanical_air_change = archetype.mechanical_air_change
_occupancy = Occupancy()
_occupancy.occupancy_density = archetype.occupancy.occupancy_density
usage_zone.occupancy = _occupancy
_appliances = Appliances()
_appliances.appliances_density = archetype.appliances.appliances_density
usage_zone.appliances = _appliances
_control = ThermalControl()
_control.mean_heating_set_point = archetype.thermal_control.mean_heating_set_point
_control.heating_set_back = archetype.thermal_control.heating_set_back
_control.mean_cooling_set_point = archetype.thermal_control.mean_cooling_set_point
_control.cooling_set_point_schedules = archetype.thermal_control.cooling_set_point_schedules
_control.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules
usage_zone.thermal_control = _control
_internal_gains = []
for archetype_internal_gain in archetype.not_detailed_source_mean_annual_internal_gains:
_internal_gain = InternalGains()
_internal_gain.average_internal_gain = archetype_internal_gain.average_internal_gain
_internal_gain.convective_fraction = archetype_internal_gain.convective_fraction
_internal_gain.radiative_fraction = archetype_internal_gain.radiative_fraction
_internal_gain.latent_fraction = archetype_internal_gain.latent_fraction
_internal_gain.schedules = archetype_internal_gain.schedules
_internal_gains.append(_internal_gain)
usage_zone.not_detailed_source_mean_annual_internal_gains = _internal_gains

View File

@ -47,12 +47,13 @@ class TestConstructionFactory(TestCase):
self.assertEqual(len(building.beam), 0, 'building beam is calculated') self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none') self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned') self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.geometrical_zones, 'no geometrical zones created') self.assertIsNotNone(building.internal_zones, 'no internal zones created')
self.assertIsNotNone(building.grounds, 'building grounds is none') self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none') self.assertIsNotNone(building.walls, 'building walls is none')
self.assertIsNotNone(building.roofs, 'building roofs is none') self.assertIsNotNone(building.roofs, 'building roofs is none')
self.assertIsNone(building.usage_zones, 'usage zones are defined') for internal_zone in building.internal_zones:
self.assertTrue(len(building.thermal_zones) > 0, 'thermal zones are not defined') self.assertIsNone(internal_zone.usage_zones, 'usage zones are defined')
self.assertTrue(len(internal_zone.thermal_zones) > 0, 'thermal zones are not defined')
self.assertIsNone(building.basement_heated, 'building basement_heated is not none') self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none') self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNone(building.terrains, 'building terrains is not none') self.assertIsNone(building.terrains, 'building terrains is not none')
@ -69,8 +70,8 @@ class TestConstructionFactory(TestCase):
self.assertIsNone(building.households, 'building households is not none') self.assertIsNone(building.households, 'building households is not none')
self.assertFalse(building.is_conditioned, 'building is conditioned') self.assertFalse(building.is_conditioned, 'building is conditioned')
def _check_thermal_zones(self, building): def _check_thermal_zones(self, internal_zone):
for thermal_zone in building.thermal_zones: for thermal_zone in internal_zone.thermal_zones:
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none') self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
self.assertIsNotNone(thermal_zone.floor_area, 'thermal_zone floor area is none') self.assertIsNotNone(thermal_zone.floor_area, 'thermal_zone floor area is none')
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined') self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
@ -81,9 +82,10 @@ class TestConstructionFactory(TestCase):
self.assertIsNotNone(thermal_zone.infiltration_rate_system_off, self.assertIsNotNone(thermal_zone.infiltration_rate_system_off,
'thermal_zone infiltration_rate_system_off is none') 'thermal_zone infiltration_rate_system_off is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'thermal_zone infiltration_rate_system_on is none') self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'thermal_zone infiltration_rate_system_on is none')
self.assertIsNone(thermal_zone.usage_zones, 'thermal_zone usage_zones is not none')
self.assertIsNotNone(thermal_zone.volume, 'thermal_zone volume is none') self.assertIsNotNone(thermal_zone.volume, 'thermal_zone volume is none')
self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not 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.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.hvac_system, 'thermal_zone hvac_system is not none')
@ -164,27 +166,28 @@ class TestConstructionFactory(TestCase):
file = 'one_building_in_kelowna.gml' file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
for building in city.buildings: for building in city.buildings:
building.function = GeometryHelper.hft_to_function[building.function] building.function = GeometryHelper.function_from_hft(building.function)
ConstructionFactory('nrcan', city).enrich() ConstructionFactory('nrcan', city).enrich()
self._check_buildings(city) self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
self._check_thermal_zones(building) for internal_zone in building.internal_zones:
for thermal_zone in building.thermal_zones: self._check_thermal_zones(internal_zone)
self._check_thermal_boundaries(thermal_zone) for thermal_zone in internal_zone.thermal_zones:
for thermal_boundary in thermal_zone.thermal_boundaries: self._check_thermal_boundaries(thermal_zone)
self.assertIsNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is not none') for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is not none') self.assertIsNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is not none')
self.assertIsNone(thermal_boundary.layers, 'layers is not none') self.assertIsNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is not none')
self.assertIsNone(thermal_boundary.layers, 'layers is not none')
self._check_thermal_openings(thermal_boundary) self._check_thermal_openings(thermal_boundary)
for thermal_opening in thermal_boundary.thermal_openings: for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNone(thermal_opening.conductivity, 'thermal_opening conductivity is not none') self.assertIsNone(thermal_opening.conductivity, 'thermal_opening conductivity is not none')
self.assertIsNone(thermal_opening.thickness, 'thermal opening thickness is not none') self.assertIsNone(thermal_opening.thickness, 'thermal opening thickness is not none')
self.assertIsNone(thermal_opening.front_side_solar_transmittance_at_normal_incidence, self.assertIsNone(thermal_opening.front_side_solar_transmittance_at_normal_incidence,
'thermal opening front_side_solar_transmittance_at_normal_incidence is not none') 'thermal opening front_side_solar_transmittance_at_normal_incidence is not none')
self.assertIsNone(thermal_opening.back_side_solar_transmittance_at_normal_incidence, self.assertIsNone(thermal_opening.back_side_solar_transmittance_at_normal_incidence,
'thermal opening back_side_solar_transmittance_at_normal_incidence is not none') 'thermal opening back_side_solar_transmittance_at_normal_incidence is not none')
def test_city_with_construction_extended_library(self): def test_city_with_construction_extended_library(self):
""" """
@ -193,41 +196,39 @@ class TestConstructionFactory(TestCase):
file = 'pluto_building.gml' file = 'pluto_building.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
for building in city.buildings: for building in city.buildings:
building.function = GeometryHelper.pluto_to_function[building.function] building.function = GeometryHelper.function_from_pluto(building.function)
ConstructionFactory('nrel', city).enrich() ConstructionFactory('nrel', city).enrich()
self._check_buildings(city) self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
self._check_thermal_zones(building) for internal_zone in building.internal_zones:
for thermal_zone in building.thermal_zones: self._check_thermal_zones(internal_zone)
self._check_thermal_boundaries(thermal_zone) for thermal_zone in internal_zone.thermal_zones:
for thermal_boundary in thermal_zone.thermal_boundaries: self._check_thermal_boundaries(thermal_zone)
if thermal_boundary.type is not cte.GROUND: for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is none') if thermal_boundary.type is not cte.GROUND:
self.assertIsNotNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is none') self.assertIsNotNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is none')
else: self.assertIsNotNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is none')
self.assertIsNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is not none') else:
self.assertIsNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is not none') self.assertIsNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is not none')
self.assertIsNotNone(thermal_boundary.layers, 'layers is none') self.assertIsNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is not none')
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
self._check_thermal_openings(thermal_boundary) self._check_thermal_openings(thermal_boundary)
for thermal_opening in thermal_boundary.thermal_openings: for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNotNone(thermal_opening.conductivity, 'thermal_opening conductivity is none') self.assertIsNotNone(thermal_opening.conductivity, 'thermal_opening conductivity is none')
self.assertIsNotNone(thermal_opening.thickness, 'thermal opening thickness is none') self.assertIsNotNone(thermal_opening.thickness, 'thermal opening thickness is none')
self.assertIsNotNone(thermal_opening.front_side_solar_transmittance_at_normal_incidence, self.assertIsNotNone(thermal_opening.front_side_solar_transmittance_at_normal_incidence,
'thermal opening front_side_solar_transmittance_at_normal_incidence is none') 'thermal opening front_side_solar_transmittance_at_normal_incidence is none')
self.assertIsNotNone(thermal_opening.back_side_solar_transmittance_at_normal_incidence, self.assertIsNotNone(thermal_opening.back_side_solar_transmittance_at_normal_incidence,
'thermal opening back_side_solar_transmittance_at_normal_incidence is none') 'thermal opening back_side_solar_transmittance_at_normal_incidence is none')
@staticmethod @staticmethod
def _internal_function(function_format, original_function): def _internal_function(function_format, original_function):
if function_format == 'hft': if function_format == 'hft':
new_function = GeometryHelper.hft_to_function[original_function] new_function = GeometryHelper.function_from_hft(original_function)
elif function_format == 'pluto': elif function_format == 'pluto':
new_function = GeometryHelper.pluto_to_function[original_function] new_function = GeometryHelper.function_from_pluto(original_function)
elif function_format == 'alkis':
# todo: not implemented yet!!
raise NotImplementedError
else: else:
raise Exception('Function key not recognized. Implemented only "hft" and "pluto"') raise Exception('Function key not recognized. Implemented only "hft" and "pluto"')
return new_function return new_function

View File

@ -0,0 +1,145 @@
"""
TestGeometryFactory test and validate the city model structure geometric parameters
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from pathlib import Path
from unittest import TestCase
from imports.geometry_factory import GeometryFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.usage_factory import UsageFactory
from imports.construction_factory import ConstructionFactory
class TestGeometryFactory(TestCase):
"""
Non-functional TestGeometryFactory
Load testing
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._city = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def _get_citygml(self, file):
file_path = (self._example_path / file).resolve()
self._city = GeometryFactory('citygml', file_path).city
self.assertIsNotNone(self._city, 'city is none')
return self._city
def _check_buildings(self, city):
for building in city.buildings:
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
for internal_zone in building.internal_zones:
self.assertIsNotNone(internal_zone.usage_zones, 'usage zones are not defined')
self.assertIsNotNone(internal_zone.thermal_zones, 'thermal zones are not defined')
#self.assertIsNotNone(building.basement_heated, 'building basement_heated is none')
#self.assertIsNotNone(building.attic_heated, 'building attic_heated is none')
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
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):
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')
@staticmethod
def _prepare_case_usage_first(city, input_key, construction_key, usage_key):
if input_key == 'pluto':
for building in city.buildings:
building.function = GeometryHelper.function_from_pluto(building.function)
elif input_key == 'hft':
for building in city.buildings:
building.function = GeometryHelper.function_from_hft(building.function)
UsageFactory(usage_key, city).enrich()
ConstructionFactory(construction_key, city).enrich()
@staticmethod
def _prepare_case_construction_first(city, input_key, construction_key, usage_key):
if input_key == 'pluto':
for building in city.buildings:
building.function = GeometryHelper.function_from_pluto(building.function)
elif input_key == 'hft':
for building in city.buildings:
building.function = GeometryHelper.function_from_hft(building.function)
ConstructionFactory(construction_key, city).enrich()
UsageFactory(usage_key, city).enrich()
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'
file_2 = 'pluto_building.gml'
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:
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:
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)

View File

@ -51,7 +51,7 @@ class TestGeometryFactory(TestCase):
self.assertEqual(len(building.beam), 0, 'building beam is calculated') self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none') self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned') self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.geometrical_zones, 'no geometrical zones created') self.assertIsNotNone(building.internal_zones, 'no internal zones created')
self.assertIsNotNone(building.grounds, 'building grounds is none') self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none') self.assertIsNotNone(building.walls, 'building walls is none')
self.assertIsNotNone(building.roofs, 'building roofs is none') self.assertIsNotNone(building.roofs, 'building roofs is none')

View File

@ -8,8 +8,6 @@ from unittest import TestCase
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.usage_factory import UsageFactory from imports.usage_factory import UsageFactory
from imports.schedules_factory import SchedulesFactory
from imports.construction_factory import ConstructionFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
@ -48,34 +46,40 @@ class TestUsageFactory(TestCase):
self.assertEqual(len(building.beam), 0, 'building beam is calculated') self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none') self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned') self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.geometrical_zones, 'no geometrical zones created') self.assertIsNotNone(building.internal_zones, 'no internal zones created')
self.assertIsNotNone(building.grounds, 'building grounds is none') self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none') self.assertIsNotNone(building.walls, 'building walls is none')
self.assertIsNotNone(building.roofs, 'building roofs is none') self.assertIsNotNone(building.roofs, 'building roofs is none')
self.assertTrue(len(building.usage_zones) > 0, 'usage zones are not defined') for internal_zone in building.internal_zones:
self.assertTrue(len(building.thermal_zones) > 0, 'thermal zones are not defined') self.assertTrue(len(internal_zone.usage_zones) > 0, 'usage zones are not defined')
self.assertIsNotNone(building.basement_heated, 'building basement_heated is none') self.assertIsNone(building.thermal_zones, 'thermal zones are defined')
self.assertIsNotNone(building.attic_heated, 'building attic_heated is none') self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNone(building.terrains, 'building terrains is not none') self.assertIsNone(building.terrains, 'building terrains is not none')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none') self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none') self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none') self.assertIsNone(building.average_storey_height, 'building average_storey_height is not none')
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none') self.assertIsNone(building.storeys_above_ground, 'building storeys_above_ground is not none')
self.assertEqual(len(building.heating), 0, 'building heating is not none') self.assertEqual(len(building.heating), 0, 'building heating is not none')
self.assertEqual(len(building.cooling), 0, 'building cooling is not none') self.assertEqual(len(building.cooling), 0, 'building cooling is not none')
self.assertIsNotNone(building.eave_height, 'building eave height is none') self.assertIsNotNone(building.eave_height, 'building eave height is none')
self.assertIsNotNone(building.storeys, 'building storeys are not defined') self.assertIsNone(building.storeys, 'building storeys are defined')
self.assertIsNotNone(building.roof_type, 'building roof type is none') self.assertIsNotNone(building.roof_type, 'building roof type is none')
self.assertIsNotNone(building.floor_area, 'building floor_area is none') self.assertIsNotNone(building.floor_area, 'building floor_area is none')
self.assertIsNone(building.households, 'building households is not none') self.assertIsNone(building.households, 'building households is not none')
self.assertTrue(building.is_conditioned, 'building is not conditioned') self.assertTrue(building.is_conditioned, 'building is not conditioned')
def _check_usage_zone(self, usage_zone):
def _check_hvac(self, thermal_zone): self.assertIsNotNone(usage_zone.usage, 'usage is none')
self.assertIsNotNone(None, 'hvac') self.assertIsNotNone(usage_zone.percentage, 'usage percentage is none')
self.assertIsNotNone(usage_zone.get_internal_gains, 'internal gains is none')
def _check_control(self, thermal_zone): self.assertIsNotNone(usage_zone.hours_day, 'hours per day is none')
self.assertIsNotNone(None, 'control') self.assertIsNotNone(usage_zone.days_year, 'days per year is none')
self.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change is none')
self.assertIsNotNone(usage_zone.thermal_control, 'thermal control is none')
self.assertIsNotNone(usage_zone.thermal_control.mean_heating_set_point, 'control heating set point is none')
self.assertIsNotNone(usage_zone.thermal_control.heating_set_back, 'control heating set back is none')
self.assertIsNotNone(usage_zone.thermal_control.mean_cooling_set_point, 'control cooling set point is none')
def test_import_comnet(self): def test_import_comnet(self):
""" """
@ -84,33 +88,45 @@ class TestUsageFactory(TestCase):
file = 'pluto_building.gml' file = 'pluto_building.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
for building in city.buildings: for building in city.buildings:
building.function = GeometryHelper.pluto_to_function[building.function] building.function = GeometryHelper.function_from_pluto(building.function)
UsageFactory('comnet', city).enrich() UsageFactory('comnet', city).enrich()
SchedulesFactory('comnet', city).enrich()
self._check_buildings(city) self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined') self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
for usage_zone in internal_zone.usage_zones: for usage_zone in internal_zone.usage_zones:
self._check_extended_usage(usage_zone) self._check_usage_zone(usage_zone)
self.assertIsNotNone(usage_zone.thermal_control.heating_set_point_schedules,
def test_import_hft(self): 'control heating set point schedule is none')
""" self.assertIsNotNone(usage_zone.thermal_control.cooling_set_point_schedules,
Enrich the city with the usage information from hft and verify it 'control cooling set point schedule is none')
""" self.assertIsNotNone(usage_zone.occupancy, 'occupancy is none')
# todo: read schedules!! occupancy = usage_zone.occupancy
file = 'pluto_building.gml' self.assertIsNotNone(occupancy.occupancy_density, 'occupancy density is none')
city = self._get_citygml(file) self.assertIsNotNone(occupancy.latent_internal_gain, 'occupancy latent internal gain is none')
for building in city.buildings: self.assertIsNotNone(occupancy.sensible_convective_internal_gain,
building.function = GeometryHelper.pluto_to_function[building.function] 'occupancy sensible convective internal gain is none')
self.assertIsNotNone(occupancy.sensible_radiative_internal_gain,
UsageFactory('hft', city).enrich() 'occupancy sensible radiant internal gain is none')
for building in city.buildings: self.assertIsNotNone(occupancy.occupancy_schedules, 'occupancy schedule is none')
for internal_zone in building.internal_zones: self.assertIsNone(occupancy.occupants, 'occupancy density is not none')
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined') self.assertIsNotNone(usage_zone.lighting, 'lighting is none')
for usage_zone in internal_zone.usage_zones: lighting = usage_zone.lighting
self._check_extended_usage(usage_zone) self.assertIsNotNone(lighting.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.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')
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')
self.assertIsNotNone(usage_zone.thermal_control.hvac_availability_schedules,
'control hvac availability is none')
def test_import_ca(self): def test_import_ca(self):
""" """
@ -119,34 +135,56 @@ class TestUsageFactory(TestCase):
file = 'one_building_in_kelowna.gml' file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
UsageFactory('ca', city).enrich() UsageFactory('ca', city).enrich()
self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined') self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
for usage_zone in internal_zone.usage_zones: for usage_zone in internal_zone.usage_zones:
self._check_reduced_usage(usage_zone) self._check_usage_zone(usage_zone)
self.assertIsNotNone(usage_zone.not_detailed_source_mean_annual_internal_gains,
'not detailed internal gains is none')
def _check_extended_usage(self, usage_zone): def test_import_hft(self):
self.assertIsNotNone(usage_zone.usage, 'usage is none') """
self.assertIsNotNone(usage_zone.not_detailed_source_mean_annual_internal_gains, 'usage is none') Enrich the city with the usage information from hft and verify it
self.assertIsNotNone(usage_zone.cooling_setpoint, 'usage is none') """
self.assertIsNotNone(usage_zone.heating_setback, 'usage is none') file = 'pluto_building.gml'
self.assertIsNotNone(usage_zone.heating_setpoint, 'usage is none') city = self._get_citygml(file)
self.assertIsNotNone(usage_zone.occupancy_density, 'usage is none') for building in city.buildings:
self.assertIsNotNone(usage_zone.hours_day, 'usage is none') building.function = GeometryHelper.function_from_pluto(building.function)
self.assertIsNotNone(usage_zone.days_year, 'usage is none')
self.assertIsNotNone(usage_zone.dhw_average_volume_pers_day, 'usage is none')
self.assertIsNotNone(usage_zone.dhw_preparation_temperature, 'usage is none')
self.assertIsNotNone(usage_zone.electrical_app_average_consumption_sqm_year, 'usage is none')
self.assertIsNotNone(usage_zone.is_heated, 'thermal_zone heated is none')
self.assertIsNotNone(usage_zone.is_cooled, 'thermal_zone cooled is none')
UsageFactory('hft', city).enrich()
def _check_reduced_usage(self, usage_zone): self._check_buildings(city)
self.assertIsNotNone(usage_zone.usage, 'usage is none') for building in city.buildings:
self.assertIsNotNone(usage_zone.internal_gains, 'usage is none') for internal_zone in building.internal_zones:
self.assertIsNotNone(usage_zone.cooling_setpoint, 'usage is none') self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
self.assertIsNotNone(usage_zone.heating_setback, 'usage is none') for usage_zone in internal_zone.usage_zones:
self.assertIsNotNone(usage_zone.heating_setpoint, 'usage is none') self._check_usage_zone(usage_zone)
self.assertIsNotNone(usage_zone.occupancy_density, 'usage is none') self.assertIsNotNone(usage_zone.thermal_control.heating_set_point_schedules,
self.assertIsNotNone(usage_zone.hours_day, 'usage is none') 'control heating set point schedule is none')
self.assertIsNotNone(usage_zone.days_year, 'usage is none') self.assertIsNotNone(usage_zone.thermal_control.cooling_set_point_schedules,
'control cooling set point schedule is none')
self.assertIsNotNone(usage_zone.occupancy, 'occupancy is none')
occupancy = usage_zone.occupancy
self.assertIsNotNone(occupancy.occupancy_density, 'occupancy density is none')
self.assertIsNotNone(occupancy.latent_internal_gain, 'occupancy latent internal gain is none')
self.assertIsNotNone(occupancy.sensible_convective_internal_gain,
'occupancy sensible convective internal gain is none')
self.assertIsNotNone(occupancy.sensible_radiative_internal_gain,
'occupancy sensible radiant internal gain is none')
self.assertIsNotNone(occupancy.occupancy_schedules, 'occupancy schedule is none')
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.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.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')
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')