Repository: gdsfactory/gdsfactory
Issue: `get_component_with_net_layers` splitting to layers  before component merging

**Describe the bug**
Using the new `get_component_with_net_layers` from #1873, the splitting to layers according to ports occurs before the  components are merged. Consequently, one now gets only the innermost component connected to the ports in the new layers instead of the final merged polygon.

**Expected behavior**
`get_component_with_net_layers` is applied after Component pre-processing to avoid user to manually `union` everything



Changed files:
gdsfactory/simulation/gmsh/xyz_mesh.py, gdsfactory/component.py

diff --git a/gdsfactory/component.py b/gdsfactory/component.py
index 4651a182a..33971b19a 100644
--- a/gdsfactory/component.py
+++ b/gdsfactory/component.py
@@ -2511,6 +2511,7 @@ class Component(_GeometryHelper):
             [xmin - wafer_padding, ymax + wafer_padding],
         ]
         padded_component.add_polygon(points, layer=wafer_layer)
+        padded_component.add_ports(self.get_ports_list())
 
         if layer_stack is None:
             raise ValueError(
diff --git a/gdsfactory/simulation/gmsh/xyz_mesh.py b/gdsfactory/simulation/gmsh/xyz_mesh.py
index 5fe0ef0d8..6b27c9171 100644
--- a/gdsfactory/simulation/gmsh/xyz_mesh.py
+++ b/gdsfactory/simulation/gmsh/xyz_mesh.py
@@ -14,7 +14,8 @@ from gdsfactory.simulation.gmsh.parse_layerstack import (
     list_unique_layerstack_z,
 )
 from gdsfactory.technology import LayerStack, LayerLevel
-from gdsfactory.typings import ComponentOrReference
+from gdsfactory.typings import ComponentOrReference, List
+from gdsfactory.geometry.union import union
 
 from meshwell.prism import Prism
 from meshwell.model import Model
@@ -62,6 +63,8 @@ def xyz_mesh(
     round_tol: int = 3,
     simplify_tol: float = 1e-3,
     n_threads: int = get_number_of_cores(),
+    portnames: List[str] = None,
+    layer_portname_delimiter: str = "#",
 ) -> bool:
     """Full 3D mesh of component.
 
@@ -78,8 +81,22 @@ def xyz_mesh(
         filename: where to save the .msh file
         round_tol: during gds --> mesh conversion cleanup, number of decimal points at which to round the gdsfactory/shapely points before introducing to gmsh
         simplify_tol: during gds --> mesh conversion cleanup, shapely "simplify" tolerance (make it so all points are at least separated by this amount)
+        n_threads: for gmsh parallelization
+        portnames: list or port polygons to converts into new layers (useful for boundary conditions)
+        layer_portname_delimiter: delimiter for the new layername/portname physicals, formatted as {layername}{delimiter}{portname}
     """
+    if portnames:
+        mesh_component = gf.Component()
+        mesh_component << union(component, by_layer=True)
+        mesh_component.add_ports(component.get_ports_list())
+        component = layerstack.get_component_with_net_layers(
+            mesh_component,
+            portnames=portnames,
+            delimiter=layer_portname_delimiter,
+        )
+
     # Fuse and cleanup polygons of same layer in case user overlapped them
+    # TODO: some duplication with union above, although this also does some useful offsetting
     layer_polygons_dict = cleanup_component(
         component, layerstack, round_tol, simplify_tol
     )
@@ -130,6 +147,7 @@ def xyz_mesh(
         global_3D_algorithm=global_3D_algorithm,
         filename=filename,
         verbosity=verbosity,
+        n_threads=n_threads,
     )
 
     return mesh_out
@@ -151,11 +169,6 @@ if __name__ == "__main__":
 
     # Generate a new component and layerstack with new logical layers
     layerstack = get_layer_stack()
-    c = layerstack.get_component_with_net_layers(
-        c,
-        portnames=["r_e2", "l_e4"],
-        delimiter="#",
-    )
 
     # FIXME: .filtered returns all layers
     # filtered_layerstack = layerstack.filtered_from_layerspec(layerspecs=c.get_layers())
@@ -167,12 +180,10 @@ if __name__ == "__main__":
                 "box",
                 "clad",
                 # "metal2",
-                "metal3#l_e4",
                 "heater",
                 "via2",
                 "core",
-                "metal3#r_e2",
-                # "metal3",
+                "metal3",
                 # "via_contact",
                 # "metal1"
             )
@@ -189,4 +200,5 @@ if __name__ == "__main__":
         filename="mesh.msh",
         default_characteristic_length=5,
         verbosity=5,
+        portnames=["r_e2", "l_e4"],
     )