diff --git a/hub/city_model_structure/energy_systems/generic_generation_system.py b/hub/city_model_structure/energy_systems/generic_generation_system.py index f5737fee..f068eba9 100644 --- a/hub/city_model_structure/energy_systems/generic_generation_system.py +++ b/hub/city_model_structure/energy_systems/generic_generation_system.py @@ -1,12 +1,14 @@ """ -Generic energy generation system definition +Energy System catalog heat 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 +Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca +Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ from __future__ import annotations from typing import Union +from hub.city_model_structure.energy_systems.performance_curve import PerformanceCurves class GenericGenerationSystem: @@ -36,6 +38,12 @@ class GenericGenerationSystem: self._cooling_output_curve = None self._cooling_fuel_consumption_curve = None self._cooling_efficiency_curve = None + self._heat_output_curve = None + self._heat_fuel_consumption_curve = None + self._heat_efficiency_curve = None + self._cooling_output_curve = None + self._cooling_fuel_consumption_curve = None + self._cooling_efficiency_curve = None @property def type(self): @@ -229,13 +237,6 @@ class GenericGenerationSystem: """ self._supply_medium = value - # self._heat_output_curve = None - # self._heat_fuel_consumption_curve = None - # self._heat_efficiency_curve = None - # self._cooling_output_curve = None - # self._cooling_fuel_consumption_curve = None - # self._cooling_efficiency_curve = None - @property def maximum_heat_supply_temperature(self): """ @@ -299,3 +300,99 @@ class GenericGenerationSystem: :param value: float """ self._minimum_cooling_supply_temperature = value + + @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 + + @heat_output_curve.setter + def heat_output_curve(self, value): + """ + Set the heat output curve of the heat generation device + :return: PerformanceCurve + """ + self._heat_output_curve = value + + @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 + + @heat_fuel_consumption_curve.setter + def heat_fuel_consumption_curve(self, value): + """ + Set the heating fuel consumption curve of the heat generation device + :return: PerformanceCurve + """ + self._heat_fuel_consumption_curve = value + + @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 + + @heat_efficiency_curve.setter + def heat_efficiency_curve(self, value): + """ + Set the heating efficiency curve of the heat generation device + :return: PerformanceCurve + """ + self._heat_efficiency_curve = value + + @property + def cooling_output_curve(self) -> Union[None, PerformanceCurves]: + """ + Get the cooling output curve of the heat generation device + :return: PerformanceCurve + """ + return self._cooling_output_curve + + @cooling_output_curve.setter + def cooling_output_curve(self, value): + """ + Set the cooling output curve of the heat generation device + :return: PerformanceCurve + """ + self._cooling_output_curve = value + + @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 + + @cooling_fuel_consumption_curve.setter + def cooling_fuel_consumption_curve(self, value): + """ + Set the heating fuel consumption curve of the heat generation device + :return: PerformanceCurve + """ + self._cooling_fuel_consumption_curve = value + + @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 + + @cooling_efficiency_curve.setter + def cooling_efficiency_curve(self, value): + """ + Set the heating efficiency curve of the heat generation device + :return: PerformanceCurve + """ + self._cooling_efficiency_curve = value diff --git a/hub/city_model_structure/energy_systems/performance_curve.py b/hub/city_model_structure/energy_systems/performance_curve.py new file mode 100644 index 00000000..4aaaef1f --- /dev/null +++ b/hub/city_model_structure/energy_systems/performance_curve.py @@ -0,0 +1,105 @@ +""" +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): + self._curve_type = None + self._dependant_variable = None + self._parameters = None + self._coefficients = None + + @property + def curve_type(self): + """ + Get 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 + + @curve_type.setter + def curve_type(self, value): + """ + Set 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 + """ + self._curve_type = value + + @property + def dependant_variable(self): + """ + Get 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 + + @dependant_variable.setter + def dependant_variable(self, value): + """ + Set 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) + """ + self._dependant_variable = value + + @property + def parameters(self): + """ + Get the list of parameters involved in fitting process as ['x', 'z'] (e.g. [source temperature, supply temperature] + in COP= *source temperature**2 + b*source temperature + c*source temperature*supply temperature + + d*supply temperature + e*supply temperature**2 + f) + :return: string + """ + return self._parameters + + @parameters.setter + def parameters(self, value): + """ + Set the list of parameters involved in fitting process as ['x', 'z'] (e.g. [source temperature, supply temperature] + in COP= *source temperature**2 + b*source temperature + c*source temperature*supply temperature + + d*supply temperature + e*supply temperature**2 + f) + :return: string + """ + self._parameters = value + + @property + def coefficients(self): + """ + Get the coefficients of the functions as list of ['a', 'b', 'c', 'd', 'e', 'f'] + :return: [coefficients] + """ + return self._coefficients + + @coefficients.setter + def coefficients(self, value): + """ + Set the coefficients of the functions as list of ['a', 'b', 'c', 'd', 'e', 'f'] + :return: [coefficients] + """ + self._coefficients = value + + diff --git a/hub/helpers/data/north_america_demand_type_to_hub_energy_demand_type.py b/hub/helpers/data/north_america_demand_type_to_hub_energy_demand_type.py new file mode 100644 index 00000000..b616e4f8 --- /dev/null +++ b/hub/helpers/data/north_america_demand_type_to_hub_energy_demand_type.py @@ -0,0 +1,28 @@ +""" +Dictionaries module for Montreal system catalog demand types to hub energy demand types +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2023 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" + +import hub.helpers.constants as cte + + +class NorthAmericaDemandTypeToHubEnergyDemandType: + """ + Montreal demand type to hub energy demand type + """ + def __init__(self): + self._dictionary = {'heating': cte.HEATING, + 'cooling': cte.COOLING, + 'domestic_hot_water': cte.DOMESTIC_HOT_WATER, + 'electricity': cte.ELECTRICITY, + } + + @property + def dictionary(self) -> dict: + """ + Get the dictionary + :return: {} + """ + return self._dictionary diff --git a/hub/helpers/dictionaries.py b/hub/helpers/dictionaries.py index 3fa8125d..efeddd4b 100644 --- a/hub/helpers/dictionaries.py +++ b/hub/helpers/dictionaries.py @@ -21,6 +21,7 @@ from hub.helpers.data.hub_usage_to_eilat_usage import HubUsageToEilatUsage from hub.helpers.data.montreal_system_to_hub_energy_generation_system import MontrealSystemToHubEnergyGenerationSystem from hub.helpers.data.montreal_demand_type_to_hub_energy_demand_type import MontrealDemandTypeToHubEnergyDemandType from hub.helpers.data.hub_function_to_montreal_custom_costs_function import HubFunctionToMontrealCustomCostsFunction +from hub.helpers.data.north_america_demand_type_to_hub_energy_demand_type import NorthAmericaDemandTypeToHubEnergyDemandType class Dictionaries: @@ -128,6 +129,13 @@ class Dictionaries: """ return MontrealDemandTypeToHubEnergyDemandType().dictionary + @property + def north_america_demand_type_to_hub_energy_demand_type(self): + """ + Get montreal custom system demand type to hub energy demand type, transformation dictionary + """ + return NorthAmericaDemandTypeToHubEnergyDemandType().dictionary + @property def hub_function_to_montreal_custom_costs_function(self) -> dict: """ diff --git a/hub/imports/energy_systems/north_america_custom_energy_system_parameters.py b/hub/imports/energy_systems/north_america_custom_energy_system_parameters.py new file mode 100644 index 00000000..e2d244f7 --- /dev/null +++ b/hub/imports/energy_systems/north_america_custom_energy_system_parameters.py @@ -0,0 +1,86 @@ +""" +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 +""" + +import logging +import copy + +from pandas import DataFrame + +from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory +from hub.city_model_structure.energy_systems.generic_distribution_system import GenericDistributionSystem +from hub.city_model_structure.energy_systems.generic_energy_system import GenericEnergySystem +from hub.city_model_structure.energy_systems.generic_generation_system import GenericGenerationSystem +from hub.city_model_structure.energy_systems.energy_system import EnergySystem +from hub.city_model_structure.energy_systems.generation_system import GenerationSystem +from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem +from hub.city_model_structure.energy_systems.emission_system import EmissionSystem +from hub.helpers.dictionaries import Dictionaries + + +class NorthAmericaCustomEnergySystemParameters: + """ + NorthAmericaCustomEnergySystemParameters class + """ + + def __init__(self, city): + self._city = city + + def enrich_buildings(self): + """ + Returns the city with the system parameters assigned to the buildings + :return: + """ + city = self._city + north_america_custom_catalog = EnergySystemsCatalogFactory('north_america').catalog + if city.energy_systems_connection_table is None: + _energy_systems_connection_table = DataFrame(columns=['Energy System Type', 'Building']) + else: + _energy_systems_connection_table = city.energy_systems_connection_table + if city.generic_energy_systems is None: + _generic_energy_systems = {} + else: + _generic_energy_systems = city.generic_energy_systems + for building in city.buildings: + archetype_name = building.energy_systems_archetype_name + try: + archetype = self._search_archetypes(north_america_custom_catalog, archetype_name) + except KeyError: + logging.error('Building %s has unknown energy system archetype for system name %s', building.name, + archetype_name) + continue + _energy_systems_connection_table, _generic_energy_systems = self._create_generic_systems( + archetype, + building, + _energy_systems_connection_table, + _generic_energy_systems + ) + city.energy_systems_connection_table = _energy_systems_connection_table + city.generic_energy_systems = _generic_energy_systems + + @staticmethod + def _search_archetypes(catalog, name): + archetypes = catalog.entries('archetypes') + for building_archetype in archetypes: + if str(name) == str(building_archetype.name): + return building_archetype + raise KeyError('archetype not found') + + @staticmethod + def _create_generic_systems(archetype, building, + _energy_systems_connection_table, _generic_energy_systems): + building_systems = [] + data = [archetype.name, building.name] + _energy_systems_connection_table.loc[len(_energy_systems_connection_table)] = data + for system in archetype.systems: + energy_system = GenericEnergySystem() + _hub_demand_types = [] + for demand_type in system.demand_types: + _hub_demand_types.append(Dictionaries().north_america_demand_type_to_hub_energy_demand_type[demand_type]) + energy_system.name = system.name + energy_system.demand_types = _hub_demand_types + _generation_system = GenericGenerationSystem() diff --git a/hub/imports/energy_systems_factory.py b/hub/imports/energy_systems_factory.py index ca4e7789..c059961c 100644 --- a/hub/imports/energy_systems_factory.py +++ b/hub/imports/energy_systems_factory.py @@ -33,6 +33,15 @@ class EnergySystemsFactory: for building in self._city.buildings: building.level_of_detail.energy_systems = 1 + def _north_america(self): + """ + Enrich the city by using north america custom energy systems catalog information + """ + MontrealCustomEnergySystemParameters(self._city).enrich_buildings() + self._city.level_of_detail.energy_systems = 2 + for building in self._city.buildings: + building.level_of_detail.energy_systems = 2 + def enrich(self): """ Enrich the city given to the class using the class given handler