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