forked from s_ranjbar/city_retrofit
greenery added to idf exporter and unittest created
This commit is contained in:
parent
43aaf79cb6
commit
1aeca13e01
@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Content:
|
||||
def __init__(self, vegetations, plants, soils):
|
||||
self._vegetations = vegetations
|
||||
|
@ -5,7 +5,7 @@ Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
from catalog_factories.data_models.greenery.soil import Soil as libs_soil
|
||||
from catalog_factories.data_models.greenery.soil import Soil as hub_soil
|
||||
|
||||
|
||||
class Plant:
|
||||
@ -20,12 +20,13 @@ class Plant:
|
||||
self._co2_sequestration = plant.co2Sequestration
|
||||
self._grows_on = []
|
||||
for soil in plant.growsOn:
|
||||
self._grows_on.append(libs_soil(soil))
|
||||
self._grows_on.append(hub_soil(soil))
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get plant name
|
||||
:return: string
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@ -33,13 +34,15 @@ class Plant:
|
||||
def category(self):
|
||||
"""
|
||||
Get plant category name
|
||||
:return: string
|
||||
"""
|
||||
return self._category
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
"""
|
||||
Get plant height
|
||||
Get plant height in m
|
||||
:return: float
|
||||
"""
|
||||
return self._height
|
||||
|
||||
@ -47,6 +50,7 @@ class Plant:
|
||||
def leaf_area_index(self):
|
||||
"""
|
||||
Get plant leaf area index
|
||||
:return: float
|
||||
"""
|
||||
return self._leaf_area_index
|
||||
|
||||
@ -54,6 +58,7 @@ class Plant:
|
||||
def leaf_reflectivity(self):
|
||||
"""
|
||||
Get plant leaf area index
|
||||
:return: float
|
||||
"""
|
||||
return self._leaf_reflectivity
|
||||
|
||||
@ -61,26 +66,30 @@ class Plant:
|
||||
def leaf_emissivity(self):
|
||||
"""
|
||||
Get plant leaf emissivity
|
||||
:return: float
|
||||
"""
|
||||
return self._leaf_emissivity
|
||||
|
||||
@property
|
||||
def minimal_stomatal_resistance(self):
|
||||
"""
|
||||
Get plant minimal stomatal resistance
|
||||
Get plant minimal stomatal resistance in s/m
|
||||
:return: float
|
||||
"""
|
||||
return self._minimal_stomatal_resistance
|
||||
|
||||
@property
|
||||
def co2_sequestration(self):
|
||||
"""
|
||||
Get plant co2 sequestration capacity
|
||||
Get plant co2 sequestration capacity in kg CO2 equivalent
|
||||
:return: float
|
||||
"""
|
||||
return self._co2_sequestration
|
||||
|
||||
@property
|
||||
def grows_on(self) -> [libs_soil]:
|
||||
def grows_on(self) -> [hub_soil]:
|
||||
"""
|
||||
Get plant compatible soils
|
||||
:return: [Soil]
|
||||
"""
|
||||
return self._grows_on
|
||||
|
@ -7,6 +7,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
|
||||
from catalog_factories.data_models.greenery.plant import Plant as libs_plant
|
||||
|
||||
|
||||
class PlantPercentage(libs_plant):
|
||||
|
||||
def __init__(self, percentage, plant_category, plant):
|
||||
@ -15,4 +16,8 @@ class PlantPercentage(libs_plant):
|
||||
|
||||
@property
|
||||
def percentage(self):
|
||||
"""
|
||||
Get plant percentage
|
||||
:return: float
|
||||
"""
|
||||
return self._percentage
|
||||
|
@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Soil:
|
||||
def __init__(self, soil):
|
||||
self._name = soil.name
|
||||
@ -23,6 +24,7 @@ class Soil:
|
||||
def name(self):
|
||||
"""
|
||||
Get soil name
|
||||
:return: string
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@ -30,27 +32,31 @@ class Soil:
|
||||
def roughness(self):
|
||||
"""
|
||||
Get soil roughness
|
||||
:return: string
|
||||
"""
|
||||
return self._roughness
|
||||
|
||||
@property
|
||||
def dry_conductivity(self):
|
||||
"""
|
||||
Get soil dry conductivity
|
||||
Get soil dry conductivity in W/mK
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_conductivity
|
||||
|
||||
@property
|
||||
def dry_density(self):
|
||||
"""
|
||||
Get soil dry density
|
||||
Get soil dry density in kg/m3
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_density
|
||||
|
||||
@property
|
||||
def dry_specific_heat(self):
|
||||
"""
|
||||
Get soil dry specific heat
|
||||
Get soil dry specific heat in J/kgK
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_specific_heat
|
||||
|
||||
@ -58,6 +64,7 @@ class Soil:
|
||||
def thermal_absorptance(self):
|
||||
"""
|
||||
Get soil thermal absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._thermal_absorptance
|
||||
|
||||
@ -65,6 +72,7 @@ class Soil:
|
||||
def solar_absorptance(self):
|
||||
"""
|
||||
Get soil solar absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._solar_absorptance
|
||||
|
||||
@ -72,6 +80,7 @@ class Soil:
|
||||
def visible_absorptance(self):
|
||||
"""
|
||||
Get soil visible absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._visible_absorptance
|
||||
|
||||
@ -79,6 +88,7 @@ class Soil:
|
||||
def saturation_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil saturation volumetric moisture content
|
||||
:return: float
|
||||
"""
|
||||
return self._saturation_volumetric_moisture_content
|
||||
|
||||
@ -86,6 +96,7 @@ class Soil:
|
||||
def residual_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil residual volumetric moisture content
|
||||
:return: float
|
||||
"""
|
||||
return self._residual_volumetric_moisture_content
|
||||
|
||||
@ -93,5 +104,6 @@ class Soil:
|
||||
def initial_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil initial volumetric moisture content
|
||||
:return: float
|
||||
"""
|
||||
return self._initial_volumetric_moisture_content
|
||||
|
@ -7,6 +7,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
|
||||
from catalog_factories.data_models.greenery.plant_percentage import PlantPercentage
|
||||
|
||||
|
||||
class Vegetation:
|
||||
def __init__(self, category, vegetation, plant_percentages):
|
||||
self._name = vegetation.name
|
||||
@ -31,6 +32,7 @@ class Vegetation:
|
||||
def name(self):
|
||||
"""
|
||||
Get vegetation name
|
||||
:return: string
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@ -38,13 +40,15 @@ class Vegetation:
|
||||
def category(self):
|
||||
"""
|
||||
Get vegetation category
|
||||
:return: string
|
||||
"""
|
||||
return self._category
|
||||
|
||||
@property
|
||||
def soil_thickness(self):
|
||||
"""
|
||||
Get soil thickness
|
||||
Get soil thickness in m
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_thickness
|
||||
|
||||
@ -52,13 +56,15 @@ class Vegetation:
|
||||
def management(self):
|
||||
"""
|
||||
Get management
|
||||
:return: string
|
||||
"""
|
||||
return self._management
|
||||
|
||||
@property
|
||||
def air_gap(self):
|
||||
"""
|
||||
Get air gap
|
||||
Get air gap in m
|
||||
:return: float
|
||||
"""
|
||||
return self._air_gap
|
||||
|
||||
@ -66,6 +72,7 @@ class Vegetation:
|
||||
def plant_percentages(self) -> [PlantPercentage]:
|
||||
"""
|
||||
Get plant percentages
|
||||
:return: [PlantPercentage]
|
||||
"""
|
||||
percentage = 0.0
|
||||
for plant_percentage in self._plant_percentages:
|
||||
@ -78,6 +85,7 @@ class Vegetation:
|
||||
def soil_name(self):
|
||||
"""
|
||||
Get soil name
|
||||
:return: string
|
||||
"""
|
||||
return self._soil_name
|
||||
|
||||
@ -85,27 +93,31 @@ class Vegetation:
|
||||
def soil_roughness(self):
|
||||
"""
|
||||
Get soil roughness
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_roughness
|
||||
|
||||
@property
|
||||
def dry_soil_conductivity(self):
|
||||
"""
|
||||
Get soil dry conductivity
|
||||
Get soil dry conductivity in W/mK
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_soil_conductivity
|
||||
|
||||
@property
|
||||
def dry_soil_density(self):
|
||||
"""
|
||||
Get soil dry density
|
||||
Get soil dry density in kg/m3
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_soil_density
|
||||
|
||||
@property
|
||||
def dry_soil_specific_heat(self):
|
||||
"""
|
||||
Get soil dry specific heat
|
||||
Get soil dry specific heat in J/kgK
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_soil_specific_heat
|
||||
|
||||
@ -113,6 +125,7 @@ class Vegetation:
|
||||
def soil_thermal_absorptance(self):
|
||||
"""
|
||||
Get soil thermal absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_thermal_absorptance
|
||||
|
||||
@ -120,6 +133,7 @@ class Vegetation:
|
||||
def soil_solar_absorptance(self):
|
||||
"""
|
||||
Get soil solar absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_solar_absorptance
|
||||
|
||||
@ -127,6 +141,7 @@ class Vegetation:
|
||||
def soil_visible_absorptance(self):
|
||||
"""
|
||||
Get soil visible absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_visible_absorptance
|
||||
|
||||
@ -134,6 +149,7 @@ class Vegetation:
|
||||
def soil_saturation_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil saturation volumetric moisture content
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_saturation_volumetric_moisture_content
|
||||
|
||||
@ -141,6 +157,7 @@ class Vegetation:
|
||||
def soil_residual_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil residual volumetric moisture content
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_residual_volumetric_moisture_content
|
||||
|
||||
@ -148,5 +165,6 @@ class Vegetation:
|
||||
def soil_initial_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil initial volumetric moisture content
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_initial_volumetric_moisture_content
|
||||
|
@ -40,8 +40,7 @@ class Surface:
|
||||
self._solid_polygon = solid_polygon
|
||||
self._pv_system_installed = None
|
||||
self._inverse = None
|
||||
# todo: do I need it???
|
||||
self._associated_thermal_boundaries = None
|
||||
# todo: create self._associated_thermal_boundaries and bring the vegetation here instead of in thermal_boundary
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from typing import List, Union
|
||||
from helpers.configuration_helper import ConfigurationHelper as ch
|
||||
@ -12,6 +13,7 @@ from city_model_structure.building_demand.layer import Layer
|
||||
from city_model_structure.building_demand.thermal_opening import ThermalOpening
|
||||
from city_model_structure.building_demand.thermal_zone import ThermalZone
|
||||
from city_model_structure.building_demand.surface import Surface
|
||||
from city_model_structure.greenery.vegetation import Vegetation
|
||||
|
||||
|
||||
class ThermalBoundary:
|
||||
@ -41,12 +43,13 @@ class ThermalBoundary:
|
||||
self._alpha_coefficient = None
|
||||
self._radiative_coefficient = None
|
||||
self._window_ratio = None
|
||||
self._calculated = False
|
||||
self._window_ration_is_calculated = False
|
||||
self._vegetation = None
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
Get thermal zone id, an universally unique identifier randomly generated
|
||||
Get thermal zone id, a universally unique identifier randomly generated
|
||||
:return: str
|
||||
"""
|
||||
if self._id is None:
|
||||
@ -249,7 +252,7 @@ class ThermalBoundary:
|
||||
:return: float
|
||||
"""
|
||||
if self.windows_areas is not None:
|
||||
if not self._calculated:
|
||||
if not self._window_ration_is_calculated:
|
||||
_calculated = True
|
||||
if len(self.windows_areas) == 0:
|
||||
self._window_ratio = 0
|
||||
@ -266,7 +269,7 @@ class ThermalBoundary:
|
||||
Set thermal boundary window ratio
|
||||
:param value: str
|
||||
"""
|
||||
if self._calculated:
|
||||
if self._window_ration_is_calculated:
|
||||
raise ValueError('Window ratio cannot be assigned when the windows are defined in the geometry.')
|
||||
self._window_ratio = float(value)
|
||||
|
||||
@ -421,3 +424,19 @@ class ThermalBoundary:
|
||||
"""
|
||||
if value is not None:
|
||||
self._radiative_coefficient = float(value)
|
||||
|
||||
@property
|
||||
def vegetation(self) -> Union[None, Vegetation]:
|
||||
"""
|
||||
Get the vegetation construction at the external surface of the thermal boundary
|
||||
:return: None or Vegetation
|
||||
"""
|
||||
return self._vegetation
|
||||
|
||||
@vegetation.setter
|
||||
def vegetation(self, value):
|
||||
"""
|
||||
Set the vegetation construction at the external surface of the thermal boundary
|
||||
:param value: Vegetation
|
||||
"""
|
||||
self._vegetation = value
|
||||
|
@ -5,14 +5,15 @@ Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
import uuid, sys
|
||||
|
||||
import uuid
|
||||
import sys
|
||||
import copy
|
||||
from typing import List, Union, TypeVar
|
||||
from city_model_structure.building_demand.occupancy import Occupancy
|
||||
from city_model_structure.building_demand.appliances import Appliances
|
||||
from city_model_structure.building_demand.lighting import Lighting
|
||||
from city_model_structure.building_demand.internal_gain import InternalGain
|
||||
from city_model_structure.attributes.schedule import Schedule
|
||||
from city_model_structure.building_demand.thermal_control import ThermalControl
|
||||
from city_model_structure.energy_systems.hvac_system import HvacSystem
|
||||
import helpers.constants as cte
|
||||
|
103
city_model_structure/greenery/plant.py
Normal file
103
city_model_structure/greenery/plant.py
Normal file
@ -0,0 +1,103 @@
|
||||
"""
|
||||
Plant class
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
from city_model_structure.greenery.soil import Soil
|
||||
|
||||
|
||||
class Plant:
|
||||
def __init__(self, name, height, leaf_area_index, leaf_reflectivity, leaf_emissivity, minimal_stomatal_resistance,
|
||||
co2_sequestration, grows_on_soils):
|
||||
self._name = name
|
||||
self._percentage = None
|
||||
self._height = height
|
||||
self._leaf_area_index = leaf_area_index
|
||||
self._leaf_reflectivity = leaf_reflectivity
|
||||
self._leaf_emissivity = leaf_emissivity
|
||||
self._minimal_stomatal_resistance = minimal_stomatal_resistance
|
||||
self._co2_sequestration = co2_sequestration
|
||||
self._grows_on = grows_on_soils
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get plant name
|
||||
:return: string
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def percentage(self):
|
||||
"""
|
||||
Get percentage of plant in vegetation
|
||||
:return: float
|
||||
"""
|
||||
return self._percentage
|
||||
|
||||
@percentage.setter
|
||||
def percentage(self, value):
|
||||
"""
|
||||
Set percentage of plant in vegetation
|
||||
:param value: float
|
||||
"""
|
||||
self._percentage = value
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
"""
|
||||
Get plant height in m
|
||||
:return: float
|
||||
"""
|
||||
return self._height
|
||||
|
||||
@property
|
||||
def leaf_area_index(self):
|
||||
"""
|
||||
Get plant leaf area index
|
||||
:return: float
|
||||
"""
|
||||
return self._leaf_area_index
|
||||
|
||||
@property
|
||||
def leaf_reflectivity(self):
|
||||
"""
|
||||
Get plant leaf area index
|
||||
:return: float
|
||||
"""
|
||||
return self._leaf_reflectivity
|
||||
|
||||
@property
|
||||
def leaf_emissivity(self):
|
||||
"""
|
||||
Get plant leaf emissivity
|
||||
:return: float
|
||||
"""
|
||||
return self._leaf_emissivity
|
||||
|
||||
@property
|
||||
def minimal_stomatal_resistance(self):
|
||||
"""
|
||||
Get plant minimal stomatal resistance in s/m
|
||||
:return: float
|
||||
"""
|
||||
return self._minimal_stomatal_resistance
|
||||
|
||||
@property
|
||||
def co2_sequestration(self):
|
||||
"""
|
||||
Get plant co2 sequestration capacity in kg CO2 equivalent
|
||||
:return: float
|
||||
"""
|
||||
return self._co2_sequestration
|
||||
|
||||
@property
|
||||
def grows_on(self) -> List[Soil]:
|
||||
"""
|
||||
Get plant compatible soils
|
||||
:return: [Soil]
|
||||
"""
|
||||
return self._grows_on
|
127
city_model_structure/greenery/soil.py
Normal file
127
city_model_structure/greenery/soil.py
Normal file
@ -0,0 +1,127 @@
|
||||
"""
|
||||
Soil class
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Soil:
|
||||
def __init__(self, name, roughness, dry_conductivity, dry_density, dry_specific_heat, thermal_absorptance,
|
||||
solar_absorptance, visible_absorptance, saturation_volumetric_moisture_content,
|
||||
residual_volumetric_moisture_content):
|
||||
self._name = name
|
||||
self._roughness = roughness
|
||||
self._dry_conductivity = dry_conductivity
|
||||
self._dry_density = dry_density
|
||||
self._dry_specific_heat = dry_specific_heat
|
||||
self._thermal_absorptance = thermal_absorptance
|
||||
self._solar_absorptance = solar_absorptance
|
||||
self._visible_absorptance = visible_absorptance
|
||||
self._saturation_volumetric_moisture_content = saturation_volumetric_moisture_content
|
||||
self._residual_volumetric_moisture_content = residual_volumetric_moisture_content
|
||||
self._initial_volumetric_moisture_content = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get soil name
|
||||
:return: string
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def roughness(self):
|
||||
"""
|
||||
Get soil roughness
|
||||
:return: string
|
||||
"""
|
||||
return self._roughness
|
||||
|
||||
@property
|
||||
def dry_conductivity(self):
|
||||
"""
|
||||
Get soil dry conductivity in W/mK
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_conductivity
|
||||
|
||||
@property
|
||||
def dry_density(self):
|
||||
"""
|
||||
Get soil dry density in kg/m3
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_density
|
||||
|
||||
@property
|
||||
def dry_specific_heat(self):
|
||||
"""
|
||||
Get soil dry specific heat in J/kgK
|
||||
:return: float
|
||||
"""
|
||||
return self._dry_specific_heat
|
||||
|
||||
@property
|
||||
def thermal_absorptance(self):
|
||||
"""
|
||||
Get soil thermal absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._thermal_absorptance
|
||||
|
||||
@property
|
||||
def solar_absorptance(self):
|
||||
"""
|
||||
Get soil solar absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._solar_absorptance
|
||||
|
||||
@property
|
||||
def visible_absorptance(self):
|
||||
"""
|
||||
Get soil visible absortance
|
||||
:return: float
|
||||
"""
|
||||
return self._visible_absorptance
|
||||
|
||||
@property
|
||||
def saturation_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil saturation volumetric moisture content
|
||||
:return: float
|
||||
"""
|
||||
return self._saturation_volumetric_moisture_content
|
||||
|
||||
@property
|
||||
def residual_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil residual volumetric moisture content
|
||||
:return: None or float
|
||||
"""
|
||||
return self._residual_volumetric_moisture_content
|
||||
|
||||
@residual_volumetric_moisture_content.setter
|
||||
def residual_volumetric_moisture_content(self, value):
|
||||
"""
|
||||
Set soil residual volumetric moisture content
|
||||
:param value: float
|
||||
"""
|
||||
self._residual_volumetric_moisture_content = value
|
||||
|
||||
@property
|
||||
def initial_volumetric_moisture_content(self):
|
||||
"""
|
||||
Get soil initial volumetric moisture content
|
||||
:return: None or float
|
||||
"""
|
||||
return self._initial_volumetric_moisture_content
|
||||
|
||||
@initial_volumetric_moisture_content.setter
|
||||
def initial_volumetric_moisture_content(self, value):
|
||||
"""
|
||||
Set soil initial volumetric moisture content
|
||||
:param value: float
|
||||
"""
|
||||
self._initial_volumetric_moisture_content = value
|
84
city_model_structure/greenery/vegetation.py
Normal file
84
city_model_structure/greenery/vegetation.py
Normal file
@ -0,0 +1,84 @@
|
||||
"""
|
||||
Vegetation class
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
from city_model_structure.greenery.soil import Soil
|
||||
from city_model_structure.greenery.plant import Plant
|
||||
|
||||
|
||||
class Vegetation:
|
||||
def __init__(self, name, soil, soil_thickness, plants):
|
||||
self._name = name
|
||||
self._management = None
|
||||
self._air_gap = None
|
||||
self._soil = soil
|
||||
self._soil_thickness = soil_thickness
|
||||
self._plants = plants
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get vegetation name
|
||||
:return: string
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def management(self):
|
||||
"""
|
||||
Get management
|
||||
:return: string
|
||||
"""
|
||||
return self._management
|
||||
|
||||
@management.setter
|
||||
def management(self, value):
|
||||
"""
|
||||
Set management
|
||||
:param value: string
|
||||
"""
|
||||
self._management = value
|
||||
|
||||
@property
|
||||
def air_gap(self):
|
||||
"""
|
||||
Get air gap in m
|
||||
:return: float
|
||||
"""
|
||||
return self._air_gap
|
||||
|
||||
@air_gap.setter
|
||||
def air_gap(self, value):
|
||||
"""
|
||||
Set air gap in m
|
||||
:param value: float
|
||||
"""
|
||||
self._air_gap = value
|
||||
|
||||
@property
|
||||
def soil(self) -> Soil:
|
||||
"""
|
||||
Get soil
|
||||
:return: Soil
|
||||
"""
|
||||
return self._soil
|
||||
|
||||
@property
|
||||
def soil_thickness(self):
|
||||
"""
|
||||
Get soil thickness in m
|
||||
:return: float
|
||||
"""
|
||||
return self._soil_thickness
|
||||
|
||||
@property
|
||||
def plants(self) -> List[Plant]:
|
||||
"""
|
||||
Get list plants in the vegetation
|
||||
:return: List[Plant]
|
||||
"""
|
||||
return self._plants
|
Binary file not shown.
@ -44,8 +44,8 @@ class Idf:
|
||||
_LOCATION = 'SITE:LOCATION'
|
||||
_WINDOW_MATERIAL_SIMPLE = 'WINDOWMATERIAL:SIMPLEGLAZINGSYSTEM'
|
||||
_WINDOW = 'WINDOW'
|
||||
_ROOFIRRIGATION = 'ROOFIRRIGATION'
|
||||
_MATERIAL_ROOFVEGETATION = 'MATERIAL:ROOFVEGETATION'
|
||||
_SIMPLE = 'Simple'
|
||||
|
||||
idf_surfaces = {
|
||||
# todo: make an enum for all the surface types
|
||||
@ -226,9 +226,12 @@ class Idf:
|
||||
|
||||
def _add_construction(self, thermal_boundary):
|
||||
for construction in self._idf.idfobjects[self._CONSTRUCTION]:
|
||||
if thermal_boundary.vegetation is not None:
|
||||
if construction.Name == f'{thermal_boundary.construction_name}_{thermal_boundary.vegetation.name}':
|
||||
return
|
||||
else:
|
||||
if construction.Name == thermal_boundary.construction_name:
|
||||
return
|
||||
|
||||
if thermal_boundary.layers is None:
|
||||
for material in self._idf.idfobjects[self._MATERIAL]:
|
||||
if material.Name == "DefaultMaterial":
|
||||
@ -239,9 +242,15 @@ class Idf:
|
||||
self._add_material(layer)
|
||||
layers = thermal_boundary.layers
|
||||
# The constructions should have at least one layer
|
||||
if thermal_boundary.vegetation is not None:
|
||||
_kwargs = {'Name': f'{thermal_boundary.construction_name}_{thermal_boundary.vegetation.name}',
|
||||
'Outside_Layer': thermal_boundary.vegetation.name}
|
||||
for i in range(0, len(layers) - 1):
|
||||
_kwargs[f'Layer_{i + 2}'] = layers[i].material.name
|
||||
else:
|
||||
_kwargs = {'Name': thermal_boundary.construction_name, 'Outside_Layer': layers[0].material.name}
|
||||
for i in range(1, len(layers) - 1):
|
||||
_kwargs[f'Layer_{i + 1}'] = layers[1].material.name
|
||||
_kwargs[f'Layer_{i + 1}'] = layers[i].material.name
|
||||
self._idf.newidfobject(self._CONSTRUCTION, **_kwargs)
|
||||
|
||||
def _add_window_construction_and_material(self, thermal_opening):
|
||||
@ -344,6 +353,8 @@ class Idf:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self._add_construction(thermal_boundary)
|
||||
if thermal_boundary.vegetation is not None:
|
||||
self._add_vegetation_material(thermal_boundary.vegetation)
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
self._add_window_construction_and_material(thermal_opening)
|
||||
usage = thermal_zone.usage
|
||||
@ -357,7 +368,6 @@ class Idf:
|
||||
self._add_heating_system(thermal_zone)
|
||||
self._add_infiltration(thermal_zone)
|
||||
self._add_occupancy(thermal_zone)
|
||||
|
||||
if self._export_type == "Surfaces":
|
||||
self._add_surfaces(building)
|
||||
else:
|
||||
@ -406,10 +416,13 @@ class Idf:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for boundary in thermal_zone.thermal_boundaries:
|
||||
idf_surface_type = self.idf_surfaces[boundary.parent_surface.type]
|
||||
# todo: thermal boundary vs. surfaces??
|
||||
if boundary.vegetation is not None:
|
||||
construction_name = f'{boundary.construction_name}_{boundary.vegetation.name}'
|
||||
else:
|
||||
construction_name = boundary.construction_name
|
||||
surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.parent_surface.name}',
|
||||
Surface_Type=idf_surface_type, Zone_Name=thermal_zone.id,
|
||||
Construction_Name=boundary.construction_name)
|
||||
Construction_Name=construction_name)
|
||||
coordinates = self._matrix_to_list(boundary.parent_surface.solid_polygon.coordinates,
|
||||
self._city.lower_corner)
|
||||
surface.setcoords(coordinates)
|
||||
@ -436,28 +449,43 @@ class Idf:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _add_vegetation_material(self, vegetation_layer):
|
||||
def _add_vegetation_material(self, vegetation):
|
||||
for vegetation_material in self._idf.idfobjects[self._MATERIAL_ROOFVEGETATION]:
|
||||
if vegetation_material.Name == vegetation_layer.name:
|
||||
if vegetation_material.Name == vegetation.name:
|
||||
return
|
||||
soil = vegetation.soil
|
||||
height = 0
|
||||
leaf_area_index = 0
|
||||
leaf_reflectivity = 0
|
||||
leaf_emissivity = 0
|
||||
minimal_stomatal_resistance = 0
|
||||
for plant in vegetation.plants:
|
||||
height += plant.percentage * plant.height
|
||||
leaf_area_index += plant.percentage * plant.leaf_area_index
|
||||
leaf_reflectivity += plant.percentage * plant.leaf_reflectivity
|
||||
leaf_emissivity += plant.percentage * plant.leaf_emissivity
|
||||
minimal_stomatal_resistance += plant.percentage * plant.minimal_stomatal_resistance
|
||||
self._idf.newidfobject(self._MATERIAL_ROOFVEGETATION,
|
||||
Name='',
|
||||
Height_of_Plants='',
|
||||
Leaf_Area_Index='',
|
||||
Leaf_Reflectivity='',
|
||||
Leaf_Emissivity='',
|
||||
Minimum_Stomatal_Resistance='',
|
||||
Soil_Layer_Name='',
|
||||
Roughness=self._ROUGHNESS,
|
||||
Thickness='',
|
||||
Conductivity_of_Dry_Soil='',
|
||||
Density_of_Dry_Soil='',
|
||||
Specific_Heat_of_Dry_Soil='',
|
||||
Thermal_Absorptance='',
|
||||
Solar_Absorptance='',
|
||||
Visible_Absorptance='',
|
||||
Saturation_Volumetric_Moisture_Content_of_the_Soil_Layer='',
|
||||
Residual_Volumetric_Moisture_Content_of_the_Soil_Layer='',
|
||||
Initial_Volumetric_Moisture_Content_of_the_Soil_Layer='',
|
||||
Moisture_Diffusion_Calculation_Method=''
|
||||
Name=vegetation.name,
|
||||
Height_of_Plants=height,
|
||||
Leaf_Area_Index=leaf_area_index,
|
||||
Leaf_Reflectivity=leaf_reflectivity,
|
||||
Leaf_Emissivity=leaf_emissivity,
|
||||
Minimum_Stomatal_Resistance=minimal_stomatal_resistance,
|
||||
Soil_Layer_Name=soil.name,
|
||||
Roughness=soil.roughness,
|
||||
Thickness=vegetation.soil_thickness,
|
||||
Conductivity_of_Dry_Soil=soil.dry_conductivity,
|
||||
Density_of_Dry_Soil=soil.dry_density,
|
||||
Specific_Heat_of_Dry_Soil=soil.dry_specific_heat,
|
||||
Thermal_Absorptance=soil.thermal_absorptance,
|
||||
Solar_Absorptance=soil.solar_absorptance,
|
||||
Visible_Absorptance=soil.visible_absorptance,
|
||||
Saturation_Volumetric_Moisture_Content_of_the_Soil_Layer=
|
||||
soil.saturation_volumetric_moisture_content,
|
||||
Residual_Volumetric_Moisture_Content_of_the_Soil_Layer=
|
||||
soil.residual_volumetric_moisture_content,
|
||||
Initial_Volumetric_Moisture_Content_of_the_Soil_Layer=
|
||||
soil.initial_volumetric_moisture_content,
|
||||
Moisture_Diffusion_Calculation_Method=self._SIMPLE
|
||||
)
|
||||
|
103
unittests/test_greenery_in_idf.py
Normal file
103
unittests/test_greenery_in_idf.py
Normal file
@ -0,0 +1,103 @@
|
||||
"""
|
||||
Greenery in idf test
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
import csv
|
||||
import helpers.constants as cte
|
||||
from unittest import TestCase
|
||||
from imports.geometry_factory import GeometryFactory
|
||||
from imports.usage_factory import UsageFactory
|
||||
from imports.construction_factory import ConstructionFactory
|
||||
from exports.exports_factory import ExportsFactory
|
||||
from city_model_structure.greenery.vegetation import Vegetation
|
||||
from city_model_structure.greenery.soil import Soil
|
||||
from city_model_structure.greenery.plant import Plant
|
||||
|
||||
|
||||
class GreeneryInIdf(TestCase):
|
||||
"""
|
||||
GreeneryInIdf TestCase 1
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def test_greenery_in_idf():
|
||||
city_file = "../unittests/tests_data/one_building_in_kelowna.gml"
|
||||
output_path = Path('../unittests/tests_outputs/').resolve()
|
||||
|
||||
city = GeometryFactory('citygml', city_file).city
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
vegetation_name = 'BaseEco'
|
||||
soil_thickness = 0.18
|
||||
soil_name = 'EcoRoofSoil'
|
||||
roughness = 'MediumSmooth'
|
||||
dry_conductivity = 0.4
|
||||
dry_density = 641
|
||||
dry_specific_heat = 1100
|
||||
thermal_absorptance = 0.95
|
||||
solar_absorptance = 0.8
|
||||
visible_absorptance = 0.7
|
||||
saturation_volumetric_moisture_content = 0.4
|
||||
residual_volumetric_moisture_content = 0.01
|
||||
soil = Soil(soil_name, roughness, dry_conductivity, dry_density, dry_specific_heat, thermal_absorptance,
|
||||
solar_absorptance, visible_absorptance, saturation_volumetric_moisture_content,
|
||||
residual_volumetric_moisture_content)
|
||||
soil.initial_volumetric_moisture_content = 0.2
|
||||
plant_name = 'plant'
|
||||
height = 0.5
|
||||
leaf_area_index = 5
|
||||
leaf_reflectivity = 0.2
|
||||
leaf_emissivity = 0.95
|
||||
minimal_stomatal_resistance = 180
|
||||
co2_sequestration = 0
|
||||
grows_on_soils = [soil]
|
||||
plant = Plant(plant_name, height, leaf_area_index, leaf_reflectivity, leaf_emissivity, minimal_stomatal_resistance,
|
||||
co2_sequestration, grows_on_soils)
|
||||
plant.percentage = 1
|
||||
plants = [plant]
|
||||
vegetation = Vegetation(vegetation_name, soil, soil_thickness, plants)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
if thermal_boundary.type == cte.ROOF:
|
||||
thermal_boundary.vegetation = vegetation
|
||||
|
||||
_idf_2 = ExportsFactory('idf', city, output_path).export_debug()
|
||||
_idf_2.run()
|
||||
with open((output_path / f'{city.name}_out.csv').resolve()) as f:
|
||||
reader = csv.reader(f, delimiter=',')
|
||||
heating = 0
|
||||
cooling = 0
|
||||
for row in reader:
|
||||
if '00:00' in row[0]:
|
||||
heating += float(row[8]) / 3600000
|
||||
cooling += float(row[9]) / 3600000
|
||||
|
||||
print('With greenery')
|
||||
print(f'heating: {heating} MWh/yr, cooling: {cooling} MWh/yr')
|
||||
|
||||
city = GeometryFactory('citygml', city_file).city
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
_idf = ExportsFactory('idf', city, output_path).export()
|
||||
_idf.run()
|
||||
with open((output_path / f'{city.name}_out.csv').resolve()) as f:
|
||||
reader = csv.reader(f, delimiter=',')
|
||||
heating = 0
|
||||
cooling = 0
|
||||
for row in reader:
|
||||
if '00:00' in row[0]:
|
||||
heating += float(row[8]) / 3600000
|
||||
cooling += float(row[9]) / 3600000
|
||||
|
||||
print('Without greenery')
|
||||
print(f'heating: {heating} MWh/yr, cooling: {cooling} MWh/yr')
|
||||
|
Loading…
Reference in New Issue
Block a user