Source code for qpdk.simulation.layout

"""Neutral geometry preparation shared by the AEDT and COMSOL exporters.

This module is pure gdsfactory geometry: it turns a QPDK mask into the physical
metal a field solver actually sees. It has no PyAEDT, MPh, or COMSOL imports so
both exporters can depend on it.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

import gdsfactory as gf

from qpdk.tech import LAYER
from qpdk.utils import (
    add_margin_to_layer,
    apply_additive_metals,
    invert_mask_polarity,
    remove_metadata_layers,
)

if TYPE_CHECKING:
    from gdsfactory.component import Component


[docs] def prepare_metal_layout( component: Component, margin_draw: float = 0.0, margin_etch: float = 0.0, *, name: str | None = None, ) -> Component: """Fold a QPDK mask into positive metal geometry for a field solver. Applies the additive metals to the etch layer, inverts the mask polarity around the component bounding box, grows the ground by ``margin_draw``, drops the etch layers, and re-adds the original ports. Args: component: The component to prepare. margin_draw: Margin in µm added to the M1/M2 draw layers. margin_etch: Margin in µm added to the M1/M2 etch layers before inversion. name: Name for the initial preparation cell. Defaults to ``f"{component.name}_metal"``. Returns: A copy of the component prepared for simulation. """ c = gf.Component(name=name or f"{component.name}_metal") c << component.copy() if margin_etch > 0.0: c = add_margin_to_layer( c, layer_margins=[ (LAYER.M1_ETCH, margin_etch), (LAYER.M2_ETCH, margin_etch), ], ) c = apply_additive_metals(c) c = invert_mask_polarity(c) if margin_draw > 0.0: c = add_margin_to_layer( c, layer_margins=[ (LAYER.M1_DRAW, margin_draw), (LAYER.M2_DRAW, margin_draw), ], ) c = c.remove_layers(layer for layer in LAYER if str(layer).endswith("_ETCH")) # type: ignore[attr-defined] c = remove_metadata_layers(c) c.add_ports(component.ports) return c