diff --git a/component/adapter.py b/component/adapter.py index 34b290a52bca49a48925b59dc613b094cb095ae0..e5975c7cc619bc47c6c3bf8148e4d65fe36509e9 100644 --- a/component/adapter.py +++ b/component/adapter.py @@ -59,6 +59,7 @@ class AssetAdapter(AbstractComponent): super().__init__( name=name, + kind=ComponentKind.ASSET_ADAPTER, commodity_1=self.grid.commodity, commodity_2=None, commodity_3=self.grid.commodity, @@ -69,14 +70,8 @@ class AssetAdapter(AbstractComponent): self.commodity = self.grid.commodity - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - match_kind = kind == ComponentKind.ALL or kind == ComponentKind.ASSET_ADAPTER - match_commodity = ( - commodity == ComponentCommodity.ALL - or commodity == self.commodity - or (isinstance(commodity, list) and self.commodity in commodity) - ) - return match_kind and match_commodity + def commodities(self): + return [self.commodity] def iter_component_parts(self): yield ComponentPart.NONE_STATE @@ -137,6 +132,7 @@ class MemberAdapter(AbstractComponent): super().__init__( name=name, + kind=ComponentKind.MEMBER_ADAPTER, commodity_1=self.grid.commodity, commodity_2=None, commodity_3=self.grid.commodity, @@ -147,14 +143,8 @@ class MemberAdapter(AbstractComponent): self.commodity = self.grid.commodity - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - match_kind = kind == ComponentKind.ALL or kind == ComponentKind.ASSET_ADAPTER - match_commodity = ( - commodity == ComponentCommodity.ALL - or commodity == self.commodity - or (isinstance(commodity, list) and self.commodity in commodity) - ) - return match_kind and match_commodity + def commodities(self): + return [self.commodity] def iter_component_parts(self): yield ComponentPart.NONE_STATE diff --git a/component/core.py b/component/core.py index 9c508ab51a17317eb602924f144796dcdde3628c..49b3c26827d6c3026d99f58b7a0209496e183923 100644 --- a/component/core.py +++ b/component/core.py @@ -55,9 +55,9 @@ class ComponentCommodity(Enum): class ComponentPart(Enum): - ALL = (1,) - DESIGN = (2,) - STATE = (3,) + ALL = 1 + DESIGN = 2 + STATE = 3 NONE_STATE = 4 @@ -78,6 +78,7 @@ class ComponentPartPattern: kind=ComponentKind.ALL, type="all", commodity=ComponentCommodity.ALL, + name="all", part=ComponentPart.ALL, ): if isinstance(kind, List) and ComponentKind.ALL in kind: @@ -95,46 +96,55 @@ class ComponentPartPattern: else: self.commodity = commodity + if isinstance(name, List) and "all" in name: + self.name = "all" + else: + self.name = name + if isinstance(part, List) and ComponentPart.ALL in part: self.part = ComponentPart.ALL else: self.part = part - def match( - self, - kind=ComponentKind.ALL, - type="all", - commodity=ComponentCommodity.ALL, - part=ComponentPart.ALL, - ): - if kind != ComponentKind.ALL and self.kind != ComponentKind.ALL: + def match(self, component, part): + if self.kind != ComponentKind.ALL: if isinstance(self.kind, List): - if kind not in self.kind: + if component.kind not in self.kind: return False else: - if kind != self.kind: + if component.kind != self.kind: return False - if type != "all" and self.type != "all": + if self.type != "all": if isinstance(self.type, List): - if type not in self.type: + if component.__class__.__name__ not in self.type: return False else: - if type != self.type: + if component.__class__.__name__ != self.type: return False - if ( - commodity != ComponentCommodity.ALL - and self.commodity != ComponentCommodity.ALL - ): + if self.commodity != ComponentCommodity.ALL: if isinstance(self.commodity, List): - if commodity not in self.commodity: + if all( + commodity not in self.commodity + for commodity in component.commodities() + ): + return False + else: + if all( + commodity != self.commodity for commodity in component.commodities() + ): + return False + + if self.name != "all": + if isinstance(self.name, List): + if component.name not in self.name: return False else: - if commodity != self.commodity: + if component.name != self.name: return False - if part != ComponentPart.ALL and self.part != ComponentPart.ALL: + if self.part != ComponentPart.ALL: if isinstance(self.part, List): if part not in self.part: return False @@ -144,23 +154,6 @@ class ComponentPartPattern: return True - @staticmethod - def match_simple( - component_kind, - component_type, - component_commodities, - pattern_kind=ComponentKind.ALL, - pattern_type="all", - pattern_commodity=ComponentCommodity.ALL, - ): - match_kind = pattern_kind == ComponentKind.ALL or pattern_kind == component_kind - match_type = pattern_type == "all" or pattern_type == component_type - match_commodity = ( - pattern_commodity == ComponentCommodity.ALL - or pattern_commodity in component_commodities - ) - return match_kind and match_type and match_commodity - class ComponentCapacity(Enum): NONE = 1 @@ -172,6 +165,7 @@ class AbstractComponent: def __init__( self, name, + kind, commodity_1, commodity_2, commodity_3, @@ -180,6 +174,7 @@ class AbstractComponent: capacity, ): self.name = name + self.kind = kind self.input_commodity_1 = commodity_1 self.input_commodity_2 = commodity_2 self.output_commodity_1 = commodity_3 @@ -241,6 +236,9 @@ class AbstractComponent: self.output_commodity_2, ) + def commodities(self): + return [] + def iter_component_parts(self): if False: yield @@ -435,6 +433,7 @@ class BaseBusBar(AbstractComponent): def __init__(self, name, commodity): super().__init__( name=name, + kind=ComponentKind.BUSBAR, commodity_1=commodity, commodity_2=None, commodity_3=commodity, @@ -445,14 +444,8 @@ class BaseBusBar(AbstractComponent): self.commodity = commodity - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - return ComponentPartPattern.match_simple( - ComponentKind.BUSBAR, - self.__class__.__name__, - [self.commodity], - pattern_kind=kind, - pattern_commodity=commodity, - ) + def commodities(self): + return [self.commodity] def iter_component_parts(self): yield ComponentPart.NONE_STATE @@ -486,6 +479,7 @@ class BaseComponent(AbstractComponent): ): super().__init__( name=name, + kind=ComponentKind.BASE, commodity_1=commodity_1, commodity_2=commodity_2, commodity_3=commodity_3, @@ -496,6 +490,11 @@ class BaseComponent(AbstractComponent): self._setup_conversions(configuration) + self.commodities_list = [] + for commodity in [commodity_1, commodity_2, commodity_3, commodity_4]: + if commodity is not None and commodity not in self.commodities_list: + self.commodities_list.append(commodity) + def _setup_conversions(self, configuration): self._load_conversions(configuration) @@ -523,19 +522,8 @@ class BaseComponent(AbstractComponent): def _load_model(self, configuration, model): configuration["efficiency"] = model["efficiency"] - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - return ComponentPartPattern.match_simple( - ComponentKind.BASE, - self.__class__.__name__, - [ - self.input_commodity_1, - self.input_commodity_2, - self.output_commodity_1, - self.output_commodity_2, - ], - pattern_kind=kind, - pattern_commodity=commodity, - ) + def commodities(self): + return self.commodities_list def iter_component_parts(self): yield ComponentPart.DESIGN @@ -655,6 +643,7 @@ class BaseConsumption(AbstractComponent): def __init__(self, name, commodity, configuration): super().__init__( name=name, + kind=ComponentKind.CONSUMPTION, commodity_1=commodity, commodity_2=None, commodity_3=None, @@ -667,14 +656,8 @@ class BaseConsumption(AbstractComponent): self.consumption = configuration["consumption"] - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - return ComponentPartPattern.match_simple( - ComponentKind.CONSUMPTION, - self.__class__.__name__, - [self.commodity], - pattern_kind=kind, - pattern_commodity=commodity, - ) + def commodities(self): + return [self.commodity] def iter_component_parts(self): yield ComponentPart.NONE_STATE @@ -703,6 +686,7 @@ class BaseGeneration(AbstractComponent): def __init__(self, name, commodity, configuration): super().__init__( name=name, + kind=ComponentKind.GENERATION, commodity_1=None, commodity_2=None, commodity_3=commodity, @@ -715,14 +699,8 @@ class BaseGeneration(AbstractComponent): self.generation = configuration["generation"] - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - return ComponentPartPattern.match_simple( - ComponentKind.GENERATION, - self.__class__.__name__, - [self.commodity], - pattern_kind=kind, - pattern_commodity=commodity, - ) + def commodities(self): + return [self.commodity] def iter_component_parts(self): yield ComponentPart.NONE_STATE @@ -751,6 +729,7 @@ class BaseGrid(AbstractComponent): def __init__(self, name, commodity, configuration): super().__init__( name=name, + kind=ComponentKind.GRID, commodity_1=commodity, commodity_2=None, commodity_3=commodity, @@ -766,14 +745,8 @@ class BaseGrid(AbstractComponent): self.peak_power_cost_ = configuration.get("peak_power_cost", 0) self.co2_emissions_ = configuration.get("co2_emissions", 0) - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - return ComponentPartPattern.match_simple( - ComponentKind.GRID, - self.__class__.__name__, - [self.commodity], - pattern_kind=kind, - pattern_commodity=commodity, - ) + def commodities(self): + return [self.commodity] def iter_component_parts(self): if self.capacity is not None: @@ -869,6 +842,7 @@ class BaseStorage(AbstractComponent): def __init__(self, name, commodity, configuration): super().__init__( name=name, + kind=ComponentKind.STORAGE, commodity_1=commodity, commodity_2=None, commodity_3=commodity, @@ -890,14 +864,8 @@ class BaseStorage(AbstractComponent): self.e2p_out = model["e2p_out"] self.self_discharging_loss = model["self_discharging_loss"] - def match(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - return ComponentPartPattern.match_simple( - ComponentKind.STORAGE, - self.__class__.__name__, - [self.commodity], - pattern_kind=kind, - pattern_commodity=commodity, - ) + def commodities(self): + return [self.commodity] def iter_component_parts(self): yield ComponentPart.DESIGN diff --git a/topology.py b/topology.py index 9138672e77a7964c29897c080a19f40433044cc2..4c09bf57bc228033d5494f631438e97c704b7775 100644 --- a/topology.py +++ b/topology.py @@ -35,12 +35,12 @@ from Model_Library.component.core import ( ComponentCommodity, ComponentKind, ComponentPart, + ComponentPartPattern, VariableLink, ) from Model_Library.component.adapter import AssetLink, MemberLink from Model_Library.optimization_model import ( EntityResult, - OptimizationBlock, OptimizationModel, VariableKind, ) @@ -266,12 +266,33 @@ class Topology: self._results = dict() self._last_result_key = None - def get_components(self, kind=ComponentKind.ALL, commodity=ComponentCommodity.ALL): - return ( - component - for component in self._components.values() - if component.match(kind=kind, commodity=commodity) + def iter_components( + self, + kind=ComponentKind.ALL, + type="all", + commodity=ComponentCommodity.ALL, + name="all", + ): + pattern = ComponentPartPattern( + kind, type, commodity, name, part=ComponentPart.ALL ) + for component in self._components.values(): + if pattern.match(component, ComponentPart.ALL): + yield component + + def iter_component_parts( + self, + kind=ComponentKind.ALL, + type="all", + commodity=ComponentCommodity.ALL, + name="all", + part=ComponentPart.ALL, + ): + pattern = ComponentPartPattern(kind, type, commodity, name, part) + for component in self._components.values(): + for part in component.iter_component_parts(): + if pattern.match(component, ComponentPart.ALL): + yield (component, part) def optimize( self, key, architecture, component_iden_strs, strategy, sub_configurations