Major changes with two objectives: homogenize the usage parameters regardless the data source, and completely uncouple geometry and construction library (before the geometry was modified after reading storey high from construction library), and construction and usage libraries (before the usage library could only be read after construction library, now ant order is accepted).

This commit is contained in:
Pilar 2022-03-24 16:51:01 -04:00 committed by guille
parent 62dcc3805b
commit 7a29bef239
28 changed files with 603 additions and 411 deletions

View File

@ -8,7 +8,6 @@ contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
from typing import List, Union
import numpy as np
from city_model_structure.building_demand.surface import Surface
from city_model_structure.building_demand.storey import Storey
from city_model_structure.city_object import CityObject
from city_model_structure.building_demand.household import Household
from city_model_structure.building_demand.internal_zone import InternalZone
@ -265,22 +264,6 @@ class Building(CityObject):
self._eave_height = max(self._eave_height, wall.upper_corner[2])
return self._eave_height
@property
def storeys(self) -> List[Storey]:
"""
Get building storeys
:return: [Storey]
"""
return self._storeys
@storeys.setter
def storeys(self, value):
"""
Set building storeys
:param value: [Storey]
"""
self._storeys = value
@property
def roof_type(self):
"""

View File

@ -58,31 +58,47 @@ WINDOW = 'Window'
DOOR = 'Door'
SKYLIGHT = 'Skylight'
# todo: homogenize function and usage!!
# function
RESIDENTIAL = 'residential'
SFH = 'single family house'
MFH = 'multifamily house'
HOTEL = 'hotel'
HOSPITAL = 'hospital'
OUTPATIENT = 'outpatient'
COMMERCIAL = 'commercial'
STRIP_MALL = 'strip mall'
WAREHOUSE = 'warehouse'
# functions and usages
SINGLE_FAMILY_HOUSE = 'single family house'
MULTI_FAMILY_HOUSE = 'multifamily house'
ROW_HOSE = 'row house'
MID_RISE_APARTMENT = 'mid rise apartment'
HIGH_RISE_APARTMENT = 'high rise apartment'
SMALL_OFFICE = 'small office'
MEDIUM_OFFICE = 'medium office'
LARGE_OFFICE = 'large office'
PRIMARY_SCHOOL = 'primary school'
SECONDARY_SCHOOL = 'secondary school'
OFFICE = 'office'
LARGE_OFFICE = 'large office'
OFFICE_WORKSHOP = 'office/workshop'
# usage
INDUSTRY = 'industry'
OFFICE_ADMINISTRATION = 'office and administration'
HEALTH_CARE = 'health care'
RETAIL = 'retail'
HALL = 'hall'
RESTAURANT = 'restaurant'
STAND_ALONE_RETAIL = 'stand alone retail'
HOSPITAL = 'hospital'
OUT_PATIENT_HEALTH_CARE = 'out-patient health care'
STRIP_MALL = 'strip mall'
SUPERMARKET = 'supermarket'
WAREHOUSE = 'warehouse'
QUICK_SERVICE_RESTAURANT = 'quick service restaurant'
FULL_SERVICE_RESTAURANT = 'full service restaurant'
SMALL_HOTEL = 'small hotel'
LARGE_HOTEL = 'large hotel'
RESIDENTIAL = 'residential'
EDUCATION = 'education'
SCHOOL_WITHOUT_SHOWER = 'school without shower'
SCHOOL_WITH_SHOWER = 'school with shower'
RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD = 'retail shop without refrigerated food'
RETAIL_SHOP_WITH_REFRIGERATED_FOOD = 'retail shop with refrigerated food'
HOTEL = 'hotel'
HOTEL_MEDIUM_CLASS = 'hotel medium class'
DORMITORY = 'dormitory'
INDUSTRY = 'industry'
RESTAURANT = 'restaurant'
HEALTH_CARE = 'health care'
RETIREMENT_HOME_OR_ORPHANAGE = 'retirement home or orphanage'
OFFICE_AND_ADMINISTRATION = 'office and administration'
EVENT_LOCATION = 'event location'
HALL = 'hall'
SPORTS_LOCATION = 'sports location'
LABOR = 'labor'
GREEN_HOUSE = 'green house'
NON_HEATED = 'non-heated'
LIGHTING = 'Lights'
OCCUPANCY = 'Occupancy'

View File

@ -6,7 +6,6 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
import sys
from imports.construction.helpers.construction_helper import ConstructionHelper
from imports.construction.nrel_physics_interface import NrelPhysicsInterface
from imports.construction.helpers.storeys_generation import StoreysGeneration
class CaPhysicsParameters(NrelPhysicsInterface):
@ -26,11 +25,11 @@ class CaPhysicsParameters(NrelPhysicsInterface):
# it is assumed that all buildings have the same archetypes' keys
for building in city.buildings:
try:
archetype = self._search_archetype(ConstructionHelper.nrcan_from_function(building.function),
archetype = self._search_archetype(ConstructionHelper.nrcan_from_libs_function(building.function),
building.year_of_construction)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: '
f'{ConstructionHelper.nrcan_from_function(building.function)} '
f'{ConstructionHelper.nrcan_from_libs_function(building.function)} '
f'and building year of construction: {building.year_of_construction}\n')
return
@ -38,12 +37,11 @@ class CaPhysicsParameters(NrelPhysicsInterface):
if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype)
thermal_zones = []
for storey in building.storeys:
thermal_zones.append(storey.thermal_zone)
building.internal_zones[0].thermal_zones = thermal_zones
self._assign_values(building.internal_zones, archetype)
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
self._calculate_view_factors(thermal_zone)
def _search_archetype(self, function, year_of_construction):
for building_archetype in self._building_archetypes:
@ -82,12 +80,3 @@ class CaPhysicsParameters(NrelPhysicsInterface):
thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio
thermal_opening.g_value = thermal_opening_archetype.g_value
thermal_opening.overall_u_value = thermal_opening_archetype.overall_u_value
@staticmethod
def _create_storeys(building, archetype):
building.average_storey_height = archetype.average_storey_height
building.storeys_above_ground = archetype.storeys_above_ground
storeys_generation = StoreysGeneration(building)
storeys = storeys_generation.storeys
building.storeys = storeys
storeys_generation.assign_thermal_zones_delimited_by_thermal_boundaries()

View File

@ -14,18 +14,26 @@ class ConstructionHelper:
# NREL
_function_to_nrel = {
cte.RESIDENTIAL: 'residential',
cte.SFH: 'single family house',
cte.MFH: 'multifamily house',
cte.HOTEL: 'hotel',
cte.HOSPITAL: 'hospital',
cte.OUTPATIENT: 'outpatient',
cte.COMMERCIAL: 'commercial',
cte.STRIP_MALL: 'strip mall',
cte.WAREHOUSE: 'warehouse',
cte.SINGLE_FAMILY_HOUSE: 'residential',
cte.MULTI_FAMILY_HOUSE: 'residential',
cte.ROW_HOSE: 'residential',
cte.MID_RISE_APARTMENT: 'midrise apartment',
cte.HIGH_RISE_APARTMENT: 'high-rise apartment',
cte.SMALL_OFFICE: 'small office',
cte.MEDIUM_OFFICE: 'medium office',
cte.LARGE_OFFICE: 'large office',
cte.PRIMARY_SCHOOL: 'primary school',
cte.SECONDARY_SCHOOL: 'secondary school',
cte.OFFICE: 'office',
cte.LARGE_OFFICE: 'large office'
cte.STAND_ALONE_RETAIL: 'stand-alone retail',
cte.HOSPITAL: 'hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'outpatient healthcare',
cte.STRIP_MALL: 'strip mall',
cte.SUPERMARKET: 'supermarket',
cte.WAREHOUSE: 'warehouse',
cte.QUICK_SERVICE_RESTAURANT: 'quick service restaurant',
cte.FULL_SERVICE_RESTAURANT: 'full service restaurant',
cte.SMALL_HOTEL: 'small hotel',
cte.LARGE_HOTEL: 'large hotel'
}
_nrel_standards = {
@ -65,19 +73,26 @@ class ConstructionHelper:
# NRCAN
_function_to_nrcan = {
cte.RESIDENTIAL: 'residential',
cte.SFH: 'single family house',
cte.MFH: 'multifamily house',
cte.HOTEL: 'hotel',
cte.HOSPITAL: 'hospital',
cte.OUTPATIENT: 'outpatient',
cte.COMMERCIAL: 'commercial',
cte.STRIP_MALL: 'strip mall',
cte.WAREHOUSE: 'warehouse',
cte.PRIMARY_SCHOOL: 'primary school',
cte.SECONDARY_SCHOOL: 'secondary school',
cte.OFFICE: 'office',
cte.LARGE_OFFICE: 'large office',
cte.OFFICE_WORKSHOP: 'residential'
cte.SINGLE_FAMILY_HOUSE: 'residential',
cte.MULTI_FAMILY_HOUSE: 'residential',
cte.ROW_HOSE: 'residential',
cte.MID_RISE_APARTMENT: 'residential',
cte.HIGH_RISE_APARTMENT: 'residential',
cte.SMALL_OFFICE: cte.SMALL_OFFICE,
cte.MEDIUM_OFFICE: cte.MEDIUM_OFFICE,
cte.LARGE_OFFICE: cte.LARGE_OFFICE,
cte.PRIMARY_SCHOOL: cte.PRIMARY_SCHOOL,
cte.SECONDARY_SCHOOL: cte.SECONDARY_SCHOOL,
cte.STAND_ALONE_RETAIL: cte.STAND_ALONE_RETAIL,
cte.HOSPITAL: cte.HOSPITAL,
cte.OUT_PATIENT_HEALTH_CARE: cte.OUT_PATIENT_HEALTH_CARE,
cte.STRIP_MALL: cte.STRIP_MALL,
cte.SUPERMARKET: cte.SUPERMARKET,
cte.WAREHOUSE: cte.WAREHOUSE,
cte.QUICK_SERVICE_RESTAURANT: cte.QUICK_SERVICE_RESTAURANT,
cte.FULL_SERVICE_RESTAURANT: cte.FULL_SERVICE_RESTAURANT,
cte.SMALL_HOTEL: cte.SMALL_HOTEL,
cte.LARGE_HOTEL: cte.LARGE_HOTEL
}
nrcan_window_types = [cte.WINDOW]
@ -92,7 +107,7 @@ class ConstructionHelper:
}
@staticmethod
def nrel_from_function(function):
def nrel_from_libs_function(function):
"""
Get NREL function from the given internal function key
:param function: str
@ -140,7 +155,7 @@ class ConstructionHelper:
return ConstructionHelper._reference_city_to_nrel_climate_zone[reference_city]
@staticmethod
def nrcan_from_function(function):
def nrcan_from_libs_function(function):
"""
Get NREL function from the given internal function key
:param function: str

View File

@ -6,12 +6,14 @@ Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
import sys
import math
import numpy as np
from typing import List
from helpers import constants as cte
from city_model_structure.attributes.polygon import Polygon
from city_model_structure.attributes.point import Point
from city_model_structure.building_demand.storey import Storey
from city_model_structure.building_demand.surface import Surface
from city_model_structure.building_demand.thermal_zone import ThermalZone
class StoreysGeneration:
@ -20,14 +22,14 @@ class StoreysGeneration:
"""
def __init__(self, building, divide_in_storeys=False):
self._building = building
self._thermal_zones = []
self._divide_in_storeys = divide_in_storeys
self._storeys = None
self._floor_area = 0
for ground in building.grounds:
self._floor_area += ground.perimeter_polygon.area
@property
def storeys(self) -> [Storey]:
def thermal_zones(self) -> List[ThermalZone]:
"""
Get subsections of building trimesh by storey in case of no interiors defined
:return: [Storey]
@ -37,7 +39,21 @@ class StoreysGeneration:
self._building.storeys_above_ground)
number_of_storeys = 1
if not self._divide_in_storeys or number_of_storeys == 1:
return [Storey('storey_0', self._building.surfaces, [None, None], self._building.volume, self._floor_area)]
storey = Storey('storey_0', self._building.surfaces, [None, None], self._building.volume, self._floor_area)
for thermal_boundary in storey.thermal_boundaries:
if thermal_boundary.type != cte.INTERIOR_WALL or thermal_boundary.type != cte.INTERIOR_SLAB:
# external thermal boundary -> only one thermal zone
thermal_zones = [storey.thermal_zone]
else:
# internal thermal boundary -> two thermal zones
grad = np.rad2deg(thermal_boundary.inclination)
if grad >= 170:
thermal_zones = [storey.thermal_zone, storey.neighbours[0]]
else:
thermal_zones = [storey.neighbours[1], storey.thermal_zone]
thermal_boundary.thermal_zones = thermal_zones
return [storey.thermal_zone]
if number_of_storeys == 0:
raise Exception('Number of storeys cannot be 0')
@ -89,7 +105,25 @@ class StoreysGeneration:
if volume < 0:
raise Exception('Error in storeys creation, volume of last storey cannot be lower that 0')
storeys.append(Storey(name, surfaces_child_last_storey, neighbours, volume, self._floor_area))
return storeys
for storey in storeys:
for thermal_boundary in storey.thermal_boundaries:
if thermal_boundary.type != cte.INTERIOR_WALL or thermal_boundary.type != cte.INTERIOR_SLAB:
# external thermal boundary -> only one thermal zone
thermal_zones = [storey.thermal_zone]
else:
# internal thermal boundary -> two thermal zones
grad = np.rad2deg(thermal_boundary.inclination)
if grad >= 170:
thermal_zones = [storey.thermal_zone, storey.neighbours[0]]
else:
thermal_zones = [storey.neighbours[1], storey.thermal_zone]
thermal_boundary.thermal_zones = thermal_zones
for storey in storeys:
self._thermal_zones.append(storey.thermal_zone)
return self._thermal_zones
@staticmethod
def _calculate_number_storeys_and_height(average_storey_height, eave_height, storeys_above_ground):
@ -139,22 +173,3 @@ class StoreysGeneration:
for point in points:
array_points.append(point.coordinates)
return np.array(array_points)
def assign_thermal_zones_delimited_by_thermal_boundaries(self):
"""
During storeys creation, the thermal boundaries and zones are also created.
It is afterwards needed to define which zones are delimited by each thermal boundary
"""
for storey in self._building.storeys:
for thermal_boundary in storey.thermal_boundaries:
if thermal_boundary.type != cte.INTERIOR_WALL or thermal_boundary.type != cte.INTERIOR_SLAB:
# external thermal boundary -> only one thermal zone
thermal_zones = [storey.thermal_zone]
else:
# internal thermal boundary -> two thermal zones
grad = np.rad2deg(thermal_boundary.inclination)
if grad >= 170:
thermal_zones = [storey.thermal_zone, storey.neighbours[0]]
else:
thermal_zones = [storey.neighbours[1], storey.thermal_zone]
thermal_boundary.thermal_zones = thermal_zones

View File

@ -10,6 +10,7 @@ from imports.construction.data_classes.building_achetype import BuildingArchetyp
from imports.construction.data_classes.thermal_boundary_archetype import ThermalBoundaryArchetype as ntba
from imports.construction.data_classes.thermal_opening_archetype import ThermalOpeningArchetype as ntoa
from imports.construction.data_classes.layer_archetype import LayerArchetype as nla
from imports.construction.helpers.storeys_generation import StoreysGeneration
class NrelPhysicsInterface:
@ -181,8 +182,57 @@ class NrelPhysicsInterface:
return thermal_boundary
raise Exception('Construction type not found')
# todo: verify windows
@staticmethod
def _calculate_view_factors(thermal_zone):
"""
Get thermal zone view factors matrix
:return: [[float]]
"""
total_area = 0
for thermal_boundary in thermal_zone.thermal_boundaries:
total_area += thermal_boundary.opaque_area
for thermal_opening in thermal_boundary.thermal_openings:
total_area += thermal_opening.area
view_factors_matrix = []
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = 0
if thermal_boundary_1.id != thermal_boundary_2.id:
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening in thermal_boundary.thermal_openings:
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
values.append(value)
view_factors_matrix.append(values)
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
values = []
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
values.append(value)
for thermal_boundary in thermal_zone.thermal_boundaries:
for thermal_opening_2 in thermal_boundary.thermal_openings:
value = 0
if thermal_opening_1.id != thermal_opening_2.id:
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
values.append(value)
view_factors_matrix.append(values)
thermal_zone.view_factors_matrix = view_factors_matrix
def enrich_buildings(self):
"""
Raise not implemented error
"""
raise NotImplementedError
@staticmethod
def _create_storeys(building, archetype):
building.average_storey_height = archetype.average_storey_height
building.storeys_above_ground = archetype.storeys_above_ground
thermal_zones = StoreysGeneration(building).thermal_zones
building.internal_zones[0].thermal_zones = thermal_zones

View File

@ -10,7 +10,6 @@ from imports.construction.nrel_physics_interface import NrelPhysicsInterface
from imports.construction.helpers.construction_helper import ConstructionHelper
from city_model_structure.building_demand.layer import Layer
from city_model_structure.building_demand.material import Material
from imports.construction.helpers.storeys_generation import StoreysGeneration
class UsPhysicsParameters(NrelPhysicsInterface):
@ -30,7 +29,7 @@ class UsPhysicsParameters(NrelPhysicsInterface):
city = self._city
# it is assumed that all buildings have the same archetypes' keys
for building in city.buildings:
building_type = ConstructionHelper.nrel_from_function(building.function)
building_type = ConstructionHelper.nrel_from_libs_function(building.function)
if building_type is None:
return
try:
@ -46,12 +45,11 @@ class UsPhysicsParameters(NrelPhysicsInterface):
if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype)
thermal_zones = []
for storey in building.storeys:
thermal_zones.append(storey.thermal_zone)
building.internal_zones[0].thermal_zones = thermal_zones
self._assign_values(building.internal_zones, archetype)
for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones:
self._calculate_view_factors(thermal_zone)
def _search_archetype(self, building_type, standard, climate_zone):
for building_archetype in self._building_archetypes:
@ -109,12 +107,3 @@ class UsPhysicsParameters(NrelPhysicsInterface):
thermal_opening_archetype.back_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
def _create_storeys(building, archetype):
building.average_storey_height = archetype.average_storey_height
building.storeys_above_ground = archetype.storeys_above_ground
storeys_generation = StoreysGeneration(building)
storeys = storeys_generation.storeys
building.storeys = storeys
storeys_generation.assign_thermal_zones_delimited_by_thermal_boundaries()

View File

@ -14,7 +14,7 @@ class SanamCustomizedUsageHelper:
usage_to_customized = {
cte.RESIDENTIAL: 'residential',
cte.INDUSTRY: 'manufacturing',
cte.OFFICE_ADMINISTRATION: 'office',
cte.OFFICE_AND_ADMINISTRATION: 'office',
cte.HOTEL: 'hotel',
cte.HEALTH_CARE: 'health',
cte.RETAIL: 'retail',

View File

@ -6,9 +6,11 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
import sys
import xmltodict
from imports.geometry.helpers.geometry_helper import GeometryHelper as gh
from imports.usage.data_classes.usage_zone_archetype import UsageZoneArchetype as huza
import helpers.constants as cte
from imports.usage.helpers.usage_helper import UsageHelper
from city_model_structure.building_demand.occupancy import Occupancy
from city_model_structure.building_demand.usage_zone import UsageZone
from imports.geometry.helpers.geometry_helper import GeometryHelper
class SanamCustomizedUsageParameters:
@ -18,15 +20,10 @@ class SanamCustomizedUsageParameters:
def __init__(self, city, base_path):
file = 'ashrae_archetypes.xml'
path = str(base_path / file)
self._city = city
self._usage_archetypes = []
with open(path) as xml:
self._archetypes = xmltodict.parse(xml.read(), force_list=('zoneUsageVariant', 'zoneUsageType'))
for zone_usage_type in self._archetypes['buildingUsageLibrary']['zoneUsageType']:
usage = zone_usage_type['id']
usage_archetype = self._parse_zone_usage_type(usage, zone_usage_type)
self._usage_archetypes.append(usage_archetype)
self._city = city
def enrich_buildings(self):
"""
@ -35,48 +32,59 @@ class SanamCustomizedUsageParameters:
"""
city = self._city
for building in city.buildings:
archetype = self._search_archetype(building.function) # todo: building.function or other translation???????
height = building.average_storey_height
if height is None:
raise Exception('Average storey height not defined, ACH cannot be calculated')
if height <= 0:
raise Exception('Average storey height is zero, ACH cannot be calculated')
libs_usage = GeometryHelper().libs_usage_from_libs_function(building.function)
comnet_usage = UsageHelper().comnet_from_libs_usage(libs_usage)
archetype = self._search_archetype(comnet_usage)
if archetype is None:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as '
f'{gh.usage_from_function(building.function)}\n')
continue
mix_usage = False
if not mix_usage:
# just one usage_zone
for usage_zone in building.usage_zones:
self._assign_values(usage_zone, archetype, height)
f'{libs_usage}\n')
return
def _search_archetype(self, building_usage):
for building_archetype in self._usage_archetypes:
if building_archetype.usage == building_usage:
return building_archetype
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.usage = libs_usage
self._assign_values(usage_zone, archetype, volume_per_area)
def _search_archetype(self, libs_usage):
comnet_usage = UsageHelper.comnet_from_libs_usage(libs_usage)
for building_archetype in self._archetypes['buildingUsageLibrary']['zoneUsageType']:
if building_archetype['id'] == comnet_usage:
usage_archetype = self._parse_usage_type(self._archetypes)
return usage_archetype
return None
@staticmethod
def _assign_values(usage_zone, archetype, height):
def _assign_values(usage_zone, archetype, volume_per_area):
usage_zone.usage = archetype.usage
# 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.
# Therefore, this walk around has been done.
if archetype.occupancy_density is not None:
usage_zone.occupancy_density = archetype.occupancy_density
archetype_mechanical_air_change = float(archetype.mechanical_air_change) * float(usage_zone.occupancy_density) \
* cte.HOUR_TO_MINUTES / cte.METERS_TO_FEET**3 / height
if archetype.occupancy.occupancy_density is not None:
if usage_zone.occupancy is None:
_occupancy = Occupancy()
usage_zone.occupancy = _occupancy
usage_zone.occupancy.occupancy_density = archetype.occupancy.occupancy_density
archetype_mechanical_air_change = float(archetype.mechanical_air_change) * \
float(usage_zone.occupancy.occupancy_density) * cte.METERS_TO_FEET ** 2 \
* cte.HOUR_TO_MINUTES / cte.METERS_TO_FEET ** 3 / volume_per_area
usage_zone.mechanical_air_change = archetype_mechanical_air_change
@staticmethod
def _parse_zone_usage_type(usage, zone_usage_type):
mechanical_air_change = zone_usage_type['endUses']['ventilation']['minimumVentilationRate']['#text']
if 'occupancy' in zone_usage_type:
occupancy_density = zone_usage_type['occupancy']['occupancyDensity']['#text']
usage_zone_archetype = huza(usage=usage, occupancy_density=occupancy_density,
mechanical_air_change=mechanical_air_change)
else:
usage_zone_archetype = huza(usage=usage, mechanical_air_change=mechanical_air_change)
def _parse_usage_type(data):
usage_zone_archetype = UsageZone()
usage_zone_archetype.usage = data['id']
usage_zone_archetype.mechanical_air_change = data['endUses']['ventilation']['minimumVentilationRate'][
'#text']
if 'occupancy' in data:
_occupancy = Occupancy()
_occupancy.occupancy_density = data['occupancy']['occupancyDensity']['#text']
usage_zone_archetype.occupancy = _occupancy
return usage_zone_archetype

View File

@ -17,10 +17,6 @@ class CustomizedImportsFactory:
self._importer_class = importer_class
self._city = city
self._base_path = base_path
for building in city.buildings:
if len(building.thermal_zones) == 0:
raise Exception('It seems that the customized imports factory is being called before the construction factory. '
'Please ensure that the construction factory is called first.')
def enrich(self):
"""

