Merge pull request 'final_energy_system_model' (#60) from final_energy_system_model into main

Reviewed-on: https://nextgenerations-cities.encs.concordia.ca/gitea/CERC/hub/pulls/60
This commit is contained in:
Guille Gutierrez 2024-03-14 09:13:21 -04:00
commit 0f0a923329
235 changed files with 32119 additions and 1140 deletions

View File

@ -1,8 +1,9 @@
""" """
Energy System catalog archetype Energy System catalog archetype, understood as a cluster of energy systems
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
""" """
from typing import List from typing import List
@ -14,20 +15,11 @@ class Archetype:
""" """
Archetype class Archetype class
""" """
def __init__(self, lod, name, systems): def __init__(self, name, systems):
self._lod = lod
self._name = name self._name = name
self._systems = systems self._systems = systems
@property
def lod(self):
"""
Get level of detail of the catalog
:return: string
"""
return self._lod
@property @property
def name(self): def name(self):
""" """
@ -49,8 +41,9 @@ class Archetype:
_systems = [] _systems = []
for _system in self.systems: for _system in self.systems:
_systems.append(_system.to_dictionary()) _systems.append(_system.to_dictionary())
content = {'Archetype': {'name': self.name, content = {
'level of detail': self.lod, 'Archetype': {
'name': self.name,
'systems': _systems 'systems': _systems
} }
} }

View File

@ -10,12 +10,11 @@ class Content:
""" """
Content class Content class
""" """
def __init__(self, archetypes, systems, generations, distributions, emissions): def __init__(self, archetypes, systems, generations=None, distributions=None):
self._archetypes = archetypes self._archetypes = archetypes
self._systems = systems self._systems = systems
self._generations = generations self._generations = generations
self._distributions = distributions self._distributions = distributions
self._emissions = emissions
@property @property
def archetypes(self): def archetypes(self):
@ -45,13 +44,6 @@ class Content:
""" """
return self._distributions return self._distributions
@property
def emission_equipments(self):
"""
All emission equipments in the catalog
"""
return self._emissions
def to_dictionary(self): def to_dictionary(self):
"""Class content to dictionary""" """Class content to dictionary"""
_archetypes = [] _archetypes = []

View File

@ -3,23 +3,35 @@ Energy System catalog distribution system
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
""" """
from typing import Union, List, TypeVar
from hub.catalog_factories.data_models.energy_systems.energy_storage_system import EnergyStorageSystem
from hub.catalog_factories.data_models.energy_systems.emission_system import EmissionSystem
GenerationSystem = TypeVar('GenerationSystem')
class DistributionSystem: class DistributionSystem:
""" """
Distribution system class Distribution system class
""" """
def __init__(self, system_id, name, system_type, supply_temperature, distribution_consumption_fix_flow, def __init__(self, system_id, model_name=None, system_type=None, supply_temperature=None,
distribution_consumption_variable_flow, heat_losses): distribution_consumption_fix_flow=None, distribution_consumption_variable_flow=None, heat_losses=None,
generation_systems=None, energy_storage_systems=None, emission_systems=None):
self._system_id = system_id self._system_id = system_id
self._name = name self._model_name = model_name
self._type = system_type self._type = system_type
self._supply_temperature = supply_temperature self._supply_temperature = supply_temperature
self._distribution_consumption_fix_flow = distribution_consumption_fix_flow self._distribution_consumption_fix_flow = distribution_consumption_fix_flow
self._distribution_consumption_variable_flow = distribution_consumption_variable_flow self._distribution_consumption_variable_flow = distribution_consumption_variable_flow
self._heat_losses = heat_losses self._heat_losses = heat_losses
self._generation_systems = generation_systems
self._energy_storage_systems = energy_storage_systems
self._emission_systems = emission_systems
@property @property
def id(self): def id(self):
@ -30,12 +42,12 @@ class DistributionSystem:
return self._system_id return self._system_id
@property @property
def name(self): def model_name(self):
""" """
Get name Get model name
:return: string :return: string
""" """
return self._name return self._model_name
@property @property
def type(self): def type(self):
@ -78,17 +90,51 @@ class DistributionSystem:
""" """
return self._heat_losses return self._heat_losses
@property
def generation_systems(self) -> Union[None, List[GenerationSystem]]:
"""
Get generation systems connected to the distribution system
:return: [GenerationSystem]
"""
return self._generation_systems
@property
def energy_storage_systems(self) -> Union[None, List[EnergyStorageSystem]]:
"""
Get energy storage systems connected to this distribution system
:return: [EnergyStorageSystem]
"""
return self._energy_storage_systems
@property
def emission_systems(self) -> Union[None, List[EmissionSystem]]:
"""
Get energy emission systems connected to this distribution system
:return: [EmissionSystem]
"""
return self._emission_systems
def to_dictionary(self): def to_dictionary(self):
"""Class content to dictionary""" """Class content to dictionary"""
_generation_systems = [_generation_system.to_dictionary() for _generation_system in
self.generation_systems] if self.generation_systems is not None else None
_energy_storage_systems = [_energy_storage_system.to_dictionary() for _energy_storage_system in
self.energy_storage_systems] if self.energy_storage_systems is not None else None
_emission_systems = [_emission_system.to_dictionary() for _emission_system in
self.emission_systems] if self.emission_systems is not None else None
content = { content = {
'Layer': { 'Layer': {
'id': self.id, 'id': self.id,
'name': self.name, 'model name': self.model_name,
'type': self.type, 'type': self.type,
'supply temperature [Celsius]': self.supply_temperature, 'supply temperature [Celsius]': self.supply_temperature,
'distribution consumption if fix flow over peak power [W/W]': self.distribution_consumption_fix_flow, 'distribution consumption if fix flow over peak power [W/W]': self.distribution_consumption_fix_flow,
'distribution consumption if variable flow over peak power [J/J]': self.distribution_consumption_variable_flow, 'distribution consumption if variable flow over peak power [J/J]': self.distribution_consumption_variable_flow,
'heat losses per energy produced [J/J]': self.heat_losses 'heat losses per energy produced [J/J]': self.heat_losses,
'generation systems connected': _generation_systems,
'energy storage systems connected': _energy_storage_systems,
'emission systems connected': _emission_systems
} }
} }
return content return content

View File

@ -0,0 +1,103 @@
"""
Energy System catalog electrical storage system
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
"""
from hub.catalog_factories.data_models.energy_systems.energy_storage_system import EnergyStorageSystem
class ElectricalStorageSystem(EnergyStorageSystem):
""""
Energy Storage System Class
"""
def __init__(self, storage_id, type_energy_stored=None, model_name=None, manufacturer=None, storage_type=None,
nominal_capacity=None, losses_ratio=None, rated_output_power=None, nominal_efficiency=None,
battery_voltage=None, depth_of_discharge=None, self_discharge_rate=None):
super().__init__(storage_id, model_name, manufacturer, nominal_capacity, losses_ratio)
self._type_energy_stored = type_energy_stored
self._storage_type = storage_type
self._rated_output_power = rated_output_power
self._nominal_efficiency = nominal_efficiency
self._battery_voltage = battery_voltage
self._depth_of_discharge = depth_of_discharge
self._self_discharge_rate = self_discharge_rate
@property
def type_energy_stored(self):
"""
Get type of energy stored from ['electrical', 'thermal']
:return: string
"""
return self._type_energy_stored
@property
def storage_type(self):
"""
Get storage type from ['lithium_ion', 'lead_acid', 'NiCd']
:return: string
"""
return self._storage_type
@property
def rated_output_power(self):
"""
Get the rated output power of storage system in Watts
:return: float
"""
return self._rated_output_power
@property
def nominal_efficiency(self):
"""
Get the nominal efficiency of the storage system
:return: float
"""
return self._nominal_efficiency
@property
def battery_voltage(self):
"""
Get the battery voltage in Volts
:return: float
"""
return self._battery_voltage
@property
def depth_of_discharge(self):
"""
Get the depth of discharge as a percentage
:return: float
"""
return self._depth_of_discharge
@property
def self_discharge_rate(self):
"""
Get the self discharge rate of battery as a percentage
:return: float
"""
return self._self_discharge_rate
def to_dictionary(self):
"""Class content to dictionary"""
content = {'Storage component': {
'storage id': self.id,
'type of energy stored': self.type_energy_stored,
'model name': self.model_name,
'manufacturer': self.manufacturer,
'storage type': self.storage_type,
'nominal capacity [J]': self.nominal_capacity,
'losses-ratio [J/J]': self.losses_ratio,
'rated power [W]': self.rated_output_power,
'nominal efficiency': self.nominal_efficiency,
'battery voltage [V]': self.battery_voltage,
'depth of discharge [%]': self.depth_of_discharge,
'self discharge rate': self.self_discharge_rate
}
}
return content

View File

@ -10,10 +10,10 @@ class EmissionSystem:
""" """
Emission system class Emission system class
""" """
def __init__(self, system_id, name, system_type, parasitic_energy_consumption): def __init__(self, system_id, model_name=None, system_type=None, parasitic_energy_consumption=None):
self._system_id = system_id self._system_id = system_id
self._name = name self._model_name = model_name
self._type = system_type self._type = system_type
self._parasitic_energy_consumption = parasitic_energy_consumption self._parasitic_energy_consumption = parasitic_energy_consumption
@ -26,12 +26,12 @@ class EmissionSystem:
return self._system_id return self._system_id
@property @property
def name(self): def model_name(self):
""" """
Get name Get model name
:return: string :return: string
""" """
return self._name return self._model_name
@property @property
def type(self): def type(self):
@ -52,7 +52,7 @@ class EmissionSystem:
def to_dictionary(self): def to_dictionary(self):
"""Class content to dictionary""" """Class content to dictionary"""
content = {'Layer': {'id': self.id, content = {'Layer': {'id': self.id,
'name': self.name, 'model name': self.model_name,
'type': self.type, 'type': self.type,
'parasitic energy consumption per energy produced [J/J]': self.parasitic_energy_consumption 'parasitic energy consumption per energy produced [J/J]': self.parasitic_energy_consumption
} }

View File

@ -0,0 +1,75 @@
"""
Energy System catalog heat generation system
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from abc import ABC
class EnergyStorageSystem(ABC):
""""
Energy Storage System Abstract Class
"""
def __init__(self, storage_id, model_name=None, manufacturer=None,
nominal_capacity=None, losses_ratio=None):
self._storage_id = storage_id
self._model_name = model_name
self._manufacturer = manufacturer
self._nominal_capacity = nominal_capacity
self._losses_ratio = losses_ratio
@property
def id(self):
"""
Get storage id
:return: string
"""
return self._storage_id
@property
def type_energy_stored(self):
"""
Get type of energy stored from ['electrical', 'thermal']
:return: string
"""
raise NotImplementedError
@property
def model_name(self):
"""
Get system model
:return: string
"""
return self._model_name
@property
def manufacturer(self):
"""
Get name of manufacturer
:return: string
"""
return self._manufacturer
@property
def nominal_capacity(self):
"""
Get the nominal capacity of the storage system in Jules
:return: float
"""
return self._nominal_capacity
@property
def losses_ratio(self):
"""
Get the losses-ratio of storage system in Jules lost / Jules stored
:return: float
"""
return self._losses_ratio
def to_dictionary(self):
"""Class content to dictionary"""
raise NotImplementedError

View File

@ -1,33 +1,33 @@
""" """
Energy System catalog generation system Energy System catalog heat generation system
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
""" """
from __future__ import annotations from __future__ import annotations
from typing import Union from abc import ABC
from typing import List, Union
from hub.catalog_factories.data_models.energy_systems.energy_storage_system import EnergyStorageSystem
from hub.catalog_factories.data_models.energy_systems.distribution_system import DistributionSystem
class GenerationSystem: class GenerationSystem(ABC):
""" """
Generation system class Heat Generation system class
""" """
def __init__(self, system_id, name, system_type, fuel_type, source_types, heat_efficiency, cooling_efficiency,
electricity_efficiency, source_temperature, source_mass_flow, storage, auxiliary_equipment):
def __init__(self, system_id, name, model_name=None, manufacturer=None, fuel_type=None,
distribution_systems=None, energy_storage_systems=None):
self._system_id = system_id self._system_id = system_id
self._name = name self._name = name
self._type = system_type self._model_name = model_name
self._manufacturer = manufacturer
self._fuel_type = fuel_type self._fuel_type = fuel_type
self._source_types = source_types self._distribution_systems = distribution_systems
self._heat_efficiency = heat_efficiency self._energy_storage_systems = energy_storage_systems
self._cooling_efficiency = cooling_efficiency
self._electricity_efficiency = electricity_efficiency
self._source_temperature = source_temperature
self._source_mass_flow = source_mass_flow
self._storage = storage
self._auxiliary_equipment = auxiliary_equipment
@property @property
def id(self): def id(self):
@ -40,108 +40,59 @@ class GenerationSystem:
@property @property
def name(self): def name(self):
""" """
Get name Get system name
:return: string :return: string
""" """
return self._name return self._name
@property @property
def type(self): def system_type(self):
""" """
Get type Get type
:return: string :return: string
""" """
return self._type raise NotImplementedError
@property
def model_name(self):
"""
Get system id
:return: float
"""
return self._model_name
@property
def manufacturer(self):
"""
Get name
:return: string
"""
return self._manufacturer
@property @property
def fuel_type(self): def fuel_type(self):
""" """
Get fuel_type from [renewable, gas, diesel, electricity, wood, coal] Get fuel_type from [renewable, gas, diesel, electricity, wood, coal, biogas]
:return: string :return: string
""" """
return self._fuel_type return self._fuel_type
@property @property
def source_types(self): def distribution_systems(self) -> Union[None, List[DistributionSystem]]:
""" """
Get source_type from [air, water, geothermal, district_heating, grid, on_site_electricity] Get distributions systems connected to this generation system
:return: [string] :return: [DistributionSystem]
""" """
return self._source_types return self._distribution_systems
@property @property
def heat_efficiency(self): def energy_storage_systems(self) -> Union[None, List[EnergyStorageSystem]]:
""" """
Get heat_efficiency Get energy storage systems connected to this generation system
:return: float :return: [EnergyStorageSystem]
""" """
return self._heat_efficiency return self._energy_storage_systems
@property
def cooling_efficiency(self):
"""
Get cooling_efficiency
:return: float
"""
return self._cooling_efficiency
@property
def electricity_efficiency(self):
"""
Get electricity_efficiency
:return: float
"""
return self._electricity_efficiency
@property
def source_temperature(self):
"""
Get source_temperature in degree Celsius
:return: float
"""
return self._source_temperature
@property
def source_mass_flow(self):
"""
Get source_mass_flow in kg/s
:return: float
"""
return self._source_mass_flow
@property
def storage(self):
"""
Get boolean storage exists
:return: bool
"""
return self._storage
@property
def auxiliary_equipment(self) -> Union[None, GenerationSystem]:
"""
Get auxiliary_equipment
:return: GenerationSystem
"""
return self._auxiliary_equipment
def to_dictionary(self): def to_dictionary(self):
"""Class content to dictionary""" """Class content to dictionary"""
_auxiliary_equipment = [] raise NotImplementedError
if self.auxiliary_equipment is not None:
_auxiliary_equipment = self.auxiliary_equipment.to_dictionary()
content = {'Layer': {'id': self.id,
'name': self.name,
'type': self.type,
'fuel type': self.fuel_type,
'source types': self.source_types,
'source temperature [Celsius]': self.source_temperature,
'source mass flow [kg/s]': self.source_mass_flow,
'heat efficiency': self.heat_efficiency,
'cooling efficiency': self.cooling_efficiency,
'electricity efficiency': self.electricity_efficiency,
'it has storage': self.storage,
'auxiliary equipment': _auxiliary_equipment
}
}
return content

View File

@ -0,0 +1,310 @@
"""
Energy System catalog non PV generation system
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
"""
from typing import Union
from hub.catalog_factories.data_models.energy_systems.performance_curves import PerformanceCurves
from hub.catalog_factories.data_models.energy_systems.generation_system import GenerationSystem
class NonPvGenerationSystem(GenerationSystem):
"""
Non PV Generation system class
"""
def __init__(self, system_id, name, system_type, model_name=None, manufacturer=None, fuel_type=None,
nominal_heat_output=None, maximum_heat_output=None, minimum_heat_output=None, source_medium=None,
supply_medium=None, heat_efficiency=None, nominal_cooling_output=None, maximum_cooling_output=None,
minimum_cooling_output=None, cooling_efficiency=None, electricity_efficiency=None,
source_temperature=None, source_mass_flow=None, nominal_electricity_output=None,
maximum_heat_supply_temperature=None, minimum_heat_supply_temperature=None,
maximum_cooling_supply_temperature=None, minimum_cooling_supply_temperature=None, heat_output_curve=None,
heat_fuel_consumption_curve=None, heat_efficiency_curve=None, cooling_output_curve=None,
cooling_fuel_consumption_curve=None, cooling_efficiency_curve=None,
distribution_systems=None, energy_storage_systems=None, dual_supply_capability=False):
super().__init__(system_id=system_id, name=name, model_name=model_name, manufacturer=manufacturer, fuel_type=fuel_type,
distribution_systems=distribution_systems, energy_storage_systems=energy_storage_systems)
self._system_type = system_type
self._nominal_heat_output = nominal_heat_output
self._maximum_heat_output = maximum_heat_output
self._minimum_heat_output = minimum_heat_output
self._heat_efficiency = heat_efficiency
self._nominal_cooling_output = nominal_cooling_output
self._maximum_cooling_output = maximum_cooling_output
self._minimum_cooling_output = minimum_cooling_output
self._cooling_efficiency = cooling_efficiency
self._electricity_efficiency = electricity_efficiency
self._nominal_electricity_output = nominal_electricity_output
self._source_medium = source_medium
self._source_temperature = source_temperature
self._source_mass_flow = source_mass_flow
self._supply_medium = supply_medium
self._maximum_heat_supply_temperature = maximum_heat_supply_temperature
self._minimum_heat_supply_temperature = minimum_heat_supply_temperature
self._maximum_cooling_supply_temperature = maximum_cooling_supply_temperature
self._minimum_cooling_supply_temperature = minimum_cooling_supply_temperature
self._heat_output_curve = heat_output_curve
self._heat_fuel_consumption_curve = heat_fuel_consumption_curve
self._heat_efficiency_curve = heat_efficiency_curve
self._cooling_output_curve = cooling_output_curve
self._cooling_fuel_consumption_curve = cooling_fuel_consumption_curve
self._cooling_efficiency_curve = cooling_efficiency_curve
self._dual_supply_capability = dual_supply_capability
@property
def system_type(self):
"""
Get type
:return: string
"""
return self._system_type
@property
def nominal_heat_output(self):
"""
Get nominal heat output of heat generation devices in W
:return: float
"""
return self._nominal_heat_output
@property
def maximum_heat_output(self):
"""
Get maximum heat output of heat generation devices in W
:return: float
"""
return self._maximum_heat_output
@property
def minimum_heat_output(self):
"""
Get minimum heat output of heat generation devices in W
:return: float
"""
return self._minimum_heat_output
@property
def source_medium(self):
"""
Get source_type from [air, water, ground, district_heating, grid, on_site_electricity]
:return: string
"""
return self._source_medium
@property
def supply_medium(self):
"""
Get the supply medium from ['air', 'water']
:return: string
"""
return self._supply_medium
@property
def heat_efficiency(self):
"""
Get heat_efficiency
:return: float
"""
return self._heat_efficiency
@property
def nominal_cooling_output(self):
"""
Get nominal cooling output of heat generation devices in W
:return: float
"""
return self._nominal_cooling_output
@property
def maximum_cooling_output(self):
"""
Get maximum heat output of heat generation devices in W
:return: float
"""
return self._maximum_cooling_output
@property
def minimum_cooling_output(self):
"""
Get minimum heat output of heat generation devices in W
:return: float
"""
return self._minimum_cooling_output
@property
def cooling_efficiency(self):
"""
Get cooling_efficiency
:return: float
"""
return self._cooling_efficiency
@property
def electricity_efficiency(self):
"""
Get electricity_efficiency
:return: float
"""
return self._electricity_efficiency
@property
def source_temperature(self):
"""
Get source_temperature in degree Celsius
:return: float
"""
return self._source_temperature
@property
def source_mass_flow(self):
"""
Get source_mass_flow in kg/s
:return: float
"""
return self._source_mass_flow
@property
def nominal_electricity_output(self):
"""
Get nominal_power_output of electricity generation devices or inverters in W
:return: float
"""
return self._nominal_electricity_output
@property
def maximum_heat_supply_temperature(self):
"""
Get the maximum heat supply temperature in degree Celsius
:return: float
"""
return self._minimum_heat_supply_temperature
@property
def minimum_heat_supply_temperature(self):
"""
Get the minimum heat supply temperature in degree Celsius
:return: float
"""
return self._minimum_heat_supply_temperature
@property
def maximum_cooling_supply_temperature(self):
"""
Get the maximum cooling supply temperature in degree Celsius
:return: float
"""
return self._maximum_cooling_supply_temperature
@property
def minimum_cooling_supply_temperature(self):
"""
Get the minimum cooling supply temperature in degree Celsius
:return: float
"""
return self._minimum_cooling_supply_temperature
@property
def heat_output_curve(self) -> Union[None, PerformanceCurves]:
"""
Get the heat output curve of the heat generation device
:return: PerformanceCurve
"""
return self._heat_output_curve
@property
def heat_fuel_consumption_curve(self) -> Union[None, PerformanceCurves]:
"""
Get the heating fuel consumption curve of the heat generation device
:return: PerformanceCurve
"""
return self._heat_fuel_consumption_curve
@property
def heat_efficiency_curve(self) -> Union[None, PerformanceCurves]:
"""
Get the heating efficiency curve of the heat generation device
:return: PerformanceCurve
"""
return self._heat_efficiency_curve
@property
def cooling_output_curve(self) -> Union[None, PerformanceCurves]:
"""
Get the heat output curve of the heat generation device
:return: PerformanceCurve
"""
return self._cooling_output_curve
@property
def cooling_fuel_consumption_curve(self) -> Union[None, PerformanceCurves]:
"""
Get the heating fuel consumption curve of the heat generation device
:return: PerformanceCurve
"""
return self._cooling_fuel_consumption_curve
@property
def cooling_efficiency_curve(self) -> Union[None, PerformanceCurves]:
"""
Get the heating efficiency curve of the heat generation device
:return: PerformanceCurve
"""
return self._cooling_efficiency_curve
@property
def dual_supply_capability(self):
"""
Get dual supply capability
:return: bool
"""
return self._dual_supply_capability
def to_dictionary(self):
"""Class content to dictionary"""
_distribution_systems = [_distribution_system.to_dictionary() for _distribution_system in
self.distribution_systems] if self.distribution_systems is not None else None
_energy_storage_systems = [_energy_storage_system.to_dictionary() for _energy_storage_system in
self.energy_storage_systems] if self.energy_storage_systems is not None else None
content = {
'Energy Generation component':
{
'id': self.id,
'model name': self.model_name,
'manufacturer': self.manufacturer,
'type': self.system_type,
'fuel type': self.fuel_type,
'nominal heat output [W]': self.nominal_heat_output,
'maximum heat output [W]': self.maximum_heat_output,
'minimum heat output [W]': self.minimum_heat_output,
'source medium': self.source_medium,
'supply medium': self.supply_medium,
'source temperature [Celsius]': self.source_temperature,
'source mass flow [kg/s]': self.source_mass_flow,
'heat efficiency': self.heat_efficiency,
'nominal cooling output [W]': self.nominal_cooling_output,
'maximum cooling output [W]': self.maximum_cooling_output,
'minimum cooling output [W]': self.minimum_cooling_output,
'cooling efficiency': self.cooling_efficiency,
'electricity efficiency': self.electricity_efficiency,
'nominal power output [W]': self.nominal_electricity_output,
'maximum heating supply temperature [Celsius]': self.maximum_heat_supply_temperature,
'minimum heating supply temperature [Celsius]': self.minimum_heat_supply_temperature,
'maximum cooling supply temperature [Celsius]': self.maximum_cooling_supply_temperature,
'minimum cooling supply temperature [Celsius]': self.minimum_cooling_supply_temperature,
'heat output curve': self.heat_output_curve,
'heat fuel consumption curve': self.heat_fuel_consumption_curve,
'heat efficiency curve': self.heat_efficiency_curve,
'cooling output curve': self.cooling_output_curve,
'cooling fuel consumption curve': self.cooling_fuel_consumption_curve,
'cooling efficiency curve': self.cooling_efficiency_curve,
'distribution systems connected': _distribution_systems,
'storage systems connected': _energy_storage_systems,
'dual supply capability': self.dual_supply_capability
}
}
return content

View File

@ -0,0 +1,72 @@
"""
Energy System catalog heat generation system
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from __future__ import annotations
class PerformanceCurves:
"""
Parameter function class
"""
def __init__(self, curve_type, dependant_variable, parameters, coefficients):
self._curve_type = curve_type
self._dependant_variable = dependant_variable
self._parameters = parameters
self._coefficients = coefficients
@property
def curve_type(self):
"""
The type of the fit function from the following
Linear =>>> y = a*x + b
Exponential =>>> y = a*(b**x)
Polynomial =>>> y = a*(x**2) + b*x + c
Power =>>> y = a*(x**b)
Second degree multivariable =>>> y = a*(x**2) + b*x + c*x*z + d*z + e*(z**2) + f
Get the type of function from ['linear', 'exponential', 'polynomial', 'power', 'second degree multivariable']
:return: string
"""
return self._curve_type
@property
def dependant_variable(self):
"""
y (e.g. COP in COP = a*source temperature**2 + b*source temperature + c*source temperature*supply temperature +
d*supply temperature + e*supply temperature**2 + f)
"""
return self._dependant_variable
@property
def parameters(self):
"""
Get the list of parameters involved in fitting process as ['x', 'z'] (e.g. [source temperature, supply temperature]
in COP=)
:return: string
"""
return self._parameters
@property
def coefficients(self):
"""
Get the coefficients of the functions as list of ['a', 'b', 'c', 'd', 'e', 'f']
:return: [coefficients]
"""
return self._coefficients
def to_dictionary(self):
"""Class content to dictionary"""
content = {'Parameter Function': {
'curve type': self.curve_type,
'dependant variable': self.dependant_variable,
'parameter(s)': self.parameters,
'coefficients': self.coefficients,
}
}
return content

View File

@ -0,0 +1,153 @@
"""
Energy System catalog heat generation system
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from hub.catalog_factories.data_models.energy_systems.generation_system import GenerationSystem
class PvGenerationSystem(GenerationSystem):
"""
Electricity Generation system class
"""
def __init__(self, system_id, name, system_type, model_name=None, manufacturer=None, electricity_efficiency=None,
nominal_electricity_output=None, nominal_ambient_temperature=None, nominal_cell_temperature=None,
nominal_radiation=None, standard_test_condition_cell_temperature=None,
standard_test_condition_maximum_power=None, cell_temperature_coefficient=None, width=None, height=None,
distribution_systems=None, energy_storage_systems=None):
super().__init__(system_id=system_id, name=name, model_name=model_name,
manufacturer=manufacturer, fuel_type='renewable', distribution_systems=distribution_systems,
energy_storage_systems=energy_storage_systems)
self._system_type = system_type
self._electricity_efficiency = electricity_efficiency
self._nominal_electricity_output = nominal_electricity_output
self._nominal_ambient_temperature = nominal_ambient_temperature
self._nominal_cell_temperature = nominal_cell_temperature
self._nominal_radiation = nominal_radiation
self._standard_test_condition_cell_temperature = standard_test_condition_cell_temperature
self._standard_test_condition_maximum_power = standard_test_condition_maximum_power
self._cell_temperature_coefficient = cell_temperature_coefficient
self._width = width
self._height = height
@property
def system_type(self):
"""
Get type
:return: string
"""
return self._system_type
@property
def nominal_electricity_output(self):
"""
Get nominal_power_output of electricity generation devices or inverters in W
:return: float
"""
return self._nominal_electricity_output
@property
def electricity_efficiency(self):
"""
Get electricity_efficiency
:return: float
"""
return self._electricity_efficiency
@property
def nominal_ambient_temperature(self):
"""
Get nominal ambient temperature of PV panels in degree Celsius
:return: float
"""
return self._nominal_ambient_temperature
@property
def nominal_cell_temperature(self):
"""
Get nominal cell temperature of PV panels in degree Celsius
:return: float
"""
return self._nominal_cell_temperature
@property
def nominal_radiation(self):
"""
Get nominal radiation of PV panels
:return: float
"""
return self._nominal_radiation
@property
def standard_test_condition_cell_temperature(self):
"""
Get standard test condition cell temperature of PV panels in degree Celsius
:return: float
"""
return self._standard_test_condition_cell_temperature
@property
def standard_test_condition_maximum_power(self):
"""
Get standard test condition maximum power of PV panels in W
:return: float
"""
return self._standard_test_condition_maximum_power
@property
def cell_temperature_coefficient(self):
"""
Get cell temperature coefficient of PV module
:return: float
"""
return self._cell_temperature_coefficient
@property
def width(self):
"""
Get PV module width in m
:return: float
"""
return self._width
@property
def height(self):
"""
Get PV module height in m
:return: float
"""
return self._height
def to_dictionary(self):
"""Class content to dictionary"""
_distribution_systems = [_distribution_system.to_dictionary() for _distribution_system in
self.distribution_systems] if self.distribution_systems is not None else None
_energy_storage_systems = [_energy_storage_system.to_dictionary() for _energy_storage_system in
self.energy_storage_systems] if self.energy_storage_systems is not None else None
content = {
'Energy Generation component':
{
'id': self.id,
'model name': self.model_name,
'manufacturer': self.manufacturer,
'type': self.system_type,
'fuel type': self.fuel_type,
'electricity efficiency': self.electricity_efficiency,
'nominal power output [W]': self.nominal_electricity_output,
'nominal ambient temperature [Celsius]': self.nominal_ambient_temperature,
'nominal cell temperature [Celsius]': self.nominal_cell_temperature,
'nominal radiation [W/m2]': self.nominal_radiation,
'standard test condition cell temperature [Celsius]': self.standard_test_condition_cell_temperature,
'standard test condition maximum power [W]': self.standard_test_condition_maximum_power,
'cell temperature coefficient': self.cell_temperature_coefficient,
'width': self.width,
'height': self.height,
'distribution systems connected': _distribution_systems,
'storage systems connected': _energy_storage_systems
}
}
return content

View File

@ -1,45 +1,36 @@
""" """
Energy System catalog equipment Energy Systems catalog System
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
""" """
from typing import Union from typing import Union, List
from pathlib import Path
from hub.catalog_factories.data_models.energy_systems.generation_system import GenerationSystem from hub.catalog_factories.data_models.energy_systems.generation_system import GenerationSystem
from hub.catalog_factories.data_models.energy_systems.distribution_system import DistributionSystem from hub.catalog_factories.data_models.energy_systems.distribution_system import DistributionSystem
from hub.catalog_factories.data_models.energy_systems.emission_system import EmissionSystem
class System: class System:
""" """
System class System class
""" """
def __init__(self,
lod,
system_id,
name,
demand_types,
generation_system,
distribution_system,
emission_system):
self._lod = lod def __init__(self,
system_id,
demand_types,
name=None,
generation_systems=None,
distribution_systems=None,
configuration_schema=None):
self._system_id = system_id self._system_id = system_id
self._name = name self._name = name
self._demand_types = demand_types self._demand_types = demand_types
self._generation_system = generation_system self._generation_systems = generation_systems
self._distribution_system = distribution_system self._distribution_systems = distribution_systems
self._emission_system = emission_system self._configuration_schema = configuration_schema
@property
def lod(self):
"""
Get level of detail of the catalog
:return: string
"""
return self._lod
@property @property
def id(self): def id(self):
@ -52,7 +43,7 @@ class System:
@property @property
def name(self): def name(self):
""" """
Get name Get the system name
:return: string :return: string
""" """
return self._name return self._name
@ -60,50 +51,49 @@ class System:
@property @property
def demand_types(self): def demand_types(self):
""" """
Get demand able to cover from [heating, cooling, domestic_hot_water, electricity] Get demand able to cover from ['heating', 'cooling', 'domestic_hot_water', 'electricity']
:return: [string] :return: [string]
""" """
return self._demand_types return self._demand_types
@property @property
def generation_system(self) -> GenerationSystem: def generation_systems(self) -> Union[None, List[GenerationSystem]]:
""" """
Get generation system Get generation systems
:return: GenerationSystem :return: [GenerationSystem]
""" """
return self._generation_system return self._generation_systems
@property @property
def distribution_system(self) -> Union[None, DistributionSystem]: def distribution_systems(self) -> Union[None, List[DistributionSystem]]:
""" """
Get distribution system Get distribution systems
:return: DistributionSystem :return: [DistributionSystem]
""" """
return self._distribution_system return self._distribution_systems
@property @property
def emission_system(self) -> Union[None, EmissionSystem]: def configuration_schema(self) -> Path:
""" """
Get emission system Get system configuration schema
:return: EmissionSystem :return: Path
""" """
return self._emission_system return self._configuration_schema
def to_dictionary(self): def to_dictionary(self):
"""Class content to dictionary""" """Class content to dictionary"""
_distribution_system = None _generation_systems = []
if self.distribution_system is not None: for _generation in self.generation_systems:
_distribution_system = self.distribution_system.to_dictionary() _generation_systems.append(_generation.to_dictionary())
_emission_system = None _distribution_systems = [_distribution.to_dictionary() for _distribution in
if self.emission_system is not None: self.distribution_systems] if self.distribution_systems is not None else None
_emission_system = self.emission_system.to_dictionary()
content = {'Layer': {'id': self.id, content = {'system': {'id': self.id,
'name': self.name, 'name': self.name,
'level of detail': self.lod,
'demand types': self.demand_types, 'demand types': self.demand_types,
'generation system': self.generation_system.to_dictionary(), 'generation system(s)': _generation_systems,
'distribution system': _distribution_system, 'distribution system(s)': _distribution_systems,
'emission system': _emission_system 'configuration schema path': self.configuration_schema
} }
} }
return content return content

View File

@ -0,0 +1,116 @@
"""
Energy System catalog thermal storage system
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
"""
from hub.catalog_factories.data_models.energy_systems.energy_storage_system import EnergyStorageSystem
from hub.catalog_factories.data_models.construction.layer import Layer
from hub.catalog_factories.data_models.construction.material import Material
class ThermalStorageSystem(EnergyStorageSystem):
""""
Energy Storage System Class
"""
def __init__(self, storage_id, type_energy_stored=None, model_name=None, manufacturer=None, storage_type=None,
nominal_capacity=None, losses_ratio=None, volume=None, height=None, layers=None,
maximum_operating_temperature=None, storage_medium=None):
super().__init__(storage_id, model_name, manufacturer, nominal_capacity, losses_ratio)
self._type_energy_stored = type_energy_stored
self._storage_type = storage_type
self._volume = volume
self._height = height
self._layers = layers
self._maximum_operating_temperature = maximum_operating_temperature
self._storage_medium = storage_medium
@property
def type_energy_stored(self):
"""
Get type of energy stored from ['electrical', 'thermal']
:return: string
"""
return self._type_energy_stored
@property
def storage_type(self):
"""
Get storage type from ['thermal', 'sensible', 'latent']
:return: string
"""
return self._storage_type
@property
def volume(self):
"""
Get the physical volume of the storage system in cubic meters
:return: float
"""
return self._volume
@property
def height(self):
"""
Get the diameter of the storage system in meters
:return: float
"""
return self._height
@property
def layers(self) -> [Layer]:
"""
Get construction layers
:return: [layer]
"""
return self._layers
@property
def maximum_operating_temperature(self):
"""
Get maximum operating temperature of the storage system in degree Celsius
:return: float
"""
return self._maximum_operating_temperature
@property
def storage_medium(self) -> Material:
"""
Get thermodynamic characteristics of the storage medium
:return: [material
"""
return self._storage_medium
def to_dictionary(self):
"""Class content to dictionary"""
_layers = None
_medias = None
if self.layers is not None:
_layers = []
for _layer in self.layers:
_layers.append(_layer.to_dictionary())
if self.storage_medium is not None:
_medias = self.storage_medium.to_dictionary()
content = {
'Storage component':
{
'storage id': self.id,
'type of energy stored': self.type_energy_stored,
'model name': self.model_name,
'manufacturer': self.manufacturer,
'storage type': self.storage_type,
'nominal capacity [J]': self.nominal_capacity,
'losses-ratio [J/J]': self.losses_ratio,
'volume [m3]': self.volume,
'height [m]': self.height,
'layers': _layers,
'maximum operating temperature [Celsius]': self.maximum_operating_temperature,
'storage_medium': self.storage_medium.to_dictionary()
}
}
return content

View File

@ -10,45 +10,46 @@ import xmltodict
from hub.catalog_factories.catalog import Catalog from hub.catalog_factories.catalog import Catalog
from hub.catalog_factories.data_models.energy_systems.system import System from hub.catalog_factories.data_models.energy_systems.system import System
from hub.catalog_factories.data_models.energy_systems.content import Content from hub.catalog_factories.data_models.energy_systems.content import Content
from hub.catalog_factories.data_models.energy_systems.generation_system import GenerationSystem from hub.catalog_factories.data_models.energy_systems.non_pv_generation_system import NonPvGenerationSystem
from hub.catalog_factories.data_models.energy_systems.pv_generation_system import PvGenerationSystem
from hub.catalog_factories.data_models.energy_systems.distribution_system import DistributionSystem from hub.catalog_factories.data_models.energy_systems.distribution_system import DistributionSystem
from hub.catalog_factories.data_models.energy_systems.emission_system import EmissionSystem from hub.catalog_factories.data_models.energy_systems.emission_system import EmissionSystem
from hub.catalog_factories.data_models.energy_systems.archetype import Archetype from hub.catalog_factories.data_models.energy_systems.archetype import Archetype
from hub.catalog_factories.data_models.energy_systems.thermal_storage_system import ThermalStorageSystem
from hub.catalog_factories.data_models.energy_systems.electrical_storage_system import ElectricalStorageSystem
class MontrealCustomCatalog(Catalog): class MontrealCustomCatalog(Catalog):
""" """
Montreal custom energy systems catalog class Montreal custom energy systems catalog class
""" """
def __init__(self, path): def __init__(self, path):
path = str(path / 'montreal_custom_systems.xml') path = str(path / 'montreal_custom_systems.xml')
with open(path, 'r', encoding='utf-8') as xml: with open(path, 'r', encoding='utf-8') as xml:
self._archetypes = xmltodict.parse(xml.read(), force_list=('system', 'system_cluster', 'equipment', self._archetypes = xmltodict.parse(xml.read(), force_list=('system', 'system_cluster', 'equipment',
'demand', 'system_id')) 'demand', 'system_id'))
self._lod = float(self._archetypes['catalog']['@lod'])
self._catalog_generation_equipments = self._load_generation_equipments() self._catalog_generation_equipments = self._load_generation_equipments()
self._catalog_distribution_equipments = self._load_distribution_equipments()
self._catalog_emission_equipments = self._load_emission_equipments() self._catalog_emission_equipments = self._load_emission_equipments()
self._catalog_distribution_equipments = self._load_distribution_equipments()
self._catalog_systems = self._load_systems() self._catalog_systems = self._load_systems()
self._catalog_archetypes = self._load_archetypes() self._catalog_archetypes = self._load_archetypes()
# store the full catalog data model in self._content # store the full catalog data model in self._content
self._content = Content(self._catalog_archetypes, self._content = Content(self._catalog_archetypes,
self._catalog_systems, self._catalog_systems,
self._catalog_generation_equipments, self._catalog_generation_equipments,
self._catalog_distribution_equipments, self._catalog_distribution_equipments)
self._catalog_emission_equipments)
def _load_generation_equipments(self): def _load_generation_equipments(self):
_equipments = [] _equipments = []
_storages = []
equipments = self._archetypes['catalog']['generation_equipments']['equipment'] equipments = self._archetypes['catalog']['generation_equipments']['equipment']
for equipment in equipments: for equipment in equipments:
equipment_id = float(equipment['@id']) equipment_id = float(equipment['@id'])
equipment_type = equipment['@type'] equipment_type = equipment['@type']
fuel_type = equipment['@fuel_type'] fuel_type = equipment['@fuel_type']
name = equipment['name'] model_name = equipment['name']
heating_efficiency = None heating_efficiency = None
if 'heating_efficiency' in equipment: if 'heating_efficiency' in equipment:
heating_efficiency = float(equipment['heating_efficiency']) heating_efficiency = float(equipment['heating_efficiency'])
@ -58,21 +59,38 @@ class MontrealCustomCatalog(Catalog):
electricity_efficiency = None electricity_efficiency = None
if 'electrical_efficiency' in equipment: if 'electrical_efficiency' in equipment:
electricity_efficiency = float(equipment['electrical_efficiency']) electricity_efficiency = float(equipment['electrical_efficiency'])
storage = literal_eval(equipment['storage'].capitalize())
generation_system = GenerationSystem(equipment_id,
name,
equipment_type,
fuel_type,
None,
heating_efficiency,
cooling_efficiency,
electricity_efficiency,
None,
None,
storage,
None)
storage_systems = None
storage = literal_eval(equipment['storage'].capitalize())
if storage:
if equipment_type == 'electricity generator':
storage_system = ElectricalStorageSystem(equipment_id)
else:
storage_system = ThermalStorageSystem(equipment_id)
storage_systems = [storage_system]
if model_name == 'PV system':
system_type = 'Photovoltaic'
generation_system = PvGenerationSystem(equipment_id,
name=None,
system_type= system_type,
model_name=model_name,
electricity_efficiency=electricity_efficiency,
energy_storage_systems=storage_systems
)
else:
generation_system = NonPvGenerationSystem(equipment_id,
name=None,
model_name=model_name,
system_type=equipment_type,
fuel_type=fuel_type,
heat_efficiency=heating_efficiency,
cooling_efficiency=cooling_efficiency,
electricity_efficiency=electricity_efficiency,
energy_storage_systems=storage_systems,
dual_supply_capability=False
)
_equipments.append(generation_system) _equipments.append(generation_system)
return _equipments return _equipments
def _load_distribution_equipments(self): def _load_distribution_equipments(self):
@ -81,7 +99,7 @@ class MontrealCustomCatalog(Catalog):
for equipment in equipments: for equipment in equipments:
equipment_id = float(equipment['@id']) equipment_id = float(equipment['@id'])
equipment_type = equipment['@type'] equipment_type = equipment['@type']
name = equipment['name'] model_name = equipment['name']
distribution_heat_losses = None distribution_heat_losses = None
if 'distribution_heat_losses' in equipment: if 'distribution_heat_losses' in equipment:
distribution_heat_losses = float(equipment['distribution_heat_losses']['#text']) / 100 distribution_heat_losses = float(equipment['distribution_heat_losses']['#text']) / 100
@ -90,15 +108,22 @@ class MontrealCustomCatalog(Catalog):
distribution_consumption_fix_flow = float(equipment['distribution_consumption_fix_flow']['#text']) / 100 distribution_consumption_fix_flow = float(equipment['distribution_consumption_fix_flow']['#text']) / 100
distribution_consumption_variable_flow = None distribution_consumption_variable_flow = None
if 'distribution_consumption_variable_flow' in equipment: if 'distribution_consumption_variable_flow' in equipment:
distribution_consumption_variable_flow = float(equipment['distribution_consumption_variable_flow']['#text']) / 100 distribution_consumption_variable_flow = float(
equipment['distribution_consumption_variable_flow']['#text']) / 100
emission_equipment = equipment['dissipation_id']
_emission_equipments = None
for equipment_archetype in self._catalog_emission_equipments:
if int(equipment_archetype.id) == int(emission_equipment):
_emission_equipments = [equipment_archetype]
distribution_system = DistributionSystem(equipment_id, distribution_system = DistributionSystem(equipment_id,
name, model_name=model_name,
equipment_type, system_type=equipment_type,
None, distribution_consumption_fix_flow=distribution_consumption_fix_flow,
distribution_consumption_fix_flow, distribution_consumption_variable_flow=distribution_consumption_variable_flow,
distribution_consumption_variable_flow, heat_losses=distribution_heat_losses,
distribution_heat_losses) emission_systems=_emission_equipments)
_equipments.append(distribution_system) _equipments.append(distribution_system)
return _equipments return _equipments
@ -109,15 +134,15 @@ class MontrealCustomCatalog(Catalog):
for equipment in equipments: for equipment in equipments:
equipment_id = float(equipment['@id']) equipment_id = float(equipment['@id'])
equipment_type = equipment['@type'] equipment_type = equipment['@type']
name = equipment['name'] model_name = equipment['name']
parasitic_consumption = None parasitic_consumption = None
if 'parasitic_consumption' in equipment: if 'parasitic_consumption' in equipment:
parasitic_consumption = float(equipment['parasitic_consumption']['#text']) / 100 parasitic_consumption = float(equipment['parasitic_consumption']['#text']) / 100
emission_system = EmissionSystem(equipment_id, emission_system = EmissionSystem(equipment_id,
name, model_name=model_name,
equipment_type, system_type=equipment_type,
parasitic_consumption) parasitic_energy_consumption=parasitic_consumption)
_equipments.append(emission_system) _equipments.append(emission_system)
return _equipments return _equipments
@ -130,28 +155,21 @@ class MontrealCustomCatalog(Catalog):
name = system['name'] name = system['name']
demands = system['demands']['demand'] demands = system['demands']['demand']
generation_equipment = system['equipments']['generation_id'] generation_equipment = system['equipments']['generation_id']
_generation_equipment = None _generation_equipments = None
for equipment_archetype in self._catalog_generation_equipments: for equipment_archetype in self._catalog_generation_equipments:
if int(equipment_archetype.id) == int(generation_equipment): if int(equipment_archetype.id) == int(generation_equipment):
_generation_equipment = equipment_archetype _generation_equipments = [equipment_archetype]
distribution_equipment = system['equipments']['distribution_id'] distribution_equipment = system['equipments']['distribution_id']
_distribution_equipment = None _distribution_equipments = None
for equipment_archetype in self._catalog_distribution_equipments: for equipment_archetype in self._catalog_distribution_equipments:
if int(equipment_archetype.id) == int(distribution_equipment): if int(equipment_archetype.id) == int(distribution_equipment):
_distribution_equipment = equipment_archetype _distribution_equipments = [equipment_archetype]
emission_equipment = system['equipments']['dissipation_id']
_emission_equipment = None
for equipment_archetype in self._catalog_emission_equipments:
if int(equipment_archetype.id) == int(emission_equipment):
_emission_equipment = equipment_archetype
_catalog_systems.append(System(self._lod, _catalog_systems.append(System(system_id,
system_id,
name,
demands, demands,
_generation_equipment, name=name,
_distribution_equipment, generation_systems=_generation_equipments,
_emission_equipment)) distribution_systems=_distribution_equipments))
return _catalog_systems return _catalog_systems
def _load_archetypes(self): def _load_archetypes(self):
@ -165,7 +183,7 @@ class MontrealCustomCatalog(Catalog):
for system_archetype in self._catalog_systems: for system_archetype in self._catalog_systems:
if int(system_archetype.id) == int(system): if int(system_archetype.id) == int(system):
_systems.append(system_archetype) _systems.append(system_archetype)
_catalog_archetypes.append(Archetype(self._lod, name, _systems)) _catalog_archetypes.append(Archetype(name, _systems))
return _catalog_archetypes return _catalog_archetypes
def names(self, category=None): def names(self, category=None):
@ -181,11 +199,9 @@ class MontrealCustomCatalog(Catalog):
for system in self._content.systems: for system in self._content.systems:
_names['systems'].append(system.name) _names['systems'].append(system.name)
for equipment in self._content.generation_equipments: for equipment in self._content.generation_equipments:
_names['generation_equipments'].append(equipment.name) _names['generation_equipments'].append(equipment.model_name)
for equipment in self._content.distribution_equipments: for equipment in self._content.distribution_equipments:
_names['distribution_equipments'].append(equipment.name) _names['distribution_equipments'].append(equipment.model_name)
for equipment in self._content.emission_equipments:
_names['emission_equipments'].append(equipment.name)
else: else:
_names = {category: []} _names = {category: []}
if category.lower() == 'archetypes': if category.lower() == 'archetypes':
@ -196,13 +212,10 @@ class MontrealCustomCatalog(Catalog):
_names[category].append(system.name) _names[category].append(system.name)
elif category.lower() == 'generation_equipments': elif category.lower() == 'generation_equipments':
for system in self._content.generation_equipments: for system in self._content.generation_equipments:
_names[category].append(system.name) _names[category].append(system.model_name)
elif category.lower() == 'distribution_equipments': elif category.lower() == 'distribution_equipments':
for system in self._content.distribution_equipments: for system in self._content.distribution_equipments:
_names[category].append(system.name) _names[category].append(system.model_name)
elif category.lower() == 'emission_equipments':
for system in self._content.emission_equipments:
_names[category].append(system.name)
else: else:
raise ValueError(f'Unknown category [{category}]') raise ValueError(f'Unknown category [{category}]')
return _names return _names
@ -222,9 +235,6 @@ class MontrealCustomCatalog(Catalog):
return self._content.generation_equipments return self._content.generation_equipments
if category.lower() == 'distribution_equipments': if category.lower() == 'distribution_equipments':
return self._content.distribution_equipments return self._content.distribution_equipments
if category.lower() == 'emission_equipments':
return self._content.emission_equipments
raise ValueError(f'Unknown category [{category}]')
def get_entry(self, name): def get_entry(self, name):
""" """
@ -238,12 +248,9 @@ class MontrealCustomCatalog(Catalog):
if entry.name.lower() == name.lower(): if entry.name.lower() == name.lower():
return entry return entry
for entry in self._content.generation_equipments: for entry in self._content.generation_equipments:
if entry.name.lower() == name.lower(): if entry.model_name.lower() == name.lower():
return entry return entry
for entry in self._content.distribution_equipments: for entry in self._content.distribution_equipments:
if entry.name.lower() == name.lower(): if entry.model_name.lower() == name.lower():
return entry
for entry in self._content.emission_equipments:
if entry.name.lower() == name.lower():
return entry return entry
raise IndexError(f"{name} doesn't exists in the catalog") raise IndexError(f"{name} doesn't exists in the catalog")

View File

@ -0,0 +1,539 @@
"""
Montreal future energy system catalog
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca
"""
import xmltodict
from pathlib import Path
from hub.catalog_factories.catalog import Catalog
from hub.catalog_factories.data_models.energy_systems.distribution_system import DistributionSystem
from hub.catalog_factories.data_models.energy_systems.emission_system import EmissionSystem
from hub.catalog_factories.data_models.energy_systems.system import System
from hub.catalog_factories.data_models.energy_systems.content import Content
from hub.catalog_factories.data_models.energy_systems.non_pv_generation_system import NonPvGenerationSystem
from hub.catalog_factories.data_models.energy_systems.pv_generation_system import PvGenerationSystem
from hub.catalog_factories.data_models.energy_systems.thermal_storage_system import ThermalStorageSystem
from hub.catalog_factories.data_models.energy_systems.performance_curves import PerformanceCurves
from hub.catalog_factories.data_models.energy_systems.archetype import Archetype
from hub.catalog_factories.data_models.construction.material import Material
from hub.catalog_factories.data_models.construction.layer import Layer
class MontrealFutureSystemCatalogue(Catalog):
"""
North america energy system catalog class
"""
def __init__(self, path):
path = str(path / 'montreal_future_systems.xml')
with open(path, 'r', encoding='utf-8') as xml:
self._archetypes = xmltodict.parse(xml.read(),
force_list=['pv_generation_component', 'templateStorages', 'demand'])
self._storage_components = self._load_storage_components()
self._generation_components = self._load_generation_components()
self._energy_emission_components = self._load_emission_equipments()
self._distribution_components = self._load_distribution_equipments()
self._systems = self._load_systems()
self._system_archetypes = self._load_archetypes()
self._content = Content(self._system_archetypes,
self._systems,
generations=self._generation_components,
distributions=self._distribution_components)
def _load_generation_components(self):
generation_components = []
non_pv_generation_components = self._archetypes['EnergySystemCatalog']['energy_generation_components'][
'non_pv_generation_component']
if non_pv_generation_components is not None:
for non_pv in non_pv_generation_components:
system_id = non_pv['system_id']
name = non_pv['name']
system_type = non_pv['system_type']
model_name = non_pv['model_name']
manufacturer = non_pv['manufacturer']
fuel_type = non_pv['fuel_type']
distribution_systems = non_pv['distribution_systems']
energy_storage_systems = None
if non_pv['energy_storage_systems'] is not None:
storage_component = non_pv['energy_storage_systems']['storage_id']
storage_systems = self._search_storage_equipment(self._load_storage_components(), storage_component)
energy_storage_systems = storage_systems
nominal_heat_output = non_pv['nominal_heat_output']
maximum_heat_output = non_pv['maximum_heat_output']
minimum_heat_output = non_pv['minimum_heat_output']
source_medium = non_pv['source_medium']
supply_medium = non_pv['supply_medium']
heat_efficiency = non_pv['heat_efficiency']
nominal_cooling_output = non_pv['nominal_cooling_output']
maximum_cooling_output = non_pv['maximum_cooling_output']
minimum_cooling_output = non_pv['minimum_cooling_output']
cooling_efficiency = non_pv['cooling_efficiency']
electricity_efficiency = non_pv['electricity_efficiency']
source_temperature = non_pv['source_temperature']
source_mass_flow = non_pv['source_mass_flow']
nominal_electricity_output = non_pv['nominal_electricity_output']
maximum_heat_supply_temperature = non_pv['maximum_heat_supply_temperature']
minimum_heat_supply_temperature = non_pv['minimum_heat_supply_temperature']
maximum_cooling_supply_temperature = non_pv['maximum_cooling_supply_temperature']
minimum_cooling_supply_temperature = non_pv['minimum_cooling_supply_temperature']
heat_output_curve = None
heat_fuel_consumption_curve = None
heat_efficiency_curve = None
cooling_output_curve = None
cooling_fuel_consumption_curve = None
cooling_efficiency_curve = None
if non_pv['heat_output_curve'] is not None:
curve_type = non_pv['heat_output_curve']['curve_type']
dependant_variable = non_pv['heat_output_curve']['dependant_variable']
parameters = non_pv['heat_output_curve']['parameters']
coefficients = list(non_pv['heat_output_curve']['coefficients'].values())
heat_output_curve = PerformanceCurves(curve_type, dependant_variable, parameters, coefficients)
if non_pv['heat_fuel_consumption_curve'] is not None:
curve_type = non_pv['heat_fuel_consumption_curve']['curve_type']
dependant_variable = non_pv['heat_fuel_consumption_curve']['dependant_variable']
parameters = non_pv['heat_fuel_consumption_curve']['parameters']
coefficients = list(non_pv['heat_fuel_consumption_curve']['coefficients'].values())
heat_fuel_consumption_curve = PerformanceCurves(curve_type, dependant_variable, parameters, coefficients)
if non_pv['heat_efficiency_curve'] is not None:
curve_type = non_pv['heat_efficiency_curve']['curve_type']
dependant_variable = non_pv['heat_efficiency_curve']['dependant_variable']
parameters = non_pv['heat_efficiency_curve']['parameters']
coefficients = list(non_pv['heat_efficiency_curve']['coefficients'].values())
heat_efficiency_curve = PerformanceCurves(curve_type, dependant_variable, parameters, coefficients)
if non_pv['cooling_output_curve'] is not None:
curve_type = non_pv['cooling_output_curve']['curve_type']
dependant_variable = non_pv['cooling_output_curve']['dependant_variable']
parameters = non_pv['cooling_output_curve']['parameters']
coefficients = list(non_pv['cooling_output_curve']['coefficients'].values())
cooling_output_curve = PerformanceCurves(curve_type, dependant_variable, parameters, coefficients)
if non_pv['cooling_fuel_consumption_curve'] is not None:
curve_type = non_pv['cooling_fuel_consumption_curve']['curve_type']
dependant_variable = non_pv['cooling_fuel_consumption_curve']['dependant_variable']
parameters = non_pv['cooling_fuel_consumption_curve']['parameters']
coefficients = list(non_pv['cooling_fuel_consumption_curve']['coefficients'].values())
cooling_fuel_consumption_curve = PerformanceCurves(curve_type, dependant_variable, parameters, coefficients)
if non_pv['cooling_efficiency_curve'] is not None:
curve_type = non_pv['cooling_efficiency_curve']['curve_type']
dependant_variable = non_pv['cooling_efficiency_curve']['dependant_variable']
parameters = non_pv['cooling_efficiency_curve']['parameters']
coefficients = list(non_pv['cooling_efficiency_curve']['coefficients'].values())
cooling_efficiency_curve = PerformanceCurves(curve_type, dependant_variable, parameters, coefficients)
dual_supply_capability = None
if non_pv['dual_supply_capability'] is not None:
if non_pv['dual_supply_capability'] == 'True':
dual_supply_capability = True
else:
dual_supply_capability = False
non_pv_component = NonPvGenerationSystem(system_id=system_id,
name=name,
system_type=system_type,
model_name=model_name,
manufacturer=manufacturer,
fuel_type=fuel_type,
nominal_heat_output=nominal_heat_output,
maximum_heat_output=maximum_heat_output,
minimum_heat_output=minimum_heat_output,
source_medium=source_medium,
supply_medium=supply_medium,
heat_efficiency=heat_efficiency,
nominal_cooling_output=nominal_cooling_output,
maximum_cooling_output=maximum_cooling_output,
minimum_cooling_output=minimum_cooling_output,
cooling_efficiency=cooling_efficiency,
electricity_efficiency=electricity_efficiency,
source_temperature=source_temperature,
source_mass_flow=source_mass_flow,
nominal_electricity_output=nominal_electricity_output,
maximum_heat_supply_temperature=maximum_heat_supply_temperature,
minimum_heat_supply_temperature=minimum_heat_supply_temperature,
maximum_cooling_supply_temperature=maximum_cooling_supply_temperature,
minimum_cooling_supply_temperature=minimum_cooling_supply_temperature,
heat_output_curve=heat_output_curve,
heat_fuel_consumption_curve=heat_fuel_consumption_curve,
heat_efficiency_curve=heat_efficiency_curve,
cooling_output_curve=cooling_output_curve,
cooling_fuel_consumption_curve=cooling_fuel_consumption_curve,
cooling_efficiency_curve=cooling_efficiency_curve,
distribution_systems=distribution_systems,
energy_storage_systems=energy_storage_systems,
dual_supply_capability=dual_supply_capability)
generation_components.append(non_pv_component)
pv_generation_components = self._archetypes['EnergySystemCatalog']['energy_generation_components'][
'pv_generation_component']
if pv_generation_components is not None:
for pv in pv_generation_components:
system_id = pv['system_id']
name = pv['name']
system_type = pv['system_type']
model_name = pv['model_name']
manufacturer = pv['manufacturer']
electricity_efficiency = pv['electricity_efficiency']
nominal_electricity_output = pv['nominal_electricity_output']
nominal_ambient_temperature = pv['nominal_ambient_temperature']
nominal_cell_temperature = pv['nominal_cell_temperature']
nominal_radiation = pv['nominal_radiation']
standard_test_condition_cell_temperature = pv['standard_test_condition_cell_temperature']
standard_test_condition_maximum_power = pv['standard_test_condition_maximum_power']
cell_temperature_coefficient = pv['cell_temperature_coefficient']
width = pv['width']
height = pv['height']
distribution_systems = pv['distribution_systems']
energy_storage_systems = None
if pv['energy_storage_systems'] is not None:
storage_component = pv['energy_storage_systems']['storage_id']
storage_systems = self._search_storage_equipment(self._load_storage_components(), storage_component)
energy_storage_systems = storage_systems
pv_component = PvGenerationSystem(system_id=system_id,
name=name,
system_type=system_type,
model_name=model_name,
manufacturer=manufacturer,
electricity_efficiency=electricity_efficiency,
nominal_electricity_output=nominal_electricity_output,
nominal_ambient_temperature=nominal_ambient_temperature,
nominal_cell_temperature=nominal_cell_temperature,
nominal_radiation=nominal_radiation,
standard_test_condition_cell_temperature=
standard_test_condition_cell_temperature,
standard_test_condition_maximum_power=standard_test_condition_maximum_power,
cell_temperature_coefficient=cell_temperature_coefficient,
width=width,
height=height,
distribution_systems=distribution_systems,
energy_storage_systems=energy_storage_systems)
generation_components.append(pv_component)
return generation_components
def _load_distribution_equipments(self):
_equipments = []
distribution_systems = self._archetypes['EnergySystemCatalog']['distribution_systems']['distribution_system']
if distribution_systems is not None:
for distribution_system in distribution_systems:
system_id = None
model_name = None
system_type = None
supply_temperature = None
distribution_consumption_fix_flow = None
distribution_consumption_variable_flow = None
heat_losses = None
generation_systems = None
energy_storage_systems = None
emission_systems = None
distribution_equipment = DistributionSystem(system_id=system_id,
model_name=model_name,
system_type=system_type,
supply_temperature=supply_temperature,
distribution_consumption_fix_flow=distribution_consumption_fix_flow,
distribution_consumption_variable_flow=
distribution_consumption_variable_flow,
heat_losses=heat_losses,
generation_systems=generation_systems,
energy_storage_systems=energy_storage_systems,
emission_systems=emission_systems
)
_equipments.append(distribution_equipment)
return _equipments
def _load_emission_equipments(self):
_equipments = []
dissipation_systems = self._archetypes['EnergySystemCatalog']['dissipation_systems']['dissipation_system']
if dissipation_systems is not None:
for dissipation_system in dissipation_systems:
system_id = None
model_name = None
system_type = None
parasitic_energy_consumption = None
emission_system = EmissionSystem(system_id=system_id,
model_name=model_name,
system_type=system_type,
parasitic_energy_consumption=parasitic_energy_consumption)
_equipments.append(emission_system)
return _equipments
def _load_storage_components(self):
storage_components = []
thermal_storages = self._archetypes['EnergySystemCatalog']['energy_storage_components']['thermalStorages']
template_storages = self._archetypes['EnergySystemCatalog']['energy_storage_components']['templateStorages']
for tes in thermal_storages:
storage_id = tes['storage_id']
type_energy_stored = tes['type_energy_stored']
model_name = tes['model_name']
manufacturer = tes['manufacturer']
storage_type = tes['storage_type']
volume = tes['physical_characteristics']['volume']
height = tes['physical_characteristics']['height']
maximum_operating_temperature = tes['maximum_operating_temperature']
materials = self._load_materials()
insulation_material_id = tes['insulation']['material_id']
insulation_material = self._search_material(materials, insulation_material_id)
material_id = tes['physical_characteristics']['material_id']
tank_material = self._search_material(materials, material_id)
thickness = float(tes['insulation']['insulationThickness']) / 100 # from cm to m
insulation_layer = Layer(None, 'insulation', insulation_material, thickness)
thickness = float(tes['physical_characteristics']['tankThickness']) / 100 # from cm to m
tank_layer = Layer(None, 'tank', tank_material, thickness)
media = self._load_media()
media_id = tes['storage_medium']['medium_id']
medium = self._search_media(media, media_id)
layers = [insulation_layer, tank_layer]
nominal_capacity = tes['nominal_capacity']
losses_ratio = tes['losses_ratio']
storage_component = ThermalStorageSystem(storage_id=storage_id,
model_name=model_name,
type_energy_stored=type_energy_stored,
manufacturer=manufacturer,
storage_type=storage_type,
nominal_capacity=nominal_capacity,
losses_ratio=losses_ratio,
volume=volume,
height=height,
layers=layers,
maximum_operating_temperature=maximum_operating_temperature,
storage_medium=medium)
storage_components.append(storage_component)
for template in template_storages:
storage_id = template['storage_id']
storage_type = template['storage_type']
type_energy_stored = template['type_energy_stored']
maximum_operating_temperature = template['maximum_operating_temperature']
height = template['physical_characteristics']['height']
materials = self._load_materials()
insulation_material_id = template['insulation']['material_id']
insulation_material = self._search_material(materials, insulation_material_id)
material_id = template['physical_characteristics']['material_id']
tank_material = self._search_material(materials, material_id)
thickness = float(template['insulation']['insulationThickness']) / 100 # from cm to m
insulation_layer = Layer(None, 'insulation', insulation_material, thickness)
thickness = float(template['physical_characteristics']['tankThickness']) / 100 # from cm to m
tank_layer = Layer(None, 'tank', tank_material, thickness)
layers = [insulation_layer, tank_layer]
media = self._load_media()
media_id = template['storage_medium']['medium_id']
medium = self._search_media(media, media_id)
model_name = template['model_name']
manufacturer = template['manufacturer']
nominal_capacity = template['nominal_capacity']
losses_ratio = template['losses_ratio']
volume = template['physical_characteristics']['volume']
storage_component = ThermalStorageSystem(storage_id=storage_id,
model_name=model_name,
type_energy_stored=type_energy_stored,
manufacturer=manufacturer,
storage_type=storage_type,
nominal_capacity=nominal_capacity,
losses_ratio=losses_ratio,
volume=volume,
height=height,
layers=layers,
maximum_operating_temperature=maximum_operating_temperature,
storage_medium=medium)
storage_components.append(storage_component)
return storage_components
def _load_systems(self):
base_path = Path(Path(__file__).parent.parent.parent / 'data/energy_systems')
_catalog_systems = []
systems = self._archetypes['EnergySystemCatalog']['systems']['system']
for system in systems:
system_id = system['id']
name = system['name']
demands = system['demands']['demand']
generation_components = system['components']['generation_id']
generation_systems = self._search_generation_equipment(self._load_generation_components(), generation_components)
configuration_schema = Path(base_path / system['schema'])
energy_system = System(system_id=system_id,
name=name,
demand_types=demands,
generation_systems=generation_systems,
distribution_systems=None,
configuration_schema=configuration_schema)
_catalog_systems.append(energy_system)
return _catalog_systems
def _load_archetypes(self):
_system_archetypes = []
system_clusters = self._archetypes['EnergySystemCatalog']['system_archetypes']['system_archetype']
for system_cluster in system_clusters:
name = system_cluster['name']
systems = system_cluster['systems']['system_id']
integer_system_ids = [int(item) for item in systems]
_systems = []
for system_archetype in self._systems:
if int(system_archetype.id) in integer_system_ids:
_systems.append(system_archetype)
_system_archetypes.append(Archetype(name=name, systems=_systems))
return _system_archetypes
def _load_materials(self):
materials = []
_materials = self._archetypes['EnergySystemCatalog']['materials']['material']
for _material in _materials:
material_id = _material['material_id']
name = _material['name']
conductivity = _material['conductivity']
solar_absorptance = _material['solar_absorptance']
thermal_absorptance = _material['thermal_absorptance']
density = _material['density']
specific_heat = _material['specific_heat']
no_mass = _material['no_mass']
visible_absorptance = _material['visible_absorptance']
thermal_resistance = _material['thermal_resistance']
material = Material(material_id,
name,
solar_absorptance=solar_absorptance,
thermal_absorptance=thermal_absorptance,
density=density,
conductivity=conductivity,
thermal_resistance=thermal_resistance,
visible_absorptance=visible_absorptance,
no_mass=no_mass,
specific_heat=specific_heat)
materials.append(material)
return materials
@staticmethod
def _search_material(materials, material_id):
_material = None
for material in materials:
if int(material.id) == int(material_id):
_material = material
break
if _material is None:
raise ValueError(f'Material with the id = [{material_id}] not found in catalog ')
return _material
def _load_media(self):
media = []
_media = [self._archetypes['EnergySystemCatalog']['media']['medium']]
for _medium in _media:
medium_id = _medium['medium_id']
density = _medium['density']
name = _medium['name']
conductivity = _medium['conductivity']
solar_absorptance = _medium['solar_absorptance']
thermal_absorptance = _medium['thermal_absorptance']
specific_heat = _medium['specific_heat']
no_mass = _medium['no_mass']
visible_absorptance = _medium['visible_absorptance']
thermal_resistance = _medium['thermal_resistance']
medium = Material(material_id=medium_id,
name=name,
solar_absorptance=solar_absorptance,
thermal_absorptance=thermal_absorptance,
visible_absorptance=visible_absorptance,
no_mass=no_mass,
thermal_resistance=thermal_resistance,
conductivity=conductivity,
density=density,
specific_heat=specific_heat)
media.append(medium)
return media
@staticmethod
def _search_media(media, medium_id):
_medium = None
for medium in media:
if int(medium.id) == int(medium_id):
_medium = medium
break
if _medium is None:
raise ValueError(f'media with the id = [{medium_id}] not found in catalog ')
return _medium
@staticmethod
def _search_generation_equipment(generation_systems, generation_id):
_generation_systems = []
if isinstance(generation_id, list):
integer_ids = [int(item) for item in generation_id]
for generation in generation_systems:
if int(generation.id) in integer_ids:
_generation_systems.append(generation)
else:
integer_id = int(generation_id)
for generation in generation_systems:
if int(generation.id) == integer_id:
_generation_systems.append(generation)
if len(_generation_systems) == 0:
_generation_systems = None
raise ValueError(f'The system with the following id is not found in catalog [{generation_id}]')
return _generation_systems
@staticmethod
def _search_storage_equipment(storage_systems, storage_id):
_storage_systems = []
for storage in storage_systems:
if storage.id in storage_id:
_storage_systems.append(storage)
if len(_storage_systems) == 0:
_storage_systems = None
raise ValueError(f'The system with the following id is not found in catalog [{storage_id}]')
return _storage_systems
def names(self, category=None):
"""
Get the catalog elements names
:parm: optional category filter
"""
if category is None:
_names = {'archetypes': [], 'systems': [], 'generation_equipments': [], 'storage_equipments': []}
for archetype in self._content.archetypes:
_names['archetypes'].append(archetype.name)
for system in self._content.systems:
_names['systems'].append(system.name)
for equipment in self._content.generation_equipments:
_names['generation_equipments'].append(equipment.name)
else:
_names = {category: []}
if category.lower() == 'archetypes':
for archetype in self._content.archetypes:
_names[category].append(archetype.name)
elif category.lower() == 'systems':
for system in self._content.systems:
_names[category].append(system.name)
elif category.lower() == 'generation_equipments':
for system in self._content.generation_equipments:
_names[category].append(system.name)
else:
raise ValueError(f'Unknown category [{category}]')
return _names
def entries(self, category=None):
"""
Get the catalog elements
:parm: optional category filter
"""
if category is None:
return self._content
if category.lower() == 'archetypes':
return self._content.archetypes
if category.lower() == 'systems':
return self._content.systems
if category.lower() == 'generation_equipments':
return self._content.generation_equipments
raise ValueError(f'Unknown category [{category}]')
def get_entry(self, name):
"""
Get one catalog element by names
:parm: entry name
"""
for entry in self._content.archetypes:
if entry.name.lower() == name.lower():
return entry
for entry in self._content.systems:
if entry.name.lower() == name.lower():
return entry
for entry in self._content.generation_equipments:
if entry.name.lower() == name.lower():
return entry
raise IndexError(f"{name} doesn't exists in the catalog")

View File

@ -9,6 +9,7 @@ from pathlib import Path
from typing import TypeVar from typing import TypeVar
from hub.catalog_factories.energy_systems.montreal_custom_catalog import MontrealCustomCatalog from hub.catalog_factories.energy_systems.montreal_custom_catalog import MontrealCustomCatalog
from hub.catalog_factories.energy_systems.montreal_future_system_catalogue import MontrealFutureSystemCatalogue
from hub.helpers.utils import validate_import_export_type from hub.helpers.utils import validate_import_export_type
Catalog = TypeVar('Catalog') Catalog = TypeVar('Catalog')
@ -32,6 +33,13 @@ class EnergySystemsCatalogFactory:
""" """
return MontrealCustomCatalog(self._path) return MontrealCustomCatalog(self._path)
@property
def _montreal_future(self):
"""
Retrieve North American catalog
"""
return MontrealFutureSystemCatalogue(self._path)
@property @property
def catalog(self) -> Catalog: def catalog(self) -> Catalog:
""" """

View File

@ -89,7 +89,8 @@ class Building(CityObject):
elif surface.type == cte.INTERIOR_SLAB: elif surface.type == cte.INTERIOR_SLAB:
self._interior_slabs.append(surface) self._interior_slabs.append(surface)
else: else:
logging.error(f'Building %s [%s] has an unexpected surface type %s.', self.name, self.aliases, surface.type) logging.error('Building %s [%s] has an unexpected surface type %s.', self.name, self.aliases, surface.type)
self._heating_consumption_disaggregated = {}
@property @property
def shell(self) -> Polyhedron: def shell(self) -> Polyhedron:
@ -702,6 +703,7 @@ class Building(CityObject):
Get total electricity consumption for distribution and emission systems in J Get total electricity consumption for distribution and emission systems in J
return: dict return: dict
""" """
_distribution_systems_electrical_consumption = {}
if len(self._distribution_systems_electrical_consumption) != 0: if len(self._distribution_systems_electrical_consumption) != 0:
return self._distribution_systems_electrical_consumption return self._distribution_systems_electrical_consumption
_peak_load = self.heating_peak_load[cte.YEAR][0] _peak_load = self.heating_peak_load[cte.YEAR][0]
@ -715,11 +717,13 @@ class Building(CityObject):
if self.energy_systems is None: if self.energy_systems is None:
return self._distribution_systems_electrical_consumption return self._distribution_systems_electrical_consumption
for energy_system in self.energy_systems: for energy_system in self.energy_systems:
emission_system = energy_system.emission_system.generic_emission_system distribution_systems = energy_system.distribution_systems
for distribution_system in distribution_systems:
emission_systems = distribution_system.emission_systems
parasitic_energy_consumption = 0 parasitic_energy_consumption = 0
if emission_system is not None: if emission_systems is not None:
parasitic_energy_consumption = emission_system.parasitic_energy_consumption for emission_system in emission_systems:
distribution_system = energy_system.distribution_system.generic_distribution_system parasitic_energy_consumption += emission_system.parasitic_energy_consumption
consumption_variable_flow = distribution_system.distribution_consumption_variable_flow consumption_variable_flow = distribution_system.distribution_consumption_variable_flow
for demand_type in energy_system.demand_types: for demand_type in energy_system.demand_types:
if demand_type.lower() == cte.HEATING.lower(): if demand_type.lower() == cte.HEATING.lower():
@ -758,15 +762,21 @@ class Building(CityObject):
if self.energy_systems is None: if self.energy_systems is None:
return None return None
for energy_system in self.energy_systems: for energy_system in self.energy_systems:
generation_systems = energy_system.generation_systems
for demand_type in energy_system.demand_types: for demand_type in energy_system.demand_types:
if demand_type.lower() == consumption_type.lower(): if demand_type.lower() == consumption_type.lower():
if consumption_type in (cte.HEATING, cte.DOMESTIC_HOT_WATER): if consumption_type in (cte.HEATING, cte.DOMESTIC_HOT_WATER):
coefficient_of_performance = energy_system.generation_system.generic_generation_system.heat_efficiency for generation_system in generation_systems:
if generation_system.heat_efficiency is not None:
coefficient_of_performance = float(generation_system.heat_efficiency)
elif consumption_type == cte.COOLING: elif consumption_type == cte.COOLING:
coefficient_of_performance = energy_system.generation_system.generic_generation_system.cooling_efficiency for generation_system in generation_systems:
if generation_system.cooling_efficiency is not None:
coefficient_of_performance = float(generation_system.cooling_efficiency)
elif consumption_type == cte.ELECTRICITY: elif consumption_type == cte.ELECTRICITY:
coefficient_of_performance = \ for generation_system in generation_systems:
energy_system.generation_system.generic_generation_system.electricity_efficiency if generation_system.electricity_efficiency is not None:
coefficient_of_performance = float(generation_system.electricity_efficiency)
if coefficient_of_performance == 0: if coefficient_of_performance == 0:
values = [0]*len(demand) values = [0]*len(demand)
final_energy_consumed = values final_energy_consumed = values
@ -797,8 +807,12 @@ class Building(CityObject):
if self.energy_systems is None: if self.energy_systems is None:
return self._onsite_electrical_production return self._onsite_electrical_production
for energy_system in self.energy_systems: for energy_system in self.energy_systems:
if energy_system.generation_system.generic_generation_system.type == cte.PHOTOVOLTAIC: for generation_system in energy_system.generation_systems:
_efficiency = energy_system.generation_system.generic_generation_system.electricity_efficiency if generation_system.system_type == cte.PHOTOVOLTAIC:
if generation_system.electricity_efficiency is not None:
_efficiency = float(generation_system.electricity_efficiency)
else:
_efficiency = 0
self._onsite_electrical_production = {} self._onsite_electrical_production = {}
for _key in self.roofs[0].global_irradiance.keys(): for _key in self.roofs[0].global_irradiance.keys():
_results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key]))] _results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key]))]
@ -811,6 +825,23 @@ class Building(CityObject):
self._onsite_electrical_production[_key] = _results self._onsite_electrical_production[_key] = _results
return self._onsite_electrical_production return self._onsite_electrical_production
@property
def heating_consumption_disaggregated(self) -> dict:
"""
Get energy consumed for heating from different fuels in J
return: dict
"""
return self._heating_consumption_disaggregated
@heating_consumption_disaggregated.setter
def heating_consumption_disaggregated(self, value):
"""
Get energy consumed for heating from different fuels in J
return: dict
"""
self._heating_consumption_disaggregated = value
@property @property
def lower_corner(self): def lower_corner(self):
""" """

View File

@ -62,7 +62,6 @@ class City:
self._level_of_detail = LevelOfDetail() self._level_of_detail = LevelOfDetail()
self._city_objects_dictionary = {} self._city_objects_dictionary = {}
self._city_objects_alias_dictionary = {} self._city_objects_alias_dictionary = {}
self._energy_systems_connection_table = None
self._generic_energy_systems = None self._generic_energy_systems = None
def _get_location(self) -> Location: def _get_location(self) -> Location:
@ -505,24 +504,6 @@ class City:
""" """
return self._level_of_detail return self._level_of_detail
@property
def energy_systems_connection_table(self) -> Union[None, DataFrame]:
"""
Get energy systems connection table which includes at least two columns: energy_system_type and associated_building
and may also include dimensioned_energy_system and connection_building_to_dimensioned_energy_system
:return: DataFrame
"""
return self._energy_systems_connection_table
@energy_systems_connection_table.setter
def energy_systems_connection_table(self, value):
"""
Set energy systems connection table which includes at least two columns: energy_system_type and associated_building
and may also include dimensioned_energy_system and connection_building_to_dimensioned_energy_system
:param value: DataFrame
"""
self._energy_systems_connection_table = value
@property @property
def generic_energy_systems(self) -> dict: def generic_energy_systems(self) -> dict:
""" """

Some files were not shown because too many files have changed in this diff Show More