finished system catalog factory

This commit is contained in:
Pilar Monsalvete 2023-04-28 14:07:07 -04:00
parent 0a96b83c22
commit 3bfb985c04
7 changed files with 246 additions and 76 deletions

View File

@ -5,28 +5,17 @@ Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union
from typing import List
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.emission_system import EmissionSystem
from hub.catalog_factories.data_models.energy_systems.equipment import Equipment
class Archetype:
def __init__(self,
lod,
name,
demand_types,
generation_system,
distribution_system,
emission_system):
def __init__(self, lod, name, equipments):
self._lod = lod
self._name = name
self._demand_types = demand_types
self._generation_system = generation_system
self._distribution_system = distribution_system
self._emission_system = emission_system
self._equipments = equipments
@property
def lod(self):
@ -45,33 +34,9 @@ class Archetype:
return f'{self._name}_lod{self._lod}'
@property
def demand_types(self):
def equipments(self) -> List[Equipment]:
"""
Get demand able to cover from [heating, cooling, domestic_hot_water, electricity]
:return: [string]
Get list of equipments that compose the total energy system
:return: [Equipment]
"""
return self._demand_types
@property
def generation_system(self) -> GenerationSystem:
"""
Get generation system
:return: GenerationSystem
"""
return self._generation_system
@property
def distribution_system(self) -> Union[None, DistributionSystem]:
"""
Get distribution system
:return: DistributionSystem
"""
return self._distribution_system
@property
def emission_system(self) -> Union[None, EmissionSystem]:
"""
Get emission system
:return: EmissionSystem
"""
return self._emission_system
return self._equipments

View File

@ -7,12 +7,20 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
class Content:
def __init__(self, archetypes):
def __init__(self, archetypes, equipments):
self._archetypes = archetypes
self._equipments = equipments
@property
def archetypes(self):
"""
All archetypes in the catalog
All archetype systems in the catalog
"""
return self._archetypes
@property
def equipments(self):
"""
All equipments in the catalog
"""
return self._equipments

View File