View File

@ -13,20 +13,20 @@ class GeometryHelper:
"""
# function
_pluto_to_function = {
'A0': cte.SFH,
'A1': cte.SFH,
'A2': cte.SFH,
'A3': cte.SFH,
'A4': cte.SFH,
'A5': cte.SFH,
'A6': cte.SFH,
'A7': cte.SFH,
'A8': cte.SFH,
'A9': cte.SFH,
'B1': cte.MFH,
'B2': cte.MFH,
'B3': cte.MFH,
'B9': cte.MFH,
'A0': cte.SINGLE_FAMILY_HOUSE,
'A1': cte.SINGLE_FAMILY_HOUSE,
'A2': cte.SINGLE_FAMILY_HOUSE,
'A3': cte.SINGLE_FAMILY_HOUSE,
'A4': cte.SINGLE_FAMILY_HOUSE,
'A5': cte.SINGLE_FAMILY_HOUSE,
'A6': cte.SINGLE_FAMILY_HOUSE,
'A7': cte.SINGLE_FAMILY_HOUSE,
'A8': cte.SINGLE_FAMILY_HOUSE,
'A9': cte.SINGLE_FAMILY_HOUSE,
'B1': cte.MULTI_FAMILY_HOUSE,
'B2': cte.MULTI_FAMILY_HOUSE,
'B3': cte.MULTI_FAMILY_HOUSE,
'B9': cte.MULTI_FAMILY_HOUSE,
'C0': cte.RESIDENTIAL,
'C1': cte.RESIDENTIAL,
'C2': cte.RESIDENTIAL,
@ -59,16 +59,16 @@ class GeometryHelper:
'F5': cte.WAREHOUSE,
'F8': cte.WAREHOUSE,
'F9': cte.WAREHOUSE,
'G0': cte.OFFICE,
'G1': cte.OFFICE,
'G2': cte.OFFICE,
'G3': cte.OFFICE,
'G4': cte.OFFICE,
'G5': cte.OFFICE,
'G6': cte.OFFICE,
'G7': cte.OFFICE,
'G8': cte.OFFICE,
'G9': cte.OFFICE,
'G0': cte.SMALL_OFFICE,
'G1': cte.SMALL_OFFICE,
'G2': cte.SMALL_OFFICE,
'G3': cte.SMALL_OFFICE,
'G4': cte.SMALL_OFFICE,
'G5': cte.SMALL_OFFICE,
'G6': cte.SMALL_OFFICE,
'G7': cte.SMALL_OFFICE,
'G8': cte.SMALL_OFFICE,
'G9': cte.SMALL_OFFICE,
'H1': cte.HOTEL,
'H2': cte.HOTEL,
'H3': cte.HOTEL,
@ -83,13 +83,13 @@ class GeometryHelper:
'HR': cte.HOTEL,
'HS': cte.HOTEL,
'I1': cte.HOSPITAL,
'I2': cte.OUTPATIENT,
'I3': cte.OUTPATIENT,
'I2': cte.OUT_PATIENT_HEALTH_CARE,
'I3': cte.OUT_PATIENT_HEALTH_CARE,
'I4': cte.RESIDENTIAL,
'I5': cte.OUTPATIENT,
'I6': cte.OUTPATIENT,
'I7': cte.OUTPATIENT,
'I9': cte.OUTPATIENT,
'I5': cte.OUT_PATIENT_HEALTH_CARE,
'I6': cte.OUT_PATIENT_HEALTH_CARE,
'I7': cte.OUT_PATIENT_HEALTH_CARE,
'I9': cte.OUT_PATIENT_HEALTH_CARE,
'J1': cte.LARGE_OFFICE,
'J2': cte.LARGE_OFFICE,
'J3': cte.LARGE_OFFICE,
@ -104,10 +104,10 @@ class GeometryHelper:
'K3': cte.STRIP_MALL,
'K4': cte.RESIDENTIAL,
'K5': cte.RESTAURANT,
'K6': cte.COMMERCIAL,
'K7': cte.COMMERCIAL,
'K8': cte.COMMERCIAL,
'K9': cte.COMMERCIAL,
'K6': cte.SUPERMARKET,
'K7': cte.SUPERMARKET,
'K8': cte.SUPERMARKET,
'K9': cte.SUPERMARKET,
'L1': cte.RESIDENTIAL,
'L2': cte.RESIDENTIAL,
'L3': cte.RESIDENTIAL,
@ -123,34 +123,34 @@ class GeometryHelper:
'N3': cte.RESIDENTIAL,
'N4': cte.RESIDENTIAL,
'N9': cte.RESIDENTIAL,
'O1': cte.OFFICE,
'O2': cte.OFFICE,
'O3': cte.OFFICE,
'O4': cte.OFFICE,
'O5': cte.OFFICE,
'O6': cte.OFFICE,
'O7': cte.OFFICE,
'O8': cte.OFFICE,
'O9': cte.OFFICE,
'O1': cte.SMALL_OFFICE,
'O2': cte.SMALL_OFFICE,
'O3': cte.SMALL_OFFICE,
'O4': cte.SMALL_OFFICE,
'O5': cte.SMALL_OFFICE,
'O6': cte.SMALL_OFFICE,
'O7': cte.SMALL_OFFICE,
'O8': cte.SMALL_OFFICE,
'O9': cte.SMALL_OFFICE,
'P1': cte.LARGE_OFFICE,
'P2': cte.HOTEL,
'P3': cte.OFFICE,
'P4': cte.OFFICE,
'P5': cte.OFFICE,
'P6': cte.OFFICE,
'P3': cte.SMALL_OFFICE,
'P4': cte.SMALL_OFFICE,
'P5': cte.SMALL_OFFICE,
'P6': cte.SMALL_OFFICE,
'P7': cte.LARGE_OFFICE,
'P8': cte.LARGE_OFFICE,
'P9': cte.OFFICE,
'Q0': cte.OFFICE,
'Q1': cte.OFFICE,
'Q2': cte.OFFICE,
'Q3': cte.OFFICE,
'Q4': cte.OFFICE,
'Q5': cte.OFFICE,
'Q6': cte.OFFICE,
'Q7': cte.OFFICE,
'Q8': cte.OFFICE,
'Q9': cte.OFFICE,
'P9': cte.SMALL_OFFICE,
'Q0': cte.SMALL_OFFICE,
'Q1': cte.SMALL_OFFICE,
'Q2': cte.SMALL_OFFICE,
'Q3': cte.SMALL_OFFICE,
'Q4': cte.SMALL_OFFICE,
'Q5': cte.SMALL_OFFICE,
'Q6': cte.SMALL_OFFICE,
'Q7': cte.SMALL_OFFICE,
'Q8': cte.SMALL_OFFICE,
'Q9': cte.SMALL_OFFICE,
'R0': cte.RESIDENTIAL,
'R1': cte.RESIDENTIAL,
'R2': cte.RESIDENTIAL,
@ -214,37 +214,47 @@ class GeometryHelper:
}
_hft_to_function = {
'residential': cte.RESIDENTIAL,
'single family house': cte.SFH,
'multifamily house': cte.MFH,
'single family house': cte.SINGLE_FAMILY_HOUSE,
'multifamily house': cte.MULTI_FAMILY_HOUSE,
'hotel': cte.HOTEL,
'hospital': cte.HOSPITAL,
'outpatient': cte.OUTPATIENT,
'commercial': cte.COMMERCIAL,
'outpatient': cte.OUT_PATIENT_HEALTH_CARE,
'commercial': cte.SUPERMARKET,
'strip mall': cte.STRIP_MALL,
'warehouse': cte.WAREHOUSE,
'primary school': cte.PRIMARY_SCHOOL,
'secondary school': cte.SECONDARY_SCHOOL,
'office': cte.OFFICE,
'office': cte.MEDIUM_OFFICE,
'large office': cte.LARGE_OFFICE
}
# usage
_function_to_usage = {
cte.RESTAURANT: cte.RESTAURANT,
cte.RESIDENTIAL: cte.RESIDENTIAL,
cte.HOSPITAL: cte.HEALTH_CARE,
cte.HOTEL: cte.HOTEL,
cte.LARGE_OFFICE: cte.OFFICE_ADMINISTRATION,
cte.OFFICE: cte.OFFICE_ADMINISTRATION,
cte.SINGLE_FAMILY_HOUSE: cte.SINGLE_FAMILY_HOUSE,
cte.MULTI_FAMILY_HOUSE: cte.MULTI_FAMILY_HOUSE,
cte.ROW_HOSE: cte.RESIDENTIAL,
cte.MID_RISE_APARTMENT: cte.RESIDENTIAL,
cte.HIGH_RISE_APARTMENT: cte.RESIDENTIAL,
cte.SMALL_OFFICE: cte.OFFICE_AND_ADMINISTRATION,
cte.MEDIUM_OFFICE: cte.OFFICE_AND_ADMINISTRATION,
cte.LARGE_OFFICE: cte.OFFICE_AND_ADMINISTRATION,
cte.PRIMARY_SCHOOL: cte.EDUCATION,
cte.SECONDARY_SCHOOL: cte.EDUCATION,
cte.RETAIL: cte.RETAIL,
cte.STRIP_MALL: cte.HALL,
cte.WAREHOUSE: cte.INDUSTRY
cte.STAND_ALONE_RETAIL: cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
cte.HOSPITAL: cte.HEALTH_CARE,
cte.OUT_PATIENT_HEALTH_CARE: cte.HEALTH_CARE,
cte.STRIP_MALL: cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
cte.SUPERMARKET: cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
cte.WAREHOUSE: cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
cte.QUICK_SERVICE_RESTAURANT: cte.RESTAURANT,
cte.FULL_SERVICE_RESTAURANT: cte.RESTAURANT,
cte.SMALL_HOTEL: cte.HOTEL,
cte.LARGE_HOTEL: cte.HOTEL
}
@staticmethod
def function_from_hft(building_hft_function):
def libs_function_from_hft(building_hft_function):
"""
Get internal function from the given HfT function
:param building_hft_function: str
@ -253,7 +263,7 @@ class GeometryHelper:
return GeometryHelper._hft_to_function[building_hft_function]
@staticmethod
def function_from_pluto(building_pluto_function):
def libs_function_from_pluto(building_pluto_function):
"""
Get internal function from the given pluto function
:param building_pluto_function: str
@ -262,7 +272,7 @@ class GeometryHelper:
return GeometryHelper._pluto_to_function[building_pluto_function]
@staticmethod
def usage_from_function(building_function):
def libs_usage_from_libs_function(building_function):
"""
Get the internal usage for the given internal building function
:param building_function: str

