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:
parent
77a8969a7e
commit
7488b6ba91
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
usage_zone.mechanical_air_change = archetype_mechanical_air_change
|
||||
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
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
@ -52,15 +54,16 @@ class DoeIdf:
|
|||
self._schedule_library = xmltodict.parse(xml.read())
|
||||
|
||||
for building in self._city.buildings:
|
||||
for usage_zone in building.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:
|
||||
self._idf_schedules_path = (base_path / schedule_archetype['idf']['path']).resolve()
|
||||
with open(self._idf_schedules_path, 'r') as file:
|
||||
idf = parseidf.parse(file.read())
|
||||
self._load_schedule(idf, usage_zone)
|
||||
break
|
||||
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:
|
||||
self._idf_schedules_path = (base_path / schedule_archetype['idf']['path']).resolve()
|
||||
with open(self._idf_schedules_path, 'r') as file:
|
||||
idf = parseidf.parse(file.read())
|
||||
self._load_schedule(idf, usage_zone)
|
||||
break
|
||||
|
||||
def _load_schedule(self, idf, usage_zone):
|
||||
schedules_day = {}
|
||||
|
@ -131,4 +134,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]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
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)
|
||||
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 as the usage zones must be '
|
||||
'firstly generated.')
|
||||
|
||||
def _doe_idf(self):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
64
recognized_functions_and_usages.md
Normal file
64
recognized_functions_and_usages.md
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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:
|
||||
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)
|
||||
|
||||
|
||||
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)
|
||||
|
|
|
@ -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,34 +112,52 @@ class TestGeometryFactory(TestCase):
|
|||
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)
|
||||
if construction_key != 'nrcan':
|
||||
for usage_key in _usage_keys:
|
||||
if usage_key != 'ca':
|
||||
city = self._get_citygml(file_2)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_construction_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
|
||||
for construction_key in _construction_keys:
|
||||
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)
|
||||
if construction_key != 'nrcan':
|
||||
for usage_key in _usage_keys:
|
||||
if usage_key != 'ca':
|
||||
city = self._get_citygml(file_2)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_usage_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
|
||||
city = self._get_citygml(file_3)
|
||||
self.assertTrue(len(city.buildings) == 10)
|
||||
|
||||
for construction_key in _construction_keys:
|
||||
if construction_key != 'nrcan':
|
||||
for usage_key in _usage_keys:
|
||||
if usage_key != 'ca':
|
||||
city = self._get_citygml(file_2)
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._prepare_case_construction_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
self._check_usage_zone(usage_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._check_thermal_zones(thermal_zone)
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -52,7 +52,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')
|
||||
|
@ -63,7 +63,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')
|
||||
|
@ -75,7 +74,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')
|
||||
|
@ -88,7 +86,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)
|
||||
|
@ -97,6 +95,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,
|
||||
|
@ -141,6 +140,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')
|
||||
|
||||
|
@ -151,7 +151,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)
|
||||
|
@ -160,6 +160,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,
|
||||
|
@ -167,24 +168,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')
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user