Merge branch 'internal_zones' into 'master'

complete modification of the structure of the classes that define the buildig...

See merge request Guille/libs!7
This commit is contained in:
Guillermo Gutierrez Morote 2022-03-24 22:52:50 +00:00
commit 91ddbb9341
87 changed files with 4139 additions and 3864 deletions

View File

@ -1,268 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="greenerycatalog" nsURI="http://ca.concordia/greenerycatalog"
nsPrefix="greenery">
<eClassifiers xsi:type="ecore:EClass" name="Soil">
<eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
<details key="constraints" value="nonNegative"/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral=""/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="roughness" eType="#//Roughness"
defaultValueLiteral="MediumRough">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="defines the relative roughness of a particular material layer. This parameter only influences the convection coefficients, more specifically the exterior convection coefficient. A nominal value is expected in with the options being &quot;VeryRough&quot;, &quot;Rough&quot;, &quot;MediumRough&quot;, &quot;MediumSmooth&quot;, &quot;Smooth&quot;, and &quot;VerySmooth&quot; in order of roughest to smoothest options."/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="conductivityOfDrySoil"
lowerBound="1" eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="1.0 W/(m*K)">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Thermal conductivity W/(m-K). Range: 0.2 to 1.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.2"/>
<details key="max" value="1.5"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="densityOfDrySoil" eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="1100 kg/m³">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Density in kg/m³. "/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.1"/>
<details key="max" value="10000"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="specificHeatOfDrySoil"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="1200 J/(kg*K)">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="in units of J/(kg-K). Range(300 to 2000)"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.2"/>
<details key="max" value="2000"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="thermalAbsorptance" eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.9">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="the fraction of incident long wavelength (>2.5 microns) radiation that is absorbed by the material. This parameter is used when calculating the long wavelength radiant exchange between various surfaces and affects the surface heat balances (both inside and outside as appropriate). For long wavelength radiant exchange, thermal emissivity and thermal emittance are equal to thermal absorptance. Range: 0 to 1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.0"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="solarAbsorptance" eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.7">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="the fraction of incident solar radiation that is absorbed by the material.&#xA;Solar radiation (0.3 to 2.537 microns) includes the visible spectrum as well as infrared and ultraviolet wavelengths. This parameter is used when calculating the amount of incident solar radiation absorbed by various surfaces and affects the surface heat balances (both inside and outside as appropriate). If solar reflectance (or reflectivity) data is available, then absorptance is equal to 1.0 minus reflectance (for opaque materials).&#xA;Range: 0 to 1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.0"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="visibleAbsorptance" eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.75">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="The visible absorptance field in the Material input syntax represents the fraction of incident visible wavelength radiation that is absorbed by the material.&#xA;Visible wavelength radiation (0.37 to 0.78 microns weighted by photopic response) is slightly different than solar radiation in that the visible band of wavelengths is much more narrow while solar radiation includes the visible spectrum as well as infrared and ultraviolet wavelengths.&#xA;This parameter is used when calculating the amount of incident visible radiation absorbed by various surfaces and affects the surface heat balances (both inside and outside as appropriate) as well as the daylighting calculations. If visible reflectance (or reflectivity) data is available, then absorptance is equal to 1.0 minus reflectance (for opaque materials).&#xA;Range: 0.5 to 1.0"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.5"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="saturationVolumetricMoistureContent"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.0">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="input of the saturation moisture content of the soil layer. Range: 0.1 to 0.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.1"/>
<details key="max" value="0.5"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="residualVolumetricMoistureContent"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.05">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Input of the residual moisture content of the soil layer. Range: 0.01 to 0.1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.01"/>
<details key="max" value="0.1"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="initialVolumetricMoistureContent"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.1">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Range: 0.05 to 0.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.05"/>
<details key="max" value="0.5"/>
</eAnnotations>
</eStructuralFeatures>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Plant">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="height" lowerBound="1"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.1 m">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Maximum height of plants. Range: 0.005 to 1 m"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.005"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="leafAreaIndex" lowerBound="1"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="2.5">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Leaf area per unit area of soil surface. Range: 0.001 to 5.0 m²/m²"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.001"/>
<details key="max" value="5.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="leafReflectivity" lowerBound="1"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.1">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Represents the fraction of incident solar radiation that is reflected by the individual leaf surfaces (albedo).&#xA;Range: 0.05 to 0.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.05"/>
<details key="max" value="0.5"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="leafEmissivity" lowerBound="1"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.9">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Ratio of thermal radiation emitted from leaf surfaces to that emitted by an ideal black body at the same temperature.&#xA;This parameter is used when calculating the long wavelength radiant exchange at the leaf surfaces.&#xA;Range: 0.8 to 1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.8"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="minimalStomatalResistance"
lowerBound="1" eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="100.0 s/m">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Resistance of the plants to moisture transport.&#xA;Plants with low values of stomatal resistance will result in higher evapotranspiration rates than plants with high resistance.&#xA;Range: 50 to 300 m/s"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="50.0"/>
<details key="max" value="300.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EReference" name="growsOn" lowerBound="1"
upperBound="-1" eType="#//Soil"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="co2Sequestration" eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="kgCO₂eq"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="SupportEnvelope">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="roughness" eType="#//Roughness"
defaultValueLiteral="MediumRough"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="solarAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="conductivity" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="visibleAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="specificHeat" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="density" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="thermalAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="GreeneryCatalog">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="description" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="source" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="plantCategories" lowerBound="1"
upperBound="-1" eType="#//PlantCategory" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="vegetationCategories" lowerBound="1"
upperBound="-1" eType="#//VegetationCategory" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="soils" upperBound="-1"
eType="#//Soil" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="PlantCategory">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Excluding (that is non-overlapping) categories like Trees, Hedeges, Grasses that help users finding a specific biol. plant species."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="plants" upperBound="-1"
eType="#//Plant" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="IrrigationSchedule">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Vegetation">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Plant life or total plant cover (as of an area)"/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="thicknessOfSoil" lowerBound="1"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="20 cm">
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0"/>
<details key="max" value="1000"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EReference" name="soil" lowerBound="1" eType="#//Soil"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="plants" lowerBound="1"
upperBound="-1" eType="#//PlantPercentage" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="management" lowerBound="1"
eType="#//Management" defaultValueLiteral="NA"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="airGap" lowerBound="1"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="0.0 cm"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="VegetationCategory">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Excluding (that is non-overlapping) categories to help users finding a specific vegetation template."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EReference" name="vegetationTemplates" upperBound="-1"
eType="#//Vegetation" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EEnum" name="Management">
<eLiterals name="Intensive"/>
<eLiterals name="Extensive" value="1"/>
<eLiterals name="SemiIntensive" value="2"/>
<eLiterals name="NA" value="3"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="PlantPercentage">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="percentage" lowerBound="1"
eType="ecore:EDataType platform:/plugin/de.hftstuttgart.cityunits.model/model/Quantities.ecore#//Quantity"
defaultValueLiteral="100">
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0"/>
<details key="max" value="100"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EReference" name="plant" lowerBound="1" eType="#//Plant"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EEnum" name="Roughness">
<eLiterals name="VeryRough"/>
<eLiterals name="Rough" value="1"/>
<eLiterals name="MediumRough" value="2"/>
<eLiterals name="MediumSmooth" value="3"/>
<eLiterals name="Smooth" value="4"/>
<eLiterals name="VerySmooth" value="5"/>
</eClassifiers>
</ecore:EPackage>

View File