@ -0,0 +1,87 @@
"""
Energy System catalog equipment
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union
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.emission_system import EmissionSystem
class Equipment:
def __init__(self,
lod,
equipment_id,
name,
demand_types,
generation_system,
distribution_system,
emission_system):
self._lod = lod
self._equipment_id = equipment_id
self._name = name
self._demand_types = demand_types
self._generation_system = generation_system
self._distribution_system = distribution_system
self._emission_system = emission_system
@property
def lod(self):
"""
Get level of detail of the catalog
:return: string
"""
return self._lod
@property
def id(self):
"""
Get equipment id
:return: string
"""
return self._equipment_id
@property
def name(self):
"""
Get name
:return: string
"""
return f'{self._name}_lod{self._lod}'
@property
def demand_types(self):
"""
Get demand able to cover from [heating, cooling, domestic_hot_water, electricity]
:return: [string]
"""
return self._demand_types
@property
def generation_system(self) -> GenerationSystem:
"""
Get generation system
:return: GenerationSystem
"""
return self._generation_system
@property
def distribution_system(self) -> Union[None, DistributionSystem]:
"""
Get distribution system
:return: DistributionSystem
"""
return self._distribution_system
@property
def emission_system(self) -> Union[None, EmissionSystem]:
"""
Get emission system
:return: EmissionSystem
"""
return self._emission_system

View File

@ -11,7 +11,7 @@ from typing import Union
class GenerationSystem:
def __init__(self, system_type, fuel_type, source_types, heat_efficiency, cooling_efficiency, electricity_efficiency,
source_temperature, source_mass_flow, storage_capacity, auxiliary_equipment):
source_temperature, source_mass_flow, storage, auxiliary_equipment):
self._type = system_type
self._fuel_type = fuel_type
@ -21,7 +21,7 @@ class GenerationSystem:
self._electricity_efficiency = electricity_efficiency
self._source_temperature = source_temperature
self._source_mass_flow = source_mass_flow
self._storage_capacity = storage_capacity
self._storage = storage
self._auxiliary_equipment = auxiliary_equipment
@property
@ -89,12 +89,12 @@ class GenerationSystem:
return self._source_mass_flow
@property
def storage_capacity(self):
def storage(self):
"""
Get storage_capacity in J
:return: float
Get boolean storage exists
:return: bool
"""
return self._storage_capacity
return self._storage
@property
def auxiliary_equipment(self) -> Union[None, GenerationSystem]:

View File

@ -8,50 +8,127 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
import xmltodict
from hub.catalog_factories.catalog import Catalog
from hub.catalog_factories.data_models.energy_systems.archetype import Archetype
from hub.catalog_factories.data_models.energy_systems.equipment import Equipment
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.distribution_system import DistributionSystem
from hub.catalog_factories.data_models.energy_systems.archetype import Archetype
class MontrealCustomCatalog(Catalog):
def __init__(self, path):
path = str(path / 'montreal_custom_systems.xml')
with open(path) as xml:
self._archetypes = xmltodict.parse(xml.read(), force_list='archetype')
self._archetypes = xmltodict.parse(xml.read(), force_list=('equipment', 'system', 'demand', 'equipment_id'))
self._lod = float(self._archetypes['catalog']['@lod'])
self._catalog_equipments = self._load_equipments()
self._catalog_archetypes = self._load_archetypes()
# store the full catalog data model in self._content
self._content = Content(self._load_archetypes())
self._content = Content(self._catalog_archetypes,
self._catalog_equipments)
def _load_equipments(self):
_catalog_equipments = []
equipments = self._archetypes['catalog']['equipments']['equipment']
for equipment in equipments:
equipment_id = float(equipment['@id'])
equipment_type = equipment['@type']
fuel_type = equipment['@fuel_type']
name = equipment['name']
demands = equipment['demands']['demand']
heating_efficiency = None
if 'heating_efficiency' in equipment:
heating_efficiency = float(equipment['heating_efficiency'])
cooling_efficiency = None
if 'cooling_efficiency' in equipment:
cooling_efficiency = float(equipment['cooling_efficiency'])
electricity_efficiency = None
if 'electricity_efficiency' in equipment:
electricity_efficiency = float(equipment['electricity_efficiency'])
distribution_heat_losses = None
if 'distribution_heat_losses' in equipment:
distribution_heat_losses = float(equipment['distribution_heat_losses']['#text']) / 100
distribution_consumption = None
if 'distribution_consumption' in equipment:
distribution_consumption = float(equipment['distribution_consumption']['#text']) / 100
storage = eval(equipment['storage'].capitalize())
generation_system = GenerationSystem(equipment_type,
fuel_type,
None,
heating_efficiency,
cooling_efficiency,
electricity_efficiency,
None,
None,
storage,
None)
distribution_system = DistributionSystem(None,
None,
distribution_consumption,
distribution_heat_losses)
_catalog_equipments.append(Equipment(self._lod,
equipment_id,
name,
demands,
generation_system,
distribution_system,
None))
return _catalog_equipments
def _load_archetypes(self):
_catalog_archetypes = []
archetypes = self._archetypes['archetypes']['archetype']
for archetype in archetypes:
name = archetype['@name']
lod = float(archetype['@lod'])
demand_types = archetype['@demands']
_catalog_archetypes.append(Archetype(lod,
name,
demand_types,
generation_system,
distribution_system,
emission_system))
systems = self._archetypes['catalog']['systems']['system']
for system in systems:
name = system['@name']
system_equipments = system['equipments']['equipment_id']
_equipments = []
for system_equipment in system_equipments:
for equipment in self._catalog_equipments:
if int(equipment.id) == int(system_equipment):
_equipments.append(equipment)
_catalog_archetypes.append(Archetype(self._lod, name, _equipments))
return _catalog_archetypes
def names(self, category=None):
"""
Get the catalog elements names
:parm: for energy systems catalog category filter does nothing as there is only one category (archetypes)
:parm: optional category filter
"""
_names = {'archetypes': []}
for archetype in self._content.archetypes:
_names['archetypes'].append(archetype.name)
if category is None:
_names = {'archetypes': [], 'equipments': []}
for archetype in self._content.archetypes:
_names['archetypes'].append(archetype.name)
for equipment in self._content.equipments:
_names['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() == 'equipments':
for equipment in self._content.equipments:
_names[category].append(equipment.name)
else:
raise ValueError(f'Unknown category [{category}]')
return _names
def entries(self, category=None):
"""
Get the catalog elements
:parm: for energy systems catalog category filter does nothing as there is only one category (archetypes)
:parm: optional category filter
"""
return self._content
if category is None:
return self._content
else:
if category.lower() == 'archetypes':
return self._content.archetypes
elif category.lower() == 'equipments':
return self._content.equipments
else:
raise ValueError(f'Unknown category [{category}]')
def get_entry(self, name):
"""
@ -61,4 +138,7 @@ class MontrealCustomCatalog(Catalog):
for entry in self._content.archetypes:
if entry.name.lower() == name.lower():
return entry
for entry in self._content.equipments:
if entry.name.lower() == name.lower():
return entry
raise IndexError(f"{name} doesn't exists in the catalog")

