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
|
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.equipment import Equipment
|
||||||
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 Archetype:
|
class Archetype:
|
||||||
def __init__(self,
|
def __init__(self, lod, name, equipments):
|
||||||
lod,
|
|
||||||
name,
|
|
||||||
demand_types,
|
|
||||||
generation_system,
|
|
||||||
distribution_system,
|
|
||||||
emission_system):
|
|
||||||
|
|
||||||
self._lod = lod
|
self._lod = lod
|
||||||
self._name = name
|
self._name = name
|
||||||
self._demand_types = demand_types
|
self._equipments = equipments
|
||||||
self._generation_system = generation_system
|
|
||||||
self._distribution_system = distribution_system
|
|
||||||
self._emission_system = emission_system
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lod(self):
|
def lod(self):
|
||||||
|
@ -45,33 +34,9 @@ class Archetype:
|
||||||
return f'{self._name}_lod{self._lod}'
|
return f'{self._name}_lod{self._lod}'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def demand_types(self):
|
def equipments(self) -> List[Equipment]:
|
||||||
"""
|
"""
|
||||||
Get demand able to cover from [heating, cooling, domestic_hot_water, electricity]
|
Get list of equipments that compose the total energy system
|
||||||
:return: [string]
|
:return: [Equipment]
|
||||||
"""
|
"""
|
||||||
return self._demand_types
|
return self._equipments
|
||||||
|
|
||||||
@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
|
|
||||||
|
|
|
@ -7,12 +7,20 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
|
||||||
|
|
||||||
class Content:
|
class Content:
|
||||||
def __init__(self, archetypes):
|
def __init__(self, archetypes, equipments):
|
||||||
self._archetypes = archetypes
|
self._archetypes = archetypes
|
||||||
|
self._equipments = equipments
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def archetypes(self):
|
def archetypes(self):
|
||||||
"""
|
"""
|
||||||
All archetypes in the catalog
|
All archetype systems in the catalog
|
||||||
"""
|
"""
|
||||||
return self._archetypes
|
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:
|
class GenerationSystem:
|
||||||
def __init__(self, system_type, fuel_type, source_types, heat_efficiency, cooling_efficiency, electricity_efficiency,
|
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._type = system_type
|
||||||
self._fuel_type = fuel_type
|
self._fuel_type = fuel_type
|
||||||
|
@ -21,7 +21,7 @@ class GenerationSystem:
|
||||||
self._electricity_efficiency = electricity_efficiency
|
self._electricity_efficiency = electricity_efficiency
|
||||||
self._source_temperature = source_temperature
|
self._source_temperature = source_temperature
|
||||||
self._source_mass_flow = source_mass_flow
|
self._source_mass_flow = source_mass_flow
|
||||||
self._storage_capacity = storage_capacity
|
self._storage = storage
|
||||||
self._auxiliary_equipment = auxiliary_equipment
|
self._auxiliary_equipment = auxiliary_equipment
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -89,12 +89,12 @@ class GenerationSystem:
|
||||||
return self._source_mass_flow
|
return self._source_mass_flow
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def storage_capacity(self):
|
def storage(self):
|
||||||
"""
|
"""
|
||||||
Get storage_capacity in J
|
Get boolean storage exists
|
||||||
:return: float
|
:return: bool
|
||||||
"""
|
"""
|
||||||
return self._storage_capacity
|
return self._storage
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def auxiliary_equipment(self) -> Union[None, GenerationSystem]:
|
def auxiliary_equipment(self) -> Union[None, GenerationSystem]:
|
||||||
|
|
|
@ -8,50 +8,127 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
from hub.catalog_factories.catalog import Catalog
|
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.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):
|
class MontrealCustomCatalog(Catalog):
|
||||||
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) as 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
|
# 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):
|
def _load_archetypes(self):
|
||||||
_catalog_archetypes = []
|
_catalog_archetypes = []
|
||||||
archetypes = self._archetypes['archetypes']['archetype']
|
systems = self._archetypes['catalog']['systems']['system']
|
||||||
for archetype in archetypes:
|
for system in systems:
|
||||||
name = archetype['@name']
|
name = system['@name']
|
||||||
lod = float(archetype['@lod'])
|
system_equipments = system['equipments']['equipment_id']
|
||||||
demand_types = archetype['@demands']
|
_equipments = []
|
||||||
_catalog_archetypes.append(Archetype(lod,
|
for system_equipment in system_equipments:
|
||||||
name,
|
for equipment in self._catalog_equipments:
|
||||||
demand_types,
|
if int(equipment.id) == int(system_equipment):
|
||||||
generation_system,
|
_equipments.append(equipment)
|
||||||
distribution_system,
|
_catalog_archetypes.append(Archetype(self._lod, name, _equipments))
|
||||||
emission_system))
|
|
||||||
return _catalog_archetypes
|
return _catalog_archetypes
|
||||||
|
|
||||||
def names(self, category=None):
|
def names(self, category=None):
|
||||||
"""
|
"""
|
||||||
Get the catalog elements names
|
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': []}
|
if category is None:
|
||||||
|
_names = {'archetypes': [], 'equipments': []}
|
||||||
for archetype in self._content.archetypes:
|
for archetype in self._content.archetypes:
|
||||||
_names['archetypes'].append(archetype.name)
|
_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
|
return _names
|
||||||
|
|
||||||
def entries(self, category=None):
|
def entries(self, category=None):
|
||||||
"""
|
"""
|
||||||
Get the catalog elements
|
Get the catalog elements
|
||||||
:parm: for energy systems catalog category filter does nothing as there is only one category (archetypes)
|
:parm: optional category filter
|
||||||
"""
|
"""
|
||||||
|
if category is None:
|
||||||
return self._content
|
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):
|
def get_entry(self, name):
|
||||||
"""
|
"""
|
||||||
|
@ -61,4 +138,7 @@ class MontrealCustomCatalog(Catalog):
|
||||||
for entry in self._content.archetypes:
|
for entry in self._content.archetypes:
|
||||||
if entry.name.lower() == name.lower():
|
if entry.name.lower() == name.lower():
|
||||||
return entry
|
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")
|
raise IndexError(f"{name} doesn't exists in the catalog")
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
</demands>
|
</demands>
|
||||||
<heating_efficiency>0.85</heating_efficiency>
|
<heating_efficiency>0.85</heating_efficiency>
|
||||||
<distribution_heat_losses units="%">25</distribution_heat_losses>
|
<distribution_heat_losses units="%">25</distribution_heat_losses>
|
||||||
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
|
<distribution_consumption units="%">100000</distribution_consumption>
|
||||||
<storage>false</storage>
|
<storage>false</storage>
|
||||||
</equipment>
|
</equipment>
|
||||||
<equipment id="4" type="furnace" fuel_type="electricity">
|
<equipment id="4" type="furnace" fuel_type="electricity">
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
</demands>
|
</demands>
|
||||||
<heating_efficiency>1</heating_efficiency>
|
<heating_efficiency>1</heating_efficiency>
|
||||||
<distribution_heat_losses units="%">25</distribution_heat_losses>
|
<distribution_heat_losses units="%">25</distribution_heat_losses>
|
||||||
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
|
<distribution_consumption units="%">100000</distribution_consumption>
|
||||||
<storage>false</storage>
|
<storage>false</storage>
|
||||||
</equipment>
|
</equipment>
|
||||||
<equipment id="5" type="baseboard" fuel_type="gas">
|
<equipment id="5" type="baseboard" fuel_type="gas">
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
</demands>
|
</demands>
|
||||||
<cooling_efficiency>3.23</cooling_efficiency>
|
<cooling_efficiency>3.23</cooling_efficiency>
|
||||||
<distribution_heat_losses units="%">0</distribution_heat_losses>
|
<distribution_heat_losses units="%">0</distribution_heat_losses>
|
||||||
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
|
<distribution_consumption units="%">100000</distribution_consumption>
|
||||||
<storage>false</storage>
|
<storage>false</storage>
|
||||||
</equipment>
|
</equipment>
|
||||||
<equipment id="8" type="cooler" fuel_type="electricity">
|
<equipment id="8" type="cooler" fuel_type="electricity">
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
</demands>
|
</demands>
|
||||||
<cooling_efficiency>3.23</cooling_efficiency>
|
<cooling_efficiency>3.23</cooling_efficiency>
|
||||||
<distribution_heat_losses units="%">0</distribution_heat_losses>
|
<distribution_heat_losses units="%">0</distribution_heat_losses>
|
||||||
<distribution_consumption units="%">NEEDED VALUE</distribution_consumption>
|
<distribution_consumption units="%">100000</distribution_consumption>
|
||||||
<storage>false</storage>
|
<storage>false</storage>
|
||||||
</equipment>
|
</equipment>
|
||||||
<equipment id="10" type="electricity generator" fuel_type="renewable">
|
<equipment id="10" type="electricity generator" fuel_type="renewable">
|
||||||
|
@ -214,7 +214,7 @@
|
||||||
<equipment_id>8</equipment_id>
|
<equipment_id>8</equipment_id>
|
||||||
</equipments>
|
</equipments>
|
||||||
</system>
|
</system>
|
||||||
<system name="system 6] electricity pv">
|
<system name="system 6 electricity pv">
|
||||||
<equipments>
|
<equipments>
|
||||||
<equipment_id>6</equipment_id>
|
<equipment_id>6</equipment_id>
|
||||||
<equipment_id>8</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