View File

@ -10,6 +10,8 @@ import parseidf
import xmltodict
from imports.schedules.helpers.schedules_helper import SchedulesHelper
from city_model_structure.attributes.schedule import Schedule
from city_model_structure.building_demand.occupancy import Occupancy
from city_model_structure.building_demand.lighting import Lighting
import helpers.constants as cte
@ -51,7 +53,8 @@ class DoeIdf:
self._schedule_library = xmltodict.parse(xml.read())
for building in self._city.buildings:
for usage_zone in building.usage_zones:
for internal_zone in building.internal_zones:
for usage_zone in internal_zone.usage_zones:
for schedule_archetype in self._schedule_library['archetypes']['archetypes']:
function = schedule_archetype['@building_type']
if SchedulesHelper.usage_from_function(function) == usage_zone.usage:
@ -129,4 +132,12 @@ class DoeIdf:
continue
schedules.append(schedule)
usage_zone.schedules = schedules
for schedule in schedules:
if schedule.type == cte.OCCUPANCY:
if usage_zone.occupancy is None:
usage_zone.occupancy = Occupancy()
usage_zone.occupancy.occupancy_schedules = [schedule]
elif schedule.type == cte.LIGHTING:
if usage_zone.lighting is None:
usage_zone.lighting = Lighting()
usage_zone.lighting.schedules = [schedule]

