diff --git a/catalog_factories/data_models/greenery/content.py b/catalog_factories/data_models/greenery/content.py index b9849d5d..e5160c61 100644 --- a/catalog_factories/data_models/greenery/content.py +++ b/catalog_factories/data_models/greenery/content.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class Content: def __init__(self, vegetations, plants, soils): self._vegetations = vegetations diff --git a/catalog_factories/data_models/greenery/plant.py b/catalog_factories/data_models/greenery/plant.py index c9102387..db7a0d6a 100644 --- a/catalog_factories/data_models/greenery/plant.py +++ b/catalog_factories/data_models/greenery/plant.py @@ -5,7 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ -from catalog_factories.data_models.greenery.soil import Soil as libs_soil +from catalog_factories.data_models.greenery.soil import Soil as hub_soil class Plant: @@ -20,12 +20,13 @@ class Plant: self._co2_sequestration = plant.co2Sequestration self._grows_on = [] for soil in plant.growsOn: - self._grows_on.append(libs_soil(soil)) + self._grows_on.append(hub_soil(soil)) @property def name(self): """ Get plant name + :return: string """ return self._name @@ -33,13 +34,15 @@ class Plant: def category(self): """ Get plant category name + :return: string """ return self._category @property def height(self): """ - Get plant height + Get plant height in m + :return: float """ return self._height @@ -47,6 +50,7 @@ class Plant: def leaf_area_index(self): """ Get plant leaf area index + :return: float """ return self._leaf_area_index @@ -54,6 +58,7 @@ class Plant: def leaf_reflectivity(self): """ Get plant leaf area index + :return: float """ return self._leaf_reflectivity @@ -61,26 +66,30 @@ class Plant: def leaf_emissivity(self): """ Get plant leaf emissivity + :return: float """ return self._leaf_emissivity @property def minimal_stomatal_resistance(self): """ - Get plant minimal stomatal resistance + Get plant minimal stomatal resistance in s/m + :return: float """ return self._minimal_stomatal_resistance @property def co2_sequestration(self): """ - Get plant co2 sequestration capacity + Get plant co2 sequestration capacity in kg CO2 equivalent + :return: float """ return self._co2_sequestration @property - def grows_on(self) -> [libs_soil]: + def grows_on(self) -> [hub_soil]: """ Get plant compatible soils + :return: [Soil] """ return self._grows_on diff --git a/catalog_factories/data_models/greenery/plant_percentage.py b/catalog_factories/data_models/greenery/plant_percentage.py index 38819f53..7501e186 100644 --- a/catalog_factories/data_models/greenery/plant_percentage.py +++ b/catalog_factories/data_models/greenery/plant_percentage.py @@ -7,6 +7,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca from catalog_factories.data_models.greenery.plant import Plant as libs_plant + class PlantPercentage(libs_plant): def __init__(self, percentage, plant_category, plant): @@ -15,4 +16,8 @@ class PlantPercentage(libs_plant): @property def percentage(self): + """ + Get plant percentage + :return: float + """ return self._percentage diff --git a/catalog_factories/data_models/greenery/soil.py b/catalog_factories/data_models/greenery/soil.py index d63d11e5..c6e8266b 100644 --- a/catalog_factories/data_models/greenery/soil.py +++ b/catalog_factories/data_models/greenery/soil.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class Soil: def __init__(self, soil): self._name = soil.name @@ -23,6 +24,7 @@ class Soil: def name(self): """ Get soil name + :return: string """ return self._name @@ -30,27 +32,31 @@ class Soil: def roughness(self): """ Get soil roughness + :return: string """ return self._roughness @property def dry_conductivity(self): """ - Get soil dry conductivity + Get soil dry conductivity in W/mK + :return: float """ return self._dry_conductivity @property def dry_density(self): """ - Get soil dry density + Get soil dry density in kg/m3 + :return: float """ return self._dry_density @property def dry_specific_heat(self): """ - Get soil dry specific heat + Get soil dry specific heat in J/kgK + :return: float """ return self._dry_specific_heat @@ -58,6 +64,7 @@ class Soil: def thermal_absorptance(self): """ Get soil thermal absortance + :return: float """ return self._thermal_absorptance @@ -65,6 +72,7 @@ class Soil: def solar_absorptance(self): """ Get soil solar absortance + :return: float """ return self._solar_absorptance @@ -72,6 +80,7 @@ class Soil: def visible_absorptance(self): """ Get soil visible absortance + :return: float """ return self._visible_absorptance @@ -79,6 +88,7 @@ class Soil: def saturation_volumetric_moisture_content(self): """ Get soil saturation volumetric moisture content + :return: float """ return self._saturation_volumetric_moisture_content @@ -86,6 +96,7 @@ class Soil: def residual_volumetric_moisture_content(self): """ Get soil residual volumetric moisture content + :return: float """ return self._residual_volumetric_moisture_content @@ -93,5 +104,6 @@ class Soil: def initial_volumetric_moisture_content(self): """ Get soil initial volumetric moisture content + :return: float """ return self._initial_volumetric_moisture_content diff --git a/catalog_factories/data_models/greenery/vegetation.py b/catalog_factories/data_models/greenery/vegetation.py index eb234b13..87a80c40 100644 --- a/catalog_factories/data_models/greenery/vegetation.py +++ b/catalog_factories/data_models/greenery/vegetation.py @@ -7,6 +7,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca from catalog_factories.data_models.greenery.plant_percentage import PlantPercentage + class Vegetation: def __init__(self, category, vegetation, plant_percentages): self._name = vegetation.name @@ -31,6 +32,7 @@ class Vegetation: def name(self): """ Get vegetation name + :return: string """ return self._name @@ -38,13 +40,15 @@ class Vegetation: def category(self): """ Get vegetation category + :return: string """ return self._category @property def soil_thickness(self): """ - Get soil thickness + Get soil thickness in m + :return: float """ return self._soil_thickness @@ -52,13 +56,15 @@ class Vegetation: def management(self): """ Get management + :return: string """ return self._management @property def air_gap(self): """ - Get air gap + Get air gap in m + :return: float """ return self._air_gap @@ -66,6 +72,7 @@ class Vegetation: def plant_percentages(self) -> [PlantPercentage]: """ Get plant percentages + :return: [PlantPercentage] """ percentage = 0.0 for plant_percentage in self._plant_percentages: @@ -78,6 +85,7 @@ class Vegetation: def soil_name(self): """ Get soil name + :return: string """ return self._soil_name @@ -85,27 +93,31 @@ class Vegetation: def soil_roughness(self): """ Get soil roughness + :return: float """ return self._soil_roughness @property def dry_soil_conductivity(self): """ - Get soil dry conductivity + Get soil dry conductivity in W/mK + :return: float """ return self._dry_soil_conductivity @property def dry_soil_density(self): """ - Get soil dry density + Get soil dry density in kg/m3 + :return: float """ return self._dry_soil_density @property def dry_soil_specific_heat(self): """ - Get soil dry specific heat + Get soil dry specific heat in J/kgK + :return: float """ return self._dry_soil_specific_heat @@ -113,6 +125,7 @@ class Vegetation: def soil_thermal_absorptance(self): """ Get soil thermal absortance + :return: float """ return self._soil_thermal_absorptance @@ -120,6 +133,7 @@ class Vegetation: def soil_solar_absorptance(self): """ Get soil solar absortance + :return: float """ return self._soil_solar_absorptance @@ -127,6 +141,7 @@ class Vegetation: def soil_visible_absorptance(self): """ Get soil visible absortance + :return: float """ return self._soil_visible_absorptance @@ -134,6 +149,7 @@ class Vegetation: def soil_saturation_volumetric_moisture_content(self): """ Get soil saturation volumetric moisture content + :return: float """ return self._soil_saturation_volumetric_moisture_content @@ -141,6 +157,7 @@ class Vegetation: def soil_residual_volumetric_moisture_content(self): """ Get soil residual volumetric moisture content + :return: float """ return self._soil_residual_volumetric_moisture_content @@ -148,5 +165,6 @@ class Vegetation: def soil_initial_volumetric_moisture_content(self): """ Get soil initial volumetric moisture content + :return: float """ return self._soil_initial_volumetric_moisture_content diff --git a/city_model_structure/attributes/edge.py b/city_model_structure/attributes/edge.py index 9fd6d75b..5a3f048b 100644 --- a/city_model_structure/attributes/edge.py +++ b/city_model_structure/attributes/edge.py @@ -32,7 +32,7 @@ class Edge: @property def id(self): """ - Get edge id, an universally unique identifier randomly generated + Get edge id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/city_model_structure/attributes/node.py b/city_model_structure/attributes/node.py index 32b82466..df450570 100644 --- a/city_model_structure/attributes/node.py +++ b/city_model_structure/attributes/node.py @@ -34,7 +34,7 @@ class Node: @property def id(self): """ - Get node id, an universally unique identifier randomly generated + Get node id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/city_model_structure/attributes/schedule.py b/city_model_structure/attributes/schedule.py index 4881fce8..638cd7ab 100644 --- a/city_model_structure/attributes/schedule.py +++ b/city_model_structure/attributes/schedule.py @@ -26,7 +26,7 @@ class Schedule: @property def id(self): """ - Get schedule id, an universally unique identifier randomly generated + Get schedule id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/city_model_structure/building_demand/internal_zone.py b/city_model_structure/building_demand/internal_zone.py index a4def3d0..8c1d3376 100644 --- a/city_model_structure/building_demand/internal_zone.py +++ b/city_model_structure/building_demand/internal_zone.py @@ -30,7 +30,7 @@ class InternalZone: @property def id(self): """ - Get internal zone id, an universally unique identifier randomly generated + Get internal zone id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/city_model_structure/building_demand/layer.py b/city_model_structure/building_demand/layer.py index 04dd7596..b7b25983 100644 --- a/city_model_structure/building_demand/layer.py +++ b/city_model_structure/building_demand/layer.py @@ -21,7 +21,7 @@ class Layer: @property def id(self): """ - Get layer id, an universally unique identifier randomly generated + Get layer id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/city_model_structure/building_demand/surface.py b/city_model_structure/building_demand/surface.py index 1778354d..8c3e8a1f 100644 --- a/city_model_structure/building_demand/surface.py +++ b/city_model_structure/building_demand/surface.py @@ -40,8 +40,7 @@ class Surface: self._solid_polygon = solid_polygon self._pv_system_installed = None self._inverse = None - # todo: do I need it??? - self._associated_thermal_boundaries = None + # todo: create self._associated_thermal_boundaries and bring the vegetation here instead of in thermal_boundary @property def name(self): diff --git a/city_model_structure/building_demand/thermal_boundary.py b/city_model_structure/building_demand/thermal_boundary.py index 5afb36a9..b058f4ff 100644 --- a/city_model_structure/building_demand/thermal_boundary.py +++ b/city_model_structure/building_demand/thermal_boundary.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ + import uuid from typing import List, Union from helpers.configuration_helper import ConfigurationHelper as ch @@ -12,6 +13,7 @@ from city_model_structure.building_demand.layer import Layer from city_model_structure.building_demand.thermal_opening import ThermalOpening from city_model_structure.building_demand.thermal_zone import ThermalZone from city_model_structure.building_demand.surface import Surface +from city_model_structure.greenery.vegetation import Vegetation class ThermalBoundary: @@ -41,12 +43,13 @@ class ThermalBoundary: self._alpha_coefficient = None self._radiative_coefficient = None self._window_ratio = None - self._calculated = False + self._window_ration_is_calculated = False + self._vegetation = None @property def id(self): """ - Get thermal zone id, an universally unique identifier randomly generated + Get thermal zone id, a universally unique identifier randomly generated :return: str """ if self._id is None: @@ -249,7 +252,7 @@ class ThermalBoundary: :return: float """ if self.windows_areas is not None: - if not self._calculated: + if not self._window_ration_is_calculated: _calculated = True if len(self.windows_areas) == 0: self._window_ratio = 0 @@ -266,7 +269,7 @@ class ThermalBoundary: Set thermal boundary window ratio :param value: str """ - if self._calculated: + if self._window_ration_is_calculated: raise ValueError('Window ratio cannot be assigned when the windows are defined in the geometry.') self._window_ratio = float(value) @@ -421,3 +424,19 @@ class ThermalBoundary: """ if value is not None: self._radiative_coefficient = float(value) + + @property + def vegetation(self) -> Union[None, Vegetation]: + """ + Get the vegetation construction at the external surface of the thermal boundary + :return: None or Vegetation + """ + return self._vegetation + + @vegetation.setter + def vegetation(self, value): + """ + Set the vegetation construction at the external surface of the thermal boundary + :param value: Vegetation + """ + self._vegetation = value diff --git a/city_model_structure/building_demand/thermal_opening.py b/city_model_structure/building_demand/thermal_opening.py index ad3cfd01..84002a08 100644 --- a/city_model_structure/building_demand/thermal_opening.py +++ b/city_model_structure/building_demand/thermal_opening.py @@ -37,7 +37,7 @@ class ThermalOpening: @property def id(self): """ - Get thermal zone id, an universally unique identifier randomly generated + Get thermal zone id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/city_model_structure/building_demand/thermal_zone.py b/city_model_structure/building_demand/thermal_zone.py index 36b6d9c3..c93675cb 100644 --- a/city_model_structure/building_demand/thermal_zone.py +++ b/city_model_structure/building_demand/thermal_zone.py @@ -5,14 +5,15 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ -import uuid, sys + +import uuid +import sys import copy from typing import List, Union, TypeVar from city_model_structure.building_demand.occupancy import Occupancy from city_model_structure.building_demand.appliances import Appliances from city_model_structure.building_demand.lighting import Lighting from city_model_structure.building_demand.internal_gain import InternalGain -from city_model_structure.attributes.schedule import Schedule from city_model_structure.building_demand.thermal_control import ThermalControl from city_model_structure.energy_systems.hvac_system import HvacSystem import helpers.constants as cte @@ -54,7 +55,7 @@ class ThermalZone: @property def id(self): """ - Get thermal zone id, an universally unique identifier randomly generated + Get thermal zone id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/city_model_structure/building_demand/usage_zone.py b/city_model_structure/building_demand/usage_zone.py index eff1afe8..74ea89f5 100644 --- a/city_model_structure/building_demand/usage_zone.py +++ b/city_model_structure/building_demand/usage_zone.py @@ -12,17 +12,18 @@ from city_model_structure.building_demand.occupancy import Occupancy from city_model_structure.building_demand.lighting import Lighting from city_model_structure.building_demand.appliances import Appliances from city_model_structure.building_demand.thermal_control import ThermalControl +import helpers.constants as cte class UsageZone: """ UsageZone class """ - def __init__(self): + def __init__(self, not_detailed_source_mean_annual_internal_gains=None): self._id = None self._usage = None self._percentage = None - self._not_detailed_source_mean_annual_internal_gains = None + self._not_detailed_source_mean_annual_internal_gains = not_detailed_source_mean_annual_internal_gains self._hours_day = None self._days_year = None # self._electrical_app_average_consumption_sqm_year = None @@ -31,11 +32,12 @@ class UsageZone: self._lighting = None self._appliances = None self._thermal_control = None + self._internal_gains = None @property def id(self): """ - Get usage zone id, an universally unique identifier randomly generated + Get usage zone id, a universally unique identifier randomly generated :return: str """ if self._id is None: @@ -76,22 +78,6 @@ class UsageZone: if value is not None: self._percentage = float(value) - @property - def not_detailed_source_mean_annual_internal_gains(self) -> List[InternalGain]: - """ - Get usage zone internal gains with unknown energy source - :return: [InternalGain] - """ - return self._not_detailed_source_mean_annual_internal_gains - - @not_detailed_source_mean_annual_internal_gains.setter - def not_detailed_source_mean_annual_internal_gains(self, value): - """ - Set usage zone internal gains with unknown energy source - :param value: [InternalGain] - """ - self._not_detailed_source_mean_annual_internal_gains = value - @property def hours_day(self) -> Union[None, float]: """ @@ -143,23 +129,6 @@ class UsageZone: if value is not None: self._mechanical_air_change = float(value) - @property - def electrical_app_average_consumption_sqm_year(self) -> Union[None, float]: - """ - Get average consumption of electrical appliances in Joules hour per square meter and year (J/m2yr) - :return: None or float - """ - return self._electrical_app_average_consumption_sqm_year - - @electrical_app_average_consumption_sqm_year.setter - def electrical_app_average_consumption_sqm_year(self, value): - """ - Set average consumption of electrical appliances in Joules per square meter and year (J/m2yr) - :param value: float - """ - if value is not None: - self._electrical_app_average_consumption_sqm_year = float(value) - @property def occupancy(self) -> Union[None, Occupancy]: """ @@ -223,3 +192,64 @@ class UsageZone: :param value: ThermalControl """ self._thermal_control = value + + @property + def internal_gains(self) -> List[InternalGain]: + """ + Calculates and returns the list of all internal gains defined + :return: [InternalGain] + """ + if self._not_detailed_source_mean_annual_internal_gains is not None: + self._internal_gains = [] + for _internal_gain in self._not_detailed_source_mean_annual_internal_gains: + self._internal_gains.append(_internal_gain) + + if self.occupancy is not None: + if self.occupancy.latent_internal_gain is not None: + _internal_gain = InternalGain() + _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 + if _total_heat_gain > 0: + _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 + else: + _internal_gain.latent_fraction = 0 + _internal_gain.radiative_fraction = 0 + _internal_gain.convective_fraction = 0 + _internal_gain.schedules = self.occupancy.occupancy_schedules + if self._internal_gains is not None: + self._internal_gains.append(_internal_gain) + else: + self._internal_gains = [_internal_gain] + + if self.lighting is not None: + _internal_gain = InternalGain() + _internal_gain.type = cte.LIGHTING + self._add_internal_gain(self.lighting, _internal_gain) + 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 = InternalGain() + _internal_gain.type = cte.APPLIANCES + self._add_internal_gain(self.appliances, _internal_gain) + if self._internal_gains is not None: + self._internal_gains.append(_internal_gain) + else: + self._internal_gains = [_internal_gain] + + return self._internal_gains + + @staticmethod + def _add_internal_gain(internal_gain_type, _internal_gain): + _internal_gain.average_internal_gain = internal_gain_type.density + _internal_gain.latent_fraction = internal_gain_type.latent_fraction + _internal_gain.radiative_fraction = internal_gain_type.radiative_fraction + _internal_gain.convective_fraction = internal_gain_type.convective_fraction + _internal_gain.schedules = internal_gain_type.schedules diff --git a/city_model_structure/greenery/plant.py b/city_model_structure/greenery/plant.py new file mode 100644 index 00000000..8962d8ee --- /dev/null +++ b/city_model_structure/greenery/plant.py @@ -0,0 +1,103 @@ +""" +Plant class +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" + +from typing import List +from city_model_structure.greenery.soil import Soil + + +class Plant: + def __init__(self, name, height, leaf_area_index, leaf_reflectivity, leaf_emissivity, minimal_stomatal_resistance, + co2_sequestration, grows_on_soils): + self._name = name + self._percentage = None + self._height = height + self._leaf_area_index = leaf_area_index + self._leaf_reflectivity = leaf_reflectivity + self._leaf_emissivity = leaf_emissivity + self._minimal_stomatal_resistance = minimal_stomatal_resistance + self._co2_sequestration = co2_sequestration + self._grows_on = grows_on_soils + + @property + def name(self): + """ + Get plant name + :return: string + """ + return self._name + + @property + def percentage(self): + """ + Get percentage of plant in vegetation + :return: float + """ + return self._percentage + + @percentage.setter + def percentage(self, value): + """ + Set percentage of plant in vegetation + :param value: float + """ + self._percentage = value + + @property + def height(self): + """ + Get plant height in m + :return: float + """ + return self._height + + @property + def leaf_area_index(self): + """ + Get plant leaf area index + :return: float + """ + return self._leaf_area_index + + @property + def leaf_reflectivity(self): + """ + Get plant leaf area index + :return: float + """ + return self._leaf_reflectivity + + @property + def leaf_emissivity(self): + """ + Get plant leaf emissivity + :return: float + """ + return self._leaf_emissivity + + @property + def minimal_stomatal_resistance(self): + """ + Get plant minimal stomatal resistance in s/m + :return: float + """ + return self._minimal_stomatal_resistance + + @property + def co2_sequestration(self): + """ + Get plant co2 sequestration capacity in kg CO2 equivalent + :return: float + """ + return self._co2_sequestration + + @property + def grows_on(self) -> List[Soil]: + """ + Get plant compatible soils + :return: [Soil] + """ + return self._grows_on diff --git a/city_model_structure/greenery/soil.py b/city_model_structure/greenery/soil.py new file mode 100644 index 00000000..b938d0b2 --- /dev/null +++ b/city_model_structure/greenery/soil.py @@ -0,0 +1,127 @@ +""" +Soil class +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" + + +class Soil: + def __init__(self, name, roughness, dry_conductivity, dry_density, dry_specific_heat, thermal_absorptance, + solar_absorptance, visible_absorptance, saturation_volumetric_moisture_content, + residual_volumetric_moisture_content): + self._name = name + self._roughness = roughness + self._dry_conductivity = dry_conductivity + self._dry_density = dry_density + self._dry_specific_heat = dry_specific_heat + self._thermal_absorptance = thermal_absorptance + self._solar_absorptance = solar_absorptance + self._visible_absorptance = visible_absorptance + self._saturation_volumetric_moisture_content = saturation_volumetric_moisture_content + self._residual_volumetric_moisture_content = residual_volumetric_moisture_content + self._initial_volumetric_moisture_content = None + + @property + def name(self): + """ + Get soil name + :return: string + """ + return self._name + + @property + def roughness(self): + """ + Get soil roughness + :return: string + """ + return self._roughness + + @property + def dry_conductivity(self): + """ + Get soil dry conductivity in W/mK + :return: float + """ + return self._dry_conductivity + + @property + def dry_density(self): + """ + Get soil dry density in kg/m3 + :return: float + """ + return self._dry_density + + @property + def dry_specific_heat(self): + """ + Get soil dry specific heat in J/kgK + :return: float + """ + return self._dry_specific_heat + + @property + def thermal_absorptance(self): + """ + Get soil thermal absortance + :return: float + """ + return self._thermal_absorptance + + @property + def solar_absorptance(self): + """ + Get soil solar absortance + :return: float + """ + return self._solar_absorptance + + @property + def visible_absorptance(self): + """ + Get soil visible absortance + :return: float + """ + return self._visible_absorptance + + @property + def saturation_volumetric_moisture_content(self): + """ + Get soil saturation volumetric moisture content + :return: float + """ + return self._saturation_volumetric_moisture_content + + @property + def residual_volumetric_moisture_content(self): + """ + Get soil residual volumetric moisture content + :return: None or float + """ + return self._residual_volumetric_moisture_content + + @residual_volumetric_moisture_content.setter + def residual_volumetric_moisture_content(self, value): + """ + Set soil residual volumetric moisture content + :param value: float + """ + self._residual_volumetric_moisture_content = value + + @property + def initial_volumetric_moisture_content(self): + """ + Get soil initial volumetric moisture content + :return: None or float + """ + return self._initial_volumetric_moisture_content + + @initial_volumetric_moisture_content.setter + def initial_volumetric_moisture_content(self, value): + """ + Set soil initial volumetric moisture content + :param value: float + """ + self._initial_volumetric_moisture_content = value diff --git a/city_model_structure/greenery/vegetation.py b/city_model_structure/greenery/vegetation.py new file mode 100644 index 00000000..3889b885 --- /dev/null +++ b/city_model_structure/greenery/vegetation.py @@ -0,0 +1,84 @@ +""" +Vegetation class +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" + +from typing import List +from city_model_structure.greenery.soil import Soil +from city_model_structure.greenery.plant import Plant + + +class Vegetation: + def __init__(self, name, soil, soil_thickness, plants): + self._name = name + self._management = None + self._air_gap = None + self._soil = soil + self._soil_thickness = soil_thickness + self._plants = plants + + @property + def name(self): + """ + Get vegetation name + :return: string + """ + return self._name + + @property + def management(self): + """ + Get management + :return: string + """ + return self._management + + @management.setter + def management(self, value): + """ + Set management + :param value: string + """ + self._management = value + + @property + def air_gap(self): + """ + Get air gap in m + :return: float + """ + return self._air_gap + + @air_gap.setter + def air_gap(self, value): + """ + Set air gap in m + :param value: float + """ + self._air_gap = value + + @property + def soil(self) -> Soil: + """ + Get soil + :return: Soil + """ + return self._soil + + @property + def soil_thickness(self): + """ + Get soil thickness in m + :return: float + """ + return self._soil_thickness + + @property + def plants(self) -> List[Plant]: + """ + Get list plants in the vegetation + :return: List[Plant] + """ + return self._plants diff --git a/city_model_structure/network.py b/city_model_structure/network.py index 77efc492..9c88bb0b 100644 --- a/city_model_structure/network.py +++ b/city_model_structure/network.py @@ -30,7 +30,7 @@ class Network(CityObject): @property def id(self): """ - Get network id, an universally unique identifier randomly generated + Get network id, a universally unique identifier randomly generated :return: str """ if self._id is None: diff --git a/data/schedules/comnet_archetypes.xlsx b/data/schedules/comnet_archetypes.xlsx deleted file mode 100644 index 8fce488c..00000000 Binary files a/data/schedules/comnet_archetypes.xlsx and /dev/null differ diff --git a/exports/formats/idf.py b/exports/formats/idf.py index 92f6b576..6625990b 100644 --- a/exports/formats/idf.py +++ b/exports/formats/idf.py @@ -44,6 +44,8 @@ class Idf: _LOCATION = 'SITE:LOCATION' _WINDOW_MATERIAL_SIMPLE = 'WINDOWMATERIAL:SIMPLEGLAZINGSYSTEM' _WINDOW = 'WINDOW' + _MATERIAL_ROOFVEGETATION = 'MATERIAL:ROOFVEGETATION' + _SIMPLE = 'Simple' idf_surfaces = { # todo: make an enum for all the surface types @@ -224,9 +226,12 @@ class Idf: def _add_construction(self, thermal_boundary): for construction in self._idf.idfobjects[self._CONSTRUCTION]: - if construction.Name == thermal_boundary.construction_name: - return - + if thermal_boundary.vegetation is not None: + if construction.Name == f'{thermal_boundary.construction_name}_{thermal_boundary.vegetation.name}': + return + else: + if construction.Name == thermal_boundary.construction_name: + return if thermal_boundary.layers is None: for material in self._idf.idfobjects[self._MATERIAL]: if material.Name == "DefaultMaterial": @@ -237,9 +242,15 @@ class Idf: self._add_material(layer) layers = thermal_boundary.layers # The constructions should have at least one layer - _kwargs = {'Name': thermal_boundary.construction_name, 'Outside_Layer': layers[0].material.name} - for i in range(1, len(layers) - 1): - _kwargs[f'Layer_{i + 1}'] = layers[1].material.name + if thermal_boundary.vegetation is not None: + _kwargs = {'Name': f'{thermal_boundary.construction_name}_{thermal_boundary.vegetation.name}', + 'Outside_Layer': thermal_boundary.vegetation.name} + for i in range(0, len(layers) - 1): + _kwargs[f'Layer_{i + 2}'] = layers[i].material.name + else: + _kwargs = {'Name': thermal_boundary.construction_name, 'Outside_Layer': layers[0].material.name} + for i in range(1, len(layers) - 1): + _kwargs[f'Layer_{i + 1}'] = layers[i].material.name self._idf.newidfobject(self._CONSTRUCTION, **_kwargs) def _add_window_construction_and_material(self, thermal_opening): @@ -342,6 +353,8 @@ class Idf: for thermal_zone in internal_zone.thermal_zones: for thermal_boundary in thermal_zone.thermal_boundaries: self._add_construction(thermal_boundary) + if thermal_boundary.vegetation is not None: + self._add_vegetation_material(thermal_boundary.vegetation) for thermal_opening in thermal_boundary.thermal_openings: self._add_window_construction_and_material(thermal_opening) usage = thermal_zone.usage @@ -355,7 +368,6 @@ class Idf: self._add_heating_system(thermal_zone) self._add_infiltration(thermal_zone) self._add_occupancy(thermal_zone) - if self._export_type == "Surfaces": self._add_surfaces(building) else: @@ -404,10 +416,13 @@ class Idf: for thermal_zone in internal_zone.thermal_zones: for boundary in thermal_zone.thermal_boundaries: idf_surface_type = self.idf_surfaces[boundary.parent_surface.type] - # todo: thermal boundary vs. surfaces?? + if boundary.vegetation is not None: + construction_name = f'{boundary.construction_name}_{boundary.vegetation.name}' + else: + construction_name = boundary.construction_name surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.parent_surface.name}', Surface_Type=idf_surface_type, Zone_Name=thermal_zone.id, - Construction_Name=boundary.construction_name) + Construction_Name=construction_name) coordinates = self._matrix_to_list(boundary.parent_surface.solid_polygon.coordinates, self._city.lower_corner) surface.setcoords(coordinates) @@ -433,3 +448,44 @@ class Idf: material['Solar_Heat_Gain_Coefficient'] == opening.g_value: return True return False + + def _add_vegetation_material(self, vegetation): + for vegetation_material in self._idf.idfobjects[self._MATERIAL_ROOFVEGETATION]: + if vegetation_material.Name == vegetation.name: + return + soil = vegetation.soil + height = 0 + leaf_area_index = 0 + leaf_reflectivity = 0 + leaf_emissivity = 0 + minimal_stomatal_resistance = 0 + for plant in vegetation.plants: + height += plant.percentage * plant.height + leaf_area_index += plant.percentage * plant.leaf_area_index + leaf_reflectivity += plant.percentage * plant.leaf_reflectivity + leaf_emissivity += plant.percentage * plant.leaf_emissivity + minimal_stomatal_resistance += plant.percentage * plant.minimal_stomatal_resistance + self._idf.newidfobject(self._MATERIAL_ROOFVEGETATION, + Name=vegetation.name, + Height_of_Plants=height, + Leaf_Area_Index=leaf_area_index, + Leaf_Reflectivity=leaf_reflectivity, + Leaf_Emissivity=leaf_emissivity, + Minimum_Stomatal_Resistance=minimal_stomatal_resistance, + Soil_Layer_Name=soil.name, + Roughness=soil.roughness, + Thickness=vegetation.soil_thickness, + Conductivity_of_Dry_Soil=soil.dry_conductivity, + Density_of_Dry_Soil=soil.dry_density, + Specific_Heat_of_Dry_Soil=soil.dry_specific_heat, + Thermal_Absorptance=soil.thermal_absorptance, + Solar_Absorptance=soil.solar_absorptance, + Visible_Absorptance=soil.visible_absorptance, + Saturation_Volumetric_Moisture_Content_of_the_Soil_Layer= + soil.saturation_volumetric_moisture_content, + Residual_Volumetric_Moisture_Content_of_the_Soil_Layer= + soil.residual_volumetric_moisture_content, + Initial_Volumetric_Moisture_Content_of_the_Soil_Layer= + soil.initial_volumetric_moisture_content, + Moisture_Diffusion_Calculation_Method=self._SIMPLE + ) diff --git a/imports/usage/ca_usage_parameters.py b/imports/usage/ca_usage_parameters.py index 56c006a0..cc5c4f41 100644 --- a/imports/usage/ca_usage_parameters.py +++ b/imports/usage/ca_usage_parameters.py @@ -9,14 +9,9 @@ import sys from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.usage.hft_usage_interface import HftUsageInterface from imports.usage.helpers.usage_helper import UsageHelper -from city_model_structure.building_demand.usage_zone import UsageZone -from city_model_structure.building_demand.internal_gain import InternalGain -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 HftUsageParameters(HftUsageInterface): """ CaUsageParameters class """ @@ -36,48 +31,11 @@ class CaUsageParameters(HftUsageInterface): archetype = self._search_archetype(usage) except KeyError: sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' - f' {building.function}\n') + f' {building.function}, that assigns building usage as ' + f'{GeometryHelper().libs_usage_from_libs_function(building.function)}\n') return for internal_zone in building.internal_zones: - usage_zone = UsageZone() - usage_zone.usage = building.function + usage_zone = self._assign_values(building.function, archetype) 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: - if building_archetype.usage == building_usage: - return building_archetype - return None - - @staticmethod - def _assign_values_usage_zone(usage_zone, archetype): - # Due to the fact that python is not a typed language, the wrong object type is assigned to - # usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains. - # Therefore, this walk around has been done. - usage_zone.mechanical_air_change = archetype.mechanical_air_change - _occupancy = Occupancy() - _occupancy.occupancy_density = archetype.occupancy.occupancy_density - usage_zone.occupancy = _occupancy - usage_zone.hours_day = archetype.hours_day - usage_zone.days_year = archetype.days_year - _appliances = Appliances() - _appliances.density = archetype.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 - usage_zone.thermal_control = _control - _internal_gains = [] - for archetype_internal_gain in archetype.not_detailed_source_mean_annual_internal_gains: - _internal_gain = InternalGain() - _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 diff --git a/imports/usage/hft_usage_interface.py b/imports/usage/hft_usage_interface.py index 09593ba7..241cd5a7 100644 --- a/imports/usage/hft_usage_interface.py +++ b/imports/usage/hft_usage_interface.py @@ -14,6 +14,7 @@ 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 +from imports.usage.helpers.usage_helper import UsageHelper class HftUsageInterface: @@ -38,15 +39,9 @@ class HftUsageInterface: @staticmethod def _parse_zone_usage_type(usage, zone_usage_type): - usage_zone_archetype = UsageZone() - usage_zone_archetype.usage = usage - if 'occupancy' in zone_usage_type: _occupancy = Occupancy() _occupancy.occupancy_density = zone_usage_type['occupancy']['occupancyDensity'] #todo: check units - usage_zone_archetype.hours_day = zone_usage_type['occupancy']['usageHoursPerDay'] - usage_zone_archetype.days_year = zone_usage_type['occupancy']['usageDaysPerYear'] - usage_zone_archetype.occupancy = _occupancy if 'internGains' in zone_usage_type['occupancy']: _internal_gain = InternalGain() @@ -72,7 +67,18 @@ class HftUsageInterface: _schedule.values = _values_float _internal_gain.schedules = [_schedule] - usage_zone_archetype.not_detailed_source_mean_annual_internal_gains = [_internal_gain] + _not_detailed_source_mean_annual_internal_gains = [_internal_gain] + usage_zone_archetype = UsageZone(_not_detailed_source_mean_annual_internal_gains) + else: + usage_zone_archetype = UsageZone() + + usage_zone_archetype.hours_day = zone_usage_type['occupancy']['usageHoursPerDay'] + usage_zone_archetype.days_year = zone_usage_type['occupancy']['usageDaysPerYear'] + usage_zone_archetype.occupancy = _occupancy + + else: + usage_zone_archetype = UsageZone() + usage_zone_archetype.usage = usage if 'endUses' in zone_usage_type: _thermal_control = ThermalControl() @@ -256,3 +262,24 @@ class HftUsageInterface: usage_zone_archetype.appliances = _appliances return usage_zone_archetype + + def _search_archetype(self, libs_usage): + building_usage = UsageHelper().hft_from_libs_usage(libs_usage) + for building_archetype in self._usage_archetypes: + if building_archetype.usage == building_usage: + return building_archetype + return None + + @staticmethod + def _assign_values(usage, archetype): + _not_detailed_source_mean_annual_internal_gains = \ + copy.deepcopy(archetype.internal_gains) + usage_zone = UsageZone(_not_detailed_source_mean_annual_internal_gains) + usage_zone.usage = usage + 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.days_year = archetype.days_year + usage_zone.hours_day = archetype.hours_day + return usage_zone diff --git a/imports/usage/hft_usage_parameters.py b/imports/usage/hft_usage_parameters.py index c5faee4d..afe7e300 100644 --- a/imports/usage/hft_usage_parameters.py +++ b/imports/usage/hft_usage_parameters.py @@ -5,12 +5,10 @@ Copyright © 2022 Concordia CERC group Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ import sys -import copy from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.usage.hft_usage_interface import HftUsageInterface from imports.usage.helpers.usage_helper import UsageHelper -from city_model_structure.building_demand.usage_zone import UsageZone class HftUsageParameters(HftUsageInterface): @@ -38,58 +36,7 @@ class HftUsageParameters(HftUsageInterface): return 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 = self._assign_values(UsageHelper().hft_from_libs_usage(libs_usage), 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: - if building_archetype.usage == building_usage: - return building_archetype - return None - - @staticmethod - def _assign_values(usage_zone, archetype): - """ # Due to the fact that python is not a typed language, the wrong object type is assigned to - # usage_zone.internal_gains when writing usage_zone.internal_gains = archetype.internal_gains. - # Therefore, this walk around has been done. - # Due to the fact that python is not a typed language, the wrong object type is assigned to - # usage_zone.occupancy when writing usage_zone.occupancy = archetype.occupancy. - # Same happens for lighting and appliances. Therefore, this walk around has been done. - 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 = InternalGain() - _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 diff --git a/imports/usage_factory.py b/imports/usage_factory.py index ad446857..69ec4922 100644 --- a/imports/usage_factory.py +++ b/imports/usage_factory.py @@ -8,9 +8,7 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord """ from pathlib import Path from imports.usage.hft_usage_parameters import HftUsageParameters -from imports.usage.ca_usage_parameters import CaUsageParameters from imports.usage.comnet_usage_parameters import ComnetUsageParameters -# todo: handle missing lambda and rise error. class UsageFactory: @@ -30,12 +28,6 @@ class UsageFactory: """ return HftUsageParameters(self._city, self._base_path).enrich_buildings() - def _ca(self): - """ - Enrich the city with Canada usage library - """ - return CaUsageParameters(self._city, self._base_path).enrich_buildings() - def _comnet(self): """ Enrich the city with COMNET usage library diff --git a/unittests/test_greenery_in_idf.py b/unittests/test_greenery_in_idf.py new file mode 100644 index 00000000..d230356b --- /dev/null +++ b/unittests/test_greenery_in_idf.py @@ -0,0 +1,103 @@ +""" +Greenery in idf test +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" +from pathlib import Path +import csv +import helpers.constants as cte +from unittest import TestCase +from imports.geometry_factory import GeometryFactory +from imports.usage_factory import UsageFactory +from imports.construction_factory import ConstructionFactory +from exports.exports_factory import ExportsFactory +from city_model_structure.greenery.vegetation import Vegetation +from city_model_structure.greenery.soil import Soil +from city_model_structure.greenery.plant import Plant + + +class GreeneryInIdf(TestCase): + """ + GreeneryInIdf TestCase 1 + """ + + @staticmethod + def test_greenery_in_idf(): + city_file = "../unittests/tests_data/one_building_in_kelowna.gml" + output_path = Path('../unittests/tests_outputs/').resolve() + + city = GeometryFactory('citygml', city_file).city + for building in city.buildings: + building.year_of_construction = 2006 + ConstructionFactory('nrel', city).enrich() + UsageFactory('comnet', city).enrich() + vegetation_name = 'BaseEco' + soil_thickness = 0.18 + soil_name = 'EcoRoofSoil' + roughness = 'MediumSmooth' + dry_conductivity = 0.4 + dry_density = 641 + dry_specific_heat = 1100 + thermal_absorptance = 0.95 + solar_absorptance = 0.8 + visible_absorptance = 0.7 + saturation_volumetric_moisture_content = 0.4 + residual_volumetric_moisture_content = 0.01 + soil = Soil(soil_name, roughness, dry_conductivity, dry_density, dry_specific_heat, thermal_absorptance, + solar_absorptance, visible_absorptance, saturation_volumetric_moisture_content, + residual_volumetric_moisture_content) + soil.initial_volumetric_moisture_content = 0.2 + plant_name = 'plant' + height = 0.5 + leaf_area_index = 5 + leaf_reflectivity = 0.2 + leaf_emissivity = 0.95 + minimal_stomatal_resistance = 180 + co2_sequestration = 0 + grows_on_soils = [soil] + plant = Plant(plant_name, height, leaf_area_index, leaf_reflectivity, leaf_emissivity, minimal_stomatal_resistance, + co2_sequestration, grows_on_soils) + plant.percentage = 1 + plants = [plant] + vegetation = Vegetation(vegetation_name, soil, soil_thickness, plants) + for building in city.buildings: + for internal_zone in building.internal_zones: + for thermal_zone in internal_zone.thermal_zones: + for thermal_boundary in thermal_zone.thermal_boundaries: + if thermal_boundary.type == cte.ROOF: + thermal_boundary.vegetation = vegetation + + _idf_2 = ExportsFactory('idf', city, output_path).export_debug() + _idf_2.run() + with open((output_path / f'{city.name}_out.csv').resolve()) as f: + reader = csv.reader(f, delimiter=',') + heating = 0 + cooling = 0 + for row in reader: + if '00:00' in row[0]: + heating += float(row[8]) / 3600000 + cooling += float(row[9]) / 3600000 + + print('With greenery') + print(f'heating: {heating} MWh/yr, cooling: {cooling} MWh/yr') + + city = GeometryFactory('citygml', city_file).city + for building in city.buildings: + building.year_of_construction = 2006 + ConstructionFactory('nrel', city).enrich() + UsageFactory('comnet', city).enrich() + _idf = ExportsFactory('idf', city, output_path).export() + _idf.run() + with open((output_path / f'{city.name}_out.csv').resolve()) as f: + reader = csv.reader(f, delimiter=',') + heating = 0 + cooling = 0 + for row in reader: + if '00:00' in row[0]: + heating += float(row[8]) / 3600000 + cooling += float(row[9]) / 3600000 + + print('Without greenery') + print(f'heating: {heating} MWh/yr, cooling: {cooling} MWh/yr') + diff --git a/unittests/test_usage_factory.py b/unittests/test_usage_factory.py index 93408819..15138579 100644 --- a/unittests/test_usage_factory.py +++ b/unittests/test_usage_factory.py @@ -127,23 +127,6 @@ class TestUsageFactory(TestCase): self.assertIsNotNone(usage_zone.thermal_control.hvac_availability_schedules, 'control hvac availability is none') - def test_import_ca(self): - """ - Enrich the city with the usage information from canada and verify it - """ - file = 'one_building_in_kelowna.gml' - city = self._get_citygml(file) - UsageFactory('ca', 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.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change is none') - self.assertIsNotNone(usage_zone.not_detailed_source_mean_annual_internal_gains, - 'not detailed internal gains is none') - def test_import_hft(self): """ Enrich the city with the usage information from hft and verify it