@ -1,318 +0,0 @@
"""Definition of meta model 'greenerycatalog'."""
from functools import partial
import pyecore.ecore as Ecore
from pyecore.ecore import *
name = 'greenerycatalog'
nsURI = 'http://ca.concordia/greenerycatalog'
nsPrefix = 'greenery'
eClass = EPackage(name=name, nsURI=nsURI, nsPrefix=nsPrefix)
eClassifiers = {}
getEClassifier = partial(Ecore.getEClassifier, searchspace=eClassifiers)
Management = EEnum('Management', literals=['Intensive', 'Extensive', 'SemiIntensive', 'NA'])
Roughness = EEnum('Roughness', literals=['VeryRough', 'Rough',
'MediumRough', 'MediumSmooth', 'Smooth', 'VerySmooth'])
class Soil(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
roughness = EAttribute(eType=Roughness, unique=True, derived=False,
changeable=True, default_value=Roughness.MediumRough)
conductivityOfDrySoil = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='1.0 W/(m*K)')
densityOfDrySoil = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='1100 kg/m³')
specificHeatOfDrySoil = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='1200 J/(kg*K)')
thermalAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.9')
solarAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.7')
visibleAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.75')
saturationVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.0')
residualVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.05')
initialVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.1')
def __init__(self, *, name=None, roughness=None, conductivityOfDrySoil=None, densityOfDrySoil=None, specificHeatOfDrySoil=None, thermalAbsorptance=None, solarAbsorptance=None, visibleAbsorptance=None, saturationVolumetricMoistureContent=None, residualVolumetricMoistureContent=None, initialVolumetricMoistureContent=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if name is not None:
self.name = name
if roughness is not None:
self.roughness = roughness
if conductivityOfDrySoil is not None:
self.conductivityOfDrySoil = conductivityOfDrySoil
if densityOfDrySoil is not None:
self.densityOfDrySoil = densityOfDrySoil
if specificHeatOfDrySoil is not None:
self.specificHeatOfDrySoil = specificHeatOfDrySoil
if thermalAbsorptance is not None:
self.thermalAbsorptance = thermalAbsorptance
if solarAbsorptance is not None:
self.solarAbsorptance = solarAbsorptance
if visibleAbsorptance is not None:
self.visibleAbsorptance = visibleAbsorptance
if saturationVolumetricMoistureContent is not None:
self.saturationVolumetricMoistureContent = saturationVolumetricMoistureContent
if residualVolumetricMoistureContent is not None:
self.residualVolumetricMoistureContent = residualVolumetricMoistureContent
if initialVolumetricMoistureContent is not None:
self.initialVolumetricMoistureContent = initialVolumetricMoistureContent
class Plant(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
height = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.1 m')
leafAreaIndex = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='2.5')
leafReflectivity = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.1')
leafEmissivity = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.9')
minimalStomatalResistance = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='100.0 s/m')
co2Sequestration = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='kgCO₂eq')
growsOn = EReference(ordered=True, unique=True, containment=False, derived=False, upper=-1)
def __init__(self, *, name=None, height=None, leafAreaIndex=None, leafReflectivity=None, leafEmissivity=None, minimalStomatalResistance=None, growsOn=None, co2Sequestration=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if name is not None:
self.name = name
if height is not None:
self.height = height
if leafAreaIndex is not None:
self.leafAreaIndex = leafAreaIndex
if leafReflectivity is not None:
self.leafReflectivity = leafReflectivity
if leafEmissivity is not None:
self.leafEmissivity = leafEmissivity
if minimalStomatalResistance is not None:
self.minimalStomatalResistance = minimalStomatalResistance
if co2Sequestration is not None:
self.co2Sequestration = co2Sequestration
if growsOn:
self.growsOn.extend(growsOn)
class SupportEnvelope(EObject, metaclass=MetaEClass):
roughness = EAttribute(eType=Roughness, unique=True, derived=False,
changeable=True, default_value=Roughness.MediumRough)
solarAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
conductivity = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
visibleAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
specificHeat = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
density = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
thermalAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
def __init__(self, *, roughness=None, solarAbsorptance=None, conductivity=None, visibleAbsorptance=None, specificHeat=None, density=None, thermalAbsorptance=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if roughness is not None:
self.roughness = roughness
if solarAbsorptance is not None:
self.solarAbsorptance = solarAbsorptance
if conductivity is not None:
self.conductivity = conductivity
if visibleAbsorptance is not None:
self.visibleAbsorptance = visibleAbsorptance
if specificHeat is not None:
self.specificHeat = specificHeat
if density is not None:
self.density = density
if thermalAbsorptance is not None:
self.thermalAbsorptance = thermalAbsorptance
class GreeneryCatalog(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
description = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
source = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
plantCategories = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
vegetationCategories = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
soils = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
def __init__(self, *, name=None, description=None, source=None, plantCategories=None, vegetationCategories=None, soils=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if name is not None:
self.name = name
if description is not None:
self.description = description
if source is not None:
self.source = source
if plantCategories:
self.plantCategories.extend(plantCategories)
if vegetationCategories:
self.vegetationCategories.extend(vegetationCategories)
if soils:
self.soils.extend(soils)
class PlantCategory(EObject, metaclass=MetaEClass):
"""Excluding (that is non-overlapping) categories like Trees, Hedeges, Grasses that help users finding a specific biol. plant species."""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
def __init__(self, *, name=None, plants=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if name is not None:
self.name = name
if plants:
self.plants.extend(plants)
class IrrigationSchedule(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
def __init__(self, *, name=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if name is not None:
self.name = name
class Vegetation(EObject, metaclass=MetaEClass):
"""Plant life or total plant cover (as of an area)"""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
thicknessOfSoil = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='20 cm')
management = EAttribute(eType=Management, unique=True, derived=False,
changeable=True, default_value=Management.NA)
airGap = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.0 cm')
soil = EReference(ordered=True, unique=True, containment=False, derived=False)
plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
def __init__(self, *, name=None, thicknessOfSoil=None, soil=None, plants=None, management=None, airGap=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if name is not None:
self.name = name
if thicknessOfSoil is not None:
self.thicknessOfSoil = thicknessOfSoil
if management is not None:
self.management = management
if airGap is not None:
self.airGap = airGap
if soil is not None:
self.soil = soil
if plants:
self.plants.extend(plants)
class VegetationCategory(EObject, metaclass=MetaEClass):
"""Excluding (that is non-overlapping) categories to help users finding a specific vegetation template."""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
vegetationTemplates = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
def __init__(self, *, vegetationTemplates=None, name=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if name is not None:
self.name = name
if vegetationTemplates:
self.vegetationTemplates.extend(vegetationTemplates)
class PlantPercentage(EObject, metaclass=MetaEClass):
percentage = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='100')
plant = EReference(ordered=True, unique=True, containment=False, derived=False)
def __init__(self, *, percentage=None, plant=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
if percentage is not None:
self.percentage = percentage
if plant is not None:
self.plant = plant

View File

@ -1,268 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="greenerycatalog" nsURI="http://ca.concordia/greenerycatalog"
nsPrefix="greenery">
<eClassifiers xsi:type="ecore:EClass" name="Soil">
<eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
<details key="constraints" value="nonNegative"/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral=""/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="roughness" eType="#//Roughness"
defaultValueLiteral="MediumRough">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="defines the relative roughness of a particular material layer. This parameter only influences the convection coefficients, more specifically the exterior convection coefficient. A nominal value is expected in with the options being &quot;VeryRough&quot;, &quot;Rough&quot;, &quot;MediumRough&quot;, &quot;MediumSmooth&quot;, &quot;Smooth&quot;, and &quot;VerySmooth&quot; in order of roughest to smoothest options."/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="conductivityOfDrySoil"
lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="1.0 W/(m*K)">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Thermal conductivity W/(m-K). Range: 0.2 to 1.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.2"/>
<details key="max" value="1.5"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="densityOfDrySoil" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="1100 kg/m³">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Density in kg/m³. "/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.1"/>
<details key="max" value="10000"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="specificHeatOfDrySoil"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="1200 J/(kg*K)">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="in units of J/(kg-K). Range(300 to 2000)"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.2"/>
<details key="max" value="2000"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="thermalAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.9">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="the fraction of incident long wavelength (>2.5 microns) radiation that is absorbed by the material. This parameter is used when calculating the long wavelength radiant exchange between various surfaces and affects the surface heat balances (both inside and outside as appropriate). For long wavelength radiant exchange, thermal emissivity and thermal emittance are equal to thermal absorptance. Range: 0 to 1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.0"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="solarAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.7">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="the fraction of incident solar radiation that is absorbed by the material.&#xA;Solar radiation (0.3 to 2.537 microns) includes the visible spectrum as well as infrared and ultraviolet wavelengths. This parameter is used when calculating the amount of incident solar radiation absorbed by various surfaces and affects the surface heat balances (both inside and outside as appropriate). If solar reflectance (or reflectivity) data is available, then absorptance is equal to 1.0 minus reflectance (for opaque materials).&#xA;Range: 0 to 1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.0"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="visibleAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.75">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="The visible absorptance field in the Material input syntax represents the fraction of incident visible wavelength radiation that is absorbed by the material.&#xA;Visible wavelength radiation (0.37 to 0.78 microns weighted by photopic response) is slightly different than solar radiation in that the visible band of wavelengths is much more narrow while solar radiation includes the visible spectrum as well as infrared and ultraviolet wavelengths.&#xA;This parameter is used when calculating the amount of incident visible radiation absorbed by various surfaces and affects the surface heat balances (both inside and outside as appropriate) as well as the daylighting calculations. If visible reflectance (or reflectivity) data is available, then absorptance is equal to 1.0 minus reflectance (for opaque materials).&#xA;Range: 0.5 to 1.0"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.5"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="saturationVolumetricMoistureContent"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.0">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="input of the saturation moisture content of the soil layer. Range: 0.1 to 0.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.1"/>
<details key="max" value="0.5"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="residualVolumetricMoistureContent"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.05">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Input of the residual moisture content of the soil layer. Range: 0.01 to 0.1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.01"/>
<details key="max" value="0.1"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="initialVolumetricMoistureContent"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.1">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Range: 0.05 to 0.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.05"/>
<details key="max" value="0.5"/>
</eAnnotations>
</eStructuralFeatures>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Plant">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="height" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.1 m">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Maximum height of plants. Range: 0.005 to 1 m"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.005"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="leafAreaIndex" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="2.5">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Leaf area per unit area of soil surface. Range: 0.001 to 5.0 m²/m²"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.001"/>
<details key="max" value="5.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="leafReflectivity" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.1">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Represents the fraction of incident solar radiation that is reflected by the individual leaf surfaces (albedo).&#xA;Range: 0.05 to 0.5"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.05"/>
<details key="max" value="0.5"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="leafEmissivity" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.9">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Ratio of thermal radiation emitted from leaf surfaces to that emitted by an ideal black body at the same temperature.&#xA;This parameter is used when calculating the long wavelength radiant exchange at the leaf surfaces.&#xA;Range: 0.8 to 1"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0.8"/>
<details key="max" value="1.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="minimalStomatalResistance"
lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="100.0 s/m">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Resistance of the plants to moisture transport.&#xA;Plants with low values of stomatal resistance will result in higher evapotranspiration rates than plants with high resistance.&#xA;Range: 50 to 300 m/s"/>
</eAnnotations>
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="50.0"/>
<details key="max" value="300.0"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EReference" name="growsOn" lowerBound="1"
upperBound="-1" eType="#//Soil"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="co2Sequestration" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="kgCO₂eq"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="SupportEnvelope">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="roughness" eType="#//Roughness"
defaultValueLiteral="MediumRough"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="solarAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="conductivity" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="visibleAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="specificHeat" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="density" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="thermalAbsorptance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
defaultValueLiteral="0.0"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="GreeneryCatalog">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="description" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="source" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="plantCategories" lowerBound="1"
upperBound="-1" eType="#//PlantCategory" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="vegetationCategories" lowerBound="1"
upperBound="-1" eType="#//VegetationCategory" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="soils" upperBound="-1"
eType="#//Soil" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="PlantCategory">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Excluding (that is non-overlapping) categories like Trees, Hedeges, Grasses that help users finding a specific biol. plant species."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="plants" upperBound="-1"
eType="#//Plant" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="IrrigationSchedule">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Vegetation">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Plant life or total plant cover (as of an area)"/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="thicknessOfSoil" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="20 cm">
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0"/>
<details key="max" value="1000"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EReference" name="soil" lowerBound="1" eType="#//Soil"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="plants" lowerBound="1"
upperBound="-1" eType="#//PlantPercentage" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="management" lowerBound="1"
eType="#//Management" defaultValueLiteral="NA"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="airGap" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="0.0 cm"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="VegetationCategory">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Excluding (that is non-overlapping) categories to help users finding a specific vegetation template."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EReference" name="vegetationTemplates" upperBound="-1"
eType="#//Vegetation" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EEnum" name="Management">
<eLiterals name="Intensive"/>
<eLiterals name="Extensive" value="1"/>
<eLiterals name="SemiIntensive" value="2"/>
<eLiterals name="NA" value="3"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="PlantPercentage">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="percentage" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="100">
<eAnnotations source="http://www.hft-stuttgart.de/UomQuantities">
<details key="min" value="0"/>
<details key="max" value="100"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EReference" name="plant" lowerBound="1" eType="#//Plant"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EEnum" name="Roughness">
<eLiterals name="VeryRough"/>
<eLiterals name="Rough" value="1"/>
<eLiterals name="MediumRough" value="2"/>
<eLiterals name="MediumSmooth" value="3"/>
<eLiterals name="Smooth" value="4"/>
<eLiterals name="VerySmooth" value="5"/>
</eClassifiers>
</ecore:EPackage>

View File

@ -16,6 +16,7 @@ from city_model_structure.attributes.plane import Plane
from city_model_structure.attributes.point import Point from city_model_structure.attributes.point import Point
import helpers.constants as cte import helpers.constants as cte
class Polygon: class Polygon:
""" """
Polygon class Polygon class
@ -78,6 +79,48 @@ class Polygon:
z = vector_0[2] * vector_1[2] z = vector_0[2] * vector_1[2]
return x+y+z return x+y+z
def contains_point(self, point):
"""
Determines if the given point is contained by the current polygon
:return: boolean
"""
# fixme: This method doesn't seems to work.
n = len(self.vertices)
angle_sum = 0
for i in range(0, n):
vector_0 = self.vertices[i]
vector_1 = self.vertices[(i+1) % n]
# set to origin
vector_0[0] = vector_0[0] - point.coordinates[0]
vector_0[1] = vector_0[1] - point.coordinates[1]
vector_0[2] = vector_0[2] - point.coordinates[2]
vector_1[0] = vector_1[0] - point.coordinates[0]
vector_1[1] = vector_1[1] - point.coordinates[1]
vector_1[2] = vector_1[2] - point.coordinates[2]
module = Polygon._module(vector_0) * Polygon._module(vector_1)
scalar_product = Polygon._scalar_product(vector_0, vector_1)
angle = np.pi/2
if module != 0:
angle = abs(np.arcsin(scalar_product / module))
angle_sum += angle
print(angle_sum)
return abs(angle_sum - math.pi*2) < cte.EPSILON
def contains_polygon(self, polygon):
"""
Determines if the given polygon is contained by the current polygon
:return: boolean
"""
print('contains')
for point in polygon.points:
print(point.coordinates, self.contains_point(point))
if not self.contains_point(point):
return False
print('Belong!')
return True
@property @property
def points_list(self) -> np.ndarray: def points_list(self) -> np.ndarray:
""" """
@ -249,7 +292,7 @@ class Polygon:
points_list = self.points_list points_list = self.points_list
normal = self.normal normal = self.normal
if np.linalg.norm(normal) == 0: if np.linalg.norm(normal) == 0:
sys.stderr.write(f'Not able to triangulate polygon [normal length is 0]') sys.stderr.write('Not able to triangulate polygon\n')
return [self] return [self]
# are points concave or convex? # are points concave or convex?
total_points_list, concave_points, convex_points = self._starting_lists(points_list, normal) total_points_list, concave_points, convex_points = self._starting_lists(points_list, normal)
@ -297,10 +340,10 @@ class Polygon:
continue continue
break break
if len(total_points_list) <= 3 and len(convex_points) > 0: if len(total_points_list) <= 3 and len(convex_points) > 0:
sys.stderr.write('Not able to triangulate polygon [convex surface]\n') sys.stderr.write('Not able to triangulate polygon\n')
return [self] return [self]
if j >= 100: if j >= 100:
sys.stderr.write('Not able to triangulate polygon [infinite loop]\n') sys.stderr.write('Not able to triangulate polygon\n')
return [self] return [self]
last_ear = self._triangle(points_list, total_points_list, concave_points[1]) last_ear = self._triangle(points_list, total_points_list, concave_points[1])
ears.append(last_ear) ears.append(last_ear)

View File

@ -114,7 +114,7 @@ class Polyhedron:
if self._trimesh is None: if self._trimesh is None:
for face in self.faces: for face in self.faces:
if len(face) != 3: if len(face) != 3:
sys.stderr.write(f'Not able to generate trimesh the face has {len(face)} vertices\n') sys.stderr.write('Not able to generate trimesh\n')
return None return None
self._trimesh = Trimesh(vertices=self.vertices, faces=self.faces) self._trimesh = Trimesh(vertices=self.vertices, faces=self.faces)
return self._trimesh return self._trimesh

View File

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

View File

@ -8,12 +8,9 @@ contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
from typing import List, Union from typing import List, Union
import numpy as np import numpy as np
from city_model_structure.building_demand.surface import Surface from city_model_structure.building_demand.surface import Surface
from city_model_structure.building_demand.thermal_zone import ThermalZone
from city_model_structure.building_demand.thermal_boundary import ThermalBoundary
from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.building_demand.storey import Storey
from city_model_structure.city_object import CityObject from city_model_structure.city_object import CityObject
from city_model_structure.building_demand.household import Household from city_model_structure.building_demand.household import Household
from city_model_structure.building_demand.internal_zone import InternalZone
from city_model_structure.attributes.polyhedron import Polyhedron from city_model_structure.attributes.polyhedron import Polyhedron
@ -34,10 +31,8 @@ class Building(CityObject):
self._floor_area = None self._floor_area = None
self._roof_type = None self._roof_type = None
self._storeys = None self._storeys = None
self._geometrical_zones = None self._internal_zones = None
self._thermal_zones = [] self._shell = None
self._thermal_boundaries = None
self._usage_zones = []
self._type = 'building' self._type = 'building'
self._heating = dict() self._heating = dict()
self._cooling = dict() self._cooling = dict()
@ -62,13 +57,26 @@ class Building(CityObject):
self._internal_walls.append(surface) self._internal_walls.append(surface)
@property @property
def geometrical_zones(self) -> List[Polyhedron]: def shell(self) -> Polyhedron:
if self._geometrical_zones is None: """
polygons = [] Get building shell
for surface in self.surfaces: :return: [Polyhedron]
polygons.append(surface.perimeter_polygon) """
self._geometrical_zones = [Polyhedron(polygons)] if self._shell is None:
return self._geometrical_zones self._shell = Polyhedron(self.surfaces)
return self._shell
@property
def internal_zones(self) -> List[InternalZone]:
"""
Get building internal zones
For Lod up to 3, there is only one internal zone which corresponds to the building shell.
In LoD 4 there can be more than one. In this case the definition of surfaces and floor area must be redefined.
:return: [InternalZone]
"""
if self._internal_zones is None:
self._internal_zones = [InternalZone(self.surfaces, self.floor_area)]
return self._internal_zones
@property @property
def grounds(self) -> List[Surface]: def grounds(self) -> List[Surface]:
@ -78,28 +86,6 @@ class Building(CityObject):
""" """
return self._grounds return self._grounds
@property
def is_heated(self):
"""
Get building heated flag
:return: Boolean
"""
for usage_zone in self.usage_zones:
if usage_zone.is_heated:
return usage_zone.is_heated
return False
@property
def is_cooled(self):
"""
Get building cooled flag
:return: Boolean
"""
for usage_zone in self.usage_zones:
if usage_zone.is_cooled:
return usage_zone.is_cooled
return False
@property @property
def roofs(self) -> List[Surface]: def roofs(self) -> List[Surface]:
""" """
@ -117,18 +103,7 @@ class Building(CityObject):
return self._walls return self._walls
@property @property
def usage_zones(self) -> List[UsageZone]: def terrains(self) -> Union[None, List[Surface]]:
"""
Get city object usage zones
:return: [UsageZone]
"""
if len(self._usage_zones) == 0:
for thermal_zone in self.thermal_zones:
self._usage_zones.extend(thermal_zone.usage_zones)
return self._usage_zones
@property
def terrains(self) -> List[Surface]:
""" """
Get city object terrain surfaces Get city object terrain surfaces
:return: [Surface] :return: [Surface]
@ -169,27 +144,6 @@ class Building(CityObject):
if value is not None: if value is not None:
self._basement_heated = int(value) self._basement_heated = int(value)
@property
def name(self):
"""
Get building name
:return: str
"""
return self._name
@property
def thermal_zones(self) -> List[ThermalZone]:
"""
Get building thermal zones
:return: [ThermalZone]
"""
if len(self._thermal_zones) == 0:
if self.storeys is None:
return []
for storey in self.storeys:
self._thermal_zones.append(storey.thermal_zone)
return self._thermal_zones
@property @property
def heated_volume(self): def heated_volume(self):
""" """
@ -213,7 +167,7 @@ class Building(CityObject):
:param value: int :param value: int
""" """
if value is not None: if value is not None:
self._year_of_construction = value self._year_of_construction = int(value)
@property @property
def function(self) -> Union[None, str]: def function(self) -> Union[None, str]:
@ -310,22 +264,6 @@ class Building(CityObject):
self._eave_height = max(self._eave_height, wall.upper_corner[2]) self._eave_height = max(self._eave_height, wall.upper_corner[2])
return self._eave_height 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 @property
def roof_type(self): def roof_type(self):
""" """
@ -341,6 +279,14 @@ class Building(CityObject):
break break
return self._roof_type return self._roof_type
@roof_type.setter
def roof_type(self, value):
"""
Set roof type for the building flat or pitch
:return: str
"""
self._roof_type = value
@property @property
def floor_area(self): def floor_area(self):
""" """
@ -354,24 +300,6 @@ class Building(CityObject):
self._floor_area += surface.perimeter_polygon.area self._floor_area += surface.perimeter_polygon.area
return self._floor_area return self._floor_area
@property
def thermal_boundaries(self) -> List[ThermalBoundary]:
"""
Get all thermal boundaries associated to the building's thermal zones
:return: [ThermalBoundary]
"""
if self._thermal_boundaries is None:
self._thermal_boundaries = []
for thermal_zone in self.thermal_zones:
_thermal_boundary_duplicated = False
for thermal_boundary in thermal_zone.thermal_boundaries:
if len(thermal_boundary.thermal_zones) > 1:
if thermal_zone != thermal_boundary.thermal_zones[1]:
self._thermal_boundaries.append(thermal_boundary)
else:
self._thermal_boundaries.append(thermal_boundary)
return self._thermal_boundaries
@property @property
def households(self) -> List[Household]: def households(self) -> List[Household]:
""" """
@ -379,3 +307,18 @@ class Building(CityObject):
:return: List[Household] :return: List[Household]
""" """
return self._households return self._households
@property
def is_conditioned(self):
"""
Get building heated flag
:return: Boolean
"""
if self.internal_zones is None:
return False
for internal_zone in self.internal_zones:
if internal_zone.usage_zones is not None:
for usage_zone in internal_zone.usage_zones:
if usage_zone.thermal_control is not None:
return True
return False

View File

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

View File

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

View File

@ -0,0 +1,123 @@
"""
InternalZone module. It saves the original geometrical information from interiors together with some attributes of those
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import uuid
from typing import Union, List
from city_model_structure.building_demand.usage_zone import UsageZone
from city_model_structure.building_demand.thermal_zone import ThermalZone
from city_model_structure.attributes.polyhedron import Polyhedron
from city_model_structure.energy_systems.hvac_system import HvacSystem
class InternalZone:
"""
InternalZone class
"""
def __init__(self, surfaces, area):
self._surfaces = surfaces
self._id = None
self._geometry = None
self._volume = None
self._area = area
self._thermal_zones = None
self._usage_zones = None
self._hvac_system = None
@property
def id(self):
"""
Get internal zone id, an universally unique identifier randomly generated
:return: str
"""
if self._id is None:
self._id = uuid.uuid4()
return self._id
@property
def geometry(self) -> Polyhedron:
"""
Get internal zone geometry
:return: Polyhedron
"""
if self._geometry is None:
polygons = []
for surface in self.surfaces:
polygons.append(surface.perimeter_polygon)
self._geometry = Polyhedron(polygons)
return self._geometry
@property
def surfaces(self):
"""
Get internal zone surfaces
:return: [Surface]
"""
return self._surfaces
@property
def volume(self):
"""
Get internal zone volume in cubic meters
:return: float
"""
return self.geometry.volume
@property
def area(self):
"""
Get internal zone area in square meters
:return: float
"""
return self._area
@property
def usage_zones(self) -> [UsageZone]:
"""
Get internal zone usage zones
:return: [UsageZone]
"""
return self._usage_zones
@usage_zones.setter
def usage_zones(self, value):
"""
Set internal zone usage zones
:param value: [UsageZone]
"""
self._usage_zones = value
@property
def hvac_system(self) -> Union[None, HvacSystem]:
"""
Get HVAC system installed for this thermal zone
:return: None or HvacSystem
"""
return self._hvac_system
@hvac_system.setter
def hvac_system(self, value):
"""
Set HVAC system installed for this thermal zone
:param value: HvacSystem
"""
self._hvac_system = value
@property
def thermal_zones(self) -> Union[None, List[ThermalZone]]:
"""
Get building thermal zones
:return: [ThermalZone]
"""
return self._thermal_zones
@thermal_zones.setter
def thermal_zones(self, value):
"""
Set city object thermal zones
:param value: [ThermalZone]
"""
self._thermal_zones = value

View File

@ -0,0 +1,103 @@
"""
Lighting module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union, List
from city_model_structure.attributes.schedule import Schedule
class Lighting:
"""
Lighting class
"""
def __init__(self):
self._lighting_density = None
self._convective_fraction = None
self._radiative_fraction = None
self._latent_fraction = None
self._schedules = None
@property
def lighting_density(self) -> Union[None, float]:
"""
Get lighting density in Watts per m2
:return: None or float
"""
return self._lighting_density
@lighting_density.setter
def lighting_density(self, value):
"""
Set lighting density in Watts per m2
:param value: float
"""
if value is not None:
self._lighting_density = float(value)
@property
def convective_fraction(self) -> Union[None, float]:
"""
Get convective fraction
:return: None or float
"""
return self._convective_fraction
@convective_fraction.setter
def convective_fraction(self, value):
"""
Set convective fraction
:param value: float
"""
if value is not None:
self._convective_fraction = float(value)
@property
def radiative_fraction(self) -> Union[None, float]:
"""
Get radiant fraction
:return: None or float
"""
return self._radiative_fraction
@radiative_fraction.setter
def radiative_fraction(self, value):
"""
Set radiant fraction
:param value: float
"""
if value is not None:
self._radiative_fraction = float(value)
@property
def latent_fraction(self) -> Union[None, float]:
"""
Get latent fraction
:return: None or float
"""
return self._latent_fraction
@latent_fraction.setter
def latent_fraction(self, value):
"""
Set latent fraction
:param value: float
"""
if value is not None:
self._latent_fraction = float(value)
@property
def schedules(self) -> Union[None, List[Schedule]]:
"""
Get schedules
:return: None or [Schedule]
"""
return self._schedules
@schedules.setter
def schedules(self, value):
"""
Set schedules
:param value: [Schedule]
"""
self._schedules = value

View File

@ -6,6 +6,7 @@ Contributor Atiya atiya.atiya@mail.concordia.ca
Contributor Mohammad Reza mohammad.seyedabadi@mail.concordia.ca Contributor Mohammad Reza mohammad.seyedabadi@mail.concordia.ca
""" """
import ast
from typing import Union from typing import Union
@ -14,6 +15,7 @@ class Material:
Material class Material class
""" """
def __init__(self): def __init__(self):
self._type = type
self._id = None self._id = None
self._name = None self._name = None
self._conductivity = None self._conductivity = None
@ -25,7 +27,30 @@ class Material:
self._visible_absorptance = None self._visible_absorptance = None
self._no_mass = False self._no_mass = False
self._thermal_resistance = None self._thermal_resistance = None
self._lca_id = None self._embodied_carbon = None
self._embodied_carbon_unit = None
self._recycling_ratio = None
self._onsite_recycling_ratio = None
self._company_recycling_ratio = None
self._landfilling_ratio = None
self._cost = None
self._cost_unit = None
@property
def type(self):
"""
Get material type
:return: str
"""
return self._type
@type.setter
def type(self, value):
"""
Set material type
:param value: string
"""
self._type = str(value)
@property @property
def id(self): def id(self):
@ -213,10 +238,137 @@ class Material:
self._thermal_resistance = float(value) self._thermal_resistance = float(value)
@property @property
def lca_id(self): def embodied_carbon(self) -> Union[None, float]:
return self._lca_id """
Get material embodied carbon
:return: None or float
"""
return self._embodied_carbon
@lca_id.setter @embodied_carbon.setter
def lca_id(self, value): def embodied_carbon(self, value):
self._lca_id = value """
Set material embodied carbon
:param value: float
"""
if value is not None:
self._embodied_carbon = float(value)
@property
def embodied_carbon_unit(self) -> Union[None, str]:
"""
Get material embodied carbon unit
:return: None or string
"""
return self._embodied_carbon
@embodied_carbon_unit.setter
def embodied_carbon_unit(self, value):
"""
Set material embodied carbon unit
:param value: string
"""
if value is not None:
self._embodied_carbon_unit = str(value)
@property
def recycling_ratio(self) -> Union[None, float]:
"""
Get material recycling ratio
:return: None or float
"""
return self._recycling_ratio
@recycling_ratio.setter
def recycling_ratio(self, value):
"""
Set material recycling ratio
:param value: float
"""
if value is not None:
self._recycling_ratio = float(value)
@property
def onsite_recycling_ratio(self) -> Union[None, float]:
"""
Get material onsite recycling ratio
:return: None or float
"""
return self._onsite_recycling_ratio
@onsite_recycling_ratio.setter
def onsite_recycling_ratio(self, value):
"""
Set material onsite recycling ratio
:param value: float
"""
if value is not None:
self._onsite_recycling_ratio = float(value)
@property
def company_recycling_ratio(self) -> Union[None, float]:
"""
Get material company recycling ratio
:return: None or float
"""
return self._company_recycling_ratio
@company_recycling_ratio.setter
def company_recycling_ratio(self, value):
"""
Set material company recycling ratio
:param value: float
"""
if value is not None:
self._company_recycling_ratio = float(value)
@property
def landfilling_ratio(self) -> Union[None, float]:
"""
Get material landfilling ratio
:return: None or float
"""
return self._landfilling_ratio
@landfilling_ratio.setter
def landfilling_ratio(self, value):
"""
Set material landfilling ratio
:param value: float
"""
if value is not None:
self._landfilling_ratio = float(value)
@property
def cost(self) -> Union[None, float]:
"""
Get material cost
:return: None or float
"""
return self._cost
@cost.setter
def cost(self, value):
"""
Set material cost
:param value: float
"""
if value is not None:
self._cost = float(value)
@property
def cost_unit(self) -> Union[None, str]:
"""
Get material cost unit
:return: None or string
"""
return self._cost_unit
@cost_unit.setter
def cost_unit(self, value):
"""
Set material cost unit
:param value: string
"""
if value is not None:
self._cost_unit = float(value)

View File

@ -0,0 +1,121 @@
"""
Occupancy module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union, List
from city_model_structure.attributes.schedule import Schedule
from city_model_structure.building_demand.occupant import Occupant
class Occupancy:
"""
Occupancy class
"""
def __init__(self):
self._occupancy_density = None
self._sensible_convective_internal_gain = None
self._sensible_radiative_internal_gain = None
self._latent_internal_gain = None
self._occupancy_schedules = None
self._occupants = None
@property
def occupancy_density(self) -> Union[None, float]:
"""
Get density in m2 per person
:return: None or float
"""
return self._occupancy_density
@occupancy_density.setter
def occupancy_density(self, value):
"""
Set density in m2 per persons
:param value: float
"""
if value is not None:
self._occupancy_density = float(value)
@property
def sensible_convective_internal_gain(self) -> Union[None, float]:
"""
Get sensible convective internal gain in Watts per m2
:return: None or float
"""
return self._sensible_convective_internal_gain
@sensible_convective_internal_gain.setter
def sensible_convective_internal_gain(self, value):
"""
Set sensible convective internal gain in Watts per m2
:param value: float
"""
if value is not None:
self._sensible_convective_internal_gain = float(value)
@property
def sensible_radiative_internal_gain(self) -> Union[None, float]:
"""
Get sensible radiant internal gain in Watts per m2
:return: None or float
"""
return self._sensible_radiative_internal_gain
@sensible_radiative_internal_gain.setter
def sensible_radiative_internal_gain(self, value):
"""
Set sensible radiant internal gain in Watts per m2
:param value: float
"""
if value is not None:
self._sensible_radiative_internal_gain = float(value)
@property
def latent_internal_gain(self) -> Union[None, float]:
"""
Get latent internal gain in Watts per m2
:return: None or float
"""
return self._latent_internal_gain
@latent_internal_gain.setter
def latent_internal_gain(self, value):
"""
Set latent internal gain in Watts per m2
:param value: float
"""
if value is not None:
self._latent_internal_gain = float(value)
@property
def occupancy_schedules(self) -> Union[None, List[Schedule]]:
"""
Get occupancy schedules
:return: None or [Schedule]
"""
return self._occupancy_schedules
@occupancy_schedules.setter
def occupancy_schedules(self, value):
"""
Set occupancy schedules
:param value: [Schedule]
"""
self._occupancy_schedules = value
@property
def occupants(self) -> Union[None, List[Occupant]]:
"""
Get list of occupants
:return: None or List of Occupant
"""
return self._occupants
@occupants.setter
def occupants(self, value):
"""
Set list of occupants
:param value: [Occupant]
"""
self._occupants = value

View File

@ -1,19 +1,16 @@
""" """
Occupants module Occupant module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from typing import TypeVar
import calendar as cal import calendar as cal
UsageZone = TypeVar('UsageZone')
class Occupant:
class Occupants:
""" """
Occupants class Occupant class
""" """
def __init__(self): def __init__(self):
@ -24,15 +21,11 @@ class Occupants:
self._heat_dissipation = None self._heat_dissipation = None
self._occupancy_rate = None self._occupancy_rate = None
self._occupant_type = None self._occupant_type = None
self._usage_zone = None
self._occupant_schedule = None
self._number_of_occupants = None
self._arrival_time = None self._arrival_time = None
self._departure_time = None self._departure_time = None
self._break_time = None self._break_time = None
self._day_of_week = None self._day_of_week = None
self._pd_of_meetings_duration = None self._pd_of_meetings_duration = None
self._complete_year_schedule = None
@property @property
def heat_dissipation(self): def heat_dissipation(self):
@ -82,46 +75,6 @@ class Occupants:
""" """
self._occupant_type = float(value) self._occupant_type = float(value)
@property
def usage_zone(self) -> UsageZone:
"""
Get the zone an occupant is in
:return: UsageZone
"""
return self._usage_zone
@property
def occupant_schedule(self):
"""
Get the schedules when an occupant is in a zone (24 values, 1 per hour of the day)
:return: [float]
"""
return self._occupant_schedule
@occupant_schedule.setter
def occupant_schedule(self, value):
"""
Set the schedules when an occupant is in a zone (24 values, 1 per hour of the day)
:param value: [float]
"""
self._occupant_schedule = [float(i) for i in value]
@property
def number_of_occupants(self):
"""
Get the number of occupants
:return: int
"""
return self._number_of_occupants
@number_of_occupants.setter
def number_of_occupants(self, value):
"""
Set the number of occupants
:param value: int
"""
self._number_of_occupants = int(value)
@property @property
def arrival_time(self): def arrival_time(self):
""" """
@ -191,27 +144,3 @@ class Occupants:
""" """
# todo @Sanam: what format are you expecting here?? # todo @Sanam: what format are you expecting here??
self._pd_of_meetings_duration = value self._pd_of_meetings_duration = value
def get_complete_year_schedule(self, schedules):
"""
Get the a non-leap year (8760 h), starting on Monday schedules out of archetypal days of week
:return: [float]
"""
if self._complete_year_schedule is None:
self._complete_year_schedule = []
for i in range(1, 13):
month_range = cal.monthrange(2015, i)[1]
for day in range(1, month_range+1):
if cal.weekday(2015, i, day) < 5:
for j in range(0, 24):
week_schedule = schedules['WD'][j]
self._complete_year_schedule.append(week_schedule)
elif cal.weekday(2015, i, day) == 5:
for j in range(0, 24):
week_schedule = schedules['Sat'][j]
self._complete_year_schedule.append(week_schedule)
else:
for j in range(0, 24):
week_schedule = schedules['Sun'][j]
self._complete_year_schedule.append(week_schedule)
return self._complete_year_schedule

View File

@ -12,12 +12,10 @@ from city_model_structure.building_demand.thermal_zone import ThermalZone
class Storey: class Storey:
# todo: rethink this class for buildings with windows
""" """
Storey class Storey class
""" """
def __init__(self, name, storey_surfaces, neighbours, volume): def __init__(self, name, storey_surfaces, neighbours, volume, floor_area):
# todo: the information of the parent surface is lost -> need to recover it
self._name = name self._name = name
self._storey_surfaces = storey_surfaces self._storey_surfaces = storey_surfaces
self._thermal_boundaries = None self._thermal_boundaries = None
@ -25,6 +23,7 @@ class Storey:
self._thermal_zone = None self._thermal_zone = None
self._neighbours = neighbours self._neighbours = neighbours
self._volume = volume self._volume = volume
self._floor_area = floor_area
@property @property
def name(self): def name(self):
@ -59,7 +58,13 @@ class Storey:
if self._thermal_boundaries is None: if self._thermal_boundaries is None:
self._thermal_boundaries = [] self._thermal_boundaries = []
for surface in self.surfaces: for surface in self.surfaces:
self._thermal_boundaries.append(ThermalBoundary(surface)) if surface.holes_polygons is None:
windows_areas = None
else:
windows_areas = []
for hole in surface.holes_polygons:
windows_areas.append(hole.area)
self._thermal_boundaries.append(ThermalBoundary(surface, surface.solid_polygon.area, windows_areas))
return self._thermal_boundaries return self._thermal_boundaries
@property @property
@ -81,7 +86,7 @@ class Storey:
:return: ThermalZone :return: ThermalZone
""" """
if self._thermal_zone is None: if self._thermal_zone is None:
self._thermal_zone = ThermalZone(self.thermal_boundaries, self.volume) self._thermal_zone = ThermalZone(self.thermal_boundaries, self.volume, self.floor_area)
return self._thermal_zone return self._thermal_zone
@property @property
@ -91,3 +96,11 @@ class Storey:
:return: float :return: float
""" """
return self._volume return self._volume
@property
def floor_area(self):
"""
Get storey's floor area in square meters
:return: float
"""
return self._floor_area

View File

@ -71,6 +71,7 @@ class Surface:
if value is not None: if value is not None:
self._id = str(value) self._id = str(value)
# todo: implement share surfaces
@property @property
def share_surfaces(self): def share_surfaces(self):
""" """
@ -191,6 +192,8 @@ class Surface:
Get surface type Ground, Wall or Roof Get surface type Ground, Wall or Roof
:return: str :return: str
""" """
# todo: there are more types: internal wall, internal floor... this method must be redefined
if self._type is None: if self._type is None:
grad = np.rad2deg(self.inclination) grad = np.rad2deg(self.inclination)
if grad >= 170: if grad >= 170:

View File

@ -5,25 +5,24 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import uuid import uuid
from typing import List, TypeVar, Union from typing import List, Union
from helpers.configuration_helper import ConfigurationHelper as ch
from city_model_structure.building_demand.layer import Layer 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_opening import ThermalOpening
from city_model_structure.building_demand.thermal_zone import ThermalZone from city_model_structure.building_demand.thermal_zone import ThermalZone
from city_model_structure.building_demand.surface import Surface from city_model_structure.building_demand.surface import Surface
Polygon = TypeVar('Polygon')
class ThermalBoundary: class ThermalBoundary:
""" """
ThermalBoundary class ThermalBoundary class
""" """
def __init__(self, surface): def __init__(self, parent_surface, opaque_area, windows_areas):
self._surface = surface self._parent_surface = parent_surface
self._opaque_area = opaque_area
self._windows_areas = windows_areas
self._id = None self._id = None
self._thermal_zones = None self._thermal_zones = None
# ToDo: up to at least LOD2 will be just one thermal opening per Thermal boundary only if window_ratio > 0,
# review for LOD3 and LOD4
self._thermal_openings = None self._thermal_openings = None
self._layers = None self._layers = None
self._outside_solar_absorptance = None self._outside_solar_absorptance = None
@ -32,16 +31,16 @@ class ThermalBoundary:
self._u_value = None self._u_value = None
self._shortwave_reflectance = None self._shortwave_reflectance = None
self._construction_name = None self._construction_name = None
self._hi = 3.5 self._hi = ch().convective_heat_transfer_coefficient_interior
self._he = 20 self._he = ch().convective_heat_transfer_coefficient_exterior
self._window_ratio = None
self._refurbishment_measure = None self._refurbishment_measure = None
self._surface_geometry = None
self._thickness = None self._thickness = None
self._virtual_internal_surface = None self._virtual_internal_surface = None
self._inside_emissivity = None self._inside_emissivity = None
self._alpha_coefficient = None self._alpha_coefficient = None
self._radiative_coefficient = None self._radiative_coefficient = None
self._window_ratio = None
self._calculated = False
@property @property
def id(self): def id(self):
@ -54,13 +53,12 @@ class ThermalBoundary:
return self._id return self._id
@property @property
def surface(self) -> Surface: def parent_surface(self) -> Surface:
""" """
Get the surface that belongs to the thermal boundary Get the surface that belongs to the thermal boundary
:return: Surface :return: Surface
""" """
# todo: in LoD4 this property will be a list of surfaces, not only one return self._parent_surface
return self._surface
@property @property
def thermal_zones(self) -> List[ThermalZone]: def thermal_zones(self) -> List[ThermalZone]:
@ -73,47 +71,35 @@ class ThermalBoundary:
@thermal_zones.setter @thermal_zones.setter
def thermal_zones(self, value): def thermal_zones(self, value):
""" """
Set the thermal zones delimited by the thermal boundary Get the thermal zones delimited by the thermal boundary
:param value: [ThermalZone] :param value: [ThermalZone]
""" """
self._thermal_zones = value self._thermal_zones = value
# todo: do I need these two??
@property @property
def azimuth(self): def azimuth(self):
""" """
Get the thermal boundary azimuth in radians Get the thermal boundary azimuth in radians
:return: float :return: float
""" """
return self._surface.azimuth return self.parent_surface.azimuth
@property @property
def inclination(self): def inclination(self):
""" """
Set the thermal boundary inclination in radians Get the thermal boundary inclination in radians
:return: float :return: float
""" """
return self._surface.inclination return self.parent_surface.inclination
@property @property
def area(self): def opaque_area(self):
""" """
Set the thermal boundary area in square meters Get the thermal boundary area in square meters
:return: float :return: float
""" """
# to check the lod without depending on that parameter return float(self._opaque_area)
if float(self.surface.solid_polygon.area) - float(self.surface.perimeter_polygon.area) < 1e-3:
area = float(self.surface.perimeter_polygon.area) * (1 - float(self.window_ratio))
else:
area = self.surface.solid_polygon.area
return area
@property
def _total_area_including_windows(self):
"""
Get the thermal boundary plus windows area in square meters
:return: float
"""
return self.surface.perimeter_polygon.area
@property @property
def thickness(self): def thickness(self):
@ -125,7 +111,8 @@ class ThermalBoundary:
self._thickness = 0.0 self._thickness = 0.0
if self.layers is not None: if self.layers is not None:
for layer in self.layers: for layer in self.layers:
self._thickness += layer.thickness if not layer.material.no_mass:
self._thickness += layer.thickness
return self._thickness return self._thickness
@property @property
@ -181,30 +168,34 @@ class ThermalBoundary:
self._outside_visible_absorptance = float(value) self._outside_visible_absorptance = float(value)
@property @property
def thermal_openings(self) -> List[ThermalOpening]: def thermal_openings(self) -> Union[None, List[ThermalOpening]]:
""" """
Get thermal boundary thermal openings Get thermal boundary thermal openings
:return: [ThermalOpening] :return: [ThermalOpening]
""" """
if self._thermal_openings is None: if self._thermal_openings is None:
if float(self.window_ratio) > 0: if self.window_ratio is not None:
thermal_opening = ThermalOpening() if self.window_ratio == 0:
thermal_opening.area = float(self._total_area_including_windows) * float(self.window_ratio) self._thermal_openings = []
thermal_opening.hi = self.hi else:
thermal_opening.he = self.he thermal_opening = ThermalOpening()
self._thermal_openings = [thermal_opening] if self.window_ratio == 1:
_area = self.opaque_area
else:
_area = self.opaque_area * self.window_ratio / (1-self.window_ratio)
thermal_opening.area = _area
self._thermal_openings = [thermal_opening]
else: else:
self._thermal_openings = [] if len(self.windows_areas) > 0:
self._thermal_openings = []
for window_area in self.windows_areas:
thermal_opening = ThermalOpening()
thermal_opening.area = window_area
self._thermal_openings.append(thermal_opening)
else:
self._thermal_openings = []
return self._thermal_openings return self._thermal_openings
@thermal_openings.setter
def thermal_openings(self, value):
"""
Set thermal boundary thermal openings
:param value: [ThermalOpening]
"""
self._thermal_openings = value
@property @property
def construction_name(self) -> Union[None, str]: def construction_name(self) -> Union[None, str]:
""" """
@ -244,24 +235,47 @@ class ThermalBoundary:
Get thermal boundary surface type Get thermal boundary surface type
:return: str :return: str
""" """
return self._surface.type return self.parent_surface.type
@property @property
def window_ratio(self) -> Union[None, float]: def window_ratio(self) -> Union[None, float]:
""" """
Get thermal boundary window ratio Get thermal boundary window ratio
:return: None or float It returns the window ratio calculated as the total windows' areas in a wall divided by
the total (opaque + transparent) area of that wall if windows are defined in the geometry imported.
If not, it returns the window ratio imported from an external source (e.g. construction library, manually assigned).
If none of those sources are available, it returns None.
:return: float
""" """
if self.windows_areas is not None:
if not self._calculated:
_calculated = True
if len(self.windows_areas) == 0:
self._window_ratio = 0
else:
total_window_area = 0
for window_area in self.windows_areas:
total_window_area += window_area
self._window_ratio = total_window_area / (self.opaque_area + total_window_area)
return self._window_ratio return self._window_ratio
@window_ratio.setter @window_ratio.setter
def window_ratio(self, value): def window_ratio(self, value):
""" """
Set thermal boundary window ratio Set thermal boundary window ratio
:param value: float :param value: str
""" """
if value is not None: if self._calculated:
self._window_ratio = float(value) raise ValueError('Window ratio cannot be assigned when the windows are defined in the geometry.')
self._window_ratio = float(value)
@property
def windows_areas(self) -> [float]:
"""
Get windows areas
:return: [float]
"""
return self._windows_areas
@property @property
def u_value(self) -> Union[None, float]: def u_value(self) -> Union[None, float]:
@ -327,7 +341,7 @@ class ThermalBoundary:
:param value: float :param value: float
""" """
if value is not None: if value is not None:
self._hi = float(value) self._hi = value
@property @property
def he(self) -> Union[None, float]: def he(self) -> Union[None, float]:
@ -344,14 +358,7 @@ class ThermalBoundary:
:param value: float :param value: float
""" """
if value is not None: if value is not None:
self._he = float(value) self._he = value
@property
def surface_geometry(self):
"""
Raises not implemented error
"""
raise NotImplementedError
@property @property
def virtual_internal_surface(self) -> Surface: def virtual_internal_surface(self) -> Surface:
@ -360,10 +367,9 @@ class ThermalBoundary:
:return: Surface :return: Surface
""" """
if self._virtual_internal_surface is None: if self._virtual_internal_surface is None:
self._virtual_internal_surface = self.surface.inverse self._virtual_internal_surface = self.parent_surface.inverse
return self._virtual_internal_surface return self._virtual_internal_surface
# todo: need extract information from construction library or assume them at the beginning of workflows
@property @property
def inside_emissivity(self) -> Union[None, float]: def inside_emissivity(self) -> Union[None, float]:
""" """

View File

@ -0,0 +1,144 @@
"""
ThermalControl module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union, List
from city_model_structure.attributes.schedule import Schedule
class ThermalControl:
"""
ThermalControl class
"""
def __init__(self):
self._mean_heating_set_point = None
self._heating_set_back = None
self._mean_cooling_set_point = None
self._hvac_availability_schedules = None
self._heating_set_point_schedules = None
self._cooling_set_point_schedules = None
@staticmethod
def _maximum_value(schedules):
maximum = -1000
for schedule in schedules:
for value in schedule.values:
if value > maximum:
maximum = value
return maximum
@staticmethod
def _minimum_value(schedules):
minimum = 1000
for schedule in schedules:
for value in schedule.values:
if value < minimum:
minimum = value
return minimum
@property
def mean_heating_set_point(self) -> Union[None, float]:
"""
Get heating set point defined for a thermal zone in Celsius
:return: None or float
"""
if self._mean_heating_set_point is None:
if self.heating_set_point_schedules is not None:
self._mean_heating_set_point = self._maximum_value(self.heating_set_point_schedules)
return self._mean_heating_set_point
@mean_heating_set_point.setter
def mean_heating_set_point(self, value):
"""
Set heating set point defined for a thermal zone in Celsius
:param value: float
"""
self._mean_heating_set_point = value
@property
def heating_set_back(self) -> Union[None, float]:
"""
Get heating set back defined for a thermal zone in Celsius
:return: None or float
"""
if self._heating_set_back is None:
if self.heating_set_point_schedules is not None:
self._heating_set_back = self._minimum_value(self.heating_set_point_schedules)
return self._heating_set_back
@heating_set_back.setter
def heating_set_back(self, value):
"""
Set heating set back defined for a thermal zone in Celsius
:param value: float
"""
if value is not None:
self._heating_set_back = float(value)
@property
def mean_cooling_set_point(self) -> Union[None, float]:
"""
Get cooling set point defined for a thermal zone in Celsius
:return: None or float
"""
if self._mean_cooling_set_point is None:
if self.cooling_set_point_schedules is not None:
self._mean_cooling_set_point = self._minimum_value(self.cooling_set_point_schedules)
return self._mean_cooling_set_point
@mean_cooling_set_point.setter
def mean_cooling_set_point(self, value):
"""
Set cooling set point defined for a thermal zone in Celsius
:param value: float
"""
self._mean_cooling_set_point = value
@property
def hvac_availability_schedules(self) -> Union[None, List[Schedule]]:
"""
Get the availability of the conditioning system defined for a thermal zone
:return: None or [Schedule]
"""
return self._hvac_availability_schedules
@hvac_availability_schedules.setter
def hvac_availability_schedules(self, value):
"""
Set the availability of the conditioning system defined for a thermal zone
:param value: [Schedule]
"""
self._hvac_availability_schedules = value
@property
def heating_set_point_schedules(self) -> Union[None, List[Schedule]]:
"""
Get heating set point schedule defined for a thermal zone in Celsius
:return: None or [Schedule]
"""
return self._heating_set_point_schedules
@heating_set_point_schedules.setter
def heating_set_point_schedules(self, value):
"""
Set heating set point schedule defined for a thermal zone in Celsius
:param value: [Schedule]
"""
self._heating_set_point_schedules = value
@property
def cooling_set_point_schedules(self) -> Union[None, List[Schedule]]:
"""
Get cooling set point schedule defined for a thermal zone in Celsius
:return: None or [Schedule]
"""
return self._cooling_set_point_schedules
@cooling_set_point_schedules.setter
def cooling_set_point_schedules(self, value):
"""
Set cooling set point schedule defined for a thermal zone in Celsius
:param value: [Schedule]
"""
self._cooling_set_point_schedules = value

View File

@ -6,6 +6,7 @@ Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import uuid import uuid
from typing import TypeVar, Union from typing import TypeVar, Union
from helpers.configuration_helper import ConfigurationHelper as ch
Polygon = TypeVar('Polygon') Polygon = TypeVar('Polygon')
@ -25,9 +26,8 @@ class ThermalOpening:
self._front_side_solar_transmittance_at_normal_incidence = None self._front_side_solar_transmittance_at_normal_incidence = None
self._back_side_solar_transmittance_at_normal_incidence = None self._back_side_solar_transmittance_at_normal_incidence = None
self._overall_u_value = None self._overall_u_value = None
self._hi = None self._hi = ch().convective_heat_transfer_coefficient_interior
self._he = None self._he = ch().convective_heat_transfer_coefficient_exterior
self._surface_geometry = None
self._inside_emissivity = None self._inside_emissivity = None
self._alpha_coefficient = None self._alpha_coefficient = None
self._radiative_coefficient = None self._radiative_coefficient = None
@ -240,15 +240,6 @@ class ThermalOpening:
if value is not None: if value is not None:
self._he = float(value) self._he = float(value)
@property
def surface_geometry(self) -> Polygon:
"""
Get the polygon that defines the thermal opening
:return: Polygon
"""
return self._surface_geometry
# todo: need extract information from construction library or assume them at the beginning of workflows
@property @property
def inside_emissivity(self) -> Union[None, float]: def inside_emissivity(self) -> Union[None, float]:
""" """

View File

@ -5,32 +5,34 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import uuid import uuid
from typing import List, TypeVar, Union from typing import List, Union, TypeVar
from city_model_structure.building_demand.usage_zone import UsageZone from city_model_structure.building_demand.usage_zone import UsageZone
import ast 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
ThermalBoundary = TypeVar('ThermalBoundary') ThermalBoundary = TypeVar('ThermalBoundary')
Polyhedron = TypeVar('Polyhedron')
class ThermalZone: class ThermalZone:
""" """
ThermalZone class ThermalZone class
""" """
def __init__(self, thermal_boundaries, volume): def __init__(self, thermal_boundaries, volume, floor_area):
self._floor_area = None self._id = None
self._floor_area = floor_area
self._thermal_boundaries = thermal_boundaries self._thermal_boundaries = thermal_boundaries
self._is_mechanically_ventilated = None
self._additional_thermal_bridge_u_value = None self._additional_thermal_bridge_u_value = None
self._effective_thermal_capacity = None self._effective_thermal_capacity = None
self._indirectly_heated_area_ratio = None self._indirectly_heated_area_ratio = None
self._infiltration_rate_system_on = None self._infiltration_rate_system_on = None
self._infiltration_rate_system_off = None self._infiltration_rate_system_off = None
self._usage_zones = []
self._volume = volume self._volume = volume
self._volume_geometry = None
self._id = None
self._ordinate_number = None self._ordinate_number = None
self._usage_zones = None
self._thermal_control = None
self._hvac_system = None
self._view_factors_matrix = None
@property @property
def id(self): def id(self):
@ -43,34 +45,11 @@ class ThermalZone:
return self._id return self._id
@property @property
def is_mechanically_ventilated(self) -> Union[None, bool]: def floor_area(self) -> float:
"""
Get thermal zone mechanical ventilation flag
:return: None or Boolean
"""
return self._is_mechanically_ventilated
@is_mechanically_ventilated.setter
def is_mechanically_ventilated(self, value):
"""
Set thermal zone mechanical ventilation flag
:param value: Boolean
"""
if value is not None:
self._is_mechanically_ventilated = ast.literal_eval(value)
@property
def floor_area(self):
""" """
Get thermal zone floor area in m2 Get thermal zone floor area in m2
:return: float :return: float
""" """
if self._floor_area is None:
self._floor_area = 0
for thermal_boundary in self.thermal_boundaries:
s = thermal_boundary.surface
if s.type == 'Ground':
self._floor_area += s.perimeter_polygon.area
return self._floor_area return self._floor_area
@property @property
@ -133,10 +112,10 @@ class ThermalZone:
self._indirectly_heated_area_ratio = float(value) self._indirectly_heated_area_ratio = float(value)
@property @property
def infiltration_rate_system_on(self) -> Union[None, float]: def infiltration_rate_system_on(self) -> Union[None, Schedule]:
""" """
Get thermal zone infiltration rate system on in air changes per hour (ACH) Get thermal zone infiltration rate system on in air changes per hour (ACH)
:return: None or float :return: None or Schedule
""" """
return self._infiltration_rate_system_on return self._infiltration_rate_system_on
@ -144,16 +123,15 @@ class ThermalZone:
def infiltration_rate_system_on(self, value): def infiltration_rate_system_on(self, value):
""" """
Set thermal zone infiltration rate system on in air changes per hour (ACH) Set thermal zone infiltration rate system on in air changes per hour (ACH)
:param value: float :param value: Schedule
""" """
if value is not None: self._infiltration_rate_system_on = value
self._infiltration_rate_system_on = float(value)
@property @property
def infiltration_rate_system_off(self) -> Union[None, float]: def infiltration_rate_system_off(self) -> Union[None, Schedule]:
""" """
Get thermal zone infiltration rate system off in air changes per hour (ACH) Get thermal zone infiltration rate system off in air changes per hour (ACH)
:return: None or float :return: None or Schedule
""" """
return self._infiltration_rate_system_off return self._infiltration_rate_system_off
@ -161,26 +139,9 @@ class ThermalZone:
def infiltration_rate_system_off(self, value): def infiltration_rate_system_off(self, value):
""" """
Set thermal zone infiltration rate system on in air changes per hour (ACH) Set thermal zone infiltration rate system on in air changes per hour (ACH)
:param value: float :param value: Schedule
""" """
if value is not None: self._infiltration_rate_system_off = value
self._infiltration_rate_system_off = float(value)
@property
def usage_zones(self) -> List[UsageZone]:
"""
Get thermal zone usage zones
:return: [UsageZone]
"""
return self._usage_zones
@usage_zones.setter
def usage_zones(self, values):
"""
Set thermal zone usage zones
:param values: [UsageZone]
"""
self._usage_zones = values
@property @property
def volume(self): def volume(self):
@ -190,14 +151,6 @@ class ThermalZone:
""" """
return self._volume return self._volume
@property
def volume_geometry(self) -> Polyhedron:
"""
Get the polyhedron defined by the thermal zone
:return: Polyhedron
"""
return self._volume_geometry
@property @property
def ordinate_number(self) -> Union[None, int]: def ordinate_number(self) -> Union[None, int]:
""" """
@ -214,3 +167,73 @@ class ThermalZone:
""" """
if value is not None: if value is not None:
self._ordinate_number = int(value) self._ordinate_number = int(value)
@property
def usage_zones(self) -> [UsageZone]:
"""
Get list of usage zones and the percentage of thermal zone's volume affected by that usage
From internal_zone
:return: [UsageZone]
"""
return self._usage_zones
@usage_zones.setter
def usage_zones(self, values):
"""
Set list of usage zones and the percentage of thermal zone's volume affected by that usage
From internal_zone
:param values: [UsageZone]
"""
self._usage_zones = values
@property
def thermal_control(self) -> Union[None, ThermalControl]:
"""
Get thermal control of this thermal zone
From internal_zone
:return: None or ThermalControl
"""
return self._thermal_control
@thermal_control.setter
def thermal_control(self, value):
"""
Set thermal control for this thermal zone
From internal_zone
:param value: ThermalControl
"""
self._thermal_control = value
@property
def hvac_system(self) -> Union[None, HvacSystem]:
"""
Get HVAC system installed for this thermal zone
From internal_zone
:return: None or HvacSystem
"""
return self._hvac_system
@hvac_system.setter
def hvac_system(self, value):
"""
Set HVAC system installed for this thermal zone
From internal_zone
:param value: HvacSystem
"""
self._hvac_system = value
@property
def view_factors_matrix(self):
"""
Get thermal zone view factors matrix
:return: [[float]]
"""
return self._view_factors_matrix
@view_factors_matrix.setter
def view_factors_matrix(self, value):
"""
Set thermal zone view factors matrix
:param value: [[float]]
"""
self._view_factors_matrix = value

View File

@ -5,13 +5,13 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
Contributors Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Contributors Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import uuid import uuid
from typing import List, TypeVar, Union from typing import List, Union
import ast import helpers.constants as cte
from city_model_structure.building_demand.internal_gains import InternalGains
InternalGains = TypeVar('InternalGains') from city_model_structure.building_demand.occupancy import Occupancy
Occupants = TypeVar('Occupants') from city_model_structure.building_demand.lighting import Lighting
Polyhedron = TypeVar('Polyhedron') from city_model_structure.building_demand.appliances import Appliances
Schedule = TypeVar('Schedule') from city_model_structure.building_demand.thermal_control import ThermalControl
class UsageZone: class UsageZone:
@ -21,23 +21,17 @@ class UsageZone:
def __init__(self): def __init__(self):
self._id = None self._id = None
self._usage = None self._usage = None
self._internal_gains = None self._percentage = None
self._heating_setpoint = None self._not_detailed_source_mean_annual_internal_gains = None
self._heating_setback = None
self._cooling_setpoint = None
self._occupancy_density = None
self._hours_day = None self._hours_day = None
self._days_year = None self._days_year = None
self._dhw_average_volume_pers_day = None # self._electrical_app_average_consumption_sqm_year = None
self._dhw_preparation_temperature = None
self._electrical_app_average_consumption_sqm_year = None
self._mechanical_air_change = None self._mechanical_air_change = None
self._occupants = None self._occupancy = None
self._schedules = None self._lighting = None
self._volume = None self._appliances = None
self._volume_geometry = None self._internal_gains = None
self._is_heated = False self._thermal_control = None
self._is_cooled = False
@property @property
def id(self): def id(self):
@ -50,71 +44,54 @@ class UsageZone:
return self._id return self._id
@property @property
def internal_gains(self) -> List[InternalGains]: def usage(self) -> Union[None, str]:
""" """
Get usage zone internal gains Get usage zone usage
:return: None or str
"""
return self._usage
@usage.setter
def usage(self, value):
"""
Set usage zone usage
:param value: str
"""
if value is not None:
self._usage = str(value)
@property
def percentage(self):
"""
Get usage zone percentage in range[0,1]
:return: float
"""
return self._percentage
@percentage.setter
def percentage(self, value):
"""
Set usage zone percentage in range[0,1]
:param value: float
"""
if value is not None:
self._percentage = float(value)
@property
def not_detailed_source_mean_annual_internal_gains(self) -> List[InternalGains]:
"""
Get usage zone internal gains with unknown energy source
:return: [InternalGains] :return: [InternalGains]
""" """
return self._internal_gains return self._not_detailed_source_mean_annual_internal_gains
@internal_gains.setter @not_detailed_source_mean_annual_internal_gains.setter
def internal_gains(self, value): def not_detailed_source_mean_annual_internal_gains(self, value):
""" """
Set usage zone internal gains Set usage zone internal gains with unknown energy source
:param value: [InternalGains] :param value: [InternalGains]
""" """
self._internal_gains = value self._not_detailed_source_mean_annual_internal_gains = value
@property
def heating_setpoint(self) -> Union[None, float]:
"""
Get usage zone heating set point in Celsius
:return: None or float
"""
return self._heating_setpoint
@heating_setpoint.setter
def heating_setpoint(self, value):
"""
Set usage zone heating set point in Celsius
:param value: float
"""
if value is not None:
self._heating_setpoint = float(value)
@property
def heating_setback(self) -> Union[None, float]:
"""
Get usage zone heating setback in Celsius
:return: None or float
"""
return self._heating_setback
@heating_setback.setter
def heating_setback(self, value):
"""
Set usage zone heating setback in Celsius
:param value: float
"""
if value is not None:
self._heating_setback = float(value)
@property
def cooling_setpoint(self) -> Union[None, float]:
"""
Get usage zone cooling setpoint in Celsius
:return: None or float
"""
return self._cooling_setpoint
@cooling_setpoint.setter
def cooling_setpoint(self, value):
"""
Set usage zone cooling setpoint in Celsius
:param value: float
"""
if value is not None:
self._cooling_setpoint = float(value)
@property @property
def hours_day(self) -> Union[None, float]: def hours_day(self) -> Union[None, float]:
@ -167,106 +144,6 @@ class UsageZone:
if value is not None: if value is not None:
self._mechanical_air_change = float(value) self._mechanical_air_change = float(value)
@property
def usage(self) -> Union[None, str]:
"""
Get usage zone usage
:return: None or str
"""
return self._usage
@usage.setter
def usage(self, value):
"""
Set usage zone usage
:param value: str
"""
if value is not None:
self._usage = str(value)
@property
def occupants(self) -> List[Occupants]:
"""
Get occupants data
:return: [Occupants]
"""
return self._occupants
@occupants.setter
def occupants(self, values):
"""
Set occupants data
:param values: [Occupants]
"""
self._occupants = values
@property
def schedules(self) -> List[Schedule]:
"""
Get usage zone schedules
:return: List[Schedule]
"""
return self._schedules
@schedules.setter
def schedules(self, values):
"""
Set usage zone schedules
:param values: List[Schedule]
"""
self._schedules = values
@property
def occupancy_density(self) -> Union[None, float]:
"""
Get density in persons per m2
:return: None or float
"""
return self._occupancy_density
@occupancy_density.setter
def occupancy_density(self, value):
"""
Set density in persons per m2
:param value: float
"""
if value is not None:
self._occupancy_density = float(value)
@property
def dhw_average_volume_pers_day(self) -> Union[None, float]:
"""
Get average DHW consumption in cubic meters per person per day
:return: None or float
"""
return self._dhw_average_volume_pers_day
@dhw_average_volume_pers_day.setter
def dhw_average_volume_pers_day(self, value):
"""
Set average DHW consumption in cubic meters per person per day
:param value: float
"""
if value is not None:
self._dhw_average_volume_pers_day = float(value)
@property
def dhw_preparation_temperature(self) -> Union[None, float]:
"""
Get preparation temperature of the DHW in Celsius
:return: None or float
"""
return self._dhw_preparation_temperature
@dhw_preparation_temperature.setter
def dhw_preparation_temperature(self, value):
"""
Set preparation temperature of the DHW in Celsius
:param value: float
"""
if value is not None:
self._dhw_preparation_temperature = float(value)
@property @property
def electrical_app_average_consumption_sqm_year(self) -> Union[None, float]: def electrical_app_average_consumption_sqm_year(self) -> Union[None, float]:
""" """
@ -285,60 +162,109 @@ class UsageZone:
self._electrical_app_average_consumption_sqm_year = float(value) self._electrical_app_average_consumption_sqm_year = float(value)
@property @property
def volume_geometry(self) -> Polyhedron: def occupancy(self) -> Union[None, Occupancy]:
""" """
Get the polyhedron defined by the usage zone Get occupancy in the usage zone
:return: Polyhedron :return: None or Occupancy
""" """
return self._volume_geometry return self._occupancy
@occupancy.setter
def occupancy(self, value):
"""
Set occupancy in the usage zone
:param value: Occupancy
"""
self._occupancy = value
@property @property
def volume(self) -> Union[None, float]: def lighting(self) -> Union[None, Lighting]:
""" """
Get the volume in cubic meters Get lighting information
:return: None or float :return: None or Lighting
""" """
return self._volume return self._lighting
@volume.setter @lighting.setter
def volume(self, value): def lighting(self, value):
""" """
Set volume in cubic meters Set lighting information
:param value: float :param value: Lighting
""" """
if value is not None: self._lighting = value
self._volume = float(value)
@property @property
def is_heated(self) -> Union[None, bool]: def appliances(self) -> Union[None, Appliances]:
""" """
Get thermal zone heated flag Get appliances information
:return: None or Boolean :return: None or Appliances
""" """
return self._is_heated return self._appliances
@is_heated.setter @appliances.setter
def is_heated(self, value): def appliances(self, value):
""" """
Set thermal zone heated flag Set appliances information
:param value: Boolean :param value: Appliances
""" """
if value is not None: self._appliances = value
self._is_heated = ast.literal_eval(value)
def get_internal_gains(self) -> [InternalGains]:
"""
Calculates and returns the list of all internal gains defined
:return: InternalGains
"""
if self.occupancy is not None:
if self.occupancy.latent_internal_gain is not None:
_internal_gain = InternalGains()
_internal_gain.type = cte.OCCUPANCY
_total_heat_gain = (self.occupancy.sensible_convective_internal_gain
+ self.occupancy.sensible_radiative_internal_gain
+ self.occupancy.latent_internal_gain)
_internal_gain.average_internal_gain = _total_heat_gain
_internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain
_internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain
_internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain
_internal_gain.schedules = self.occupancy.occupancy_schedules
self._internal_gains = [_internal_gain]
if self.lighting is not None:
_internal_gain = InternalGains()
_internal_gain.type = cte.LIGHTING
_internal_gain.average_internal_gain = self.lighting.lighting_density
_internal_gain.latent_fraction = self.lighting.latent_fraction
_internal_gain.radiative_fraction = self.lighting.radiative_fraction
_internal_gain.convective_fraction = self.lighting.convective_fraction
_internal_gain.schedules = self.lighting.schedules
if self._internal_gains is not None:
self._internal_gains.append(_internal_gain)
else:
self._internal_gains = [_internal_gain]
if self.appliances is not None:
_internal_gain = InternalGains()
_internal_gain.type = cte.APPLIANCES
_internal_gain.average_internal_gain = self.appliances.appliances_density
_internal_gain.latent_fraction = self.appliances.latent_fraction
_internal_gain.radiative_fraction = self.appliances.radiative_fraction
_internal_gain.convective_fraction = self.appliances.convective_fraction
_internal_gain.schedules = self.appliances.schedules
if self._internal_gains is not None:
self._internal_gains.append(_internal_gain)
else:
self._internal_gains = [_internal_gain]
return self._internal_gains
@property @property
def is_cooled(self) -> Union[None, bool]: def thermal_control(self) -> Union[None, ThermalControl]:
""" """
Get thermal zone cooled flag Get thermal control of this thermal zone
:return: None or Boolean :return: None or ThermalControl
""" """
return self._is_cooled return self._thermal_control
@is_cooled.setter @thermal_control.setter
def is_cooled(self, value): def thermal_control(self, value):
""" """
Set thermal zone cooled flag Set thermal control for this thermal zone
:param value: Boolean :param value: ThermalControl
""" """
if value is not None: self._thermal_control = value
self._is_cooled = ast.literal_eval(value)

View File

@ -36,13 +36,21 @@ class CityObject:
self._beam = dict() self._beam = dict()
self._sensors = [] self._sensors = []
@property
def name(self):
"""
Get building name
:return: str
"""
return self._name
@property @property
def lod(self) -> int: def lod(self) -> int:
""" """
Get city object level of detail 1, 2, 3 or 4 Get city object level of detail 1, 2, 3 or 4
:return: int :return: int
""" """
lod = math.log(self._lod, 2) + 1 lod = int(math.log(self._lod, 2) + 1)
return lod return lod
@property @property

View File

@ -0,0 +1,32 @@
"""
HvacSystem module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union
class HvacSystem:
"""
HvacSystem class
"""
def __init__(self):
self._type = None
@property
def type(self) -> Union[None, str]:
"""
Get hvac system type a thermal zone
:return: None or str
"""
return self._type
@type.setter
def type(self, value):
"""
Set heating set point defined for a thermal zone
:param value: str
"""
if value is not None:
self._type = str(value)

View File

@ -0,0 +1,45 @@
"""
Energy Sensor module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import pandas as pd
from city_model_structure.iot.sensor import Sensor
class ConcordiaEnergySensor(Sensor):
"""
Concordia energy sensor.
"""
def __init__(self, name):
super().__init__()
self._name = name
self._interval = 5
self._interval_units = 'minutes'
self._type = 'ConcordiaEnergySensor'
self._units = 'kW'
self._measures = pd.DataFrame(columns=["Date time", "Energy consumption"])
@property
def measures(self) -> pd.DataFrame:
"""
Get sensor measures [yyyy-mm-dd, hh:mm:ss kW]
:return: DataFrame["Date time", "Energy consumption"]
"""
return self._measures
@measures.deleter
def measures(self):
"""
Delete sensor measures
"""
self._measures.drop = None
def add_period(self, measures):
"""
Add or update a period measures to the dataframe
"""
measures = self._measures.append(measures, ignore_index=True)
self._measures = measures.drop_duplicates('Date time', keep='last')

View File

@ -0,0 +1,45 @@
"""
Gas Flow Sensor module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import pandas as pd
from city_model_structure.iot.sensor import Sensor
class ConcordiaGasFlowSensor(Sensor):
"""
Concordia gas flow sensor.
"""
def __init__(self, name):
super().__init__()
self._name = name
self._interval = 5
self._interval_units = 'minutes'
self._type = 'ConcordiaGasFlowSensor'
self._units = 'm3'
self._measures = pd.DataFrame(columns=["Date time", "Gas Flow Cumulative Monthly"])
@property
def measures(self) -> pd.DataFrame:
"""
Get sensor measures [yyyy-mm-dd, hh:mm:ss m3]
:return: DataFrame["Date time", "Gas Flow Cumulative Monthly"]
"""
return self._measures
@measures.deleter
def measures(self):
"""
Delete sensor measures
"""
self._measures.drop = None
def add_period(self, measures):
"""
Add or update a period measures to the dataframe
"""
measures = self._measures.append(measures, ignore_index=True)
self._measures = measures.drop_duplicates('Date time', keep='last')

View File

@ -0,0 +1,45 @@
"""
Temperature Sensor module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import pandas as pd
from city_model_structure.iot.sensor import Sensor
class ConcordiaTemperatureSensor(Sensor):
"""
Concordia temperature sensor.
"""
def __init__(self, name):
super().__init__()
self._name = name
self._interval = 5
self._interval_units = 'minutes'
self._type = 'ConcordiaTemperatureSensor'
self._units = 'Celsius'
self._measures = pd.DataFrame(columns=["Date time", "Temperature"])
@property
def measures(self) -> pd.DataFrame:
"""
Get sensor measures [yyyy-mm-dd, hh:mm:ss Celsius]
:return: DataFrame["Date time", "Temperature"]
"""
return self._measures
@measures.deleter
def measures(self):
"""
Delete sensor measures
"""
self._measures.drop = None
def add_period(self, measures):
"""
Add or update a period measures to the dataframe
"""
measures = self._measures.append(measures, ignore_index=True)
self._measures = measures.drop_duplicates('Date time', keep='last')

View File

@ -1,73 +1,76 @@
""" """
Sensor module Sensor module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import uuid
from city_model_structure.iot.sensor_measure import SensorMeasure from helpers.location import Location
from city_model_structure.iot.sensor_type import SensorType
class Sensor: class Sensor:
""" """
Sensor abstract class Sensor abstract class
""" """
def __init__(self, sensor_id=None, model=None, sensor_type=None, indoor=False, board=None): def __init__(self):
self._id = sensor_id self._name = None
self._model = model self._type = None
self._type = sensor_type self._units = None
self._indoor = indoor self._location = None
self._board = board
self._measures = []
@property @property
def id(self): def name(self):
""" """
Get the sensor id a random uuid will be assigned if no ID was provided to the constructor Get sensor name
:return: Id :return: str
""" """
if self._id is None: if self._name is None:
self._id = uuid.uuid4() raise ValueError('Undefined sensor name')
return self._id return self._name
@name.setter
def name(self, value):
"""
Set sensor name
:param value: str
"""
if value is not None:
self._name = str(value)
@property @property
def type(self) -> SensorType: def type(self):
""" """
Get sensor type Get sensor type
:return: SensorTypeEnum or Error :return: str
""" """
if self._type is None:
raise ValueError('Unknown sensor type')
return self._type return self._type
@property @property
def model(self): def units(self):
""" """
Get sensor model is any Get sensor units
:return: str or None :return: str
""" """
return self._model return self._units
@property @property
def board(self): def location(self) -> Location:
""" """
Get sensor board if any Get sensor location
:return: str or None :return: Location
""" """
return self._model return self._location
@location.setter
def location(self, value):
"""
Set sensor location
:param value: Location
"""
self._location = value
@property @property
def indoor(self): def measures(self):
"""
Get is the sensor it's located indoor or outdoor
:return: boolean
"""
return self._indoor
@property
def measures(self) -> [SensorMeasure]:
""" """
Raises not implemented error Raises not implemented error
""" """
return self._measures raise NotImplementedError

View File

@ -1,40 +0,0 @@
"""
Sensor measure module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
class SensorMeasure:
def __init__(self, latitude, longitude, utc_timestamp, value):
self._latitude = latitude
self._longitude = longitude
self._utc_timestamp = utc_timestamp
self._value = value
@property
def latitude(self):
"""
Get measure latitude
"""
return self._latitude
@property
def longitude(self):
"""
Get measure longitude
"""
return self._longitude
@property
def utc_timestamp(self):
"""
Get measure timestamp in utc
"""
return self._utc_timestamp
@property
def value(self):
"""
Get sensor measure value
"""
return self._value

View File

@ -1,20 +0,0 @@
"""
Sensor type module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from enum import Enum
class SensorType(Enum):
HUMIDITY = 0
TEMPERATURE = 1
CO2 = 2
NOISE = 3
PRESSURE = 4
DIRECT_RADIATION = 5
DIFFUSE_RADIATION = 6
GLOBAL_RADIATION = 7
AIR_QUALITY = 8
GAS_FLOW = 9
ENERGY = 10

View File

@ -1,41 +0,0 @@
"""
Station
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import uuid
from city_model_structure.iot.sensor import Sensor
class Station:
def __init__(self, station_id=None, _mobile=False):
self._id = station_id
self._mobile = _mobile
self._sensors = []
@property
def id(self):
"""
Get the station id a random uuid will be assigned if no ID was provided to the constructor
:return: Id
"""
if self._id is None:
self._id = uuid.uuid4()
return self._id
@property
def _mobile(self):
"""
Get if the station is mobile or not
:return: bool
"""
return self._mobile
@property
def sensors(self) -> [Sensor]:
"""
Get the sensors belonging to the station
:return: [Sensor]
"""
return self._sensors

View File

@ -1,242 +0,0 @@
"""
Material module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Atiya atiya.atiya@mail.concordia.ca
Contributor Mohammad Reza mohammad.seyedabadi@mail.concordia.ca
"""
from typing import Union
class LcaMaterial:
def __init__(self):
self._id = None
self._type = None
self._name = None
self._density = None
self._density_unit = None
self._embodied_carbon = None
self._embodied_carbon_unit = None
self._recycling_ratio = None
self._company_recycling_ratio = None
self._onsite_recycling_ratio = None
self._landfilling_ratio = None
self._cost = None
self._cost_unit = None
@property
def id(self):
"""
Get material id
:return: int
"""
return self._id
@id.setter
def id(self, value):
"""
Set material id
:param value: int
"""
self._id = int(value)
@property
def type(self):
"""
Get material type
:return: str
"""
return self._type
@type.setter
def type(self, value):
"""
Set material type
:param value: string
"""
self._type = str(value)
@property
def name(self):
"""
Get material name
:return: str
"""
return self._name
@name.setter
def name(self, value):
"""
Set material name
:param value: string
"""
self._name = str(value)
@property
def density(self) -> Union[None, float]:
"""
Get material density in kg/m3
:return: None or float
"""
return self._density
@density.setter
def density(self, value):
"""
Set material density
:param value: float
"""
if value is not None:
self._density = float(value)
@property
def density_unit(self) -> Union[None, str]:
"""
Get material density unit
:return: None or string
"""
return self._density_unit
@density_unit.setter
def density_unit(self, value):
"""
Set material density unit
:param value: string
"""
if value is not None:
self._density_unit = str(value)
@property
def embodied_carbon(self) -> Union[None, float]:
"""
Get material embodied carbon
:return: None or float
"""
return self._embodied_carbon
@embodied_carbon.setter
def embodied_carbon(self, value):
"""
Set material embodied carbon
:param value: float
"""
if value is not None:
self._embodied_carbon = float(value)
@property
def embodied_carbon_unit(self) -> Union[None, str]:
"""
Get material embodied carbon unit
:return: None or string
"""
return self._embodied_carbon
@embodied_carbon_unit.setter
def embodied_carbon_unit(self, value):
"""
Set material embodied carbon unit
:param value: string
"""
if value is not None:
self._embodied_carbon_unit = str(value)
@property
def recycling_ratio(self) -> Union[None, float]:
"""
Get material recycling ratio
:return: None or float
"""
return self._recycling_ratio
@recycling_ratio.setter
def recycling_ratio(self, value):
"""
Set material recycling ratio
:param value: float
"""
if value is not None:
self._recycling_ratio = float(value)
@property
def onsite_recycling_ratio(self) -> Union[None, float]:
"""
Get material onsite recycling ratio
:return: None or float
"""
return self._onsite_recycling_ratio
@onsite_recycling_ratio.setter
def onsite_recycling_ratio(self, value):
"""
Set material onsite recycling ratio
:param value: float
"""
if value is not None:
self._onsite_recycling_ratio = float(value)
@property
def company_recycling_ratio(self) -> Union[None, float]:
"""
Get material company recycling ratio
:return: None or float
"""
return self._company_recycling_ratio
@company_recycling_ratio.setter
def company_recycling_ratio(self, value):
"""
Set material company recycling ratio
:param value: float
"""
if value is not None:
self._company_recycling_ratio = float(value)
@property
def landfilling_ratio(self) -> Union[None, float]:
"""
Get material landfilling ratio
:return: None or float
"""
return self._landfilling_ratio
@landfilling_ratio.setter
def landfilling_ratio(self, value):
"""
Set material landfilling ratio
:param value: float
"""
if value is not None:
self._landfilling_ratio = float(value)
@property
def cost(self) -> Union[None, float]:
"""
Get material cost
:return: None or float
"""
return self._cost
@cost.setter
def cost(self, value):
"""
Set material cost
:param value: float
"""
if value is not None:
self._cost = float(value)
@property
def cost_unit(self) -> Union[None, str]:
"""
Get material cost unit
:return: None or string
"""
return self._cost_unit
@cost_unit.setter
def cost_unit(self, value):
"""
Set material cost unit
:param value: string
"""
if value is not None:
self._cost_unit = float(value)

View File

@ -11,3 +11,5 @@ comnet_occupancy_sensible_radiant = 0.1
comnet_plugs_latent = 0 comnet_plugs_latent = 0
comnet_plugs_convective = 0.75 comnet_plugs_convective = 0.75
comnet_plugs_radiant = 0.25 comnet_plugs_radiant = 0.25
convective_heat_transfer_coefficient_interior = 3.5
convective_heat_transfer_coefficient_exterior = 20

View File

@ -105,84 +105,52 @@
#wall below grade #wall below grade
<construction type="basement_wall" id="17" name="wall below grade_post 2010"> <construction type="basement_wall" id="17" name="wall below grade_post 2010">
<overall_u_value units="W/m2 K">0.512</overall_u_value> <overall_u_value units="W/m2 K">0.512</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="basement_wall" id="18" name="wall below grade_2001-2010"> <construction type="basement_wall" id="18" name="wall below grade_2001-2010">
<overall_u_value units="W/m2 K">0.512</overall_u_value> <overall_u_value units="W/m2 K">0.512</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="basement_wall" id="19" name="wall below grade_1996-2000"> <construction type="basement_wall" id="19" name="wall below grade_1996-2000">
<overall_u_value units="W/m2 K">0.67</overall_u_value> <overall_u_value units="W/m2 K">0.67</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="basement_wall" id="20" name="wall below grade_1984-1995"> <construction type="basement_wall" id="20" name="wall below grade_1984-1995">
<overall_u_value units="W/m2 K">0.848</overall_u_value> <overall_u_value units="W/m2 K">0.848</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="basement_wall" id="21" name="wall below grade_1978-1983"> <construction type="basement_wall" id="21" name="wall below grade_1978-1983">
<overall_u_value units="W/m2 K">1.048</overall_u_value> <overall_u_value units="W/m2 K">1.048</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="basement_wall" id="22" name="wall below grade_1961-1977"> <construction type="basement_wall" id="22" name="wall below grade_1961-1977">
<overall_u_value units="W/m2 K">1.154</overall_u_value> <overall_u_value units="W/m2 K">1.154</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="basement_wall" id="23" name="wall below grade_1946-1960"> <construction type="basement_wall" id="23" name="wall below grade_1946-1960">
<overall_u_value units="W/m2 K">1.243</overall_u_value> <overall_u_value units="W/m2 K">1.243</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="basement_wall" id="24" name="wall below grade_before 1946"> <construction type="basement_wall" id="24" name="wall below grade_before 1946">
<overall_u_value units="W/m2 K">1.425</overall_u_value> <overall_u_value units="W/m2 K">1.425</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
#slab on grade #slab on grade
<construction type="floor" id="25" name="slab on grade_post 2010"> <construction type="floor" id="25" name="slab on grade_post 2010">
<overall_u_value units="W/m2 K">0.512</overall_u_value> <overall_u_value units="W/m2 K">0.512</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="floor" id="26" name="slab on grade_2001-2010"> <construction type="floor" id="26" name="slab on grade_2001-2010">
<overall_u_value units="W/m2 K">0.67</overall_u_value> <overall_u_value units="W/m2 K">0.67</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="floor" id="27" name="slab on grade_1996-2000"> <construction type="floor" id="27" name="slab on grade_1996-2000">
<overall_u_value units="W/m2 K">0.67</overall_u_value> <overall_u_value units="W/m2 K">0.67</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="floor" id="28" name="slab on grade_1984-1995"> <construction type="floor" id="28" name="slab on grade_1984-1995">
<overall_u_value units="W/m2 K">0.848</overall_u_value> <overall_u_value units="W/m2 K">0.848</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="floor" id="29" name="slab on grade_1978-1983"> <construction type="floor" id="29" name="slab on grade_1978-1983">
<overall_u_value units="W/m2 K">0.848</overall_u_value> <overall_u_value units="W/m2 K">0.848</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="floor" id="30" name="slab on grade_1961-1977"> <construction type="floor" id="30" name="slab on grade_1961-1977">
<overall_u_value units="W/m2 K">1.05</overall_u_value> <overall_u_value units="W/m2 K">1.05</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="floor" id="31" name="slab on grade_1946-1960"> <construction type="floor" id="31" name="slab on grade_1946-1960">
<overall_u_value units="W/m2 K">1.154</overall_u_value> <overall_u_value units="W/m2 K">1.154</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
<construction type="floor" id="32" name="slab on grade_before 1946"> <construction type="floor" id="32" name="slab on grade_before 1946">
<overall_u_value units="W/m2 K">1.154</overall_u_value> <overall_u_value units="W/m2 K">1.154</overall_u_value>
<outside_solar_absorptance units="-">0</outside_solar_absorptance>
<shortwave_reflectance units="-">0</shortwave_reflectance>
</construction> </construction>
</constructions> </constructions>
</library> </library>

View File

@ -39,7 +39,7 @@
</window> </window>
</windows> </windows>
<materials> <materials>
<material id="1" name="MAT-CC05 8 HW CONCRETE" lca_id="7"> <material id="1" name="MAT-CC05 8 HW CONCRETE">
<conductivity units="W/m K">1.311</conductivity> <conductivity units="W/m K">1.311</conductivity>
<density units="kg/m3">2240</density> <density units="kg/m3">2240</density>
<specific_heat units="J/kg K">836.8</specific_heat> <specific_heat units="J/kg K">836.8</specific_heat>
@ -47,14 +47,14 @@
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.7</visible_absorptance> <visible_absorptance units="-">0.7</visible_absorptance>
</material> </material>
<material id="2" name="CP02 CARPET PAD" lca_id="7"> <material id="2" name="CP02 CARPET PAD">
<no_mass>true</no_mass> <no_mass>true</no_mass>
<thermal_resistance units="m2 K/W">0.21648</thermal_resistance> <thermal_resistance units="m2 K/W">0.21648</thermal_resistance>
<thermal_absorptance units="-">0.9</thermal_absorptance> <thermal_absorptance units="-">0.9</thermal_absorptance>
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.8</visible_absorptance> <visible_absorptance units="-">0.8</visible_absorptance>
</material> </material>
<material id="3" name="Floor Insulation [4]" lca_id="7"> <material id="3" name="Floor Insulation [4]">
<conductivity units="W/m K">0.045</conductivity> <conductivity units="W/m K">0.045</conductivity>
<density units="kg/m3">265</density> <density units="kg/m3">265</density>
<specific_heat units="J/kg K">836.8</specific_heat> <specific_heat units="J/kg K">836.8</specific_heat>
@ -62,7 +62,7 @@
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.7</visible_absorptance> <visible_absorptance units="-">0.7</visible_absorptance>
</material> </material>
<material id="4" name="1IN Stucco" lca_id="7"> <material id="4" name="1IN Stucco">
<conductivity units="W/m K">0.6918</conductivity> <conductivity units="W/m K">0.6918</conductivity>
<density units="kg/m3">1858</density> <density units="kg/m3">1858</density>
<specific_heat units="J/kg K">837</specific_heat> <specific_heat units="J/kg K">837</specific_heat>
@ -70,7 +70,7 @@
<solar_absorptance units="-">0.92</solar_absorptance> <solar_absorptance units="-">0.92</solar_absorptance>
<visible_absorptance units="-">0.92</visible_absorptance> <visible_absorptance units="-">0.92</visible_absorptance>
</material> </material>
<material id="5" name="8IN Concrete HW" lca_id="7"> <material id="5" name="8IN Concrete HW">
<conductivity units="W/m K">1.7296</conductivity> <conductivity units="W/m K">1.7296</conductivity>
<density units="kg/m3">2243</density> <density units="kg/m3">2243</density>
<specific_heat units="J/kg K">837</specific_heat> <specific_heat units="J/kg K">837</specific_heat>
@ -78,7 +78,7 @@
<solar_absorptance units="-">0.65</solar_absorptance> <solar_absorptance units="-">0.65</solar_absorptance>
<visible_absorptance units="-">0.65</visible_absorptance> <visible_absorptance units="-">0.65</visible_absorptance>
</material> </material>
<material id="6" name="Wall Insulation [37]" lca_id="7"> <material id="6" name="Wall Insulation [37]">
<conductivity units="W/m K">0.0432</conductivity> <conductivity units="W/m K">0.0432</conductivity>
<density units="kg/m3">91</density> <density units="kg/m3">91</density>
<specific_heat units="J/kg K">837</specific_heat> <specific_heat units="J/kg K">837</specific_heat>
@ -86,7 +86,7 @@
<solar_absorptance units="-">0.5</solar_absorptance> <solar_absorptance units="-">0.5</solar_absorptance>
<visible_absorptance units="-">0.5</visible_absorptance> <visible_absorptance units="-">0.5</visible_absorptance>
</material> </material>
<material id="7" name="1/2IN Gypsum" lca_id="7"> <material id="7" name="1/2IN Gypsum">
<conductivity units="W/m K">0.16</conductivity> <conductivity units="W/m K">0.16</conductivity>
<density units="kg/m3">784.9</density> <density units="kg/m3">784.9</density>
<specific_heat units="J/kg K">830</specific_heat> <specific_heat units="J/kg K">830</specific_heat>
@ -94,7 +94,7 @@
<solar_absorptance units="-">0.92</solar_absorptance> <solar_absorptance units="-">0.92</solar_absorptance>
<visible_absorptance units="-">0.92</visible_absorptance> <visible_absorptance units="-">0.92</visible_absorptance>
</material> </material>
<material id="8" name="Wood Siding" lca_id="7"> <material id="8" name="Wood Siding">
<conductivity units="W/m K">0.11</conductivity> <conductivity units="W/m K">0.11</conductivity>
<density units="kg/m3">544.62</density> <density units="kg/m3">544.62</density>
<specific_heat units="J/kg K">1210</specific_heat> <specific_heat units="J/kg K">1210</specific_heat>
@ -102,7 +102,7 @@
<solar_absorptance units="-">0.78</solar_absorptance> <solar_absorptance units="-">0.78</solar_absorptance>
<visible_absorptance units="-">0.78</visible_absorptance> <visible_absorptance units="-">0.78</visible_absorptance>
</material> </material>
<material id="9" name="Wood Shingles" lca_id="7"> <material id="9" name="Wood Shingles">
<conductivity units="W/m K">0.115</conductivity> <conductivity units="W/m K">0.115</conductivity>
<density units="kg/m3">513</density> <density units="kg/m3">513</density>
<specific_heat units="J/kg K">1255</specific_heat> <specific_heat units="J/kg K">1255</specific_heat>
@ -110,7 +110,7 @@
<solar_absorptance units="-">0.78</solar_absorptance> <solar_absorptance units="-">0.78</solar_absorptance>
<visible_absorptance units="-">0.78</visible_absorptance> <visible_absorptance units="-">0.78</visible_absorptance>
</material> </material>
<material id="10" name="1IN Wood Decking" lca_id="7"> <material id="10" name="1IN Wood Decking">
<conductivity units="W/m K">0.1211</conductivity> <conductivity units="W/m K">0.1211</conductivity>
<density units="kg/m3">593</density> <density units="kg/m3">593</density>
<specific_heat units="J/kg K">2510</specific_heat> <specific_heat units="J/kg K">2510</specific_heat>
@ -118,7 +118,7 @@
<solar_absorptance units="-">0.78</solar_absorptance> <solar_absorptance units="-">0.78</solar_absorptance>
<visible_absorptance units="-">0.78</visible_absorptance> <visible_absorptance units="-">0.78</visible_absorptance>
</material> </material>
<material id="11" name="Roof Insulation [23]" lca_id="7"> <material id="11" name="Roof Insulation [23]">
<conductivity units="W/m K">0.049</conductivity> <conductivity units="W/m K">0.049</conductivity>
<density units="kg/m3">265</density> <density units="kg/m3">265</density>
<specific_heat units="J/kg K">836.8</specific_heat> <specific_heat units="J/kg K">836.8</specific_heat>
@ -126,14 +126,14 @@
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.7</visible_absorptance> <visible_absorptance units="-">0.7</visible_absorptance>
</material> </material>
<material id="12" name="MAT-SHEATH" lca_id="7"> <material id="12" name="MAT-SHEATH">
<no_mass>true</no_mass> <no_mass>true</no_mass>
<thermal_resistance units="m2 K/W">0.36256</thermal_resistance> <thermal_resistance units="m2 K/W">0.36256</thermal_resistance>
<thermal_absorptance units="-">0.9</thermal_absorptance> <thermal_absorptance units="-">0.9</thermal_absorptance>
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.7</visible_absorptance> <visible_absorptance units="-">0.7</visible_absorptance>
</material> </material>
<material id="14" name="Metal Decking" lca_id="7"> <material id="14" name="Metal Decking">
<conductivity units="W/m K">45.006</conductivity> <conductivity units="W/m K">45.006</conductivity>
<density units="kg/m3">7680</density> <density units="kg/m3">7680</density>
<specific_heat units="J/kg K">418.4</specific_heat> <specific_heat units="J/kg K">418.4</specific_heat>
@ -141,7 +141,7 @@
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.3</visible_absorptance> <visible_absorptance units="-">0.3</visible_absorptance>
</material> </material>
<material id="15" name="Roof Membrane" lca_id="7"> <material id="15" name="Roof Membrane">
<conductivity units="W/m K">0.16</conductivity> <conductivity units="W/m K">0.16</conductivity>
<density units="kg/m3">1121.29</density> <density units="kg/m3">1121.29</density>
<specific_heat units="J/kg K">1460</specific_heat> <specific_heat units="J/kg K">1460</specific_heat>
@ -149,28 +149,28 @@
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.7</visible_absorptance> <visible_absorptance units="-">0.7</visible_absorptance>
</material> </material>
<material id="16" name="CP02 CARPET PAD" lca_id="7"> <material id="16" name="CP02 CARPET PAD">
<no_mass>true</no_mass> <no_mass>true</no_mass>
<thermal_resistance units="m2 K/W">0.21648</thermal_resistance> <thermal_resistance units="m2 K/W">0.21648</thermal_resistance>
<thermal_absorptance units="-">0.9</thermal_absorptance> <thermal_absorptance units="-">0.9</thermal_absorptance>
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.8</visible_absorptance> <visible_absorptance units="-">0.8</visible_absorptance>
</material> </material>
<material id="18" name="CP02 CARPET PAD" lca_id="7"> <material id="18" name="CP02 CARPET PAD">
<no_mass>true</no_mass> <no_mass>true</no_mass>
<thermal_resistance units="m2 K/W">0.21648</thermal_resistance> <thermal_resistance units="m2 K/W">0.21648</thermal_resistance>
<thermal_absorptance units="-">0.9</thermal_absorptance> <thermal_absorptance units="-">0.9</thermal_absorptance>
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.8</visible_absorptance> <visible_absorptance units="-">0.8</visible_absorptance>
</material> </material>
<material id="20" name="CP02 CARPET PAD" lca_id="7"> <material id="20" name="CP02 CARPET PAD">
<no_mass>true</no_mass> <no_mass>true</no_mass>
<thermal_resistance units="m2 K/W">0.21648</thermal_resistance> <thermal_resistance units="m2 K/W">0.21648</thermal_resistance>
<thermal_absorptance units="-">0.9</thermal_absorptance> <thermal_absorptance units="-">0.9</thermal_absorptance>
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.8</visible_absorptance> <visible_absorptance units="-">0.8</visible_absorptance>
</material> </material>
<material id="21" name="Wall Insulation [38]" lca_id="7"> <material id="21" name="Wall Insulation [38]">
<conductivity units="W/m K">0.045</conductivity> <conductivity units="W/m K">0.045</conductivity>
<density units="kg/m3">265</density> <density units="kg/m3">265</density>
<specific_heat units="J/kg K">836.8</specific_heat> <specific_heat units="J/kg K">836.8</specific_heat>
@ -178,7 +178,7 @@
<solar_absorptance units="-">0.7</solar_absorptance> <solar_absorptance units="-">0.7</solar_absorptance>
<visible_absorptance units="-">0.7</visible_absorptance> <visible_absorptance units="-">0.7</visible_absorptance>
</material> </material>
<material id="22" name="metal siding" lca_id="7"> <material id="22" name="metal siding">
<conductivity units="W/m K">44.96</conductivity> <conductivity units="W/m K">44.96</conductivity>
<density units="kg/m3">7688.86</density> <density units="kg/m3">7688.86</density>
<specific_heat units="J/kg K">410</specific_heat> <specific_heat units="J/kg K">410</specific_heat>

View File

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<greenery:GreeneryCatalog xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:greenery="http://ca.concordia/greenerycatalog">
<plantCategories name="Flowers">
<plants name="Camellia Sasanqua" height="0.4 m" leafAreaIndex="2.18" leafReflectivity="0.2" leafEmissivity="0.9" minimalStomatalResistance="288 s/m" growsOn="//@soils.0 //@soils.2 //@soils.4 //@soils.3 //@soils.1"/>
<plants name="Rhododendron" height="0.5 m" leafAreaIndex="1.85" minimalStomatalResistance="161 s/m" growsOn="//@soils.0 //@soils.3"/>
<plants name="Ligustrum Japonicum 'Howardii' " height="0.48 m" leafAreaIndex="4.93" minimalStomatalResistance="172 s/m" growsOn="//@soils.0 //@soils.3"/>
<plants name="Viburnum Dilatatum (Thunb)" height="0.7 m" leafAreaIndex="5" minimalStomatalResistance="212 s/m" growsOn="//@soils.0 //@soils.3 //@soils.2 //@soils.4 //@soils.1"/>
<plants name="Lorpetalum Chinense var. Rubrum" height="0.7 m" leafAreaIndex="2" leafReflectivity="0.1" minimalStomatalResistance="228 s/m" growsOn="//@soils.0 //@soils.2 //@soils.3 //@soils.1"/>
<plants name="Buxus sinica" height="0.45 m" leafAreaIndex="4.03" minimalStomatalResistance="165 s/m" growsOn="//@soils.2 //@soils.0 //@soils.3 //@soils.5 //@soils.1"/>
<plants name="Sedum acre" height="0.1 m" leafAreaIndex="3.5" leafReflectivity="0.36" leafEmissivity="0.9" growsOn="//@soils.2 //@soils.0 //@soils.1 //@soils.3"/>
<plants name="Frankenia thymifolia" height="0.15 m" leafAreaIndex="3.6" leafReflectivity="0.32" leafEmissivity="0.83" growsOn="//@soils.2 //@soils.1 //@soils.0 //@soils.3"/>
<plants name="Vinca major" leafAreaIndex="2.7" leafReflectivity="0.25" leafEmissivity="0.78" growsOn="//@soils.2 //@soils.0 //@soils.3 //@soils.1"/>
<plants name="Ivy (hedera helix)" height="0.1 m" leafAreaIndex="5" growsOn="//@soils.4 //@soils.1 //@soils.2 //@soils.0 //@soils.3"/>
</plantCategories>
<plantCategories name="Grass">
<plants name="Lawn" height="0.06 m" leafAreaIndex="1.4" leafReflectivity="0.1" minimalStomatalResistance="50 s/m" growsOn="//@soils.2"/>
</plantCategories>
<plantCategories name="Farming">
<plants name="Strawberry" growsOn="//@soils.2"/>
<plants name="Tomato" leafEmissivity="0.8" growsOn="//@soils.2 //@soils.3"/>
<plants name="Lettuce" growsOn="//@soils.2"/>
</plantCategories>
<vegetationCategories name="Urban Greening">
<vegetationTemplates name="Grass" soil="//@soils.1" management="Extensive">
<plants plant="//@plantCategories.1/@plants.0"/>
</vegetationTemplates>
</vegetationCategories>
<vegetationCategories name="Green Facade">
<vegetationTemplates name="Green Facade" soil="//@soils.2">
<plants percentage="100" plant="//@plantCategories.0/@plants.9"/>
</vegetationTemplates>
</vegetationCategories>
<vegetationCategories name="GreenRoof">
<vegetationTemplates name="Green Roof" thicknessOfSoil="20 cm" soil="//@soils.2">
<plants percentage="10" plant="//@plantCategories.0/@plants.5"/>
<plants percentage="10" plant="//@plantCategories.0/@plants.0"/>
<plants percentage="10" plant="//@plantCategories.0/@plants.8"/>
<plants percentage="10" plant="//@plantCategories.0/@plants.2"/>
<plants percentage="10" plant="//@plantCategories.0/@plants.4"/>
<plants percentage="10" plant="//@plantCategories.0/@plants.6"/>
<plants percentage="10" plant="//@plantCategories.0/@plants.1"/>
<plants percentage="10" plant="//@plantCategories.0/@plants.3"/>
<plants percentage="20" plant="//@plantCategories.0/@plants.7"/>
</vegetationTemplates>
</vegetationCategories>
<vegetationCategories name="Rooftop Farming">
<vegetationTemplates name="Rooftop Farming" thicknessOfSoil="30 cm" soil="//@soils.2">
<plants percentage="19" plant="//@plantCategories.2/@plants.0"/>
<plants percentage="60" plant="//@plantCategories.2/@plants.1"/>
<plants percentage="21" plant="//@plantCategories.2/@plants.2"/>
</vegetationTemplates>
</vegetationCategories>
<soils name="Sand" conductivityOfDrySoil="1.26 W/(m·K)" saturationVolumetricMoistureContent="0.43" residualVolumetricMoistureContent="0.045"/>
<soils name="Loamy sand" conductivityOfDrySoil="0.35 W/(m·K)" saturationVolumetricMoistureContent="0.41" residualVolumetricMoistureContent="0.057"/>
<soils name="Loam" conductivityOfDrySoil="0.67 W/(m·K)" specificHeatOfDrySoil="900 J/(kg·K)" thermalAbsorptance="0.9" saturationVolumetricMoistureContent="0.43" residualVolumetricMoistureContent="0.078"/>
<soils name="Sandy Loam" conductivityOfDrySoil="1.06 W/(m·K)" saturationVolumetricMoistureContent="0.41" residualVolumetricMoistureContent="0.065"/>
<soils name="Clay loam" conductivityOfDrySoil="0.7 W/(m·K)" saturationVolumetricMoistureContent="0.41" residualVolumetricMoistureContent="0.095"/>
<soils name="Silt" conductivityOfDrySoil="0.35 W/(m·K)" saturationVolumetricMoistureContent="0.46" residualVolumetricMoistureContent="0.034"/>
</greenery:GreeneryCatalog>

View File

@ -1,394 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<library name="LCA"> <library name="LCA">
<building_materials>
<material type = "brick" id="1" name= "clay brick">
<density unit= "ton/m3"> 1.8 </density>
<embodied_carbon unit= "kgCO2/ton"> 560 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "brick" id="2" name= "light clay brick">
<density unit= "ton/m3"> 1.2 </density>
<embodied_carbon unit= "kgCO2/ton"> 310 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "brick" id="3" name= "refractory">
<density unit= "ton/m3"> 2 </density>
<embodied_carbon unit= "kgCO2/ton"> 3080 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "brick" id="4" name= "sand-lime brick">
<density unit= "ton/m3"> 1.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 300 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="5" name= "light weight expanded clay">
<density unit= "ton/m3"> 1.6 </density>
<embodied_carbon unit= "kgCO2/ton"> 900 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="6" name= "lightweight Expanded perlite">
<density unit= "ton/m3"> 1.6 </density>
<embodied_carbon unit= "kgCO2/ton"> 2340 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="7" name= "lightweight expanded vermiculite">
<density unit= "ton/m3"> 1.6 </density>
<embodied_carbon unit= "kgCO2/ton"> 1570 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="8" name= "lightweight polystyrene">
<density unit= "ton/m3"> 1.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 1840 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="9" name= "lightweight pumice">
<density unit= "ton/m3"> 1.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 410 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="10" name= "concrete 20 MPa">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 160 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="11" name= "concrete 25 MPa">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 170 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="12" name= "concrete 30-32 MPa">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 230 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="13" name= "concrete 35 MPae">
<density unit= "ton/m3"> 2.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 240 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="14" name= "concrete 50 MPa">
<density unit= "ton/m3"> 2.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 280 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="15" name= "concrete block">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 170 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="16" name= "concrete roof tile">
<density unit= "ton/m3"> 1.2 </density>
<embodied_carbon unit= "kgCO2/ton"> 440 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "glass" id="17" name= "flat glass, coated">
<density unit= "ton/m3"> 2.58 </density>
<embodied_carbon unit= "kgCO2/ton"> 2660 </embodied_carbon>
<recycling_ratio> 0.95 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.05 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "glass" id="18" name= "glass fibre">
<density unit= "ton/m3"> 2.58 </density>
<embodied_carbon unit= "kgCO2/ton"> 5260 </embodied_carbon>
<recycling_ratio> 0.95 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.05 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="19" name= "cellulose fibre">
<density unit= "ton/m3"> 0.06 </density>
<embodied_carbon unit= "kgCO2/ton"> 1760 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="20" name= "cork slab">
<density unit= "ton/m3"> 0.122 </density>
<embodied_carbon unit= "kgCO2/ton"> 3080 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="21" name= "polystyren foam">
<density unit= "ton/m3"> 0.028 </density>
<embodied_carbon unit= "kgCO2/ton"> 3180 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="22" name= "polystyrene 10% recycled">
<density unit= "ton/m3"> 0.024 </density>
<embodied_carbon unit= "kgCO2/ton"> 5140 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="23" name= "stone wool">
<density unit= "ton/m3"> 0.1 </density>
<embodied_carbon unit= "kgCO2/ton"> 6040 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="24" name= "foam glass">
<density unit= "ton/m3"> 0.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 5380 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="25" name= "glass wool mat">
<density unit= "ton/m3"> 0.032 </density>
<embodied_carbon unit= "kgCO2/ton"> 2150 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="26" name= "fiberboard, hard">
<density unit= "ton/m3"> 0.9 </density>
<embodied_carbon unit= "kgCO2/ton"> 3420 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="27" name= "three layerd laminated board">
<density unit= "ton/m3"> 0.7 </density>
<embodied_carbon unit= "kgCO2/ton"> 1430 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="28" name= "fibreboard, soft">
<density unit= "ton/m3"> 0.65 </density>
<embodied_carbon unit= "kgCO2/ton"> 2780 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="29" name= "plywood">
<density unit= "ton/m3"> 0.72 </density>
<embodied_carbon unit= "kgCO2/ton"> 2190 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="30" name= "acrylic filler">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 1070 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="31" name= "anhydrite floor">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 240 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="32" name= "base plaster">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 430 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="33" name= "cement cast plaster floor">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 340 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="34" name= "cement tile">
<density unit= "ton/m3"> 1.2 </density>
<embodied_carbon unit= "kgCO2/ton"> 440 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="35" name= "ceramic tile">
<density unit= "ton/m3"> 2.1 </density>
<embodied_carbon unit= "kgCO2/ton"> 1410 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="36" name= "clay plaster">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 250 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="37" name= "fiber cement corrugated slab">
<density unit= "ton/m3"> 1.44 </density>
<embodied_carbon unit= "kgCO2/ton"> 1480 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="38" name= "fiber cement facing tile">
<density unit= "ton/m3"> 1.44 </density>
<embodied_carbon unit= "kgCO2/ton"> 2220 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="39" name= "gypsum fibreboard">
<density unit= "ton/m3"> 1.27 </density>
<embodied_carbon unit= "kgCO2/ton"> 3960 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="40" name= "gypsum plaster board">
<density unit= "ton/m3"> 1.15 </density>
<embodied_carbon unit= "kgCO2/ton"> 760 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "metal" id="41" name= "steel">
<density unit= "ton/m3"> 8 </density>
<embodied_carbon unit= "kgCO2/ton"> 3160 </embodied_carbon>
<recycling_ratio> 0.98</recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.02 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "metal" id="42" name= "aluminium">
<density unit= "ton/m3"> 2.7 </density>
<embodied_carbon unit= "kgCO2/ton"> 5370 </embodied_carbon>
<recycling_ratio> 0.98</recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.02 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "metal" id="43" name= "reinforcing steel">
<density unit= "ton/m3"> 7.85 </density>
<embodied_carbon unit= "kgCO2/ton"> 3910 </embodied_carbon>
<recycling_ratio> 0.98</recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.02 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
</building_materials>
<fuels> <fuels>
<fuel id="1" name= "Black_coal"> <fuel id="1" name= "Black_coal">
<carbon_emission_factor unit= "kgCO2/ kWh" > 0.32 </carbon_emission_factor> <carbon_emission_factor unit= "kgCO2/ kWh" > 0.32 </carbon_emission_factor>
@ -556,4 +167,393 @@
<carbon_emission_factor unit= "kgCO2/kWh"> 1.00000 </carbon_emission_factor> <carbon_emission_factor unit= "kgCO2/kWh"> 1.00000 </carbon_emission_factor>
</vehicle> </vehicle>
</vehicles> </vehicles>
<building_materials>
<material type = "brick" id="1" name= "clay brick">
<density unit= "ton/m3"> 1.8 </density>
<embodied_carbon unit= "kgCO2/ton"> 560 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "brick" id="2" name= "light clay brick">
<density unit= "ton/m3"> 1.2 </density>
<embodied_carbon unit= "kgCO2/ton"> 310 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "brick" id="3" name= "refractory">
<density unit= "ton/m3"> 2 </density>
<embodied_carbon unit= "kgCO2/ton"> 3080 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "brick" id="4" name= "sand-lime brick">
<density unit= "ton/m3"> 1.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 300 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
<company_recycling_ratio> 0.7 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="1" name= "light weight expanded clay">
<density unit= "ton/m3"> 1.6 </density>
<embodied_carbon unit= "kgCO2/ton"> 900 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="2" name= "lightweight Expanded perlite">
<density unit= "ton/m3"> 1.6 </density>
<embodied_carbon unit= "kgCO2/ton"> 2340 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="3" name= "lightweight expanded vermiculite">
<density unit= "ton/m3"> 1.6 </density>
<embodied_carbon unit= "kgCO2/ton"> 1570 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="4" name= "lightweight polystyrene">
<density unit= "ton/m3"> 1.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 1840 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="5" name= "lightweight pumice">
<density unit= "ton/m3"> 1.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 410 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="6" name= "concrete 20 MPa">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 160 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="7" name= "concrete 25 MPa">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 170 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="8" name= "concrete 30-32 MPa">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 230 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="9" name= "concrete 35 MPae">
<density unit= "ton/m3"> 2.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 240 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="10" name= "concrete 50 MPa">
<density unit= "ton/m3"> 2.4 </density>
<embodied_carbon unit= "kgCO2/ton"> 280 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="11" name= "concrete block">
<density unit= "ton/m3"> 2.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 170 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "concrete" id="12" name= "concrete roof tile">
<density unit= "ton/m3"> 1.2 </density>
<embodied_carbon unit= "kgCO2/ton"> 440 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "glass" id="1" name= "flat glass, coated">
<density unit= "ton/m3"> 2.58 </density>
<embodied_carbon unit= "kgCO2/ton"> 2660 </embodied_carbon>
<recycling_ratio> 0.95 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.05 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "glass" id="2" name= "glass fibre">
<density unit= "ton/m3"> 2.58 </density>
<embodied_carbon unit= "kgCO2/ton"> 5260 </embodied_carbon>
<recycling_ratio> 0.95 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.05 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="1" name= "cellulose fibre">
<density unit= "ton/m3"> 0.06 </density>
<embodied_carbon unit= "kgCO2/ton"> 1760 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="2" name= "cork slab">
<density unit= "ton/m3"> 0.122 </density>
<embodied_carbon unit= "kgCO2/ton"> 3080 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="3" name= "polystyren foam">
<density unit= "ton/m3"> 0.028 </density>
<embodied_carbon unit= "kgCO2/ton"> 3180 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="4" name= "polystyrene 10% recycled">
<density unit= "ton/m3"> 0.024 </density>
<embodied_carbon unit= "kgCO2/ton"> 5140 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="5" name= "stone wool">
<density unit= "ton/m3"> 0.1 </density>
<embodied_carbon unit= "kgCO2/ton"> 6040 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="6" name= "foam glass">
<density unit= "ton/m3"> 0.3 </density>
<embodied_carbon unit= "kgCO2/ton"> 5380 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "insulation" id="7" name= "glass wool mat">
<density unit= "ton/m3"> 0.032 </density>
<embodied_carbon unit= "kgCO2/ton"> 2150 </embodied_carbon>
<recycling_ratio> 0.9 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="1" name= "fiberboard, hard">
<density unit= "ton/m3"> 0.9 </density>
<embodied_carbon unit= "kgCO2/ton"> 3420 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="2" name= "three layerd laminated board">
<density unit= "ton/m3"> 0.7 </density>
<embodied_carbon unit= "kgCO2/ton"> 1430 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="3" name= "fibreboard, soft">
<density unit= "ton/m3"> 0.65 </density>
<embodied_carbon unit= "kgCO2/ton"> 2780 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="4" name= "plywood">
<density unit= "ton/m3"> 0.72 </density>
<embodied_carbon unit= "kgCO2/ton"> 2190 </embodied_carbon>
<recycling_ratio> 0.6 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.4 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="1" name= "acrylic filler">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 1070 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="2" name= "anhydrite floor">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 240 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="3" name= "base plaster">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 430 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="4" name= "cement cast plaster floor">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 340 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="5" name= "cement tile">
<density unit= "ton/m3"> 1.2 </density>
<embodied_carbon unit= "kgCO2/ton"> 440 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="6" name= "ceramic tile">
<density unit= "ton/m3"> 2.1 </density>
<embodied_carbon unit= "kgCO2/ton"> 1410 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="7" name= "clay plaster">
<density unit= "ton/m3"> 1.43 </density>
<embodied_carbon unit= "kgCO2/ton"> 250 </embodied_carbon>
<recycling_ratio> 0 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 0 </company_recycling_ratio>
<landfilling_ratio> 1 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="8" name= "fiber cement corrugated slab">
<density unit= "ton/m3"> 1.44 </density>
<embodied_carbon unit= "kgCO2/ton"> 1480 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="9" name= "fiber cement facing tile">
<density unit= "ton/m3"> 1.44 </density>
<embodied_carbon unit= "kgCO2/ton"> 2220 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "wood" id="10" name= "gypsum fibreboard">
<density unit= "ton/m3"> 1.27 </density>
<embodied_carbon unit= "kgCO2/ton"> 3960 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "covering" id="11" name= "gypsum plaster board">
<density unit= "ton/m3"> 1.15 </density>
<embodied_carbon unit= "kgCO2/ton"> 760 </embodied_carbon>
<recycling_ratio> 0.8 </recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.2 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "metal" id="1" name= "steel">
<density unit= "ton/m3"> 8 </density>
<embodied_carbon unit= "kgCO2/ton"> 3160 </embodied_carbon>
<recycling_ratio> 0.98</recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.02 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "metal" id="2" name= "aluminium">
<density unit= "ton/m3"> 2.7 </density>
<embodied_carbon unit= "kgCO2/ton"> 5370 </embodied_carbon>
<recycling_ratio> 0.98</recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.02 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
<material type = "metal" id="3" name= "reinforcing steel">
<density unit= "ton/m3"> 7.85 </density>
<embodied_carbon unit= "kgCO2/ton"> 3910 </embodied_carbon>
<recycling_ratio> 0.98</recycling_ratio>
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
<company_recycling_ratio> 1 </company_recycling_ratio>
<landfilling_ratio> 0.02 </landfilling_ratio>
<cost unit= "...."> .... </cost>
</material>
</building_materials>
</library> </library>

Binary file not shown.

View File

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

View File

@ -329,7 +329,7 @@ class EnergyAde:
}, },
'energy:area': { 'energy:area': {
'@uom': 'm2', '@uom': 'm2',
'#text': f'{thermal_boundary.area}' '#text': f'{thermal_boundary.opaque_area}'
}, },
'energy:surfaceGeometry': { 'energy:surfaceGeometry': {
'gml:MultiSurface': { 'gml:MultiSurface': {

View File

@ -105,3 +105,19 @@ class ConfigurationHelper:
:return: 0.1 :return: 0.1
""" """
return self._config.getfloat('buildings', 'comnet_occupancy_sensible_radiant').real return self._config.getfloat('buildings', 'comnet_occupancy_sensible_radiant').real
@property
def convective_heat_transfer_coefficient_interior(self) -> float:
"""
Get configured convective heat transfer coefficient for surfaces inside the building
:return: 3.5
"""
return self._config.getfloat('buildings', 'convective_heat_transfer_coefficient_interior').real
@property
def convective_heat_transfer_coefficient_exterior(self) -> float:
"""
Get configured convective heat transfer coefficient for surfaces outside the building
:return: 20
"""
return self._config.getfloat('buildings', 'convective_heat_transfer_coefficient_exterior').real

View File

@ -11,6 +11,7 @@ KELVIN = 273.15
HOUR_TO_MINUTES = 60 HOUR_TO_MINUTES = 60
METERS_TO_FEET = 3.28084 METERS_TO_FEET = 3.28084
BTU_H_TO_WATTS = 0.29307107 BTU_H_TO_WATTS = 0.29307107
KILO_WATTS_HOUR_TO_JULES = 3600000
# time # time
SECOND = 'second' SECOND = 'second'
@ -57,39 +58,66 @@ WINDOW = 'Window'
DOOR = 'Door' DOOR = 'Door'
SKYLIGHT = 'Skylight' SKYLIGHT = 'Skylight'
# todo: homogenize function and usage!! # functions and usages
# function SINGLE_FAMILY_HOUSE = 'single family house'
RESIDENTIAL = 'residential' MULTI_FAMILY_HOUSE = 'multifamily house'
SFH = 'single family house' ROW_HOSE = 'row house'
MFH = 'multifamily house' MID_RISE_APARTMENT = 'mid rise apartment'
HOTEL = 'hotel' HIGH_RISE_APARTMENT = 'high rise apartment'
HOSPITAL = 'hospital' SMALL_OFFICE = 'small office'
OUTPATIENT = 'outpatient' MEDIUM_OFFICE = 'medium office'
COMMERCIAL = 'commercial' LARGE_OFFICE = 'large office'
STRIP_MALL = 'strip mall'
WAREHOUSE = 'warehouse'
PRIMARY_SCHOOL = 'primary school' PRIMARY_SCHOOL = 'primary school'
SECONDARY_SCHOOL = 'secondary school' SECONDARY_SCHOOL = 'secondary school'
OFFICE = 'office' STAND_ALONE_RETAIL = 'stand alone retail'
LARGE_OFFICE = 'large office' HOSPITAL = 'hospital'
OFFICE_WORKSHOP = 'office/workshop' OUT_PATIENT_HEALTH_CARE = 'out-patient health care'
STRIP_MALL = 'strip mall'
# usage SUPERMARKET = 'supermarket'
INDUSTRY = 'industry' WAREHOUSE = 'warehouse'
OFFICE_ADMINISTRATION = 'office and administration' QUICK_SERVICE_RESTAURANT = 'quick service restaurant'
HEALTH_CARE = 'health care' FULL_SERVICE_RESTAURANT = 'full service restaurant'
RETAIL = 'retail' SMALL_HOTEL = 'small hotel'
HALL = 'hall' LARGE_HOTEL = 'large hotel'
RESTAURANT = 'restaurant' RESIDENTIAL = 'residential'
EDUCATION = 'education' 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' LIGHTING = 'Lights'
OCCUPANCY = 'Occupancy' OCCUPANCY = 'Occupancy'
RECEPTACLE = 'Receptacle' APPLIANCES = 'Appliances'
HVAC_AVAILABILITY = 'HVAC Avail' HVAC_AVAILABILITY = 'HVAC Avail'
INFILTRATION = 'Infiltration' INFILTRATION = 'Infiltration'
COOLING_SET_POINT = 'ClgSetPt' COOLING_SET_POINT = 'ClgSetPt'
HEATING_SET_POINT = 'HtgSetPt' HEATING_SET_POINT = 'HtgSetPt'
# todo: are any of these two the receptacle concept??
EQUIPMENT = 'Equipment' EQUIPMENT = 'Equipment'
ACTIVITY = 'Activity' ACTIVITY = 'Activity'
# Geometry
EPSILON = 0.0000001
# HVAC types
ONLY_HEATING = 'Heating'
ONLY_COOLING = 'Colling'
ONLY_VENTILATION = 'Ventilation'
HEATING_AND_VENTILATION = 'Heating and ventilation'
COOLING_AND_VENTILATION = 'Cooling and ventilation'
HEATING_AND_COLLING = 'Heating and cooling'
FULL_HVAC = 'Heating and cooling and ventilation'

View File

@ -5,7 +5,7 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
""" """
import calendar as cal import calendar as cal
import pandas as pd import pandas as pd
from city_model_structure.building_demand.occupants import Occupants from city_model_structure.building_demand.occupant import Occupant
import helpers.constants as cte import helpers.constants as cte
@ -34,7 +34,7 @@ class MonthlyToHourlyDemand:
# todo: if these are data frames, then they should be called as (Occupancy should be in low case): # todo: if these are data frames, then they should be called as (Occupancy should be in low case):
# usage_zone.schedules.Occupancy # usage_zone.schedules.Occupancy
# self._conditioning_seasons.heating # self._conditioning_seasons.heating
occupancy = Occupants().get_complete_year_schedule(usage_zone.schedules['Occupancy']) occupancy = Occupant().get_complete_year_schedule(usage_zone.schedules['Occupancy'])
heating_schedule = self._conditioning_seasons['heating'] heating_schedule = self._conditioning_seasons['heating']
hourly_heating = [] hourly_heating = []
@ -92,7 +92,7 @@ class MonthlyToHourlyDemand:
for usage_zone in self._building.usage_zones: for usage_zone in self._building.usage_zones:
temp_set = float(usage_zone.cooling_setpoint) temp_set = float(usage_zone.cooling_setpoint)
temp_back = 100 temp_back = 100
occupancy = Occupants().get_complete_year_schedule(usage_zone.schedules['Occupancy']) occupancy = Occupant().get_complete_year_schedule(usage_zone.schedules['Occupancy'])
cooling_schedule = self._conditioning_seasons['cooling'] cooling_schedule = self._conditioning_seasons['cooling']
hourly_cooling = [] hourly_cooling = []

View File

@ -6,7 +6,6 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
import sys import sys
from imports.construction.helpers.construction_helper import ConstructionHelper from imports.construction.helpers.construction_helper import ConstructionHelper
from imports.construction.nrel_physics_interface import NrelPhysicsInterface from imports.construction.nrel_physics_interface import NrelPhysicsInterface
from imports.construction.helpers.storeys_generation import StoreysGeneration
class CaPhysicsParameters(NrelPhysicsInterface): class CaPhysicsParameters(NrelPhysicsInterface):
@ -25,16 +24,24 @@ class CaPhysicsParameters(NrelPhysicsInterface):
city = self._city city = self._city
# it is assumed that all buildings have the same archetypes' keys # it is assumed that all buildings have the same archetypes' keys
for building in city.buildings: for building in city.buildings:
archetype = self._search_archetype(ConstructionHelper.nrcan_from_function(building.function), try:
building.year_of_construction) archetype = self._search_archetype(ConstructionHelper.nrcan_from_libs_function(building.function),
if archetype is None: building.year_of_construction)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: ' sys.stderr.write(f'Building {building.name} has unknown archetype for building function: '
f'{ConstructionHelper.nrcan_from_function(building.function)} ' f'{ConstructionHelper.nrcan_from_libs_function(building.function)} '
f'and building year of construction: {building.year_of_construction}\n') f'and building year of construction: {building.year_of_construction}\n')
continue return
self._create_storeys(building, archetype) # if building has no thermal zones defined from geometry, one thermal zone per storey is assigned
self._assign_values(building, archetype) if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype)
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): def _search_archetype(self, function, year_of_construction):
for building_archetype in self._building_archetypes: for building_archetype in self._building_archetypes:
@ -47,33 +54,29 @@ class CaPhysicsParameters(NrelPhysicsInterface):
return building_archetype return building_archetype
return None return None
def _assign_values(self, building, archetype): def _assign_values(self, internal_zones, archetype):
for thermal_zone in building.thermal_zones: for internal_zone in internal_zones:
thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value for thermal_zone in internal_zone.thermal_zones:
thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value
thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on
for thermal_boundary in thermal_zone.thermal_boundaries: thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off
construction_type = ConstructionHelper.nrcan_construction_types[thermal_boundary.type] for thermal_boundary in thermal_zone.thermal_boundaries:
thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type) construction_type = ConstructionHelper.nrcan_construction_types[thermal_boundary.type]
thermal_boundary.u_value = thermal_boundary_archetype.overall_u_value thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type)
thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance thermal_boundary.u_value = thermal_boundary_archetype.overall_u_value
thermal_boundary.construction_name = thermal_boundary_archetype.construction_name thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance
thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio thermal_boundary.construction_name = thermal_boundary_archetype.construction_name
if thermal_boundary.thermal_openings is not None: try:
for thermal_opening in thermal_boundary.thermal_openings: thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio
if thermal_boundary_archetype.thermal_opening is not None: except ValueError:
thermal_opening_archetype = thermal_boundary_archetype.thermal_opening # This is the normal operation way when the windows are defined in the geometry
thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio continue
thermal_opening.g_value = thermal_opening_archetype.g_value if thermal_boundary.thermal_openings is not None:
thermal_opening.overall_u_value = thermal_opening_archetype.overall_u_value for thermal_opening in thermal_boundary.thermal_openings:
if thermal_boundary_archetype.thermal_opening_archetype is not None:
@staticmethod thermal_opening_archetype = thermal_boundary_archetype.thermal_opening_archetype
def _create_storeys(building, archetype): thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio
building.average_storey_height = archetype.average_storey_height thermal_opening.g_value = thermal_opening_archetype.g_value
building.storeys_above_ground = archetype.storeys_above_ground thermal_opening.overall_u_value = thermal_opening_archetype.overall_u_value
storeys_generation = StoreysGeneration(building)
storeys = storeys_generation.storeys
building.storeys = storeys
storeys_generation.assign_thermal_zones_delimited_by_thermal_boundaries()

View File

@ -1,15 +1,15 @@
""" """
NrelBuildingArchetype stores construction information by building archetypes BuildingArchetype stores construction information by building archetypes
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from typing import List from typing import List
from imports.construction.data_classes.nrel_thermal_boundary_archetype import NrelThermalBoundaryArchetype from imports.construction.data_classes.thermal_boundary_archetype import ThermalBoundaryArchetype
class NrelBuildingArchetype: class BuildingArchetype:
""" """
NrelBuildingArchetype class BuildingArchetype class
""" """
def __init__(self, archetype_keys, average_storey_height, storeys_above_ground, effective_thermal_capacity, def __init__(self, archetype_keys, average_storey_height, storeys_above_ground, effective_thermal_capacity,
additional_thermal_bridge_u_value, indirectly_heated_area_ratio, infiltration_rate_system_off, additional_thermal_bridge_u_value, indirectly_heated_area_ratio, infiltration_rate_system_off,
@ -89,7 +89,7 @@ class NrelBuildingArchetype:
return self._infiltration_rate_system_on return self._infiltration_rate_system_on
@property @property
def thermal_boundary_archetypes(self) -> List[NrelThermalBoundaryArchetype]: def thermal_boundary_archetypes(self) -> List[ThermalBoundaryArchetype]:
""" """
Get thermal boundary archetypes associated to the building archetype Get thermal boundary archetypes associated to the building archetype
:return: list of boundary archetypes :return: list of boundary archetypes

View File

@ -1,17 +1,16 @@
""" """
NrelLayerArchetype stores layer and materials information, complementing the NrelBuildingArchetype class LayerArchetype stores layer and materials information, complementing the BuildingArchetype class
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
class NrelLayerArchetype: class LayerArchetype:
""" """
NrelLayerArchetype class LayerArchetype class
""" """
def __init__(self, name, solar_absorptance, thermal_absorptance, visible_absorptance, thickness=None, def __init__(self, name, solar_absorptance, thermal_absorptance, visible_absorptance, thickness=None,
conductivity=None, specific_heat=None, density=None, no_mass=False, thermal_resistance=None, conductivity=None, specific_heat=None, density=None, no_mass=False, thermal_resistance=None):
lca_id=None):
self._thickness = thickness self._thickness = thickness
self._conductivity = conductivity self._conductivity = conductivity
self._specific_heat = specific_heat self._specific_heat = specific_heat
@ -22,12 +21,11 @@ class NrelLayerArchetype:
self._no_mass = no_mass self._no_mass = no_mass
self._name = name self._name = name
self._thermal_resistance = thermal_resistance self._thermal_resistance = thermal_resistance
self._lca_id = lca_id
@property @property
def thickness(self): def thickness(self):
""" """
Get nrel layer archetype thickness in meters Get thickness in meters
:return: float :return: float
""" """
return self._thickness return self._thickness
@ -35,7 +33,7 @@ class NrelLayerArchetype:
@property @property
def conductivity(self): def conductivity(self):
""" """
Get nrel layer archetype conductivity in W/mK Get conductivity in W/mK
:return: float :return: float
""" """
return self._conductivity return self._conductivity
@ -43,7 +41,7 @@ class NrelLayerArchetype:
@property @property
def specific_heat(self): def specific_heat(self):
""" """
Get nrel layer archetype conductivity in J/kgK Get specific heat in J/kgK
:return: float :return: float
""" """
return self._specific_heat return self._specific_heat
@ -51,7 +49,7 @@ class NrelLayerArchetype:
@property @property
def density(self): def density(self):
""" """
Get nrel layer archetype density in kg/m3 Get density in kg/m3
:return: float :return: float
""" """
return self._density return self._density
@ -59,7 +57,7 @@ class NrelLayerArchetype:
@property @property
def solar_absorptance(self): def solar_absorptance(self):
""" """
Get nrel layer archetype solar absorptance Get solar absorptance
:return: float :return: float
""" """
return self._solar_absorptance return self._solar_absorptance
@ -67,7 +65,7 @@ class NrelLayerArchetype:
@property @property
def thermal_absorptance(self): def thermal_absorptance(self):
""" """
Get nrel layer archetype thermal absorptance Get thermal absorptance
:return: float :return: float
""" """
return self._thermal_absorptance return self._thermal_absorptance
@ -75,7 +73,7 @@ class NrelLayerArchetype:
@property @property
def visible_absorptance(self): def visible_absorptance(self):
""" """
Get nrel layer archetype visible absorptance Get visible absorptance
:return: float :return: float
""" """
return self._visible_absorptance return self._visible_absorptance
@ -83,7 +81,7 @@ class NrelLayerArchetype:
@property @property
def no_mass(self) -> bool: def no_mass(self) -> bool:
""" """
Get nrel layer archetype no mass flag Get no mass flag
:return: Boolean :return: Boolean
""" """
return self._no_mass return self._no_mass
@ -91,7 +89,7 @@ class NrelLayerArchetype:
@property @property
def name(self): def name(self):
""" """
Get nrel layer archetype name Get name
:return: str :return: str
""" """
return self._name return self._name
@ -99,15 +97,7 @@ class NrelLayerArchetype:
@property @property
def thermal_resistance(self): def thermal_resistance(self):
""" """
Get nrel layer archetype thermal resistance in m2K/W Get thermal resistance in m2K/W
:return: float :return: float
""" """
return self._thermal_resistance return self._thermal_resistance
@property
def lca_id(self):
"""
Get nrel lca_id equivalent for the material
:return: int
"""
return self._lca_id

View File

@ -1,99 +0,0 @@
"""
NrelThermalBoundaryArchetype stores thermal boundaries information, complementing the NrelBuildingArchetype class
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import List
from imports.construction.data_classes.nrel_layer_archetype import NrelLayerArchetype
from imports.construction.data_classes.nrel_thermal_opening_archetype import NrelThermalOpeningArchetype
class NrelThermalBoundaryArchetype:
"""
NrelThermalBoundaryArchetype class
"""
def __init__(self, boundary_type, window_ratio, construction_name, layers, thermal_opening,
outside_solar_absorptance=None, outside_thermal_absorptance=None, outside_visible_absorptance=None,
overall_u_value=None):
self._boundary_type = boundary_type
self._outside_solar_absorptance = outside_solar_absorptance
self._outside_thermal_absorptance = outside_thermal_absorptance
self._outside_visible_absorptance = outside_visible_absorptance
self._window_ratio = window_ratio
self._construction_name = construction_name
self._overall_u_value = overall_u_value
self._layers = layers
self._thermal_opening = thermal_opening
@property
def boundary_type(self):
"""
Get nrel thermal boundary archetype type
:return: str
"""
return self._boundary_type
@property
def outside_solar_absorptance(self):
"""
Get nrel thermal boundary archetype outside solar absorptance
:return: float
"""
return self._outside_solar_absorptance
@property
def outside_thermal_absorptance(self):
"""
Get nrel thermal boundary archetype outside thermal absorptance
:return: float
"""
return self._outside_thermal_absorptance
@property
def outside_visible_absorptance(self):
"""
Get nrel thermal boundary archetype outside visible absorptance
:return: float
"""
return self._outside_visible_absorptance
@property
def window_ratio(self):
"""
Get nrel thermal boundary archetype window ratio
:return: float
"""
return self._window_ratio
@property
def construction_name(self):
"""
Get nrel thermal boundary archetype construction name
:return: str
"""
return self._construction_name
@property
def layers(self) -> List[NrelLayerArchetype]:
"""
Get nrel thermal boundary archetype layers
:return: [NrelLayerArchetype]
"""
return self._layers
@property
def thermal_opening(self) -> NrelThermalOpeningArchetype:
"""
Get nrel thermal boundary archetype
:return: NrelThermalOpeningArchetype
"""
return self._thermal_opening
@property
def overall_u_value(self):
"""
Get nrel thermal boundary archetype overall U-value in W/m2K
:return: float
"""
return self._overall_u_value

View File

@ -0,0 +1,136 @@
"""
ThermalBoundaryArchetype stores thermal boundaries information, complementing the BuildingArchetype class
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import List
from imports.construction.data_classes.layer_archetype import LayerArchetype
from imports.construction.data_classes.thermal_opening_archetype import ThermalOpeningArchetype
class ThermalBoundaryArchetype:
"""
ThermalBoundaryArchetype class
"""
def __init__(self, boundary_type, window_ratio, construction_name, layers, thermal_opening,
outside_solar_absorptance=None, outside_thermal_absorptance=None, outside_visible_absorptance=None,
overall_u_value=None, shortwave_reflectance=None, inside_emissivity=None, alpha_coefficient=None,
radiative_coefficient=None):
self._boundary_type = boundary_type
self._outside_solar_absorptance = outside_solar_absorptance
self._outside_thermal_absorptance = outside_thermal_absorptance
self._outside_visible_absorptance = outside_visible_absorptance
self._window_ratio = window_ratio
self._construction_name = construction_name
self._overall_u_value = overall_u_value
self._layers = layers
self._thermal_opening_archetype = thermal_opening
self._shortwave_reflectance = shortwave_reflectance
self._inside_emissivity = inside_emissivity
self._alpha_coefficient = alpha_coefficient
self._radiative_coefficient = radiative_coefficient
@property
def boundary_type(self):
"""
Get type
:return: str
"""
return self._boundary_type
@property
def outside_solar_absorptance(self):
"""
Get outside solar absorptance
:return: float
"""
return self._outside_solar_absorptance
@property
def outside_thermal_absorptance(self):
"""
Get outside thermal absorptance
:return: float
"""
return self._outside_thermal_absorptance
@property
def outside_visible_absorptance(self):
"""
Get outside visible absorptance
:return: float
"""
return self._outside_visible_absorptance
@property
def window_ratio(self):
"""
Get window ratio
:return: float
"""
return self._window_ratio
@property
def construction_name(self):
"""
Get construction name
:return: str
"""
return self._construction_name
@property
def layers(self) -> List[LayerArchetype]:
"""
Get layers
:return: [NrelLayerArchetype]
"""
return self._layers
@property
def thermal_opening_archetype(self) -> ThermalOpeningArchetype:
"""
Get thermal opening archetype
:return: ThermalOpeningArchetype
"""
return self._thermal_opening_archetype
@property
def overall_u_value(self):
"""
Get overall U-value in W/m2K
:return: float
"""
return self._overall_u_value
@property
def shortwave_reflectance(self):
"""
Get shortwave reflectance
:return: float
"""
return self._shortwave_reflectance
@property
def inside_emissivity(self):
"""
Get emissivity inside
:return: float
"""
return self._inside_emissivity
@property
def alpha_coefficient(self):
"""
Get alpha coefficient
:return: float
"""
return self._alpha_coefficient
@property
def radiative_coefficient(self):
"""
Get radiative coefficient
:return: float
"""
return self._radiative_coefficient

View File

@ -1,30 +1,34 @@
""" """
NrelThermalOpeningArchetype stores thermal openings information, complementing the NrelBuildingArchetype class ThermalOpeningArchetype stores thermal openings information, complementing the BuildingArchetype class
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
class NrelThermalOpeningArchetype: class ThermalOpeningArchetype:
""" """
NrelThermalOpeningArchetype class ThermalOpeningArchetype class
""" """
def __init__(self, conductivity=None, frame_ratio=None, g_value=None, thickness=None, def __init__(self, conductivity=None, frame_ratio=None, g_value=None, thickness=None,
back_side_solar_transmittance_at_normal_incidence=None, back_side_solar_transmittance_at_normal_incidence=None,
front_side_solar_transmittance_at_normal_incidence=None, shgc=None, overall_u_value=None): front_side_solar_transmittance_at_normal_incidence=None, overall_u_value=None,
openable_ratio=None, inside_emissivity=None, alpha_coefficient=None, radiative_coefficient=None):
self._conductivity = conductivity self._conductivity = conductivity
self._frame_ratio = frame_ratio self._frame_ratio = frame_ratio
self._g_value = g_value self._g_value = g_value
self._thickness = thickness self._thickness = thickness
self._back_side_solar_transmittance_at_normal_incidence = back_side_solar_transmittance_at_normal_incidence self._back_side_solar_transmittance_at_normal_incidence = back_side_solar_transmittance_at_normal_incidence
self._front_side_solar_transmittance_at_normal_incidence = front_side_solar_transmittance_at_normal_incidence self._front_side_solar_transmittance_at_normal_incidence = front_side_solar_transmittance_at_normal_incidence
self._shgc = shgc
self._overall_u_value = overall_u_value self._overall_u_value = overall_u_value
self._openable_ratio = openable_ratio
self._inside_emissivity = inside_emissivity
self._alpha_coefficient = alpha_coefficient
self._radiative_coefficient = radiative_coefficient
@property @property
def conductivity(self): def conductivity(self):
""" """
Get nrel thermal opening archetype conductivity in W/mK Get conductivity in W/mK
:return: float :return: float
""" """
return self._conductivity return self._conductivity
@ -32,7 +36,7 @@ class NrelThermalOpeningArchetype:
@property @property
def frame_ratio(self): def frame_ratio(self):
""" """
Get nrel thermal opening archetype frame ratio Get frame ratio
:return: float :return: float
""" """
return self._frame_ratio return self._frame_ratio
@ -40,7 +44,7 @@ class NrelThermalOpeningArchetype:
@property @property
def g_value(self): def g_value(self):
""" """
Get nrel thermal opening archetype g-value Get g-value, also called shgc
:return: float :return: float
""" """
return self._g_value return self._g_value
@ -48,7 +52,7 @@ class NrelThermalOpeningArchetype:
@property @property
def thickness(self): def thickness(self):
""" """
Get nrel thermal opening archetype thickness in meters Get thickness in meters
:return: float :return: float
""" """
return self._thickness return self._thickness
@ -56,7 +60,7 @@ class NrelThermalOpeningArchetype:
@property @property
def back_side_solar_transmittance_at_normal_incidence(self): def back_side_solar_transmittance_at_normal_incidence(self):
""" """
Get nrel thermal opening archetype back side solar transmittance at normal incidence Get back side solar transmittance at normal incidence
:return: float :return: float
""" """
return self._back_side_solar_transmittance_at_normal_incidence return self._back_side_solar_transmittance_at_normal_incidence
@ -64,23 +68,47 @@ class NrelThermalOpeningArchetype:
@property @property
def front_side_solar_transmittance_at_normal_incidence(self): def front_side_solar_transmittance_at_normal_incidence(self):
""" """
Get nrel thermal opening archetype front side solar transmittance at normal incidence Get front side solar transmittance at normal incidence
:return: float :return: float
""" """
return self._front_side_solar_transmittance_at_normal_incidence return self._front_side_solar_transmittance_at_normal_incidence
@property
def shgc(self):
"""
Get nrel thermal opening archetype shcg
:return: float
"""
return self._shgc
@property @property
def overall_u_value(self): def overall_u_value(self):
""" """
Get nrel thermal opening archetype overall U-value in W/m2K Get overall U-value in W/m2K
:param value: float :return: float
""" """
return self._overall_u_value return self._overall_u_value
@property
def openable_ratio(self):
"""
Get openable ratio
:return: float
"""
return self._openable_ratio
@property
def inside_emissivity(self):
"""
Get emissivity inside
:return: float
"""
return self._inside_emissivity
@property
def alpha_coefficient(self):
"""
Get alpha coefficient
:return: float
"""
return self._alpha_coefficient
@property
def radiative_coefficient(self):
"""
Get radiative coefficient
:return: float
"""
return self._radiative_coefficient

View File

@ -12,27 +12,35 @@ class ConstructionHelper:
Construction helper Construction helper
""" """
# NREL # NREL
function_to_nrel = { _function_to_nrel = {
cte.RESIDENTIAL: 'residential', cte.RESIDENTIAL: 'residential',
cte.SFH: 'single family house', cte.SINGLE_FAMILY_HOUSE: 'residential',
cte.MFH: 'multifamily house', cte.MULTI_FAMILY_HOUSE: 'residential',
cte.HOTEL: 'hotel', cte.ROW_HOSE: 'residential',
cte.HOSPITAL: 'hospital', cte.MID_RISE_APARTMENT: 'midrise apartment',
cte.OUTPATIENT: 'outpatient', cte.HIGH_RISE_APARTMENT: 'high-rise apartment',
cte.COMMERCIAL: 'commercial', cte.SMALL_OFFICE: 'small office',
cte.STRIP_MALL: 'strip mall', cte.MEDIUM_OFFICE: 'medium office',
cte.WAREHOUSE: 'warehouse', cte.LARGE_OFFICE: 'large office',
cte.PRIMARY_SCHOOL: 'primary school', cte.PRIMARY_SCHOOL: 'primary school',
cte.SECONDARY_SCHOOL: 'secondary school', cte.SECONDARY_SCHOOL: 'secondary school',
cte.OFFICE: 'office', cte.STAND_ALONE_RETAIL: 'stand-alone retail',
cte.LARGE_OFFICE: 'large office' 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_function_default_value = 'residential'
nrel_standards = { _nrel_standards = {
'ASHRAE Std189': 1, 'ASHRAE Std189': 1,
'ASHRAE 90.1_2004': 2 'ASHRAE 90.1_2004': 2
} }
reference_city_to_nrel_climate_zone = { _reference_city_to_nrel_climate_zone = {
'Miami': 'ASHRAE_2004:1A', 'Miami': 'ASHRAE_2004:1A',
'Houston': 'ASHRAE_2004:2A', 'Houston': 'ASHRAE_2004:2A',
'Phoenix': 'ASHRAE_2004:2B', 'Phoenix': 'ASHRAE_2004:2B',
@ -51,6 +59,7 @@ class ConstructionHelper:
'Fairbanks': 'ASHRAE_2004:8A' 'Fairbanks': 'ASHRAE_2004:8A'
} }
nrel_window_types = [cte.WINDOW, cte.DOOR, cte.SKYLIGHT] nrel_window_types = [cte.WINDOW, cte.DOOR, cte.SKYLIGHT]
nrel_construction_types = { nrel_construction_types = {
cte.WALL: 'exterior wall', cte.WALL: 'exterior wall',
cte.INTERIOR_WALL: 'interior wall', cte.INTERIOR_WALL: 'interior wall',
@ -62,24 +71,32 @@ class ConstructionHelper:
} }
# NRCAN # NRCAN
function_to_nrcan = { _function_to_nrcan = {
cte.RESIDENTIAL: 'residential', cte.RESIDENTIAL: 'residential',
cte.SFH: 'single family house', cte.SINGLE_FAMILY_HOUSE: 'residential',
cte.MFH: 'multifamily house', cte.MULTI_FAMILY_HOUSE: 'residential',
cte.HOTEL: 'hotel', cte.ROW_HOSE: 'residential',
cte.HOSPITAL: 'hospital', cte.MID_RISE_APARTMENT: 'residential',
cte.OUTPATIENT: 'outpatient', cte.HIGH_RISE_APARTMENT: 'residential',
cte.COMMERCIAL: 'commercial', cte.SMALL_OFFICE: cte.SMALL_OFFICE,
cte.STRIP_MALL: 'strip mall', cte.MEDIUM_OFFICE: cte.MEDIUM_OFFICE,
cte.WAREHOUSE: 'warehouse', cte.LARGE_OFFICE: cte.LARGE_OFFICE,
cte.PRIMARY_SCHOOL: 'primary school', cte.PRIMARY_SCHOOL: cte.PRIMARY_SCHOOL,
cte.SECONDARY_SCHOOL: 'secondary school', cte.SECONDARY_SCHOOL: cte.SECONDARY_SCHOOL,
cte.OFFICE: 'office', cte.STAND_ALONE_RETAIL: cte.STAND_ALONE_RETAIL,
cte.LARGE_OFFICE: 'large office', cte.HOSPITAL: cte.HOSPITAL,
cte.OFFICE_WORKSHOP: 'residential' 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_function_default_value = 'residential'
nrcan_window_types = [cte.WINDOW] nrcan_window_types = [cte.WINDOW]
nrcan_construction_types = { nrcan_construction_types = {
cte.WALL: 'wall', cte.WALL: 'wall',
cte.GROUND_WALL: 'basement_wall', cte.GROUND_WALL: 'basement_wall',
@ -90,17 +107,16 @@ class ConstructionHelper:
} }
@staticmethod @staticmethod
def nrel_from_function(function): def nrel_from_libs_function(function):
""" """
Get NREL function from the given internal function key Get NREL function from the given internal function key
:param function: str :param function: str
:return: str :return: str
""" """
try: try:
return ConstructionHelper.function_to_nrel[function] return ConstructionHelper._function_to_nrel[function]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default NREL function "residential"\n') sys.stderr.write('Error: keyword not found.\n')
return ConstructionHelper.nrel_function_default_value
@staticmethod @staticmethod
def yoc_to_nrel_standard(year_of_construction): def yoc_to_nrel_standard(year_of_construction):
@ -136,17 +152,16 @@ class ConstructionHelper:
:return: str :return: str
""" """
reference_city = ConstructionHelper.city_to_reference_city(city) reference_city = ConstructionHelper.city_to_reference_city(city)
return ConstructionHelper.reference_city_to_nrel_climate_zone[reference_city] return ConstructionHelper._reference_city_to_nrel_climate_zone[reference_city]
@staticmethod @staticmethod
def nrcan_from_function(function): def nrcan_from_libs_function(function):
""" """
Get NREL function from the given internal function key Get NREL function from the given internal function key
:param function: str :param function: str
:return: str :return: str
""" """
try: try:
return ConstructionHelper.function_to_nrcan[function] return ConstructionHelper._function_to_nrcan[function]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default NRCAN function "residential"\n') sys.stderr.write('Error: keyword not found.\n')
return ConstructionHelper.nrcan_function_default_value

View File

@ -1,17 +1,19 @@
""" """
Storeys generation helper Storeys generation helper
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import sys import sys
import math import math
import numpy as np import numpy as np
from typing import List
from helpers import constants as cte from helpers import constants as cte
from city_model_structure.attributes.polygon import Polygon from city_model_structure.attributes.polygon import Polygon
from city_model_structure.attributes.point import Point from city_model_structure.attributes.point import Point
from city_model_structure.building_demand.storey import Storey from city_model_structure.building_demand.storey import Storey
from city_model_structure.building_demand.surface import Surface from city_model_structure.building_demand.surface import Surface
from city_model_structure.building_demand.thermal_zone import ThermalZone
class StoreysGeneration: class StoreysGeneration:
@ -20,11 +22,14 @@ class StoreysGeneration:
""" """
def __init__(self, building, divide_in_storeys=False): def __init__(self, building, divide_in_storeys=False):
self._building = building self._building = building
self._thermal_zones = []
self._divide_in_storeys = divide_in_storeys 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 @property
def storeys(self) -> [Storey]: def thermal_zones(self) -> List[ThermalZone]:
""" """
Get subsections of building trimesh by storey in case of no interiors defined Get subsections of building trimesh by storey in case of no interiors defined
:return: [Storey] :return: [Storey]
@ -34,7 +39,21 @@ class StoreysGeneration:
self._building.storeys_above_ground) self._building.storeys_above_ground)
number_of_storeys = 1 number_of_storeys = 1
if not self._divide_in_storeys or 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)] 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: if number_of_storeys == 0:
raise Exception('Number of storeys cannot be 0') raise Exception('Number of storeys cannot be 0')
@ -79,14 +98,32 @@ class StoreysGeneration:
surfaces_child.append(ceiling) surfaces_child.append(ceiling)
volume = ceiling.area_above_ground * height volume = ceiling.area_above_ground * height
total_volume += volume total_volume += volume
storeys.append(Storey(name, surfaces_child, neighbours, volume)) storeys.append(Storey(name, surfaces_child, neighbours, volume, self._floor_area))
name = 'storey_' + str(number_of_storeys - 1) name = 'storey_' + str(number_of_storeys - 1)
neighbours = ['storey_' + str(number_of_storeys - 2), None] neighbours = ['storey_' + str(number_of_storeys - 2), None]
volume = self._building.volume - total_volume volume = self._building.volume - total_volume
if volume < 0: if volume < 0:
raise Exception('Error in storeys creation, volume of last storey cannot be lower that 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)) 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 @staticmethod
def _calculate_number_storeys_and_height(average_storey_height, eave_height, storeys_above_ground): def _calculate_number_storeys_and_height(average_storey_height, eave_height, storeys_above_ground):
@ -136,22 +173,3 @@ class StoreysGeneration:
for point in points: for point in points:
array_points.append(point.coordinates) array_points.append(point.coordinates)
return np.array(array_points) 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.surface.type != cte.INTERIOR_WALL or thermal_boundary.surface.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.surface.inclination)
if grad >= 170:
thermal_zones = [storey.thermal_zone, storey.neighbours[0]]
else:
thermal_zones = [storey.neighbours[1], storey.thermal_zone]
thermal_boundary.thermal_zones = thermal_zones

View File

@ -6,10 +6,11 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
""" """
import xmltodict import xmltodict
from imports.construction.data_classes.nrel_building_achetype import NrelBuildingArchetype as nba from imports.construction.data_classes.building_achetype import BuildingArchetype as nba
from imports.construction.data_classes.nrel_thermal_boundary_archetype import NrelThermalBoundaryArchetype as ntba from imports.construction.data_classes.thermal_boundary_archetype import ThermalBoundaryArchetype as ntba
from imports.construction.data_classes.nrel_thermal_opening_archetype import NrelThermalOpeningArchetype as ntoa from imports.construction.data_classes.thermal_opening_archetype import ThermalOpeningArchetype as ntoa
from imports.construction.data_classes.nrel_layer_archetype import NrelLayerArchetype as nla from imports.construction.data_classes.layer_archetype import LayerArchetype as nla
from imports.construction.helpers.storeys_generation import StoreysGeneration
class NrelPhysicsInterface: class NrelPhysicsInterface:
@ -71,7 +72,6 @@ class NrelPhysicsInterface:
for current_layer in c_lib['layers']['layer']: for current_layer in c_lib['layers']['layer']:
material_lib = self._search_construction_type('material', current_layer['material']) material_lib = self._search_construction_type('material', current_layer['material'])
name = material_lib['@name'] name = material_lib['@name']
lca_id = material_lib['@lca_id']
solar_absorptance = material_lib['solar_absorptance']['#text'] solar_absorptance = material_lib['solar_absorptance']['#text']
thermal_absorptance = material_lib['thermal_absorptance']['#text'] thermal_absorptance = material_lib['thermal_absorptance']['#text']
visible_absorptance = material_lib['visible_absorptance']['#text'] visible_absorptance = material_lib['visible_absorptance']['#text']
@ -82,7 +82,7 @@ class NrelPhysicsInterface:
if units != 'm2 K/W': if units != 'm2 K/W':
raise Exception(f'thermal resistance units = {units}, expected m2 K/W') raise Exception(f'thermal resistance units = {units}, expected m2 K/W')
layer = nla(name, solar_absorptance, thermal_absorptance, visible_absorptance, no_mass=no_mass, layer = nla(name, solar_absorptance, thermal_absorptance, visible_absorptance, no_mass=no_mass,
thermal_resistance=thermal_resistance, lca_id=lca_id) thermal_resistance=thermal_resistance)
else: else:
thickness = current_layer['thickness']['#text'] thickness = current_layer['thickness']['#text']
units = current_layer['thickness']['@units'] units = current_layer['thickness']['@units']
@ -101,7 +101,7 @@ class NrelPhysicsInterface:
if units != 'kg/m3': if units != 'kg/m3':
raise Exception(f'density units = {units}, expected kg/m3') raise Exception(f'density units = {units}, expected kg/m3')
layer = nla(name, solar_absorptance, thermal_absorptance, visible_absorptance, thickness=thickness, layer = nla(name, solar_absorptance, thermal_absorptance, visible_absorptance, thickness=thickness,
conductivity=conductivity, specific_heat=specific_heat, density=density, lca_id=lca_id) conductivity=conductivity, specific_heat=specific_heat, density=density)
layers.append(layer) layers.append(layer)
thermal_opening = None thermal_opening = None
@ -150,10 +150,14 @@ class NrelPhysicsInterface:
units = c_lib['overall_u_value']['@units'] units = c_lib['overall_u_value']['@units']
if units != 'W/m2 K': if units != 'W/m2 K':
raise Exception(f'overall U-value units = {units}, expected W/m2 K') raise Exception(f'overall U-value units = {units}, expected W/m2 K')
outside_solar_absorptance = c_lib['outside_solar_absorptance']['#text'] if 'outside_solar_absorptance' in c_lib:
thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers, outside_solar_absorptance = c_lib['outside_solar_absorptance']['#text']
thermal_opening, outside_solar_absorptance=outside_solar_absorptance, thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers,
overall_u_value=overall_u_value) thermal_opening, outside_solar_absorptance=outside_solar_absorptance,
overall_u_value=overall_u_value)
else:
thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers,
thermal_opening, overall_u_value=overall_u_value)
else: else:
thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers, thermal_boundary_archetype = ntba(construction_type, window_ratio, construction_name, layers,
thermal_opening) thermal_opening)
@ -178,8 +182,57 @@ class NrelPhysicsInterface:
return thermal_boundary return thermal_boundary
raise Exception('Construction type not found') 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): def enrich_buildings(self):
""" """
Raise not implemented error Raise not implemented error
""" """
raise NotImplementedError raise NotImplementedError
@staticmethod
def _create_storeys(building, archetype):
building.average_storey_height = archetype.average_storey_height
building.storeys_above_ground = archetype.storeys_above_ground
thermal_zones = StoreysGeneration(building).thermal_zones
building.internal_zones[0].thermal_zones = thermal_zones

View File

@ -10,7 +10,6 @@ from imports.construction.nrel_physics_interface import NrelPhysicsInterface
from imports.construction.helpers.construction_helper import ConstructionHelper from imports.construction.helpers.construction_helper import ConstructionHelper
from city_model_structure.building_demand.layer import Layer from city_model_structure.building_demand.layer import Layer
from city_model_structure.building_demand.material import Material from city_model_structure.building_demand.material import Material
from imports.construction.helpers.storeys_generation import StoreysGeneration
class UsPhysicsParameters(NrelPhysicsInterface): class UsPhysicsParameters(NrelPhysicsInterface):
@ -30,19 +29,27 @@ class UsPhysicsParameters(NrelPhysicsInterface):
city = self._city city = self._city
# it is assumed that all buildings have the same archetypes' keys # it is assumed that all buildings have the same archetypes' keys
for building in city.buildings: for building in city.buildings:
building_type = ConstructionHelper.nrel_from_function(building.function) building_type = ConstructionHelper.nrel_from_libs_function(building.function)
if building_type is None: if building_type is None:
return return
archetype = self._search_archetype(building_type, try:
ConstructionHelper.yoc_to_nrel_standard(building.year_of_construction), archetype = self._search_archetype(building_type,
self._climate_zone) ConstructionHelper.yoc_to_nrel_standard(building.year_of_construction),
if archetype is None: self._climate_zone)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} ' sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} '
f'and building year of construction: {building.year_of_construction}\n') f'and building year of construction: {building.year_of_construction}\n')
continue return
self._create_storeys(building, archetype) # if building has no thermal zones defined from geometry, one thermal zone per storey is assigned
self._assign_values(building, archetype) if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype)
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): def _search_archetype(self, building_type, standard, climate_zone):
for building_archetype in self._building_archetypes: for building_archetype in self._building_archetypes:
@ -53,57 +60,50 @@ class UsPhysicsParameters(NrelPhysicsInterface):
return building_archetype return building_archetype
return None return None
def _assign_values(self, building, archetype): def _assign_values(self, internal_zones, archetype):
for thermal_zone in building.thermal_zones: for internal_zone in internal_zones:
thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value for thermal_zone in internal_zone.thermal_zones:
thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity thermal_zone.additional_thermal_bridge_u_value = archetype.additional_thermal_bridge_u_value
thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio thermal_zone.effective_thermal_capacity = archetype.effective_thermal_capacity
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on thermal_zone.indirectly_heated_area_ratio = archetype.indirectly_heated_area_ratio
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_system_on
for thermal_boundary in thermal_zone.thermal_boundaries: thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_system_off
construction_type = ConstructionHelper.nrel_construction_types[thermal_boundary.type] for thermal_boundary in thermal_zone.thermal_boundaries:
thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type) construction_type = ConstructionHelper.nrel_construction_types[thermal_boundary.type]
if thermal_boundary_archetype.outside_solar_absorptance is not None: thermal_boundary_archetype = self._search_construction_in_archetype(archetype, construction_type)
thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance thermal_boundary.outside_solar_absorptance = thermal_boundary_archetype.outside_solar_absorptance
thermal_boundary.outside_thermal_absorptance = thermal_boundary_archetype.outside_thermal_absorptance thermal_boundary.outside_thermal_absorptance = thermal_boundary_archetype.outside_thermal_absorptance
thermal_boundary.outside_visible_absorptance = thermal_boundary_archetype.outside_visible_absorptance thermal_boundary.outside_visible_absorptance = thermal_boundary_archetype.outside_visible_absorptance
thermal_boundary.construction_name = thermal_boundary_archetype.construction_name thermal_boundary.construction_name = thermal_boundary_archetype.construction_name
thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio try:
thermal_boundary.layers = [] thermal_boundary.window_ratio = thermal_boundary_archetype.window_ratio
for layer_archetype in thermal_boundary_archetype.layers: except ValueError:
layer = Layer() # This is the normal operation way when the windows are defined in the geometry
layer.thickness = layer_archetype.thickness continue
material = Material() thermal_boundary.layers = []
material.name = layer_archetype.name for layer_archetype in thermal_boundary_archetype.layers:
material.no_mass = layer_archetype.no_mass layer = Layer()
material.density = layer_archetype.density layer.thickness = layer_archetype.thickness
material.conductivity = layer_archetype.conductivity material = Material()
material.specific_heat = layer_archetype.specific_heat material.name = layer_archetype.name
material.solar_absorptance = layer_archetype.solar_absorptance material.no_mass = layer_archetype.no_mass
material.thermal_absorptance = layer_archetype.thermal_absorptance material.density = layer_archetype.density
material.visible_absorptance = layer_archetype.visible_absorptance material.conductivity = layer_archetype.conductivity
material.thermal_resistance = layer_archetype.thermal_resistance material.specific_heat = layer_archetype.specific_heat
if layer_archetype.lca_id is not None: material.solar_absorptance = layer_archetype.solar_absorptance
material.lca_id = layer_archetype.lca_id material.thermal_absorptance = layer_archetype.thermal_absorptance
layer.material = material material.visible_absorptance = layer_archetype.visible_absorptance
thermal_boundary.layers.append(layer) material.thermal_resistance = layer_archetype.thermal_resistance
for thermal_opening in thermal_boundary.thermal_openings: layer.material = material
if thermal_boundary_archetype.thermal_opening is not None: thermal_boundary.layers.append(layer)
thermal_opening_archetype = thermal_boundary_archetype.thermal_opening for thermal_opening in thermal_boundary.thermal_openings:
thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio if thermal_boundary_archetype.thermal_opening_archetype is not None:
thermal_opening.g_value = thermal_opening_archetype.g_value thermal_opening_archetype = thermal_boundary_archetype.thermal_opening_archetype
thermal_opening.conductivity = thermal_opening_archetype.conductivity thermal_opening.frame_ratio = thermal_opening_archetype.frame_ratio
thermal_opening.thickness = thermal_opening_archetype.thickness thermal_opening.g_value = thermal_opening_archetype.g_value
thermal_opening.back_side_solar_transmittance_at_normal_incidence = \ thermal_opening.conductivity = thermal_opening_archetype.conductivity
thermal_opening_archetype.back_side_solar_transmittance_at_normal_incidence thermal_opening.thickness = thermal_opening_archetype.thickness
thermal_opening.front_side_solar_transmittance_at_normal_incidence = \ thermal_opening.back_side_solar_transmittance_at_normal_incidence = \
thermal_opening_archetype.front_side_solar_transmittance_at_normal_incidence thermal_opening_archetype.back_side_solar_transmittance_at_normal_incidence
thermal_opening.front_side_solar_transmittance_at_normal_incidence = \
@staticmethod thermal_opening_archetype.front_side_solar_transmittance_at_normal_incidence
def _create_storeys(building, archetype):
building.average_storey_height = archetype.average_storey_height
building.storeys_above_ground = archetype.storeys_above_ground
storeys_generation = StoreysGeneration(building)
storeys = storeys_generation.storeys
building.storeys = storeys
storeys_generation.assign_thermal_zones_delimited_by_thermal_boundaries()

View File

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

View File

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

View File

@ -17,10 +17,6 @@ class CustomizedImportsFactory:
self._importer_class = importer_class self._importer_class = importer_class
self._city = city self._city = city
self._base_path = base_path 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): def enrich(self):
""" """

View File

@ -83,7 +83,7 @@ class CityGml:
surfaces = CityGmlLod2(city_object).surfaces surfaces = CityGmlLod2(city_object).surfaces
else: else:
raise NotImplementedError("Not supported level of detail") raise NotImplementedError("Not supported level of detail")
return Building(name, lod, surfaces, year_of_construction, function, self._lower_corner, []) return Building(name, lod, surfaces, year_of_construction, function, self._lower_corner, terrains=None)
def _create_parts_consisting_building(self, city_object): def _create_parts_consisting_building(self, city_object):
name = city_object['@id'] name = city_object['@id']

View File

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

View File

@ -76,6 +76,6 @@ class Obj:
perimeter_polygon = solid_polygon perimeter_polygon = solid_polygon
surface = Surface(solid_polygon, perimeter_polygon) surface = Surface(solid_polygon, perimeter_polygon)
surfaces.append(surface) surfaces.append(surface)
building = Building(name, lod, surfaces, year_of_construction, function, self._lower_corner) building = Building(name, lod, surfaces, year_of_construction, function, self._lower_corner, terrains=None)
self._city.add_city_object(building) self._city.add_city_object(building)
return self._city return self._city

View File

@ -3,16 +3,18 @@ Rhino module parses rhino files and import the geometry into the city model stru
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import numpy as np
from numpy import inf from numpy import inf
from rhino3dm import * #from rhino3dm import *
from rhino3dm._rhino3dm import MeshType #from rhino3dm._rhino3dm import MeshType
from city_model_structure.attributes.point import Point
import numpy as np
from helpers.configuration_helper import ConfigurationHelper
from city_model_structure.attributes.polygon import Polygon from city_model_structure.attributes.polygon import Polygon
from city_model_structure.building import Building from city_model_structure.building import Building
from city_model_structure.building_demand.surface import Surface as LibsSurface
from city_model_structure.city import City from city_model_structure.city import City
from helpers.configuration_helper import ConfigurationHelper from city_model_structure.building_demand.surface import Surface as LibsSurface
from helpers.constants import EPSILON
from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
@ -25,7 +27,19 @@ class Rhino:
self._max_x = self._max_y = self._max_z = min_float self._max_x = self._max_y = self._max_z = min_float
@staticmethod @staticmethod
def _solid_points(coordinates): def _in_perimeter(wall, corner):
res = wall.contains_point(Point(corner))
print(f'belong: {res} wall:({wall.coordinates}) corner: ({corner})')
return res
@staticmethod
def _add_hole(solid_polygon, hole):
first = solid_polygon.points[0]
points = first + hole.points + solid_polygon.points
return Polygon(points)
@staticmethod
def _solid_points(coordinates) -> np.ndarray:
solid_points = np.fromstring(coordinates, dtype=float, sep=' ') solid_points = np.fromstring(coordinates, dtype=float, sep=' ')
solid_points = GeometryHelper.to_points_matrix(solid_points) solid_points = GeometryHelper.to_points_matrix(solid_points)
return solid_points return solid_points
@ -82,6 +96,7 @@ class Rhino:
windows.append(Polygon(surface.perimeter_polygon.inverse)) windows.append(Polygon(surface.perimeter_polygon.inverse))
else: else:
buildings.append(rhino_object) buildings.append(rhino_object)
print(f'windows: {len(windows)}')
# todo: this method will be pretty inefficient # todo: this method will be pretty inefficient
for hole in windows: for hole in windows:
corner = hole.coordinates[0] corner = hole.coordinates[0]

View File

@ -8,7 +8,6 @@ import xmltodict
from pathlib import Path from pathlib import Path
from city_model_structure.machine import Machine from city_model_structure.machine import Machine
class LcaMachine: class LcaMachine:
def __init__(self, city, base_path): def __init__(self, city, base_path):
self._city = city self._city = city
@ -17,15 +16,12 @@ class LcaMachine:
def enrich(self): def enrich(self):
self._city.machines = [] self._city.machines = []
# print(self._base_path)
path = Path(self._base_path / 'lca_data.xml').resolve() path = Path(self._base_path / 'lca_data.xml').resolve()
with open(path) as xml: with open(path) as xml:
self._lca = xmltodict.parse(xml.read()) self._lca = xmltodict.parse(xml.read())
for machine in self._lca["library"]["machines"]['machine']: for machine in self._lca["library"]["machines"]['machine']:
self._city.machines.append(Machine(machine['@id'], machine['@name'], machine['work_efficiency']['#text'], self._city.machines.append(Machine(machine['@id'], machine['@name'], machine['work_efficiency']['#text'],
machine['work_efficiency']['@unit'], machine['work_efficiency']['@unit'], machine['energy_consumption_rate']['#text'],
machine['energy_consumption_rate']['#text'], machine['energy_consumption_rate']['@unit'], machine['carbon_emission_factor']['#text'],
machine['energy_consumption_rate']['@unit'], machine['carbon_emission_factor']['@unit']))
machine['carbon_emission_factor']['#text'],
machine['carbon_emission_factor']['@unit']))

View File

@ -7,8 +7,6 @@ Contributor Mohammad Reza mohammad.seyedabadi@mail.concordia.ca
import xmltodict import xmltodict
from pathlib import Path from pathlib import Path
from city_model_structure.building_demand.material import Material from city_model_structure.building_demand.material import Material
from city_model_structure.lca_material import LcaMaterial as LcaMat
class LcaMaterial: class LcaMaterial:
def __init__(self, city, base_path): def __init__(self, city, base_path):
@ -17,25 +15,26 @@ class LcaMaterial:
self._lca = None self._lca = None
def enrich(self): def enrich(self):
self._city.lca_materials = [] self._city.materials = []
path = Path(self._base_path / 'lca_data.xml').resolve() path = Path(self._base_path / 'lca_data.xml').resolve()
with open(path) as xml: with open(path) as xml:
self._lca = xmltodict.parse(xml.read()) self._lca = xmltodict.parse(xml.read())
for material in self._lca["library"]["building_materials"]['material']: for material in self._lca["library"]["building_materials"]['material']:
_lca_material = LcaMat() _material = Material()
_lca_material.type = material['@type'] _material.type = material['@type']
_lca_material.id = material['@id'] _material.id = material['@id']
_lca_material.name = material['@name'] _material.name = material['@name']
_lca_material.density = material['density']['#text'] _material.density=material['density']['#text']
_lca_material.density_unit = material['density']['@unit'] _material.density_unit=material['density']['@unit']
_lca_material.embodied_carbon = material['embodied_carbon']['#text'] _material.embodied_carbon=material['embodied_carbon']['#text']
_lca_material.embodied_carbon_unit = material['embodied_carbon']['@unit'] _material.embodied_carbon_unit=material['embodied_carbon']['@unit']
_lca_material.recycling_ratio = material['recycling_ratio'] _material.recycling_ratio=material['recycling_ratio']
_lca_material.onsite_recycling_ratio = material['onsite_recycling_ratio'] _material.onsite_recycling_ratio=material['onsite_recycling_ratio']
_lca_material.company_recycling_ratio = material['company_recycling_ratio'] _material.company_recycling_ratio=material['company_recycling_ratio']
_lca_material.landfilling_ratio = material['landfilling_ratio'] _material.landfilling_ratio=material['landfilling_ratio']
_lca_material.cost = 10 # todo: change this into material['cost']['#text'] _material.cost=material['cost']['#text']
_lca_material._cost_unit = material['cost']['@unit'] _material._cost_unit=material['cost']['@unit']
self._city.lca_materials.append(_lca_material)
self._city.materials.append(_material)

View File

@ -10,6 +10,8 @@ import parseidf
import xmltodict import xmltodict
from imports.schedules.helpers.schedules_helper import SchedulesHelper from imports.schedules.helpers.schedules_helper import SchedulesHelper
from city_model_structure.attributes.schedule import Schedule 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 import helpers.constants as cte
@ -51,15 +53,16 @@ class DoeIdf:
self._schedule_library = xmltodict.parse(xml.read()) self._schedule_library = xmltodict.parse(xml.read())
for building in self._city.buildings: for building in self._city.buildings:
for usage_zone in building.usage_zones: for internal_zone in building.internal_zones:
for schedule_archetype in self._schedule_library['archetypes']['archetypes']: for usage_zone in internal_zone.usage_zones:
function = schedule_archetype['@building_type'] for schedule_archetype in self._schedule_library['archetypes']['archetypes']:
if SchedulesHelper.usage_from_function(function) == usage_zone.usage: function = schedule_archetype['@building_type']
self._idf_schedules_path = (base_path / schedule_archetype['idf']['path']).resolve() if SchedulesHelper.usage_from_function(function) == usage_zone.usage:
with open(self._idf_schedules_path, 'r') as file: self._idf_schedules_path = (base_path / schedule_archetype['idf']['path']).resolve()
idf = parseidf.parse(file.read()) with open(self._idf_schedules_path, 'r') as file:
self._load_schedule(idf, usage_zone) idf = parseidf.parse(file.read())
break self._load_schedule(idf, usage_zone)
break
def _load_schedule(self, idf, usage_zone): def _load_schedule(self, idf, usage_zone):
schedules_day = {} schedules_day = {}
@ -129,4 +132,12 @@ class DoeIdf:
continue continue
schedules.append(schedule) schedules.append(schedule)
usage_zone.schedules = schedules for schedule in schedules:
if schedule.type == cte.OCCUPANCY:
if usage_zone.occupancy is None:
usage_zone.occupancy = Occupancy()
usage_zone.occupancy.occupancy_schedules = [schedule]
elif schedule.type == cte.LIGHTING:
if usage_zone.lighting is None:
usage_zone.lighting = Lighting()
usage_zone.lighting.schedules = [schedule]

View File

@ -12,43 +12,42 @@ class SchedulesHelper:
""" """
Schedules helper Schedules helper
""" """
usage_to_comnet = { _usage_to_comnet = {
cte.RESIDENTIAL: 'C-12 Residential', cte.RESIDENTIAL: 'C-12 Residential',
cte.INDUSTRY: 'C-10 Warehouse', cte.INDUSTRY: 'C-10 Warehouse',
cte.OFFICE_ADMINISTRATION: 'C-5 Office', cte.OFFICE_AND_ADMINISTRATION: 'C-5 Office',
cte.HOTEL: 'C-3 Hotel', cte.HOTEL: 'C-3 Hotel',
cte.HEALTH_CARE: 'C-2 Health', 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.HALL: 'C-8 Retail',
cte.RESTAURANT: 'C-7 Restaurant', cte.RESTAURANT: 'C-7 Restaurant',
cte.EDUCATION: 'C-9 School' cte.EDUCATION: 'C-9 School'
} }
comnet_default_value = 'C-12 Residential'
comnet_to_data_type = { _comnet_to_data_type = {
'Fraction': cte.FRACTION, 'Fraction': cte.FRACTION,
'OnOff': cte.ON_OFF, 'OnOff': cte.ON_OFF,
'Temperature': cte.TEMPERATURE 'Temperature': cte.TEMPERATURE
} }
# usage # usage
function_to_usage = { _function_to_usage = {
'full service restaurant': cte.RESTAURANT, 'full service restaurant': cte.RESTAURANT,
'high-rise apartment': cte.RESIDENTIAL, 'high-rise apartment': cte.RESIDENTIAL,
'hospital': cte.HEALTH_CARE, 'hospital': cte.HEALTH_CARE,
'large hotel': cte.HOTEL, 'large hotel': cte.HOTEL,
'large office': cte.OFFICE_ADMINISTRATION, 'large office': cte.OFFICE_AND_ADMINISTRATION,
'medium office': cte.OFFICE_ADMINISTRATION, 'medium office': cte.OFFICE_AND_ADMINISTRATION,
'midrise apartment': cte.RESIDENTIAL, 'midrise apartment': cte.RESIDENTIAL,
'outpatient healthcare': cte.HEALTH_CARE, 'outpatient healthcare': cte.HEALTH_CARE,
'primary school': cte.EDUCATION, 'primary school': cte.EDUCATION,
'quick service restaurant': cte.RESTAURANT, 'quick service restaurant': cte.RESTAURANT,
'secondary school': cte.EDUCATION, 'secondary school': cte.EDUCATION,
'small hotel': cte.HOTEL, 'small hotel': cte.HOTEL,
'small office': cte.OFFICE_ADMINISTRATION, 'small office': cte.OFFICE_AND_ADMINISTRATION,
'stand-alone-retail': cte.RETAIL, 'stand-alone-retail': cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
'strip mall': cte.HALL, 'strip mall': cte.HALL,
'supermarket': cte.RETAIL, 'supermarket': cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
'warehouse': cte.INDUSTRY, 'warehouse': cte.INDUSTRY,
'residential': cte.RESIDENTIAL 'residential': cte.RESIDENTIAL
} }
@ -61,10 +60,9 @@ class SchedulesHelper:
:return: str :return: str
""" """
try: try:
return SchedulesHelper.usage_to_comnet[usage] return SchedulesHelper._usage_to_comnet[usage]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default Comnet schedules "residential"\n') sys.stderr.write('Error: keyword not found.\n')
return SchedulesHelper.comnet_default_value
@staticmethod @staticmethod
def data_type_from_comnet(comnet_data_type): def data_type_from_comnet(comnet_data_type):
@ -74,7 +72,7 @@ class SchedulesHelper:
:return: str :return: str
""" """
try: try:
return SchedulesHelper.comnet_to_data_type[comnet_data_type] return SchedulesHelper._comnet_to_data_type[comnet_data_type]
except KeyError: except KeyError:
raise ValueError(f"Error: comnet data type keyword not found.") raise ValueError(f"Error: comnet data type keyword not found.")
@ -85,4 +83,4 @@ class SchedulesHelper:
:param building_function: str :param building_function: str
:return: str :return: str
""" """
return SchedulesHelper.function_to_usage[building_function] return SchedulesHelper._function_to_usage[building_function]

View File

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

View File

@ -5,6 +5,7 @@ Copyright © 2021 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
""" """
import pandas as pd import pandas as pd
from imports.sensors.concordia_file_report import ConcordiaFileReport from imports.sensors.concordia_file_report import ConcordiaFileReport
from city_model_structure.iot.concordia_energy_sensor import ConcordiaEnergySensor
class ConcordiaEnergyConsumption(ConcordiaFileReport): class ConcordiaEnergyConsumption(ConcordiaFileReport):

View File

@ -5,7 +5,7 @@ Copyright © 2021 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
""" """
import pandas as pd import pandas as pd
from imports.sensors.concordia_file_report import ConcordiaFileReport from imports.sensors.concordia_file_report import ConcordiaFileReport
from city_model_structure.iot.concordia_gas_flow_sensor import ConcordiaGasFlowSensor
class ConcordiaGasFlow(ConcordiaFileReport): class ConcordiaGasFlow(ConcordiaFileReport):
@ -24,7 +24,6 @@ class ConcordiaGasFlow(ConcordiaFileReport):
building_measures = [self._measures["Date time"], self._measures[self._sensor_point[self._sensors[i]]]] building_measures = [self._measures["Date time"], self._measures[self._sensor_point[self._sensors[i]]]]
building_headers = ["Date time", "Gas Flow Cumulative Monthly"] building_headers = ["Date time", "Gas Flow Cumulative Monthly"]
building_energy_consumption = pd.concat(building_measures, keys=building_headers, axis=1) building_energy_consumption = pd.concat(building_measures, keys=building_headers, axis=1)
"""
sensor = ConcordiaGasFlowSensor(self._sensors[i]) sensor = ConcordiaGasFlowSensor(self._sensors[i])
sensor_exist = False sensor_exist = False
for j in range(len(obj.sensors)): for j in range(len(obj.sensors)):
@ -35,4 +34,3 @@ class ConcordiaGasFlow(ConcordiaFileReport):
if not sensor_exist: if not sensor_exist:
sensor.add_period(building_energy_consumption) sensor.add_period(building_energy_consumption)
obj.sensors.append(sensor) obj.sensors.append(sensor)
"""

View File

@ -5,6 +5,7 @@ Copyright © 2021 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
""" """
import pandas as pd import pandas as pd
from imports.sensors.concordia_file_report import ConcordiaFileReport from imports.sensors.concordia_file_report import ConcordiaFileReport
from city_model_structure.iot.concordia_temperature_sensor import ConcordiaTemperatureSensor
class ConcordiaTemperature(ConcordiaFileReport): class ConcordiaTemperature(ConcordiaFileReport):
@ -22,7 +23,6 @@ class ConcordiaTemperature(ConcordiaFileReport):
building_measures = [self._measures["Date time"], self._measures[self._sensor_point[self._sensors[i]]]] building_measures = [self._measures["Date time"], self._measures[self._sensor_point[self._sensors[i]]]]
building_headers = ["Date time", "Temperature"] building_headers = ["Date time", "Temperature"]
building_energy_consumption = pd.concat(building_measures, keys=building_headers, axis=1) building_energy_consumption = pd.concat(building_measures, keys=building_headers, axis=1)
"""
sensor = ConcordiaTemperatureSensor(self._sensors[i]) sensor = ConcordiaTemperatureSensor(self._sensors[i])
sensor_exist = False sensor_exist = False
for j in range(len(obj.sensors)): for j in range(len(obj.sensors)):
@ -33,4 +33,3 @@ class ConcordiaTemperature(ConcordiaFileReport):
if not sensor_exist: if not sensor_exist:
sensor.add_period(building_energy_consumption) sensor.add_period(building_energy_consumption)
obj.sensors.append(sensor) obj.sensors.append(sensor)
"""

View File

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

View File

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

View File

@ -1,144 +0,0 @@
"""
HftUsageZoneArchetype stores usage information by building archetypes
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import List
from imports.usage.data_classes.hft_internal_gains_archetype import HftInternalGainsArchetype
class HftUsageZoneArchetype:
"""
HftUsageZoneArchetype class
"""
def __init__(self, usage=None, internal_gains=None, heating_set_point=None, heating_set_back=None,
cooling_set_point=None, occupancy_density=None, hours_day=None, days_year=None,
dhw_average_volume_pers_day=None, dhw_preparation_temperature=None,
electrical_app_average_consumption_sqm_year=None, mechanical_air_change=None,
occupancy=None, schedules=None):
self._usage = usage
self._internal_gains = internal_gains
self._heating_setpoint = heating_set_point
self._heating_setback = heating_set_back
self._cooling_setpoint = cooling_set_point
self._occupancy_density = occupancy_density
self._hours_day = hours_day
self._days_year = days_year
self._dhw_average_volume_pers_day = dhw_average_volume_pers_day
self._dhw_preparation_temperature = dhw_preparation_temperature
self._electrical_app_average_consumption_sqm_year = electrical_app_average_consumption_sqm_year
self._mechanical_air_change = mechanical_air_change
self._occupancy = occupancy
self._schedules = schedules
@property
def internal_gains(self) -> List[HftInternalGainsArchetype]:
"""
Get usage zone internal gains
:return: [InternalGains]
"""
return self._internal_gains
@property
def heating_setpoint(self):
"""
Get usage zone heating set point in celsius grads
:return: float
"""
return self._heating_setpoint
@property
def heating_setback(self):
"""
Get usage zone heating setback in celsius grads
:return: float
"""
return self._heating_setback
@property
def cooling_setpoint(self):
"""
Get usage zone cooling setpoint in celsius grads
:return: float
"""
return self._cooling_setpoint
@property
def hours_day(self):
"""
Get usage zone usage hours per day
:return: float
"""
return self._hours_day
@property
def days_year(self):
"""
Get usage zone usage days per year
:return: float
"""
return self._days_year
@property
def mechanical_air_change(self):
"""
Set usage zone mechanical air change in air change per hour (ACH)
:return: float
"""
return self._mechanical_air_change
@property
def usage(self):
"""
Get usage zone usage
:return: str
"""
return self._usage
@property
def occupancy(self):
"""
Get schedules data
:return: [Occupancy]
"""
return self._occupancy
@property
def schedules(self):
"""
Get schedules
:return: [Schedule_Values]
"""
return self._schedules
@property
def occupancy_density(self):
"""
Get schedules density in persons per m2
:return: float
"""
return self._occupancy_density
@property
def dhw_average_volume_pers_day(self):
"""
Get average DHW consumption in m3 per person per day
:return: float
"""
return self._dhw_average_volume_pers_day
@property
def dhw_preparation_temperature(self):
"""
Get preparation temperature of the DHW in degree Celsius
:return: float
"""
return self._dhw_preparation_temperature
@property
def electrical_app_average_consumption_sqm_year(self):
"""
Get average consumption of electrical appliances in Joules per m2 and year (J/m2yr)
:return: float
"""
return self._electrical_app_average_consumption_sqm_year

View File

@ -0,0 +1,98 @@
"""
UsageZoneArchetype stores usage information by usage type
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import List
from imports.usage.data_classes.hft_internal_gains_archetype import HftInternalGainsArchetype
class UsageZoneArchetype:
"""
UsageZoneArchetype class
"""
def __init__(self, usage=None, not_detailed_source_mean_annual_internal_gains=None, hours_day=None, days_year=None,
electrical_app_average_consumption_sqm_year=None, mechanical_air_change=None, occupancy=None,
lighting=None, appliances=None):
self._usage = usage
self._not_detailed_source_mean_annual_internal_gains = not_detailed_source_mean_annual_internal_gains
self._hours_day = hours_day
self._days_year = days_year
self._electrical_app_average_consumption_sqm_year = electrical_app_average_consumption_sqm_year
self._mechanical_air_change = mechanical_air_change
self._occupancy = occupancy
self._lighting = lighting
self._appliances = appliances
@property
def not_detailed_source_mean_annual_internal_gains(self) -> List[HftInternalGainsArchetype]:
"""
Get usage zone internal gains from not detailed heating source in W/m2
:return: [InternalGains]
"""
return self._not_detailed_source_mean_annual_internal_gains
@property
def hours_day(self):
"""
Get usage zone usage hours per day
:return: float
"""
return self._hours_day
@property
def days_year(self):
"""
Get usage zone usage days per year
:return: float
"""
return self._days_year
@property
def mechanical_air_change(self):
"""
Set usage zone mechanical air change in air change per hour (ACH)
:return: float
"""
return self._mechanical_air_change
@property
def usage(self):
"""
Get usage zone usage
:return: str
"""
return self._usage
@property
def electrical_app_average_consumption_sqm_year(self):
"""
Get average consumption of electrical appliances in Joules per m2 and year (J/m2yr)
:return: float
"""
return self._electrical_app_average_consumption_sqm_year
@property
def occupancy(self):
"""
Get occupancy data
:return: Occupancy
"""
return self._occupancy
@property
def lighting(self):
"""
Get lighting data
:return: Lighting
"""
return self._lighting
@property
def appliances(self):
"""
Get appliances data
:return: Appliances
"""
return self._appliances

View File

@ -11,54 +11,104 @@ class UsageHelper:
""" """
Usage helper class Usage helper class
""" """
usage_to_hft = { _usage_to_hft = {
cte.RESIDENTIAL: 'residential', cte.RESIDENTIAL: 'residential',
cte.INDUSTRY: 'industry', cte.SINGLE_FAMILY_HOUSE: 'Single family house',
cte.OFFICE_ADMINISTRATION: 'office and administration', 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.HOTEL: 'hotel',
cte.HEALTH_CARE: 'health care', cte.HOTEL_MEDIUM_CLASS: 'hotel (Medium-class)',
cte.RETAIL: 'retail', cte.DORMITORY: 'dormitory',
cte.HALL: 'hall', cte.INDUSTRY: 'industry',
cte.RESTAURANT: 'restaurant', cte.RESTAURANT: 'restaurant',
cte.EDUCATION: 'education' cte.HEALTH_CARE: 'health care',
} cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Home for the aged or orphanage',
hft_default_value = 'residential' 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 @staticmethod
def hft_from_usage(usage): def hft_from_libs_usage(usage):
""" """
Get HfT usage from the given internal usage key Get HfT usage from the given internal usage key
:param usage: str :param usage: str
:return: str :return: str
""" """
try: try:
return UsageHelper.usage_to_hft[usage] return UsageHelper._usage_to_hft[usage]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default HfT usage "residential"\n') sys.stderr.write('Error: keyword not found to translate from libs_usage to hft usage.\n')
return UsageHelper.hft_default_value
usage_to_comnet = { _usage_to_comnet = {
cte.RESIDENTIAL: 'BA Multifamily', cte.RESIDENTIAL: 'BA Multifamily',
cte.INDUSTRY: 'BA Manufacturing Facility', cte.SINGLE_FAMILY_HOUSE: 'BA Multifamily',
cte.OFFICE_ADMINISTRATION: 'BA Office', 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: '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.HEALTH_CARE: 'BA Hospital',
cte.RETAIL: 'BA Retail', cte.RETIREMENT_HOME_OR_ORPHANAGE: 'BA Multifamily',
cte.HALL: 'BA Town Hall', cte.OFFICE_AND_ADMINISTRATION: 'BA Office',
cte.RESTAURANT: 'BA Dining: Bar Lounge/Leisure', cte.EVENT_LOCATION: 'BA Convention Center',
cte.EDUCATION: 'BA School/University' 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_default_value = 'BA Multifamily'
_comnet_schedules_key_to_comnet_schedules = {
'C-1 Assembly': 'C-1 Assembly',
'C-2 Public': 'C-2 Health',
'C-3 Hotel Motel': 'C-3 Hotel',
'C-4 Manufacturing': 'C-4 Manufacturing',
'C-5 Office': 'C-5 Office',
'C-6 Parking Garage': 'C-6 Parking',
'C-7 Restaurant': 'C-7 Restaurant',
'C-8 Retail': 'C-8 Retail',
'C-9 Schools': 'C-9 School',
'C-10 Warehouse': 'C-10 Warehouse',
'C-11 Laboratory': 'C-11 Lab',
'C-12 Residential': 'C-12 Residential',
'C-13 Data Center': 'C-13 Data',
'C-14 Gymnasium': 'C-14 Gymnasium'}
@staticmethod @staticmethod
def comnet_from_usage(usage): def comnet_from_libs_usage(usage):
""" """
Get Comnet usage from the given internal usage key Get Comnet usage from the given internal usage key
:param usage: str :param usage: str
:return: str :return: str
""" """
try: try:
return UsageHelper.usage_to_comnet[usage] return UsageHelper._usage_to_comnet[usage]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default Comnet usage "BA Multifamily"\n') sys.stderr.write('Error: keyword not found to translate from libs_usage to comnet usage.\n')
return UsageHelper.comnet_default_value
@staticmethod
def schedules_key(usage):
"""
Get Comnet schedules key from the list found in the Comnet usage file
:param usage: str
:return: str
"""
try:
return UsageHelper._comnet_schedules_key_to_comnet_schedules[usage]
except KeyError:
sys.stderr.write('Error: Comnet keyword not found. An update of the Comnet files might have been '
'done changing the keywords.\n')

View File

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

View File

@ -4,11 +4,12 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import sys 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.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.usage_zone import UsageZone
from city_model_structure.building_demand.internal_gains import InternalGains
class HftUsageParameters(HftUsageInterface): class HftUsageParameters(HftUsageInterface):
@ -18,9 +19,6 @@ class HftUsageParameters(HftUsageInterface):
def __init__(self, city, base_path): def __init__(self, city, base_path):
super().__init__(base_path, 'de_library.xml') super().__init__(base_path, 'de_library.xml')
self._city = city self._city = city
# todo: this is a wrong location for self._min_air_change -> re-think where to place this info
# and where it comes from
self._min_air_change = 0
def enrich_buildings(self): def enrich_buildings(self):
""" """
@ -29,23 +27,25 @@ class HftUsageParameters(HftUsageInterface):
""" """
city = self._city city = self._city
for building in city.buildings: for building in city.buildings:
archetype = self._search_archetype(gh.usage_from_function(building.function)) usage = GeometryHelper().libs_usage_from_libs_function(building.function)
if archetype is None: try:
archetype = self._search_archetype(usage)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as ' f' {building.function}, that assigns building usage as '
f'{gh.usage_from_function(building.function)}\n') f'{GeometryHelper().libs_usage_from_libs_function(building.function)}\n')
continue return
# todo: what to do with mix-usage usage from gml?
mix_usage = False
if not mix_usage:
# just one usage_zone
for thermal_zone in building.thermal_zones:
usage_zone = UsageZone()
self._assign_values(usage_zone, archetype)
usage_zone.volume = thermal_zone.volume
thermal_zone.usage_zones = [usage_zone]
def _search_archetype(self, building_usage): for internal_zone in building.internal_zones:
usage_zone = UsageZone()
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, libs_usage):
building_usage = UsageHelper().hft_from_libs_usage(libs_usage)
for building_archetype in self._usage_archetypes: for building_archetype in self._usage_archetypes:
if building_archetype.usage == building_usage: if building_archetype.usage == building_usage:
return building_archetype return building_archetype
@ -53,26 +53,42 @@ class HftUsageParameters(HftUsageInterface):
@staticmethod @staticmethod
def _assign_values(usage_zone, archetype): def _assign_values(usage_zone, archetype):
usage_zone.usage = archetype.usage """ # Due to the fact that python is not a typed language, the wrong object type is assigned to
# Due to the fact that python is not a typed language, the wrong object type is assigned to
# usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains. # usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains.
# Therefore, this walk around has been done. # Therefore, this walk around has been done.
internal_gains = [] # Due to the fact that python is not a typed language, the wrong object type is assigned to
for archetype_internal_gain in archetype.internal_gains: # usage_zone.occupancy when writing usage_zone.occupancy = archetype.occupancy.
internal_gain = InternalGains() # Same happens for lighting and appliances. Therefore, this walk around has been done.
internal_gain.average_internal_gain = archetype_internal_gain.average_internal_gain
internal_gain.convective_fraction = archetype_internal_gain.convective_fraction
internal_gain.radiative_fraction = archetype_internal_gain.radiative_fraction
internal_gain.latent_fraction = archetype_internal_gain.latent_fraction
internal_gains.append(internal_gain)
usage_zone.internal_gains = internal_gains
usage_zone.heating_setpoint = archetype.heating_setpoint
usage_zone.heating_setback = archetype.heating_setback
usage_zone.cooling_setpoint = archetype.cooling_setpoint
usage_zone.occupancy_density = archetype.occupancy_density
usage_zone.hours_day = archetype.hours_day
usage_zone.days_year = archetype.days_year
usage_zone.dhw_average_volume_pers_day = archetype.dhw_average_volume_pers_day
usage_zone.dhw_preparation_temperature = archetype.dhw_preparation_temperature
usage_zone.electrical_app_average_consumption_sqm_year = archetype.electrical_app_average_consumption_sqm_year
usage_zone.mechanical_air_change = archetype.mechanical_air_change usage_zone.mechanical_air_change = archetype.mechanical_air_change
_occupancy = Occupancy()
_occupancy.occupancy_density = archetype.occupancy.occupancy_density
usage_zone.occupancy = _occupancy
_appliances = Appliances()
_appliances.appliances_density = archetype.appliances.appliances_density
usage_zone.appliances = _appliances
_control = ThermalControl()
_control.mean_heating_set_point = archetype.thermal_control.mean_heating_set_point
_control.heating_set_back = archetype.thermal_control.heating_set_back
_control.mean_cooling_set_point = archetype.thermal_control.mean_cooling_set_point
_control.cooling_set_point_schedules = archetype.thermal_control.cooling_set_point_schedules
_control.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules
usage_zone.thermal_control = _control
_internal_gains = []
for archetype_internal_gain in archetype.not_detailed_source_mean_annual_internal_gains:
_internal_gain = InternalGains()
_internal_gain.average_internal_gain = archetype_internal_gain.average_internal_gain
_internal_gain.convective_fraction = archetype_internal_gain.convective_fraction
_internal_gain.radiative_fraction = archetype_internal_gain.radiative_fraction
_internal_gain.latent_fraction = archetype_internal_gain.latent_fraction
_internal_gain.schedules = archetype_internal_gain.schedules
_internal_gains.append(_internal_gain)
usage_zone.not_detailed_source_mean_annual_internal_gains = _internal_gains
"""
usage_zone.mechanical_air_change = archetype.mechanical_air_change
usage_zone.occupancy = copy.deepcopy(archetype.occupancy)
usage_zone.appliances = copy.deepcopy(archetype.appliances)
usage_zone.thermal_control = copy.deepcopy(archetype.thermal_control)
usage_zone.not_detailed_source_mean_annual_internal_gains = \
copy.deepcopy(archetype.not_detailed_source_mean_annual_internal_gains)
usage_zone.days_year = archetype.days_year
usage_zone.hours_day = archetype.hours_day

View File

@ -22,10 +22,6 @@ class UsageFactory:
self._handler = '_' + handler.lower().replace(' ', '_') self._handler = '_' + handler.lower().replace(' ', '_')
self._city = city self._city = city
self._base_path = base_path self._base_path = base_path
for building in city.buildings:
if len(building.thermal_zones) == 0:
raise Exception('It seems that the usage factory is being called before the construction factory. '
'Please ensure that the construction factory is called first.')
def _hft(self): def _hft(self):
""" """

View File

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

View File

@ -13,7 +13,7 @@ openpyxl~=3.0.7
networkx~=2.5.1 networkx~=2.5.1
parseidf~=1.0.0 parseidf~=1.0.0
ply~=3.11 ply~=3.11
rhino3dm~=7.11.1 rhino3dm~=7.7.0
scipy==1.7.1 scipy==1.7.1
PyYAML==6.0 PyYAML==6.0
yaml~=0.2.5 yaml~=0.2.5

View File

@ -1,15 +1,16 @@
""" """
TestConstructionFactory test and validate the city model structure construction parameters TestConstructionFactory test and validate the city model structure construction parameters
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2022 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
import helpers.constants as cte
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.construction_factory import ConstructionFactory from imports.construction_factory import ConstructionFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.life_cycle_assessment_factory import LifeCycleAssessment
class TestConstructionFactory(TestCase): class TestConstructionFactory(TestCase):
""" """
@ -23,46 +24,139 @@ class TestConstructionFactory(TestCase):
self._city = None self._city = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve() self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def _get_citygml(self, file=None): def _get_citygml(self, file):
if file is None:
file = 'pluto_building.gml'
file_path = (self._example_path / file).resolve() file_path = (self._example_path / file).resolve()
self._city = GeometryFactory('citygml', file_path).city self._city = GeometryFactory('citygml', file_path).city
LifeCycleAssessment('material', self._city).enrich()
self.assertIsNotNone(self._city, 'city is none') self.assertIsNotNone(self._city, 'city is none')
return self._city return self._city
def test_city_with_construction_extended_library(self): def _check_buildings(self, city):
"""
Enrich the city with the physic information and verify it
:return: None
"""
city = self._get_citygml()
for building in city.buildings: for building in city.buildings:
building.function = GeometryHelper.pluto_to_function[building.function] self.assertIsNotNone(building.name, 'building name is none')
self.assertIsNotNone(building.surfaces, 'Building has no surfaces') self.assertIsNotNone(building.lod, 'building lod is none')
self.assertIsNotNone(building.type, 'building type is none')
self.assertIsNotNone(building.volume, 'building volume is none')
self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
self.assertIsNotNone(building.centroid, 'building centroid is none')
self.assertIsNotNone(building.max_height, 'building max_height is none')
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none')
self.assertIsNotNone(building.roofs, 'building roofs is none')
for internal_zone in building.internal_zones:
self.assertIsNone(internal_zone.usage_zones, 'usage zones are defined')
self.assertTrue(len(internal_zone.thermal_zones) > 0, 'thermal zones are not defined')
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNone(building.terrains, 'building terrains is not none')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none')
self.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.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')
self.assertFalse(building.is_conditioned, 'building is conditioned')
# case 1: NREL def _check_thermal_zones(self, internal_zone):
ConstructionFactory('nrel', city).enrich() for thermal_zone in internal_zone.thermal_zones:
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
self.assertIsNotNone(thermal_zone.floor_area, 'thermal_zone floor area is none')
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, 'additional_thermal_bridge_u_value is none')
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'thermal_zone effective_thermal_capacity is none')
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio,
'thermal_zone indirectly_heated_area_ratio is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_off,
'thermal_zone infiltration_rate_system_off is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'thermal_zone infiltration_rate_system_on is none')
self.assertIsNotNone(thermal_zone.volume, 'thermal_zone volume is none')
self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not none')
self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none')
self.assertIsNone(thermal_zone.usage_zones, 'thermal_zone usage_zones is not none')
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal_control is not none')
self.assertIsNone(thermal_zone.hvac_system, 'thermal_zone hvac_system is not none')
def _check_thermal_boundaries(self, thermal_zone):
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 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')
self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none')
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
if thermal_boundary.type is not cte.GROUND:
self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none')
self.assertIsNotNone(thermal_boundary.shortwave_reflectance, 'shortwave_reflectance is none')
else:
self.assertIsNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is not none')
self.assertIsNone(thermal_boundary.shortwave_reflectance, 'shortwave_reflectance is not none')
self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none')
self.assertIsNotNone(thermal_boundary.construction_name, 'construction_name is none')
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')
self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none')
self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none')
self.assertIsNotNone(thermal_boundary.hi, 'hi is none')
self.assertIsNotNone(thermal_boundary.he, 'he is none')
self.assertIsNotNone(thermal_boundary.virtual_internal_surface, 'virtual_internal_surface is none')
self.assertIsNone(thermal_boundary.inside_emissivity, 'inside_emissivity is not none')
self.assertIsNone(thermal_boundary.alpha_coefficient, 'alpha_coefficient is not none')
self.assertIsNone(thermal_boundary.radiative_coefficient, 'radiative_coefficient is not none')
def _check_thermal_openings(self, thermal_boundary):
for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none')
self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none')
self.assertRaises(Exception, lambda: thermal_opening.openable_ratio,
'thermal_opening openable_ratio is not raising an exception')
self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is not none')
self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is not none')
self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is not none')
self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is not none')
self.assertIsNotNone(thermal_opening.he, 'thermal opening he is not none')
self.assertIsNone(thermal_opening.inside_emissivity, 'thermal opening inside_emissivity is not none')
self.assertIsNone(thermal_opening.alpha_coefficient, 'thermal opening alpha_coefficient is not none')
self.assertIsNone(thermal_opening.radiative_coefficient, 'thermal opening radiative_coefficient is not none')
def test_citygml_function(self):
"""
Test city objects' functions in the city
"""
# case 1: hft
file = 'one_building_in_kelowna.gml'
function_format = 'hft'
city = self._get_citygml(file)
for building in city.buildings: for building in city.buildings:
self.assertIsNotNone(building.average_storey_height, 'average_storey_height is none') building.function = self._internal_function(function_format, building.function)
self.assertIsNotNone(building.storeys_above_ground, 'storeys_above_ground is none') self.assertEqual(building.function, 'residential', 'format hft')
self.assertIsNot(len(building.thermal_zones), 0, 'no building thermal_zones defined')
for thermal_zone in building.thermal_zones: # case 2: Pluto
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'effective_thermal_capacity is none') file = 'pluto_building.gml'
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, function_format = 'pluto'
'additional_thermal_bridge_u_value is none') city = self._get_citygml(file)
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, 'indirectly_heated_area_ratio is none') for building in city.buildings:
self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'infiltration_rate_system_on is none') building.function = self._internal_function(function_format, building.function)
self.assertIsNotNone(thermal_zone.infiltration_rate_system_off, 'infiltration_rate_system_off is none') self.assertEqual(building.function, 'secondary school', 'format pluto')
self.assertIsNotNone(thermal_zone.thermal_boundaries, 'thermal_boundaries is none')
for thermal_boundary in thermal_zone.thermal_boundaries: # case 3: Alkis
if thermal_boundary.surface.type != 'Ground': file = 'one_building_in_kelowna_alkis.gml'
self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') function_format = 'alkis'
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') city = self._get_citygml(file)
for layer in thermal_boundary.layers: for building in city.buildings:
self.assertTrue(city.lca_material(layer.material.lca_id) is not None) self.assertRaises(Exception, lambda: self._internal_function(function_format, building.function))
def test_city_with_construction_reduced_library(self): def test_city_with_construction_reduced_library(self):
""" """
@ -71,22 +165,69 @@ class TestConstructionFactory(TestCase):
file = 'one_building_in_kelowna.gml' file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
for building in city.buildings: for building in city.buildings:
building.function = GeometryHelper.hft_to_function[building.function] building.function = GeometryHelper.libs_function_from_hft(building.function)
# case 2: NRCAN
ConstructionFactory('nrcan', city).enrich() ConstructionFactory('nrcan', city).enrich()
self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
self.assertIsNotNone(building.average_storey_height, 'average_storey_height is none') for internal_zone in building.internal_zones:
self.assertIsNotNone(building.storeys_above_ground, 'storeys_above_ground is none') self._check_thermal_zones(internal_zone)
self.assertIsNot(len(building.thermal_zones), 0, 'no building thermal_zones defined') for thermal_zone in internal_zone.thermal_zones:
for thermal_zone in building.thermal_zones: self._check_thermal_boundaries(thermal_zone)
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'effective_thermal_capacity is none') for thermal_boundary in thermal_zone.thermal_boundaries:
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, self.assertIsNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is not none')
'additional_thermal_bridge_u_value is none') self.assertIsNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is not none')
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, 'indirectly_heated_area_ratio is none') self.assertIsNone(thermal_boundary.layers, 'layers is not none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'infiltration_rate_system_on is none')
self.assertIsNotNone(thermal_zone.infiltration_rate_system_off, 'infiltration_rate_system_off is none') self._check_thermal_openings(thermal_boundary)
self.assertIsNotNone(thermal_zone.thermal_boundaries, 'thermal_boundaries is none') for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNot(len(thermal_zone.thermal_boundaries), 0, 'no boundaries of thermal_zone defined') self.assertIsNone(thermal_opening.conductivity, 'thermal_opening conductivity is not none')
for thermal_boundary in thermal_zone.thermal_boundaries: self.assertIsNone(thermal_opening.thickness, 'thermal opening thickness is not none')
self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') self.assertIsNone(thermal_opening.front_side_solar_transmittance_at_normal_incidence,
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') 'thermal opening front_side_solar_transmittance_at_normal_incidence is not none')
self.assertIsNone(thermal_opening.back_side_solar_transmittance_at_normal_incidence,
'thermal opening back_side_solar_transmittance_at_normal_incidence is not none')
def test_city_with_construction_extended_library(self):
"""
Enrich the city with the construction information and verify it
"""
file = 'pluto_building.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.function = GeometryHelper.libs_function_from_pluto(building.function)
ConstructionFactory('nrel', city).enrich()
self._check_buildings(city)
for building in city.buildings:
for internal_zone in building.internal_zones:
self._check_thermal_zones(internal_zone)
for thermal_zone in internal_zone.thermal_zones:
self._check_thermal_boundaries(thermal_zone)
for thermal_boundary in thermal_zone.thermal_boundaries:
if thermal_boundary.type is not cte.GROUND:
self.assertIsNotNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is none')
self.assertIsNotNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is none')
else:
self.assertIsNone(thermal_boundary.outside_thermal_absorptance, 'outside_thermal_absorptance is not none')
self.assertIsNone(thermal_boundary.outside_visible_absorptance, 'outside_visible_absorptance is not none')
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
self._check_thermal_openings(thermal_boundary)
for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNotNone(thermal_opening.conductivity, 'thermal_opening conductivity is none')
self.assertIsNotNone(thermal_opening.thickness, 'thermal opening thickness is none')
self.assertIsNotNone(thermal_opening.front_side_solar_transmittance_at_normal_incidence,
'thermal opening front_side_solar_transmittance_at_normal_incidence is none')
self.assertIsNotNone(thermal_opening.back_side_solar_transmittance_at_normal_incidence,
'thermal opening back_side_solar_transmittance_at_normal_incidence is none')
@staticmethod
def _internal_function(function_format, original_function):
if function_format == 'hft':
new_function = GeometryHelper.libs_function_from_hft(original_function)
elif function_format == 'pluto':
new_function = GeometryHelper.libs_function_from_pluto(original_function)
else:
raise Exception('Function key not recognized. Implemented only "hft" and "pluto"')
return new_function

View File

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

View File

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

View File

@ -0,0 +1,163 @@
"""
TestGeometryFactory test and validate the city model structure geometric parameters
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from pathlib import Path
from unittest import TestCase
from imports.geometry_factory import GeometryFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.usage_factory import UsageFactory
from imports.construction_factory import ConstructionFactory
class TestGeometryFactory(TestCase):
"""
Non-functional TestGeometryFactory
Load testing
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._city = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def _get_citygml(self, file):
file_path = (self._example_path / file).resolve()
self._city = GeometryFactory('citygml', file_path).city
self.assertIsNotNone(self._city, 'city is none')
return self._city
def _check_buildings(self, city):
for building in city.buildings:
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
for internal_zone in building.internal_zones:
self.assertIsNotNone(internal_zone.usage_zones, 'usage zones are not defined')
self.assertIsNotNone(internal_zone.thermal_zones, 'thermal zones are not defined')
#self.assertIsNotNone(building.basement_heated, 'building basement_heated is none')
#self.assertIsNotNone(building.attic_heated, 'building attic_heated is none')
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none')
self.assertTrue(building.is_conditioned, 'building is_conditioned is not conditioned')
def _check_usage_zone(self, usage_zone):
self.assertIsNotNone(usage_zone.id, 'usage id is none')
def _check_thermal_zones(self, thermal_zone):
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
self.assertIsNone(thermal_zone.usage_zones, 'thermal_zone usage_zones is not none')
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal_control is not none')
@staticmethod
def _prepare_case_usage_first(city, input_key, construction_key, usage_key):
if input_key == 'pluto':
for building in city.buildings:
building.function = GeometryHelper.libs_function_from_pluto(building.function)
elif input_key == 'hft':
for building in city.buildings:
building.function = GeometryHelper.libs_function_from_hft(building.function)
UsageFactory(usage_key, city).enrich()
ConstructionFactory(construction_key, city).enrich()
@staticmethod
def _prepare_case_construction_first(city, input_key, construction_key, usage_key):
if input_key == 'pluto':
for building in city.buildings:
building.function = GeometryHelper.libs_function_from_pluto(building.function)
elif input_key == 'hft':
for building in city.buildings:
building.function = GeometryHelper.libs_function_from_hft(building.function)
ConstructionFactory(construction_key, city).enrich()
UsageFactory(usage_key, city).enrich()
def test_enrichment(self):
"""
Test enrichment of the city with different order and all possible combinations
:return: None
"""
file_1 = 'one_building_in_kelowna.gml'
file_2 = 'pluto_building.gml'
file_3 = 'C40_Final.gml'
_construction_keys = ['nrel', 'nrcan']
_usage_keys = ['ca', 'comnet'] # todo: add 'hft'
for construction_key in _construction_keys:
for usage_key in _usage_keys:
city = self._get_citygml(file_1)
self.assertTrue(len(city.buildings) == 1)
self._prepare_case_construction_first(city, 'hft', construction_key, usage_key)
self._check_buildings(city)
for building in city.buildings:
for internal_zone in building.internal_zones:
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
for usage_zone in internal_zone.usage_zones:
self._check_usage_zone(usage_zone)
for thermal_zone in internal_zone.thermal_zones:
self._check_thermal_zones(thermal_zone)
for construction_key in _construction_keys:
for usage_key in _usage_keys:
city = self._get_citygml(file_1)
self.assertTrue(len(city.buildings) == 1)
self._prepare_case_usage_first(city, 'hft', construction_key, usage_key)
self._check_buildings(city)
for building in city.buildings:
for internal_zone in building.internal_zones:
self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
for usage_zone in internal_zone.usage_zones:
self._check_usage_zone(usage_zone)
for thermal_zone in internal_zone.thermal_zones:
self._check_thermal_zones(thermal_zone)
for construction_key in _construction_keys:
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:
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)

View File

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

View File

@ -6,8 +6,6 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper
from city_model_structure.building_demand.thermal_opening import ThermalOpening
class TestGeometryFactory(TestCase): class TestGeometryFactory(TestCase):
@ -36,20 +34,66 @@ class TestGeometryFactory(TestCase):
self.assertIsNotNone(self._city, 'city is none') self.assertIsNotNone(self._city, 'city is none')
return self._city return self._city
@staticmethod def _check_buildings(self, city):
def _internal_function(function_format, original_function): for building in city.buildings:
new_function = original_function self.assertIsNotNone(building.name, 'building name is none')
if function_format == 'hft': self.assertIsNotNone(building.lod, 'building lod is none')
new_function = GeometryHelper.hft_to_function[original_function] self.assertIsNotNone(building.type, 'building type is none')
elif function_format == 'pluto': self.assertIsNotNone(building.volume, 'building volume is none')
new_function = GeometryHelper.pluto_to_function[original_function] self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
elif function_format == 'alkis': self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
# todo: not implemented yet!! self.assertIsNotNone(building.surfaces, 'building surfaces is none')
raise NotImplementedError self.assertIsNotNone(building.centroid, 'building centroid is none')
return new_function self.assertIsNotNone(building.max_height, 'building max_height is none')
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
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.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')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNone(building.average_storey_height, 'building average_storey_height is not none')
self.assertIsNone(building.storeys_above_ground, 'building storeys_above_ground is not none')
self.assertEqual(len(building.heating), 0, 'building heating is not none')
self.assertEqual(len(building.cooling), 0, 'building cooling is not none')
self.assertIsNotNone(building.eave_height, 'building eave height is none')
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')
self.assertFalse(building.is_conditioned, 'building is_conditioned is conditioned')
def _check_surfaces(self, building):
for surface in building.surfaces:
self.assertIsNotNone(surface.name, 'surface name is none')
self.assertIsNotNone(surface.id, 'surface id is none')
self.assertIsNone(surface.swr, 'surface swr is not none')
self.assertIsNotNone(surface.lower_corner, 'surface envelope_lower_corner is none')
self.assertIsNotNone(surface.upper_corner, 'surface envelope_upper_corner is none')
self.assertIsNotNone(surface.area_below_ground, 'surface area_below_ground is none')
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
self.assertIsNotNone(surface.azimuth, 'surface azimuth is none')
self.assertIsNotNone(surface.type, 'surface type is none')
self.assertIsNotNone(surface.inclination, 'surface inclination is none')
self.assertEqual(len(surface.global_irradiance), 0, 'global irradiance is calculated')
self.assertIsNotNone(surface.perimeter_polygon, 'surface perimeter_polygon is none')
self.assertIsNone(surface.holes_polygons, 'surface hole_polygons is not none')
self.assertIsNotNone(surface.solid_polygon, 'surface solid_polygon is none')
self.assertIsNone(surface.pv_system_installed, 'surface PV system installed is not none')
# citygml_classes # citygml_classes
def test_citygml_buildings(self): def test_import_citygml(self):
""" """
Test city objects in the city Test city objects in the city
:return: None :return: None
@ -57,175 +101,9 @@ class TestGeometryFactory(TestCase):
file = 'one_building_in_kelowna.gml' file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
self.assertTrue(len(city.buildings) == 1) self.assertTrue(len(city.buildings) == 1)
self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
self.assertIsNotNone(building.name, 'building name is none') self._check_surfaces(building)
self.assertIsNotNone(building.lod, 'building lod is none')
self.assertIsNotNone(building.centroid, 'building centroid is none')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNotNone(building.volume, 'building volume is none')
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
self.assertIsNotNone(building.surfaces[0].name, 'surface not found')
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
self.assertIsNotNone(building.terrains, 'building terrains is none')
self.assertIsNone(building.average_storey_height, 'building average_storey_height is not none')
self.assertIsNotNone(building.type, 'building type is none')
self.assertIsNotNone(building.max_height, 'building max_height is none')
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
def test_citygml_surfaces(self):
"""
Test surfaces in city objects
:return: None
"""
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
for surface in building.surfaces:
self.assertIsNotNone(surface.name, 'surface name is none')
self.assertIsNotNone(surface.type, 'surface type is none')
self.assertIsNotNone(surface.azimuth, 'surface azimuth is none')
self.assertIsNotNone(surface.inclination, 'surface inclination is none')
self.assertIsNotNone(surface.area_below_ground, 'surface area_below_ground is none')
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
self.assertIsNotNone(surface.global_irradiance, 'monthly irradiance is none')
self.assertIsNone(surface.swr, 'surface swr is not none')
self.assertIsNotNone(surface.lower_corner, 'surface envelope_lower_corner is none')
self.assertIsNotNone(surface.upper_corner, 'surface envelope_upper_corner is none')
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
self.assertIsNotNone(surface.perimeter_polygon, 'surface perimeter_polygon is none')
self.assertIsNone(surface.holes_polygons, 'surface hole_polygons is not none')
self.assertIsNotNone(surface.solid_polygon, 'surface solid_polygon is none')
def test_citygml_thermal_zone(self):
"""
Test thermal zones in city objects
:return: None
"""
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
self.assertIsNot(len(building.thermal_zones), 0, 'no building thermal_zones defined')
for thermal_zone in building.thermal_zones:
self.assertIsNotNone(thermal_zone.thermal_boundaries, 'thermal_zone thermal_boundaries is none')
self.assertIsNotNone(thermal_zone.floor_area, 'thermal_zone floor_area is none')
self.assertIsNone(thermal_zone.additional_thermal_bridge_u_value,
'thermal_zone additional_thermal_bridge_u_value is not none')
self.assertIsNone(thermal_zone.effective_thermal_capacity,
'thermal_zone effective_thermal_capacity is not none')
self.assertIsNone(thermal_zone.indirectly_heated_area_ratio,
'thermal_zone indirectly_heated_area_ratio is not none')
self.assertIsNone(thermal_zone.infiltration_rate_system_off,
'thermal_zone infiltration_rate_system_off is not none')
self.assertIsNone(thermal_zone.infiltration_rate_system_on,
'thermal_zone infiltration_rate_system_on is not none')
self.assertIsNone(thermal_zone.usage_zones,
'thermal_zone usage_zones are not none')
def test_citygml_thermal_boundary(self):
"""
Test thermal boundaries in thermal zones
:return: None
"""
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
self.assertIsNot(len(building.thermal_zones), 0, 'no building thermal_zones defined')
for thermal_zone in building.thermal_zones:
self.assertIsNot(len(thermal_zone.thermal_boundaries), 0, 'no building thermal_boundaries defined')
for thermal_boundary in thermal_zone.thermal_boundaries:
print(thermal_boundary.surface.type)
print(thermal_boundary.surface.area_above_ground)
self.assertIsNotNone(thermal_boundary.surface, 'thermal_boundary surface is none')
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
self.assertIsNotNone(thermal_boundary.area, 'thermal_boundary area is none')
self.assertIsNotNone(thermal_boundary.azimuth, 'thermal_boundary azimuth is none')
self.assertIsNotNone(thermal_boundary.thermal_zones, 'thermal_boundary delimits is none')
self.assertIsNotNone(thermal_boundary.inclination, 'thermal_boundary inclination is none')
def test_citygml_thermal_opening(self):
"""
Test thermal openings in thermal zones
:return: None
"""
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
self.assertIsNot(len(building.thermal_zones), 0, 'no building thermal_zones defined')
for thermal_zone in building.thermal_zones:
self.assertIsNot(len(thermal_zone.thermal_boundaries), 0, 'no building thermal_boundaries defined')
for thermal_boundary in thermal_zone.thermal_boundaries:
thermal_opening: ThermalOpening
for thermal_opening in thermal_boundary.thermal_openings:
self.assertIsNone(thermal_opening.frame_ratio, 'thermal_opening frame_ratio was initialized')
self.assertIsNone(thermal_opening.g_value, 'thermal_opening g_value was initialized')
self.assertIsNone(thermal_opening.conductivity, 'thermal_opening conductivity_w_mk was initialized')
self.assertIsNone(thermal_opening.back_side_solar_transmittance_at_normal_incidence,
'thermal_opening back_side_solar_transmittance_at_normal_incidence was initialized')
self.assertRaises(Exception, lambda: thermal_opening.openable_ratio,
'thermal_opening openable_ratio is not raising an exception')
self.assertIsNone(thermal_opening.front_side_solar_transmittance_at_normal_incidence,
'thermal_opening front_side_solar_transmittance_at_normal_incidence was initialized')
self.assertIsNone(thermal_opening.thickness, 'thermal_opening thickness_m was initialized')
self.assertRaises(Exception, lambda: thermal_opening.overall_u_value,
'thermal_opening u_value was initialized')
self.assertIsNone(thermal_opening.overall_u_value, 'thermal_opening overall_u_value was initialized')
self.assertIsNone(thermal_opening.hi, 'thermal_opening hi was initialized')
self.assertIsNone(thermal_opening.he, 'thermal_opening he was initialized')
def test_citygml_function(self):
"""
Test city objects' functions in the city
:return: None
"""
# case 1: hft
file = 'one_building_in_kelowna.gml'
function_format = 'hft'
city = self._get_citygml(file)
for building in city.buildings:
building.function = self._internal_function(function_format, building.function)
self.assertEqual(building.function, 'residential', 'format hft')
# case 2: Pluto
file = 'pluto_building.gml'
function_format = 'pluto'
city = self._get_citygml(file)
for building in city.buildings:
building.function = self._internal_function(function_format, building.function)
self.assertEqual(building.function, 'secondary school', 'format pluto')
# case 3: Alkis
file = 'one_building_in_kelowna_alkis.gml'
function_format = 'alkis'
city = self._get_citygml(file)
for building in city.buildings:
self.assertRaises(Exception, lambda: self._internal_function(function_format, building.function))
def test_citygml_storeys(self):
"""
Test division by storeys of buildings
:return: None
"""
file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
print('building')
for surface in building.surfaces:
print(surface.name)
print(surface.type)
print(surface.perimeter_polygon.area)
building.average_storey_height = 1.5
building.storeys_above_ground = 2
storeys = building.storeys
for storey in storeys:
print(storey.name)
print(storey.neighbours)
for surface in storey.surfaces:
print(surface.name)
print(surface.type)
print(surface.perimeter_polygon.area)
# obj # obj
def test_import_obj(self): def test_import_obj(self):
@ -235,8 +113,10 @@ class TestGeometryFactory(TestCase):
file = 'kelowna.obj' file = 'kelowna.obj'
city = self._get_obj(file) city = self._get_obj(file)
self.assertIsNotNone(city, 'city is none') self.assertIsNotNone(city, 'city is none')
self.assertTrue(len(city.buildings) == 1)
self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
self.assertIsNotNone(building, 'building is none') self._check_surfaces(building)
# osm # osm
def test_subway(self): def test_subway(self):

View File

@ -47,10 +47,8 @@ class TestLifeCycleAssessment(TestCase):
city_file = "../unittests/tests_data/C40_Final.gml" city_file = "../unittests/tests_data/C40_Final.gml"
city = GeometryFactory('citygml', city_file).city city = GeometryFactory('citygml', city_file).city
LifeCycleAssessment('material', city).enrich() LifeCycleAssessment('material', city).enrich()
self.assertTrue(len(city.lca_materials) > 0) for material in city.materials:
for lca_material in city.lca_materials: self.assertTrue(len(city.materials) > 0)
lca_mat = city.lca_material(lca_material.id)
self.assertTrue(lca_mat is not None)

View File

@ -31,30 +31,10 @@ class TestSchedulesFactory(TestCase):
ConstructionFactory('nrel', _city).enrich() ConstructionFactory('nrel', _city).enrich()
self.assertIsNotNone(_city, 'city is none') self.assertIsNotNone(_city, 'city is none')
for building in _city.buildings: 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() UsageFactory('hft', _city).enrich()
return _city 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): def test_doe_idf_archetypes(self):
""" """
Enrich the city with doe_idf schedule archetypes and verify it Enrich the city with doe_idf schedule archetypes and verify it
@ -64,6 +44,22 @@ class TestSchedulesFactory(TestCase):
occupancy_handler = 'doe_idf' occupancy_handler = 'doe_idf'
SchedulesFactory(occupancy_handler, city).enrich() SchedulesFactory(occupancy_handler, city).enrich()
for building in city.buildings: for building in city.buildings:
for usage_zone in building.usage_zones: for internal_zone in building.internal_zones:
for schedule in usage_zone.schedules: self.assertTrue(len(internal_zone.usage_zones) > 0)
print(schedule) for usage_zone in internal_zone.usage_zones:
self.assertIsNot(len(usage_zone.occupancy.occupancy_schedules), 0, 'no occupancy schedules defined')
for schedule in usage_zone.occupancy.occupancy_schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)
self.assertIsNot(len(usage_zone.lighting.schedules), 0, 'no lighting schedules defined')
for schedule in usage_zone.lighting.schedules:
self.assertIsNotNone(schedule.type)
self.assertIsNotNone(schedule.values)
self.assertIsNotNone(schedule.data_type)
self.assertIsNotNone(schedule.time_step)
self.assertIsNotNone(schedule.time_range)
self.assertIsNotNone(schedule.day_types)

View File

@ -50,8 +50,8 @@ class TestSensorsFactory(TestCase):
Load concordia sensors and verify it Load concordia sensors and verify it
""" """
SensorsFactory('cec', self._city, self._end_point).enrich() SensorsFactory('cec', self._city, self._end_point).enrich()
# SensorsFactory('cgf', self._city, self._end_point).enrich() SensorsFactory('cgf', self._city, self._end_point).enrich()
# SensorsFactory('ct', self._city, self._end_point).enrich() SensorsFactory('ct', self._city, self._end_point).enrich()
for city_object in self._city.city_objects: for city_object in self._city.city_objects:
print(city_object.name, len(city_object.sensors)) print(city_object.name, len(city_object.sensors))
for sensor in city_object.sensors: for sensor in city_object.sensors:

View File

@ -7,9 +7,7 @@ from pathlib import Path
from unittest import TestCase from unittest import TestCase
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.construction_factory import ConstructionFactory
from imports.usage_factory import UsageFactory from imports.usage_factory import UsageFactory
from imports.construction_factory import ConstructionFactory
from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
from imports.construction_factory import ConstructionFactory from imports.construction_factory import ConstructionFactory
@ -23,66 +21,161 @@ class TestUsageFactory(TestCase):
Configure test environment Configure test environment
:return: :return:
""" """
self._city = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve() self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def _get_citygml(self, file): def _get_citygml(self, file):
file_path = (self._example_path / file).resolve() file_path = (self._example_path / file).resolve()
_city = GeometryFactory('citygml', file_path).city self._city = GeometryFactory('citygml', file_path).city
self.assertIsNotNone(_city, 'city is none') self.assertIsNotNone(self._city, 'city is none')
return _city return self._city
def test_comnet(self): def _check_buildings(self, city):
for building in city.buildings:
self.assertIsNotNone(building.name, 'building name is none')
self.assertIsNotNone(building.lod, 'building lod is none')
self.assertIsNotNone(building.type, 'building type is none')
self.assertIsNotNone(building.volume, 'building volume is none')
self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
self.assertIsNotNone(building.centroid, 'building centroid is none')
self.assertIsNotNone(building.max_height, 'building max_height is none')
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
self.assertIsNotNone(building.grounds, 'building grounds is none')
self.assertIsNotNone(building.walls, 'building walls is none')
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(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')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNone(building.average_storey_height, 'building average_storey_height is not none')
self.assertIsNone(building.storeys_above_ground, 'building storeys_above_ground is not none')
self.assertEqual(len(building.heating), 0, 'building heating is not none')
self.assertEqual(len(building.cooling), 0, 'building cooling is not none')
self.assertIsNotNone(building.eave_height, 'building eave height is none')
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')
self.assertTrue(building.is_conditioned, 'building is not conditioned')
def _check_usage_zone(self, usage_zone):
self.assertIsNotNone(usage_zone.usage, 'usage is none')
self.assertIsNotNone(usage_zone.percentage, 'usage percentage is none')
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.thermal_control, 'thermal control is none')
self.assertIsNotNone(usage_zone.thermal_control.mean_heating_set_point, 'control heating set point is none')
self.assertIsNotNone(usage_zone.thermal_control.heating_set_back, 'control heating set back is none')
self.assertIsNotNone(usage_zone.thermal_control.mean_cooling_set_point, 'control cooling set point is none')
def test_import_comnet(self):
"""
Enrich the city with the usage information from comnet and verify it
"""
file = 'pluto_building.gml' file = 'pluto_building.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
for building in city.buildings: for building in city.buildings:
building.function = GeometryHelper.pluto_to_function[building.function] building.function = GeometryHelper.libs_function_from_pluto(building.function)
ConstructionFactory('nrel', city).enrich()
UsageFactory('comnet', city).enrich() UsageFactory('comnet', city).enrich()
self._check_buildings(city)
def test_city_with_usage(self):
"""
Enrich the city with the usage information and verify it
:return: None
"""
# case 1: HFT
file = 'pluto_building.gml'
city = self._get_citygml(file)
for building in city.buildings: for building in city.buildings:
building.function = GeometryHelper.pluto_to_function[building.function] for internal_zone in building.internal_zones:
ConstructionFactory('nrel', city).enrich() self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
UsageFactory('hft', city).enrich() for usage_zone in internal_zone.usage_zones:
for building in city.buildings: self._check_usage_zone(usage_zone)
self.assertIsNot(len(building.usage_zones), 0, 'no building usage_zones defined') self.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change is none')
for usage_zone in building.usage_zones: self.assertIsNotNone(usage_zone.thermal_control.heating_set_point_schedules,
self.assertIsNotNone(usage_zone.usage, 'usage is none') 'control heating set point schedule is none')
self.assertIsNotNone(usage_zone.internal_gains, 'usage is none') self.assertIsNotNone(usage_zone.thermal_control.cooling_set_point_schedules,
self.assertIsNotNone(usage_zone.cooling_setpoint, 'usage is none') 'control cooling set point schedule is none')
self.assertIsNotNone(usage_zone.heating_setback, 'usage is none') self.assertIsNotNone(usage_zone.occupancy, 'occupancy is none')
self.assertIsNotNone(usage_zone.heating_setpoint, 'usage is none') occupancy = usage_zone.occupancy
self.assertIsNotNone(usage_zone.occupancy_density, 'usage is none') self.assertIsNotNone(occupancy.occupancy_density, 'occupancy density is none')
self.assertIsNotNone(usage_zone.hours_day, 'usage is none') self.assertIsNotNone(occupancy.latent_internal_gain, 'occupancy latent internal gain is none')
self.assertIsNotNone(usage_zone.days_year, 'usage is none') self.assertIsNotNone(occupancy.sensible_convective_internal_gain,
self.assertIsNotNone(usage_zone.dhw_average_volume_pers_day, 'usage is none') 'occupancy sensible convective internal gain is none')
self.assertIsNotNone(usage_zone.dhw_preparation_temperature, 'usage is none') self.assertIsNotNone(occupancy.sensible_radiative_internal_gain,
self.assertIsNotNone(usage_zone.electrical_app_average_consumption_sqm_year, 'usage is none') 'occupancy sensible radiant internal gain is none')
self.assertIsNotNone(usage_zone.is_heated, 'thermal_zone heated is none') self.assertIsNotNone(occupancy.occupancy_schedules, 'occupancy schedule is none')
self.assertIsNotNone(usage_zone.is_cooled, 'thermal_zone cooled is none') self.assertIsNone(occupancy.occupants, 'occupancy density is not none')
self.assertIsNotNone(usage_zone.lighting, 'lighting is none')
lighting = usage_zone.lighting
self.assertIsNotNone(lighting.lighting_density, 'lighting density is none')
self.assertIsNotNone(lighting.latent_fraction, 'lighting latent fraction is none')
self.assertIsNotNone(lighting.convective_fraction, 'lighting convective fraction is none')
self.assertIsNotNone(lighting.radiative_fraction, 'lighting radiant fraction is none')
self.assertIsNotNone(lighting.schedules, 'lighting schedule is none')
self.assertIsNotNone(usage_zone.appliances, 'appliances is none')
appliances = usage_zone.appliances
self.assertIsNotNone(appliances.appliances_density, 'appliances density is none')
self.assertIsNotNone(appliances.latent_fraction, 'appliances latent fraction is none')
self.assertIsNotNone(appliances.convective_fraction, 'appliances convective fraction is none')
self.assertIsNotNone(appliances.radiative_fraction, 'appliances radiant fraction is none')
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')
self.assertIsNotNone(usage_zone.thermal_control.hvac_availability_schedules,
'control hvac availability is none')
def test_import_ca(self):
# case 2: CA """
Enrich the city with the usage information from canada and verify it
"""
file = 'one_building_in_kelowna.gml' file = 'one_building_in_kelowna.gml'
city = self._get_citygml(file) city = self._get_citygml(file)
ConstructionFactory('nrel', city).enrich()
UsageFactory('ca', city).enrich() UsageFactory('ca', city).enrich()
self._check_buildings(city)
for building in city.buildings: for building in city.buildings:
self.assertIsNot(len(building.usage_zones), 0, 'no building usage_zones defined') for internal_zone in building.internal_zones:
for usage_zone in building.usage_zones: self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined')
self.assertIsNotNone(usage_zone.usage, 'usage is none') for usage_zone in internal_zone.usage_zones:
self.assertIsNotNone(usage_zone.internal_gains, 'usage is none') self._check_usage_zone(usage_zone)
self.assertIsNotNone(usage_zone.cooling_setpoint, 'usage is none') self.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change is none')
self.assertIsNotNone(usage_zone.heating_setback, 'usage is none') self.assertIsNotNone(usage_zone.not_detailed_source_mean_annual_internal_gains,
self.assertIsNotNone(usage_zone.heating_setpoint, 'usage is none') 'not detailed internal gains is none')
self.assertIsNotNone(usage_zone.occupancy_density, 'usage is none')
self.assertIsNotNone(usage_zone.hours_day, 'usage is none') def test_import_hft(self):
self.assertIsNotNone(usage_zone.days_year, 'usage is none') """
Enrich the city with the usage information from hft and verify it
"""
file = 'pluto_building.gml'
city = self._get_citygml(file)
for building in city.buildings:
building.function = GeometryHelper.libs_function_from_pluto(building.function)
UsageFactory('hft', city).enrich()
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)
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,
'control cooling set point schedule is none')
self.assertIsNotNone(usage_zone.occupancy, 'occupancy is none')
occupancy = usage_zone.occupancy
self.assertIsNotNone(occupancy.occupancy_density, 'occupancy density is none')
self.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.assertIsNone(usage_zone.lighting, 'lighting is not none')
self.assertIsNone(usage_zone.appliances, 'appliances is not none')