View File

@ -15,10 +15,10 @@ class SchedulesHelper:
_usage_to_comnet = {
cte.RESIDENTIAL: 'C-12 Residential',
cte.INDUSTRY: 'C-10 Warehouse',
cte.OFFICE_ADMINISTRATION: 'C-5 Office',
cte.OFFICE_AND_ADMINISTRATION: 'C-5 Office',
cte.HOTEL: 'C-3 Hotel',
cte.HEALTH_CARE: 'C-2 Health',
cte.RETAIL: 'C-8 Retail',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'C-8 Retail',
cte.HALL: 'C-8 Retail',
cte.RESTAURANT: 'C-7 Restaurant',
cte.EDUCATION: 'C-9 School'
@ -36,18 +36,18 @@ class SchedulesHelper:
'high-rise apartment': cte.RESIDENTIAL,
'hospital': cte.HEALTH_CARE,
'large hotel': cte.HOTEL,
'large office': cte.OFFICE_ADMINISTRATION,
'medium office': cte.OFFICE_ADMINISTRATION,
'large office': cte.OFFICE_AND_ADMINISTRATION,
'medium office': cte.OFFICE_AND_ADMINISTRATION,
'midrise apartment': cte.RESIDENTIAL,
'outpatient healthcare': cte.HEALTH_CARE,
'primary school': cte.EDUCATION,
'quick service restaurant': cte.RESTAURANT,
'secondary school': cte.EDUCATION,
'small hotel': cte.HOTEL,
'small office': cte.OFFICE_ADMINISTRATION,
'stand-alone-retail': cte.RETAIL,
'small office': cte.OFFICE_AND_ADMINISTRATION,
'stand-alone-retail': cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
'strip mall': cte.HALL,
'supermarket': cte.RETAIL,
'supermarket': cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
'warehouse': cte.INDUSTRY,
'residential': cte.RESIDENTIAL
}

