diff --git a/hub/catalog_factories/data_models/energy_systems/content.py b/hub/catalog_factories/data_models/energy_systems/content.py
index 8042a73d..d3fd9068 100644
--- a/hub/catalog_factories/data_models/energy_systems/content.py
+++ b/hub/catalog_factories/data_models/energy_systems/content.py
@@ -10,12 +10,13 @@ class Content:
"""
Content class
"""
- def __init__(self, archetypes, systems, generations, distributions, emissions):
+ def __init__(self, archetypes, systems, generations, distributions, emissions, storages):
self._archetypes = archetypes
self._systems = systems
self._generations = generations
self._distributions = distributions
self._emissions = emissions
+ self._storages = storages
@property
def archetypes(self):
@@ -52,6 +53,13 @@ class Content:
"""
return self._emissions
+ @property
+ def storage_equipments(self):
+ """
+ All storage equipments in the catalog
+ """
+ return self._storages
+
def to_dictionary(self):
"""Class content to dictionary"""
_archetypes = []
diff --git a/hub/catalog_factories/energy_systems/energy_system_catalog.py b/hub/catalog_factories/energy_systems/energy_system_catalog.py
deleted file mode 100644
index 564b5d40..00000000
--- a/hub/catalog_factories/energy_systems/energy_system_catalog.py
+++ /dev/null
@@ -1,251 +0,0 @@
-"""
-Energy system catalog
-SPDX - License - Identifier: LGPL - 3.0 - or -later
-Copyright © 2022 Concordia CERC group
-Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
-Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
-"""
-
-from ast import literal_eval
-import xmltodict
-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.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.energy_emission_system import EnergyEmissionSystem
-from hub.catalog_factories.data_models.energy_systems.performance_curves import PerformanceCurves
-from hub.catalog_factories.data_models.energy_systems.archetype import Archetype
-
-
-class EnergySystem(Catalog):
- """
- Montreal custom energy systems catalog class
- """
- def __init__(self, path):
- path = str(path / 'montreal_custom_systems.xml')
- with open(path, 'r', encoding='utf-8') as xml:
- self._archetypes = xmltodict.parse(xml.read(), force_list=('system', 'system_cluster', 'equipment',
- 'demand', 'system_id'))
-
- self._lod = float(self._archetypes['catalog']['@lod'])
-
- 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_systems = self._load_systems()
- self._catalog_archetypes = self._load_archetypes()
-
- # store the full catalog data model in self._content
- self._content = Content(self._catalog_archetypes,
- self._catalog_systems,
- self._catalog_generation_equipments,
- self._catalog_distribution_equipments,
- self._catalog_emission_equipments)
-
- def _load_generation_equipments(self):
- _equipments = []
- equipments = self._archetypes['catalog']['generation_equipments']['equipment']
- for equipment in equipments:
- equipment_id = float(equipment['@id'])
- equipment_type = equipment['@type']
- fuel_type = equipment['@fuel_type']
- name = equipment['name']
- 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 'electrical_efficiency' in equipment:
- 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)
-
- _equipments.append(generation_system)
- return _equipments
-
- def _load_distribution_equipments(self):
- _equipments = []
- equipments = self._archetypes['catalog']['distribution_equipments']['equipment']
- for equipment in equipments:
- equipment_id = float(equipment['@id'])
- equipment_type = equipment['@type']
- name = equipment['name']
- distribution_heat_losses = None
- if 'distribution_heat_losses' in equipment:
- distribution_heat_losses = float(equipment['distribution_heat_losses']['#text']) / 100
- distribution_consumption_fix_flow = None
- if 'distribution_consumption_fix_flow' in equipment:
- distribution_consumption_fix_flow = float(equipment['distribution_consumption_fix_flow']['#text']) / 100
- distribution_consumption_variable_flow = None
- if 'distribution_consumption_variable_flow' in equipment:
- distribution_consumption_variable_flow = float(equipment['distribution_consumption_variable_flow']['#text']) / 100
-
- distribution_system = DistributionSystem(equipment_id,
- name,
- equipment_type,
- None,
- distribution_consumption_fix_flow,
- distribution_consumption_variable_flow,
- distribution_heat_losses)
-
- _equipments.append(distribution_system)
- return _equipments
-
- def _load_emission_equipments(self):
- _equipments = []
- equipments = self._archetypes['catalog']['dissipation_equipments']['equipment']
- for equipment in equipments:
- equipment_id = float(equipment['@id'])
- equipment_type = equipment['@type']
- name = equipment['name']
- parasitic_consumption = None
- if 'parasitic_consumption' in equipment:
- parasitic_consumption = float(equipment['parasitic_consumption']['#text']) / 100
-
- emission_system = EnergyEmissionSystem(equipment_id,
- name,
- equipment_type,
- parasitic_consumption)
-
- _equipments.append(emission_system)
- return _equipments
-
- def _load_systems(self):
- _catalog_systems = []
- systems = self._archetypes['catalog']['systems']['system']
- for system in systems:
- system_id = float(system['@id'])
- name = system['name']
- demands = system['demands']['demand']
- generation_equipment = system['equipments']['generation_id']
- _generation_equipment = None
- for equipment_archetype in self._catalog_generation_equipments:
- if int(equipment_archetype.id) == int(generation_equipment):
- _generation_equipment = equipment_archetype
- distribution_equipment = system['equipments']['distribution_id']
- _distribution_equipment = None
- for equipment_archetype in self._catalog_distribution_equipments:
- if int(equipment_archetype.id) == int(distribution_equipment):
- _distribution_equipment = 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,
- system_id,
- name,
- demands,
- _generation_equipment,
- _distribution_equipment,
- _emission_equipment))
- return _catalog_systems
-
- def _load_archetypes(self):
- _catalog_archetypes = []
- system_clusters = self._archetypes['catalog']['system_clusters']['system_cluster']
- for system_cluster in system_clusters:
- name = system_cluster['@name']
- systems = system_cluster['systems']['system_id']
- _systems = []
- for system in systems:
- for system_archetype in self._catalog_systems:
- if int(system_archetype.id) == int(system):
- _systems.append(system_archetype)
- _catalog_archetypes.append(Archetype(self._lod, name, _systems))
- return _catalog_archetypes
-
- def names(self, category=None):
- """
- Get the catalog elements names
- :parm: optional category filter
- """
- if category is None:
- _names = {'archetypes': [], 'systems': [], 'generation_equipments': [], 'distribution_equipments': [],
- 'emission_equipments':[]}
- for archetype in self._content.archetypes:
- _names['archetypes'].append(archetype.manufacturer)
- for system in self._content.systems:
- _names['systems'].append(system.manufacturer)
- for equipment in self._content.generation_equipments:
- _names['generation_equipments'].append(equipment.manufacturer)
- for equipment in self._content.distribution_equipments:
- _names['distribution_equipments'].append(equipment.manufacturer)
- for equipment in self._content.emission_equipments:
- _names['emission_equipments'].append(equipment.manufacturer)
- else:
- _names = {category: []}
- if category.lower() == 'archetypes':
- for archetype in self._content.archetypes:
- _names[category].append(archetype.manufacturer)
- elif category.lower() == 'systems':
- for system in self._content.systems:
- _names[category].append(system.manufacturer)
- elif category.lower() == 'generation_equipments':
- for system in self._content.generation_equipments:
- _names[category].append(system.manufacturer)
- elif category.lower() == 'distribution_equipments':
- for system in self._content.distribution_equipments:
- _names[category].append(system.manufacturer)
- elif category.lower() == 'emission_equipments':
- for system in self._content.emission_equipments:
- _names[category].append(system.manufacturer)
- 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
- if category.lower() == '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):
- """
- Get one catalog element by names
- :parm: entry name
- """
- for entry in self._content.archetypes:
- if entry.manufacturer.lower() == name.lower():
- return entry
- for entry in self._content.systems:
- if entry.manufacturer.lower() == name.lower():
- return entry
- for entry in self._content.generation_equipments:
- if entry.manufacturer.lower() == name.lower():
- return entry
- for entry in self._content.distribution_equipments:
- if entry.manufacturer.lower() == name.lower():
- return entry
- for entry in self._content.emission_equipments:
- if entry.manufacturer.lower() == name.lower():
- return entry
- raise IndexError(f"{name} doesn't exists in the catalog")
diff --git a/hub/catalog_factories/energy_systems/north_america_energy_system_catalog.py b/hub/catalog_factories/energy_systems/north_america_energy_system_catalog.py
new file mode 100644
index 00000000..86d8f215
--- /dev/null
+++ b/hub/catalog_factories/energy_systems/north_america_energy_system_catalog.py
@@ -0,0 +1,109 @@
+"""
+North america energy system catalog
+SPDX - License - Identifier: LGPL - 3.0 - or -later
+Copyright © 2022 Concordia CERC group
+Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
+Code contributors: Saeed Ranjbar saeed.ranjbar@concordia.ca
+"""
+
+from ast import literal_eval
+import xmltodict
+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.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.energy_emission_system import EnergyEmissionSystem
+from hub.catalog_factories.data_models.energy_systems.energy_storage_system import EnergyStorageSystem
+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 NorthAmericaEnergySystemCatalog(Catalog):
+ """
+ North america energy system catalog class
+ """
+ def __init__(self, path):
+ path = str(path / 'Tools4CitiesESMF.xml')
+ with open(path, 'r', encoding='utf-8') as xml:
+ self._archetypes = xmltodict.parse(xml.read())
+# self._systems = self._load_systems()
+# self._generation_components = self._load_generation_components()
+ self._storage_components = self._load_storage_components()
+ print(self._storage_components)
+# self._system_archetypes = self._load_system_archetypes()
+
+ # store the full catalog data model in self._content
+# self._content = Content(self._system_archetypes,
+# self._systems,
+# self._generation_components,
+# None,
+# None,
+# self._storage_components)
+
+ def _load_storage_components(self):
+ storage_components = []
+ components = self._archetypes['encomp:EnergySystemCatalog']['energycomponent']['thermalStorages']
+ for component in components:
+ model_name = component['@modelName']
+ manufacturer = component['@manufacturer']
+ volume = component['@volume']
+ height = component['@height']
+ maximum_operating_temperature = component['@maxTemp']
+ materials = self._load_materials()
+ material_name = component['@insulationMaterial']
+ insulation_material = self._search_material(materials, material_name)
+ material_name = component['@tankMaterial']
+ tank_material = self._search_material(materials, material_name)
+ thickness = float(component['@insulationThickness']) / 100 # from cm to m
+ insulation_layer = Layer(None, 'insulation', insulation_material, thickness)
+ thickness = float(component['@tankThickness']) / 100 # from cm to m
+ tank_layer = Layer(None, 'insulation', tank_material, thickness)
+ # the convention is from outside to inside
+ layers = [insulation_layer, tank_layer]
+ storage_component = EnergyStorageSystem(model_name,
+ manufacturer,
+ 'thermal',
+ volume,
+ None,
+ None,
+ None,
+ None,
+ None,
+ height,
+ layers,
+ maximum_operating_temperature)
+ storage_components.append(storage_component)
+ return storage_components
+
+ def _load_materials(self):
+ materials = []
+ _materials = self._archetypes['encomp:EnergySystemCatalog']['energycomponent']['materials']
+ for _material in _materials:
+ name = _material['@name']
+ thermal_conductivity = _material['@thermalConductivity']
+ material = Material(None,
+ name,
+ None,
+ None,
+ None,
+ False,
+ None,
+ thermal_conductivity,
+ None,
+ None)
+ materials.append(material)
+ return materials
+
+ @staticmethod
+ def _search_material(materials, material_name):
+ _material = None
+ for material in materials:
+ if material.name == material_name:
+ _material = material
+ return _material
+
+ if _material is None:
+ raise ValueError(f'Material not found in catalog [{material_name}]')
diff --git a/hub/catalog_factories/energy_systems_catalog_factory.py b/hub/catalog_factories/energy_systems_catalog_factory.py
index 4b59eeda..6e102bc3 100644
--- a/hub/catalog_factories/energy_systems_catalog_factory.py
+++ b/hub/catalog_factories/energy_systems_catalog_factory.py
@@ -9,6 +9,7 @@ from pathlib import Path
from typing import TypeVar
from hub.catalog_factories.energy_systems.montreal_custom_catalog import MontrealCustomCatalog
+from hub.catalog_factories.energy_systems.north_america_energy_system_catalog import NorthAmericaEnergySystemCatalog
from hub.helpers.utils import validate_import_export_type
Catalog = TypeVar('Catalog')
@@ -32,6 +33,13 @@ class EnergySystemsCatalogFactory:
"""
return MontrealCustomCatalog(self._path)
+ @property
+ def _north_america(self):
+ """
+ Retrieve North American catalog
+ """
+ return NorthAmericaEnergySystemCatalog(self._path)
+
@property
def catalog(self) -> Catalog:
"""
diff --git a/hub/data/energy_systems/Tools4CitiesESMF.encomp b/hub/data/energy_systems/Tools4CitiesESMF.xml
similarity index 88%
rename from hub/data/energy_systems/Tools4CitiesESMF.encomp
rename to hub/data/energy_systems/Tools4CitiesESMF.xml
index 06c9e622..6ee58c84 100644
--- a/hub/data/energy_systems/Tools4CitiesESMF.encomp
+++ b/hub/data/energy_systems/Tools4CitiesESMF.xml
@@ -23,11 +23,11 @@
-
-
-
-
-
+
+
+
+
+
@@ -37,7 +37,7 @@
-
+
diff --git a/tests/test_systems_catalog.py b/tests/test_systems_catalog.py
index f17038cb..48446d50 100644
--- a/tests/test_systems_catalog.py
+++ b/tests/test_systems_catalog.py
@@ -35,3 +35,5 @@ class TestSystemsCatalog(TestCase):
with self.assertRaises(IndexError):
catalog.get_entry('unknown')
+ def test_north_america_systems_catalog(self):
+ catalog = EnergySystemsCatalogFactory('north_america').catalog