View File

@ -30,7 +30,7 @@
</demands>
<heating_efficiency>0.85</heating_efficiency>
<distribution_heat_losses units="%">25</distribution_heat_losses>
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
<distribution_consumption units="%">100000</distribution_consumption>
<storage>false</storage>
</equipment>
<equipment id="4" type="furnace" fuel_type="electricity">
@ -41,7 +41,7 @@
</demands>
<heating_efficiency>1</heating_efficiency>
<distribution_heat_losses units="%">25</distribution_heat_losses>
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
<distribution_consumption units="%">100000</distribution_consumption>
<storage>false</storage>
</equipment>
<equipment id="5" type="baseboard" fuel_type="gas">
@ -73,7 +73,7 @@
</demands>
<cooling_efficiency>3.23</cooling_efficiency>
<distribution_heat_losses units="%">0</distribution_heat_losses>
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
<distribution_consumption units="%">100000</distribution_consumption>
<storage>false</storage>
</equipment>
<equipment id="8" type="cooler" fuel_type="electricity">
@ -93,7 +93,7 @@
</demands>
<cooling_efficiency>3.23</cooling_efficiency>
<distribution_heat_losses units="%">0</distribution_heat_losses>
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
<distribution_consumption units="%">100000</distribution_consumption>
<storage>false</storage>
</equipment>
<equipment id="10" type="electricity generator" fuel_type="renewable">
@ -214,7 +214,7 @@
<equipment_id>8</equipment_id>
</equipments>
</system>
<system name="system 6] electricity pv">
<system name="system 6 electricity pv">
<equipments>
<equipment_id>6</equipment_id>
<equipment_id>8</equipment_id>

View File

@ -0,0 +1,30 @@
"""
TestSystemsCatalog
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 unittest import TestCase
from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory
class TestSystemsCatalog(TestCase):
def test_montreal_custom_catalog(self):
catalog = EnergySystemsCatalogFactory('montreal_custom').catalog
catalog_categories = catalog.names()
archetypes = catalog.names('archetypes')
self.assertEqual(18, len(archetypes['archetypes']))
equipments = catalog.names('equipments')
self.assertEqual(10, len(equipments['equipments']))
with self.assertRaises(ValueError):
catalog.names('unknown')
# retrieving all the entries should not raise any exceptions
for category in catalog_categories:
for value in catalog_categories[category]:
catalog.get_entry(value)
with self.assertRaises(IndexError):
catalog.get_entry('unknown')