View File

@ -6,7 +6,6 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
"""
from pathlib import Path
from imports.schedules.comnet_schedules_parameters import ComnetSchedules
from imports.schedules.doe_idf import DoeIdf
@ -19,15 +18,11 @@ class SchedulesFactory:
self._city = city
self._base_path = base_path
for building in city.buildings:
if len(building.usage_zones) == 0:
for internal_zone in building.internal_zones:
if len(internal_zone.usage_zones) == 0:
raise Exception('It seems that the schedule factory is being called before the usage factory. '
'Please ensure that the usage factory is called first.')
def _comnet(self):
"""
Enrich the city by using COMNET schedules as data source
"""
ComnetSchedules(self._city, self._base_path)
'Please ensure that the usage factory is called first as the usage zones must be '
'firstly generated.')
def _doe_idf(self):
"""

View File

@ -5,7 +5,9 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
"""
import sys
from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.usage.hft_usage_interface import HftUsageInterface
from imports.usage.helpers.usage_helper import UsageHelper
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.occupancy import Occupancy
@ -28,9 +30,9 @@ class CaUsageParameters(HftUsageInterface):
"""
city = self._city
for building in city.buildings:
usage = GeometryHelper().libs_usage_from_libs_function(building.function)
try:
print(building.function)
archetype = self._search_archetype(building.function)
archetype = self._search_archetype(usage)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}\n')
@ -43,7 +45,8 @@ class CaUsageParameters(HftUsageInterface):
self._assign_values_usage_zone(usage_zone, archetype)
internal_zone.usage_zones = [usage_zone]
def _search_archetype(self, building_usage):
def _search_archetype(self, libs_usage):
building_usage = UsageHelper().hft_from_libs_usage(libs_usage)
for building_archetype in self._usage_archetypes:
if building_archetype.usage == building_usage:
return building_archetype

