finished system catalog factory
This commit is contained in:
parent
0a96b83c22
commit
3bfb985c04
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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]:
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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>
|
||||
|
|
30
hub/unittests/test_systems_catalog.py
Normal file
30
hub/unittests/test_systems_catalog.py
Normal 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')
|
Loading…
Reference in New Issue
Block a user