View File

@ -175,13 +175,13 @@ class ComnetUsageParameters:
return _usage_zone
def _search_archetypes(self, usage):
def _search_archetypes(self, libs_usage):
for item in self._data['lighting']:
comnet_usage = UsageHelper.comnet_from_usage(usage)
comnet_usage = UsageHelper.comnet_from_libs_usage(libs_usage)
if comnet_usage == item:
usage_archetype = self._parse_usage_type(comnet_usage, self._data, self._xls)
return usage_archetype
return None, None
return None
def enrich_buildings(self):
"""
@ -190,13 +190,13 @@ class ComnetUsageParameters:
"""
city = self._city
for building in city.buildings:
usage = GeometryHelper.usage_from_function(building.function)
usage = GeometryHelper.libs_usage_from_libs_function(building.function)
try:
archetype_usage = self._search_archetypes(usage)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as '
f'{GeometryHelper.usage_from_function(building.function)}\n')
f'{GeometryHelper.libs_usage_from_libs_function(building.function)}\n')
return
for internal_zone in building.internal_zones:

View File

@ -13,17 +13,30 @@ class UsageHelper:
"""
_usage_to_hft = {
cte.RESIDENTIAL: 'residential',
cte.INDUSTRY: 'industry',
cte.OFFICE_ADMINISTRATION: 'office and administration',
cte.SINGLE_FAMILY_HOUSE: 'Single family house',
cte.MULTI_FAMILY_HOUSE: 'Multi-family house',
cte.EDUCATION: 'education',
cte.SCHOOL_WITHOUT_SHOWER: 'school without shower',
cte.SCHOOL_WITH_SHOWER: 'school with shower',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'retail shop / refrigerated food',
cte.HOTEL: 'hotel',
cte.HEALTH_CARE: 'health care',
cte.RETAIL: 'retail',
cte.HALL: 'hall',
cte.HOTEL_MEDIUM_CLASS: 'hotel (Medium-class)',
cte.DORMITORY: 'dormitory',
cte.INDUSTRY: 'industry',
cte.RESTAURANT: 'restaurant',
cte.EDUCATION: 'education'}
cte.HEALTH_CARE: 'health care',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Home for the aged or orphanage',
cte.OFFICE_AND_ADMINISTRATION: 'office and administration',
cte.EVENT_LOCATION: 'event location',
cte.HALL: 'hall',
cte.SPORTS_LOCATION: 'sport location',
cte.LABOR: 'Labor',
cte.GREEN_HOUSE: 'green house',
cte.NON_HEATED: 'non-heated'}
@staticmethod
def hft_from_usage(usage):
def hft_from_libs_usage(usage):
"""
Get HfT usage from the given internal usage key
:param usage: str
@ -32,18 +45,32 @@ class UsageHelper:
try:
return UsageHelper._usage_to_hft[usage]
except KeyError:
sys.stderr.write('Error: keyword not found.\n')
sys.stderr.write('Error: keyword not found to translate from libs_usage to hft usage.\n')
_usage_to_comnet = {
cte.RESIDENTIAL: 'BA Multifamily',
cte.INDUSTRY: 'BA Manufacturing Facility',
cte.OFFICE_ADMINISTRATION: 'BA Office',
cte.SINGLE_FAMILY_HOUSE: 'BA Multifamily',
cte.MULTI_FAMILY_HOUSE: 'BA Multifamily',
cte.EDUCATION: 'BA School/University',
cte.SCHOOL_WITHOUT_SHOWER: 'BA School/University',
cte.SCHOOL_WITH_SHOWER: 'BA School/University',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'BA Retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'BA Retail',
cte.HOTEL: 'BA Hotel',
cte.HOTEL_MEDIUM_CLASS: 'BA Hotel',
cte.DORMITORY: 'BA Dormitory',
cte.INDUSTRY: 'BA Manufacturing Facility',
cte.RESTAURANT: 'BA Dining: Family',
cte.HEALTH_CARE: 'BA Hospital',
cte.RETAIL: 'BA Retail',
cte.HALL: 'BA Town Hall',
cte.RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
cte.EDUCATION: 'BA School/University'}
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'BA Multifamily',
cte.OFFICE_AND_ADMINISTRATION: 'BA Office',
cte.EVENT_LOCATION: 'BA Convention Center',
cte.HALL: 'BA Convention Center',
cte.SPORTS_LOCATION: 'BA Sports Arena',
cte.LABOR: 'BA Gymnasium',
cte.GREEN_HOUSE: cte.GREEN_HOUSE,
cte.NON_HEATED: cte.NON_HEATED
}
_comnet_schedules_key_to_comnet_schedules = {
'C-1 Assembly': 'C-1 Assembly',
@ -62,7 +89,7 @@ class UsageHelper:
'C-14 Gymnasium': 'C-14 Gymnasium'}
@staticmethod
def comnet_from_usage(usage):
def comnet_from_libs_usage(usage):
"""
Get Comnet usage from the given internal usage key
:param usage: str
@ -71,7 +98,7 @@ class UsageHelper:
try:
return UsageHelper._usage_to_comnet[usage]
except KeyError:
sys.stderr.write('Error: keyword not found.\n')
sys.stderr.write('Error: keyword not found to translate from libs_usage to comnet usage.\n')
@staticmethod
def schedules_key(usage):

View File

@ -5,6 +5,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import xmltodict
import copy
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.occupancy import Occupancy
@ -33,8 +34,6 @@ class HftUsageInterface:
usage = usage_zone_variant['id']
usage_archetype_variant = self._parse_zone_usage_variant(usage, usage_archetype, usage_zone_variant)
self._usage_archetypes.append(usage_archetype_variant)
for usage in self._usage_archetypes:
print(usage.usage)
@staticmethod
def _parse_zone_usage_type(usage, zone_usage_type):
@ -135,7 +134,7 @@ class HftUsageInterface:
@staticmethod
def _parse_zone_usage_variant(usage, usage_zone, usage_zone_variant):
# the variants mimic the inheritance concept from OOP
usage_zone_archetype = usage_zone
usage_zone_archetype = copy.deepcopy(usage_zone)
usage_zone_archetype.usage = usage
if 'occupancy' in usage_zone_variant:

View File

@ -4,14 +4,12 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import sys
import copy
from imports.geometry.helpers.geometry_helper import GeometryHelper as gh
from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.usage.hft_usage_interface import HftUsageInterface
from imports.usage.helpers.usage_helper import UsageHelper
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.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):
@ -29,23 +27,25 @@ class HftUsageParameters(HftUsageInterface):
"""
city = self._city
for building in city.buildings:
usage = gh.usage_from_function(building.function)
usage = GeometryHelper().libs_usage_from_libs_function(building.function)
try:
archetype = self._search_archetype(usage)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as '
f'{gh.usage_from_function(building.function)}\n')
f'{GeometryHelper().libs_usage_from_libs_function(building.function)}\n')
return
for internal_zone in building.internal_zones:
usage_zone = UsageZone()
usage_zone.usage = building.function
libs_usage = GeometryHelper().libs_usage_from_libs_function(building.function)
usage_zone.usage = UsageHelper().hft_from_libs_usage(libs_usage)
self._assign_values(usage_zone, archetype)
usage_zone.percentage = 1
internal_zone.usage_zones = [usage_zone]
def _search_archetype(self, building_usage):
def _search_archetype(self, libs_usage):
building_usage = UsageHelper().hft_from_libs_usage(libs_usage)
for building_archetype in self._usage_archetypes:
if building_archetype.usage == building_usage:
return building_archetype
@ -53,7 +53,7 @@ class HftUsageParameters(HftUsageInterface):
@staticmethod
def _assign_values(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.
# Therefore, this walk around has been done.
# Due to the fact that python is not a typed language, the wrong object type is assigned to
@ -83,3 +83,12 @@ class HftUsageParameters(HftUsageInterface):
_internal_gain.schedules = archetype_internal_gain.schedules
_internal_gains.append(_internal_gain)
usage_zone.not_detailed_source_mean_annual_internal_gains = _internal_gains
"""
usage_zone.mechanical_air_change = archetype.mechanical_air_change
usage_zone.occupancy = copy.deepcopy(archetype.occupancy)
usage_zone.appliances = copy.deepcopy(archetype.appliances)
usage_zone.thermal_control = copy.deepcopy(archetype.thermal_control)
usage_zone.not_detailed_source_mean_annual_internal_gains = \
copy.deepcopy(archetype.not_detailed_source_mean_annual_internal_gains)
usage_zone.days_year = archetype.days_year
usage_zone.hours_day = archetype.hours_day

View File

@ -0,0 +1,64 @@
# Functions and usages internally recognized within the libs
The libs uses a list of building functions a building usages that are the only ones recognized. All new categories should be added to the dicctionaries that translate from the input formats to the libs functions. From the libs functions to the libs usages and from the libs usages and libs functions to the output formats.
Input formats accepted:
* Function:
* pluto
* hft
Output formats accepted:
* Function:
* nrel
* nrcan
* Usage:
* ca
* hft
* comnet
Libs_functions:
* single family house
* multi family house
* row hose
* mid rise apartment
* high rise apartment
* residential
* small office
* medium office
* large office
* primary school
* secondary school
* stand alone retail
* hospital
* out-patient health care
* strip mall
* supermarket
* ware house
* quick service restaurant
* full service restaurant
* small hotel
* large hotel
Libs_usage:
* residential
* single family house
* multi family house
* education
* school without shower
* school with shower
* retail shop without refrigerated food
* retail shop with refrigerated food
* hotel
* hotel medium class
* dormitory
* industry
* restaurant
* health care
* retirement home or orphanage
* office and administration
* event location
* hall
* sports location
* labor
* green-house
* non-heated

View File

@ -64,7 +64,6 @@ class TestConstructionFactory(TestCase):
self.assertEqual(len(building.heating), 0, 'building heating 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.storeys, 'building storeys are not defined')
self.assertIsNotNone(building.roof_type, 'building roof type is none')
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
self.assertIsNone(building.households, 'building households is not none')
@ -93,7 +92,7 @@ class TestConstructionFactory(TestCase):
for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_boundary.id, 'thermal_boundary id is none')
self.assertIsNotNone(thermal_boundary.parent_surface, 'thermal_boundary surface is none')
self.assertIsNotNone(thermal_boundary.thermal_zones, 'thermal_boundary delimits is none')
self.assertIsNotNone(thermal_boundary.thermal_zones, 'thermal_boundary delimits no thermal zone')
self.assertIsNotNone(thermal_boundary.opaque_area, 'thermal_boundary area is none')
self.assertIsNotNone(thermal_boundary.azimuth, 'thermal_boundary azimuth is none')
self.assertIsNotNone(thermal_boundary.inclination, 'thermal_boundary inclination is none')
@ -166,7 +165,7 @@ class TestConstructionFactory(TestCase):
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.function = GeometryHelper.function_from_hft(building.function)
building.function = GeometryHelper.libs_function_from_hft(building.function)
ConstructionFactory('nrcan', city).enrich()
self._check_buildings(city)
@ -196,7 +195,7 @@ class TestConstructionFactory(TestCase):
file = 'pluto_building.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.function = GeometryHelper.function_from_pluto(building.function)
building.function = GeometryHelper.libs_function_from_pluto(building.function)
ConstructionFactory('nrel', city).enrich()
self._check_buildings(city)
@ -226,9 +225,9 @@ class TestConstructionFactory(TestCase):
@staticmethod
def _internal_function(function_format, original_function):
if function_format == 'hft':
new_function = GeometryHelper.function_from_hft(original_function)
new_function = GeometryHelper.libs_function_from_hft(original_function)
elif function_format == 'pluto':
new_function = GeometryHelper.function_from_pluto(original_function)
new_function = GeometryHelper.libs_function_from_pluto(original_function)
else:
raise Exception('Function key not recognized. Implemented only "hft" and "pluto"')
return new_function

View File

@ -6,8 +6,8 @@ Copyright © 2021 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
from pathlib import Path
from unittest import TestCase
import helpers.constants as cte
from imports.geometry_factory import GeometryFactory
from imports.construction_factory import ConstructionFactory
from imports.usage_factory import UsageFactory
from imports.customized_imports_factory import CustomizedImportsFactory
from imports.customized_imports.sanam_customized_usage_parameters import SanamCustomizedUsageParameters as scp
@ -28,7 +28,6 @@ class TestCustomizedImportsFactory(TestCase):
file_path = (self._example_path / file).resolve()
_city = GeometryFactory('citygml', file_path).city
self.assertIsNotNone(_city, 'city is none')
ConstructionFactory('nrel', _city).enrich()
UsageFactory('hft', _city).enrich()
return _city
@ -44,6 +43,9 @@ class TestCustomizedImportsFactory(TestCase):
CustomizedImportsFactory(scp, city).enrich()
for building in city.buildings:
self.assertIsNot(len(building.usage_zones), 0, 'no building usage_zones defined')
for usage_zone in building.usage_zones:
self.assertIsNotNone(usage_zone.mechanical_air_change, 'usage is none')
self.assertIsNot(len(building.internal_zones), 0, 'no building internal_zones defined')
for internal_zone in building.internal_zones:
for usage_zone in internal_zone.usage_zones:
if usage_zone.usage != cte.RESIDENTIAL:
self.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change rate is none')
self.assertIsNotNone(usage_zone.occupancy.occupancy_density, 'occupancy density us none')

View File

@ -34,15 +34,22 @@ class TestBuildings(TestCase):
ExportsFactory('idf', city, output_path).export()
self.assertEqual(10, len(city.buildings))
for building in city.buildings:
self.assertTrue(len(building.usage_zones) > 0)
for usage_zone in building.usage_zones:
self.assertIsNot(len(usage_zone.schedules), 0, 'no usage_zones schedules defined')
for schedule in usage_zone.schedules:
for internal_zone in building.internal_zones:
self.assertTrue(len(internal_zone.usage_zones) > 0)
for usage_zone in internal_zone.usage_zones:
self.assertIsNot(len(usage_zone.occupancy.occupancy_schedules), 0, 'no occupancy schedules defined')
for schedule in usage_zone.occupancy.occupancy_schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)
self.assertIsNot(len(usage_zone.lighting.schedules), 0, 'no lighting schedules defined')
for schedule in usage_zone.lighting.schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)

View File

@ -54,10 +54,10 @@ class TestGeometryFactory(TestCase):
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)
building.function = GeometryHelper.libs_function_from_pluto(building.function)
elif input_key == 'hft':
for building in city.buildings:
building.function = GeometryHelper.function_from_hft(building.function)
building.function = GeometryHelper.libs_function_from_hft(building.function)
UsageFactory(usage_key, city).enrich()
ConstructionFactory(construction_key, city).enrich()
@ -65,10 +65,10 @@ class TestGeometryFactory(TestCase):
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)
building.function = GeometryHelper.libs_function_from_pluto(building.function)
elif input_key == 'hft':
for building in city.buildings:
building.function = GeometryHelper.function_from_hft(building.function)
building.function = GeometryHelper.libs_function_from_hft(building.function)
ConstructionFactory(construction_key, city).enrich()
UsageFactory(usage_key, city).enrich()
@ -112,6 +112,7 @@ class TestGeometryFactory(TestCase):
self._check_thermal_zones(thermal_zone)
for construction_key in _construction_keys:
if construction_key != 'nrcan':
for usage_key in _usage_keys:
if usage_key != 'ca':
city = self._get_citygml(file_2)
@ -127,6 +128,7 @@ class TestGeometryFactory(TestCase):
self._check_thermal_zones(thermal_zone)
for construction_key in _construction_keys:
if construction_key != 'nrcan':
for usage_key in _usage_keys:
if usage_key != 'ca':
city = self._get_citygml(file_2)
@ -143,3 +145,19 @@ class TestGeometryFactory(TestCase):
city = self._get_citygml(file_3)
self.assertTrue(len(city.buildings) == 10)
for construction_key in _construction_keys:
if construction_key != 'nrcan':
for usage_key in _usage_keys:
if usage_key != 'ca':
city = self._get_citygml(file_2)
self.assertTrue(len(city.buildings) == 1)
self._prepare_case_construction_first(city, 'pluto', construction_key, usage_key)
self._check_buildings(city)
for building in city.buildings:
for internal_zone in building.internal_zones:
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
for usage_zone in internal_zone.usage_zones:
self._check_usage_zone(usage_zone)
for thermal_zone in internal_zone.thermal_zones:
self._check_thermal_zones(thermal_zone)

View File

@ -9,8 +9,8 @@ from pathlib import Path
from unittest import TestCase
import pandas as pd
from imports.geometry_factory import GeometryFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.construction_factory import ConstructionFactory
from imports.schedules_factory import SchedulesFactory
from imports.usage_factory import UsageFactory
from exports.exports_factory import ExportsFactory
import helpers.constants as cte
@ -45,9 +45,10 @@ class TestExports(TestCase):
else:
file_path = (self._example_path / 'one_building_in_kelowna.gml').resolve()
self._complete_city = self._get_citygml(file_path)
for building in self._complete_city.buildings:
building.function = GeometryHelper().libs_function_from_hft(building.function)
ConstructionFactory('nrel', self._complete_city).enrich()
UsageFactory('ca', self._complete_city).enrich()
SchedulesFactory('comnet', self._complete_city).enrich()
cli = 'C:\\Users\\Pilar\\PycharmProjects\\monthlyenergybalance\\tests_data\\weather\\inseldb_Summerland.cli'
self._complete_city.climate_file = Path(cli)
self._complete_city.climate_reference_city = 'Summerland'

View File

@ -55,8 +55,10 @@ class TestGeometryFactory(TestCase):
self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none')
self.assertIsNotNone(building.roofs, 'building roofs is none')
self.assertIsNone(building.usage_zones, 'usage zones are defined')
self.assertIsNone(building.thermal_zones, 'thermal zones are defined')
self.assertIsNotNone(building.internal_zones, 'building internal zones is none')
for internal_zone in building.internal_zones:
self.assertIsNone(internal_zone.usage_zones, 'usage zones are defined')
self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined')
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')
@ -67,7 +69,6 @@ class TestGeometryFactory(TestCase):
self.assertEqual(len(building.heating), 0, 'building heating 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.assertIsNone(building.storeys, 'building storeys are defined')
self.assertIsNotNone(building.roof_type, 'building roof type is none')
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
self.assertIsNone(building.households, 'building households is not none')

View File

@ -31,30 +31,10 @@ class TestSchedulesFactory(TestCase):
ConstructionFactory('nrel', _city).enrich()
self.assertIsNotNone(_city, 'city is none')
for building in _city.buildings:
building.function = GeometryHelper.hft_to_function[building.function]
building.function = GeometryHelper.libs_function_from_hft(building.function)
UsageFactory('hft', _city).enrich()
return _city
def test_comnet_archetypes(self):
"""
Enrich the city with commet schedule archetypes and verify it
"""
file = (self._example_path / 'one_building_in_kelowna.gml').resolve()
city = self._get_citygml(file)
occupancy_handler = 'comnet'
SchedulesFactory(occupancy_handler, city).enrich()
for building in city.buildings:
self.assertIsNot(len(building.usage_zones), 0, 'no building usage_zones defined')
for usage_zone in building.usage_zones:
self.assertIsNot(len(usage_zone.schedules), 0, 'no usage_zones schedules defined')
for schedule in usage_zone.schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)
def test_doe_idf_archetypes(self):
"""
Enrich the city with doe_idf schedule archetypes and verify it
@ -64,7 +44,22 @@ class TestSchedulesFactory(TestCase):
occupancy_handler = 'doe_idf'
SchedulesFactory(occupancy_handler, city).enrich()
for building in city.buildings:
for usage_zone in building.usage_zones:
for schedule in usage_zone.schedules:
print(schedule)
print(usage_zone.schedules[schedule])
for internal_zone in building.internal_zones:
self.assertTrue(len(internal_zone.usage_zones) > 0)
for usage_zone in internal_zone.usage_zones:
self.assertIsNot(len(usage_zone.occupancy.occupancy_schedules), 0, 'no occupancy schedules defined')
for schedule in usage_zone.occupancy.occupancy_schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)
self.assertIsNot(len(usage_zone.lighting.schedules), 0, 'no lighting schedules defined')
for schedule in usage_zone.lighting.schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)

View File

@ -53,7 +53,7 @@ class TestUsageFactory(TestCase):
self.assertIsNotNone(building.roofs, 'building roofs is none')
for internal_zone in building.internal_zones:
self.assertTrue(len(internal_zone.usage_zones) > 0, 'usage zones are not defined')
self.assertIsNone(building.thermal_zones, 'thermal zones are defined')
self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined')
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')
@ -64,7 +64,6 @@ class TestUsageFactory(TestCase):
self.assertEqual(len(building.heating), 0, 'building heating 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.assertIsNone(building.storeys, 'building storeys are defined')
self.assertIsNotNone(building.roof_type, 'building roof type is none')
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
self.assertIsNone(building.households, 'building households is not none')
@ -76,7 +75,6 @@ class TestUsageFactory(TestCase):
self.assertIsNotNone(usage_zone.get_internal_gains, 'internal gains is none')
self.assertIsNotNone(usage_zone.hours_day, 'hours per day is none')
self.assertIsNotNone(usage_zone.days_year, 'days per year is none')
self.assertIsNotNone(usage_zone.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')
@ -89,7 +87,7 @@ class TestUsageFactory(TestCase):
file = 'pluto_building.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.function = GeometryHelper.function_from_pluto(building.function)
building.function = GeometryHelper.libs_function_from_pluto(building.function)
UsageFactory('comnet', city).enrich()
self._check_buildings(city)
@ -98,6 +96,7 @@ class TestUsageFactory(TestCase):
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)
self.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change is none')
self.assertIsNotNone(usage_zone.thermal_control.heating_set_point_schedules,
'control heating set point schedule is none')
self.assertIsNotNone(usage_zone.thermal_control.cooling_set_point_schedules,
@ -142,6 +141,7 @@ class TestUsageFactory(TestCase):
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)
self.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change is none')
self.assertIsNotNone(usage_zone.not_detailed_source_mean_annual_internal_gains,
'not detailed internal gains is none')
@ -152,7 +152,7 @@ class TestUsageFactory(TestCase):
file = 'pluto_building.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.function = GeometryHelper.function_from_pluto(building.function)
building.function = GeometryHelper.libs_function_from_pluto(building.function)
UsageFactory('hft', city).enrich()
self._check_buildings(city)
@ -161,6 +161,7 @@ class TestUsageFactory(TestCase):
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)
self.assertIsNone(usage_zone.mechanical_air_change, 'mechanical air change is not none')
self.assertIsNotNone(usage_zone.thermal_control.heating_set_point_schedules,
'control heating set point schedule is none')
self.assertIsNotNone(usage_zone.thermal_control.cooling_set_point_schedules,
@ -168,24 +169,13 @@ class TestUsageFactory(TestCase):
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.latent_internal_gain, 'occupancy latent internal gain is none')
self.assertIsNone(occupancy.sensible_convective_internal_gain,
'occupancy sensible convective internal gain is not none')
self.assertIsNone(occupancy.sensible_radiative_internal_gain,
'occupancy sensible radiant internal gain is not none')
self.assertIsNone(occupancy.occupancy_schedules, 'occupancy schedule is not 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')
self.assertIsNone(usage_zone.lighting, 'lighting is not none')
self.assertIsNone(usage_zone.appliances, 'appliances is not none')