Skip to content

eigenmode

Eigenmode simulation class for resonance/mode finding.

This module provides the EigenmodeSim class for finding resonant frequencies and mode shapes.

Classes:

  • EigenmodeSim –

    Eigenmode simulation for finding resonant frequencies.

EigenmodeSim

Bases: _PalaceSimBase

Eigenmode simulation for finding resonant frequencies.

This class configures and runs eigenmode simulations to find resonant frequencies and mode shapes of structures.

Example

from gsim.palace import EigenmodeSim

sim = EigenmodeSim() sim.set_geometry(component) sim.set_stack() sim.set_airbox(margin_x=120.0, margin_above=120.0, margin_below=20.0) sim.add_port("o1", layer="topmetal2", length=5.0) sim.solver.eigenmode.target = 50e9 sim.set_output_dir("./sim") sim.mesh(preset="default") results = sim.run() # dict[str, Path] print(results["eig.csv"])

Attributes:

Methods:

  • add_cpw_port –

    Add a coplanar waveguide (CPW) port.

  • add_impedance_boundary –

    Add an Impedance boundary on the interface between two dielectric layers.

  • add_pec –

    Add a PEC block between two stack layers.

  • add_port –

    Add a single-element lumped port.

  • add_symmetry_plane –

    Simulate half of a mirror-symmetric structure.

  • add_two_terminal_port –

    Add a two-terminal lumped port for true 1-port S11 simulation.

  • add_wave_port –

    Add a single element wave port.

  • get_status –

    Get the current status of this simulation's cloud job.

  • group_legacy_solver_settings –

    Move legacy constructor arguments into their solver groups.

  • mesh –

    Generate the mesh for Palace simulation.

  • plot_mesh –

    Plot the mesh using PyVista.

  • plot_stack –

    Plot the layer stack visualization.

  • preview –

    Preview the mesh without running simulation.

  • print_mesh_stats –

    Print mesh statistics from the last mesh generation.

  • run –

    Run the eigenmode sim on GDSFactory+ cloud.

  • run_local –

    Run simulation locally using Palace.

  • set_airbox –

    Configure an explicit weak-priority airbox for meshing.

  • set_eigenmode –

    Configure eigenmode simulation.

  • set_geometry –

    Set the gdsfactory component for simulation.

  • set_material –

    Override or add material properties.

  • set_numerical –

    Deprecated alias for set_solver, with the same order-2 defaults.

  • set_output_dir –

    Set the output directory for mesh and config files.

  • set_pn_junction –

    Apply the depletion capacitance of a PN junction between two layers.

  • set_refinement –

    Configure Palace's adaptive mesh refinement (AMR).

  • set_solver –

    Set common solver controls, preserving problem-specific settings.

  • set_stack –

    Configure the layer stack.

  • show_stack –

    Print the layer stack table.

  • start –

    Start cloud execution for this simulation's uploaded job.

  • upload –

    Write the inputs and upload them. Does NOT start execution.

  • validate_config –

    Validate the simulation configuration.

  • validate_mesh –

    Validate the generated mesh and config before cloud submission.

  • wait_for_results –

    Wait for this simulation's cloud job, then download and parse results.

  • write_config –

    Write Palace config.json after mesh generation.

boundary_mode property writable

boundary_mode: BoundaryModeConfig | None

Compatibility alias for solver.boundary_mode (None for other modes).

component property

component: Component | None

Get the current component (for backward compatibility).

driven property writable

driven: DrivenConfig | None

Compatibility alias for solver.driven (None for other modes).

eigenmode property writable

eigenmode: EigenmodeConfig

Deprecated alias for solver.eigenmode, retaining the original type.

electrostatic property writable

electrostatic: ElectrostaticConfig | None

Compatibility alias for solver.electrostatic (None for other modes).

has_mesh property

has_mesh: bool

Whether mesh() has run and left a mesh to read.

mesh_groups property

mesh_groups: dict[str, Any]

Physical groups of the generated mesh, once meshed.

Raises:

mesh_path property

mesh_path: Path

Path of the generated mesh (um), once meshed.

Raises:

numerical property writable

numerical: SolverConfig

Compatibility alias for the common controls in solver.

output_dir property

output_dir: Path | None

Get the current output directory.

add_cpw_port

add_cpw_port(
    name: str,
    *,
    layer: str,
    s_width: float,
    gap_width: float,
    length: float = 2.0,
    offset: float | None = None,
    impedance: float = 50.0,
    excited: bool = True,
) -> None

Add a coplanar waveguide (CPW) port.

CPW ports consist of two elements (upper and lower gaps) that are excited with opposite E-field directions to create the CPW mode.

Place a single gdsfactory port at the center of the signal conductor. The two gap element surfaces are computed from s_width and gap_width.

Parameters:

  • name (str) –

    Port name (must match a component port at the signal center)

  • layer (str) –

    Target conductor layer (e.g., "topmetal2")

  • s_width (float) –

    Width of the signal (center) conductor (um)

  • gap_width (float) –

    Width of each gap between signal and ground (um)

  • length (float, default: 2.0 ) –

    Port extent along direction (um)

  • offset (float | None, default: None ) –

    Shift the port inward along the waveguide (um). Positive moves away from the boundary, into the conductor. Defaults to length/2 (port flush with conductor edge).

  • impedance (float, default: 50.0 ) –

    Port impedance (Ohms)

  • excited (bool, default: True ) –

    Whether this port is excited

Example

sim.add_cpw_port( ... "left", layer="topmetal2", s_width=20, gap_width=15, length=5.0 ... )

add_impedance_boundary

add_impedance_boundary(
    layer_a: str,
    layer_b: str,
    *,
    capacitance: float | None = None,
    resistance: float | None = None,
    inductance: float | None = None,
    name: str | None = None,
) -> None

Add an Impedance boundary on the interface between two dielectric layers.

The capacitance, resistance, and inductance values are absolute and are divided by the interface curve length internally to produce the per-unit-length Cs, Rs, Ls values expected by Palace.

Parameters:

  • layer_a (str) –

    First dielectric layer name.

  • layer_b (str) –

    Second dielectric layer name.

  • capacitance (float | None, default: None ) –

    Absolute capacitance [F].

  • resistance (float | None, default: None ) –

    Absolute resistance [Ohm].

  • inductance (float | None, default: None ) –

    Absolute inductance [H].

  • name (str | None, default: None ) –

    Optional display name.

add_pec

add_pec(*, gds_layer: tuple[int, int], from_layer: str, to_layer: str) -> None

Add a PEC block between two stack layers.

The PEC block is a user-drawn polygon on a GDS layer that gets extruded between from_layer.zmin and to_layer.zmax and treated as a PEC boundary. This is a common practice in commercial EM solvers for connecting ground planes across metal layers at port boundaries.

Parameters:

  • gds_layer (tuple[int, int]) –

    GDS layer tuple where the PEC polygon is drawn.

  • from_layer (str) –

    Stack layer name — extrusion starts at this layer's zmin.

  • to_layer (str) –

    Stack layer name — extrusion ends at this layer's zmax.

Example

sim.add_pec( ... gds_layer=(65000, 0), from_layer="metal1", to_layer="topmetal2" ... )

add_port

add_port(
    name: str,
    *,
    layer: str | None = None,
    from_layer: str | None = None,
    to_layer: str | None = None,
    length: float | None = None,
    offset: float = 0.0,
    impedance: float = 50.0,
    resistance: float | None = None,
    inductance: float | None = None,
    capacitance: float | None = None,
    excited: bool = True,
    geometry: Literal["inplane", "gap", "interlayer", "via"] = "inplane",
) -> None

Add a single-element lumped port.

Parameters:

  • name (str) –

    Port name (must match component port name)

  • layer (str | None, default: None ) –

    Target layer for inplane ports

  • from_layer (str | None, default: None ) –

    First conductor layer for interlayer ports

  • to_layer (str | None, default: None ) –

    Second conductor layer for interlayer ports

  • length (float | None, default: None ) –

    Port extent along direction (um)

  • offset (float, default: 0.0 ) –

    Shift the port inward along the waveguide (um). Positive moves away from the boundary, into the conductor.

  • impedance (float, default: 50.0 ) –

    Port impedance (Ohms)

  • resistance (float | None, default: None ) –

    Series resistance (Ohms)

  • inductance (float | None, default: None ) –

    Series inductance (H)

  • capacitance (float | None, default: None ) –

    Shunt capacitance (F)

  • excited (bool, default: True ) –

    Whether this port is excited

  • geometry (Literal['inplane', 'gap', 'interlayer', 'via'], default: 'inplane' ) –

    "inplane", "gap", or "interlayer". Gap ports are vertical sheets with GDS width spanning the gap along orientation, centered in the gap and extending through the conductor layer thickness. Gap ports currently require cardinal orientations; omit length. "interlayer" creates a Z-directed sheet between two layers. "via" is a deprecated alias for "interlayer". Use :meth:add_cpw_port for the "cpw" lumped-port geometry.

Example

sim.add_port("o1", layer="topmetal2", length=5.0) sim.add_port( ... "feed", ... from_layer="metal1", ... to_layer="topmetal2", ... geometry="interlayer", ... )

add_symmetry_plane

add_symmetry_plane(
    axis: Literal["x", "y"] = "y",
    position: float = 0.0,
    kind: Literal["pec", "pmc"] = "pmc",
    keep: Literal["positive", "negative"] = "positive",
    *,
    verify_symmetry: bool = True,
) -> None

Simulate half of a mirror-symmetric structure.

A PMC plane selects the even (common) mode, a PEC plane the odd (differential) mode. Only one plane is supported, and only for driven and eigenmode simulations.

Parameters:

  • axis (Literal['x', 'y'], default: 'y' ) –

    Axis normal to the plane.

  • position (float, default: 0.0 ) –

    Plane position along axis in um, aligned to the owning layout's database grid. Checked during geometry extraction.

  • kind (Literal['pec', 'pmc'], default: 'pmc' ) –

    "pmc" (even mode) or "pec" (odd mode).

  • keep (Literal['positive', 'negative'], default: 'positive' ) –

    Side of the plane that is simulated.

  • verify_symmetry (bool, default: True ) –

    Check that the layout is mirror-symmetric.

Raises:

Example

sim.add_symmetry_plane(axis="y", position=0.0, kind="pec")

add_two_terminal_port

add_two_terminal_port(
    plus_port: str,
    minus_port: str,
    *,
    layer: str,
    impedance: float = 50.0,
    excited: bool = True,
) -> None

Add a two-terminal lumped port for true 1-port S11 simulation.

Combines two GDS ports into a single Palace LumpedPort with two EDGE-geometry elements (vertical surfaces spanning the conductor thickness). No artificial reference layer is needed — P1 is the excitation and P2 is the reference, both on the same metal layer.

Parameters:

  • plus_port (str) –

    GDS port name for the + (excitation) terminal

  • minus_port (str) –

    GDS port name for the - (reference) terminal

  • layer (str) –

    Conductor layer containing both terminals (e.g., "metal1")

  • impedance (float, default: 50.0 ) –

    Port impedance in Ohms (default: 50)

  • excited (bool, default: True ) –

    Whether this port is excited (default: True)

Example

sim.add_two_terminal_port("P1", "P2", layer="metal1", excited=True)

add_wave_port

add_wave_port(
    name: str,
    *,
    layer: str | None = None,
    z_margin: float = 0.0,
    lateral_margin: float = 0.0,
    max_size: bool = False,
    mode: int = 1,
    excited: bool = True,
    offset: float = 0.0,
    eigensolver_type: Literal["Default", "SLEPc", "ARPACK"] | None = None,
    eigensolver_tol: float | None = None,
    eigensolver_ksp_tol: float | None = None,
    eigensolver_max_size: int | None = None,
    eigensolver_verbose: int | None = None,
) -> None

Add a single element wave port.

Parameters:

  • name (str) –

    Port name (must match a component port at the signal center)

  • layer (str | None, default: None ) –

    Target conductor layer (e.g., "topmetal2")

  • z_margin (float, default: 0.0 ) –

    Margin in z direction

  • lateral_margin (float, default: 0.0 ) –

    Margin in x/y directions Ignores lateral margin and port_width.

  • max_size (bool, default: False ) –

    When True, automatically set z_margin and lateral_margin to fill the full simulation domain boundary on that side. Overrides z_margin and lateral_margin values.

  • mode (int, default: 1 ) –

    Mode number to excite.

  • excited (bool, default: True ) –

    Whether this port is excited

  • offset (float, default: 0.0 ) –

    Offset distance used for scattering parameter de-embedding.

  • eigensolver_type (Literal['Default', 'SLEPc', 'ARPACK'] | None, default: None ) –

    Palace SolverType for this port's 2D mode eigenproblem ("Default", "SLEPc" or "ARPACK"). None uses Palace's own default.

  • eigensolver_tol (float | None, default: None ) –

    Palace EigenTol for this port's mode solve. None uses Palace's own default.

  • eigensolver_ksp_tol (float | None, default: None ) –

    Palace KSPTol for this port's mode solve. None uses Palace's own default.

  • eigensolver_max_size (int | None, default: None ) –

    Palace MaxSize (eigensolver subspace dimension) for this port's mode solve - unrelated to max_size above, which sizes geometry. None lets Palace pick its own default.

  • eigensolver_verbose (int | None, default: None ) –

    Palace Verbose level for this port's mode solve. None uses Palace's own default.

Example

sim.add_wave_port( ... "w1", ... layer="topmetal2", ... max_size=True, ... mode=1, ... excited=True, ... offset=0.0, ... )

get_status

get_status() -> str

Get the current status of this simulation's cloud job.

Returns:

  • str –

    Status string ("created", "queued", "running",

  • str –

    "completed", "failed").

Raises:

  • ValueError –

    If no job has been submitted yet.

group_legacy_solver_settings classmethod

group_legacy_solver_settings(values: Any) -> Any

Move legacy constructor arguments into their solver groups.

mesh

mesh(
    *,
    preset: Literal["coarse", "default", "fine"] | None = None,
    refined_mesh_size: float | None = None,
    max_mesh_size: float | None = None,
    margin: float | None = None,
    margin_x: float | None = None,
    margin_y: float | None = None,
    z_above: float | None = None,
    z_below: float | None = None,
    airbox_margin: float | None = None,
    fmax: float | None = None,
    planar_conductors: bool | None = None,
    show_gui: bool = False,
    model_name: str = "palace",
    verbose: bool = True,
    verbosity: int = 0,
    auto_size: bool = False,
    cells_per_feature: int = 2,
    periodic_axis: str | None = None,
    decimate_tolerance: float | None = None,
    merge_via_distance: float | None = None,
    curve_fit_mode: Literal["line", "spline", "bspline"] | None = None,
    curve_fit_layers: list[str] | None = None,
    curve_fit_tolerance_um: float | None = None,
    curve_fit_min_points: int | None = None,
    curve_fit_corner_angle_deg: float | None = None,
    high_order_elements: bool | None = None,
    high_order_order: int | None = None,
    high_order_optimize: bool | None = None,
    refinement_boxes: list[tuple[float, float, float, float, float]] | None = None,
    algorithm_3d: Literal["delaunay", "hxt"] | None = None,
    threads: int | None = None,
    surface_threads: int | None = None,
) -> SimulationResult

Generate the mesh for Palace simulation.

Only generates the mesh file (palace.msh). Config is generated separately with write_config().

Requires set_output_dir() to be called first.

Parameters:

  • preset (Literal['coarse', 'default', 'fine'] | None, default: None ) –

    Mesh quality preset ("coarse", "default", "fine")

  • refined_mesh_size (float | None, default: None ) –

    Mesh size near conductors (um), overrides preset

  • max_mesh_size (float | None, default: None ) –

    Max mesh size in air/dielectric (um), overrides preset

  • margin (float | None, default: None ) –

    XY margin around design (um), overrides preset

  • margin_x (float | None, default: None ) –

    X-axis margin (um). Overrides margin for X.

  • margin_y (float | None, default: None ) –

    Y-axis margin (um). Overrides margin for Y.

  • z_above (float | None, default: None ) –

    Airbox extension above stack top (um).

  • z_below (float | None, default: None ) –

    Airbox extension below stack bottom (um).

  • airbox_margin (float | None, default: None ) –

    Deprecated. Use set_airbox().

  • fmax (float | None, default: None ) –

    Max frequency for mesh sizing (Hz), overrides preset

  • planar_conductors (bool | None, default: None ) –

    Treat conductors as 2D PEC surfaces

  • show_gui (bool, default: False ) –

    Show gmsh GUI during meshing

  • model_name (str, default: 'palace' ) –

    Base name for output files: <model_name>.msh and output/<model_name>. A plain name, without path separators

  • verbose (bool, default: True ) –

    Print progress messages

  • verbosity (int, default: 0 ) –

    Gmsh OCC verbosity level (0=silent, 1-99=increasing)

  • auto_size (bool, default: False ) –

    If True, scale refined_mesh_size down to the smallest conductor feature / cells_per_feature. Off by default so presets use their literal refined_mesh_size. Explicit refined_mesh_size overrides always bypass auto-sizing.

  • cells_per_feature (int, default: 2 ) –

    Target cells across the smallest conductor feature for auto-sizing and resolution warnings. Default 2.

  • periodic_axis (str | None, default: None ) –

    Optional periodic axis ("x" or "y") for periodic meshing constraints on opposite domain sides.

  • decimate_tolerance (float | None, default: None ) –

    Relative tolerance for polygon decimation (None = no decimation; typical 0.001-0.01). Reduces vertex count on curved geometry before meshing.

  • merge_via_distance (float | None, default: None ) –

    Max gap (um) between nearby via polygons to merge before extrusion. Pass 0 to disable merging (keep each via as a separate volume). Defaults to the preset's value (typically 2.0 um). Merging fills the gaps between the vias, so a dense via array can grow to several times its drawn area; a warning is logged when the area grows by more than 5%.

  • curve_fit_mode (Literal['line', 'spline', 'bspline'] | None, default: None ) –

    Patterned dielectric boundary mode (line/spline/bspline).

  • curve_fit_layers (list[str] | None, default: None ) –

    Layer names where spline fitting is applied.

  • curve_fit_tolerance_um (float | None, default: None ) –

    Point merge tolerance before fitting.

  • curve_fit_min_points (int | None, default: None ) –

    Min contour points required to fit curves.

  • curve_fit_corner_angle_deg (float | None, default: None ) –

    Turn-angle threshold used to split sharp corners from smooth curve-fit segments.

  • high_order_elements (bool | None, default: None ) –

    Enable high-order geometric mesh elements.

  • high_order_order (int | None, default: None ) –

    Polynomial order for high-order elements.

  • high_order_optimize (bool | None, default: None ) –

    Run gmsh high-order optimization after meshing.

  • refinement_boxes (list[tuple[float, float, float, float, float]] | None, default: None ) –

    Native-2D cross-section meshes only: boxes held to an element size, each (h_min, h_max, z_min, z_max, size) in um. Refinement lines size the elements on them only; a box holds the size over an area.

  • algorithm_3d (Literal['delaunay', 'hxt'] | None, default: None ) –

    Gmsh 3D meshing algorithm, "delaunay" or "hxt".

  • threads (int | None, default: None ) –

    Threads for 3D meshing (see MeshConfig).

  • surface_threads (int | None, default: None ) –

    Threads for 1D and 2D meshing. Above 1 the mesh differs from run to run.

Returns:

Raises:

  • ValueError –

    If output_dir not set, configuration is invalid, or model_name is not a plain file name

Example

sim.set_output_dir("./sim") result = sim.mesh(preset="fine", planar_conductors=True) print(f"Mesh saved to: {result.mesh_path}")

plot_mesh

plot_mesh(
    output: str | Path | None = None,
    show_groups: list[str] | None = None,
    interactive: bool | None = None,
    style: Literal["wireframe", "solid"] = "wireframe",
    transparent_groups: list[str] | None = None,
) -> None

Plot the mesh using PyVista.

Requires mesh() to be called first.

Parameters:

  • output (str | Path | None, default: None ) –

    Output PNG path (only used for static rendering).

  • show_groups (list[str] | None, default: None ) –

    List of group name patterns to show (None = all). Example: ["metal", "P"] to show metal layers and ports.

  • interactive (bool | None, default: None ) –

    If True, force an interactive 3D viewer (a widget on the shared trame server in a notebook, or a blocking window otherwise). If False, save a static PNG. If None (default), follow the session flag from gsim.viz.set_interactive_mode — off by default, so plots render statically until enabled.

  • style (Literal['wireframe', 'solid'], default: 'wireframe' ) –

    "wireframe" (edges only) or "solid" (coloured surfaces per physical group).

  • transparent_groups (list[str] | None, default: None ) –

    Group names rendered at low opacity in solid mode. Ignored in wireframe mode.

Raises:

  • ValueError –

    If output_dir not set or mesh file doesn't exist

Example

sim.mesh(preset="default") sim.plot_mesh(show_groups=["metal", "P"]) sim.plot_mesh(style="solid", transparent_groups=["Absorbing_boundary"])

plot_stack

plot_stack() -> None

Plot the layer stack visualization.

Example

sim.plot_stack()

preview

preview(
    *,
    preset: Literal["coarse", "default", "fine"] | None = None,
    refined_mesh_size: float | None = None,
    max_mesh_size: float | None = None,
    margin: float | None = None,
    margin_x: float | None = None,
    margin_y: float | None = None,
    z_above: float | None = None,
    z_below: float | None = None,
    airbox_margin: float | None = None,
    fmax: float | None = None,
    planar_conductors: bool | None = None,
    show_gui: bool = True,
    auto_size: bool = False,
    cells_per_feature: int = 2,
    curve_fit_mode: Literal["line", "spline", "bspline"] | None = None,
    curve_fit_layers: list[str] | None = None,
    curve_fit_tolerance_um: float | None = None,
    curve_fit_min_points: int | None = None,
    curve_fit_corner_angle_deg: float | None = None,
    high_order_elements: bool | None = None,
    high_order_order: int | None = None,
    high_order_optimize: bool | None = None,
    algorithm_3d: Literal["delaunay", "hxt"] | None = None,
    threads: int | None = None,
    surface_threads: int | None = None,
    decimate_tolerance: float | None = None,
) -> None

Preview the mesh without running simulation.

Opens the gmsh GUI to visualize the mesh interactively.

Parameters:

  • preset (Literal['coarse', 'default', 'fine'] | None, default: None ) –

    Mesh quality preset ("coarse", "default", "fine")

  • refined_mesh_size (float | None, default: None ) –

    Mesh size near conductors (um)

  • max_mesh_size (float | None, default: None ) –

    Max mesh size in air/dielectric (um)

  • margin (float | None, default: None ) –

    XY margin around design (um)

  • margin_x (float | None, default: None ) –

    X-axis margin (um). Overrides margin for X.

  • margin_y (float | None, default: None ) –

    Y-axis margin (um). Overrides margin for Y.

  • z_above (float | None, default: None ) –

    Airbox extension above stack top (um).

  • z_below (float | None, default: None ) –

    Airbox extension below stack bottom (um).

  • airbox_margin (float | None, default: None ) –

    Deprecated. Use set_airbox().

  • fmax (float | None, default: None ) –

    Max frequency for mesh sizing (Hz)

  • planar_conductors (bool | None, default: None ) –

    Treat conductors as 2D PEC surfaces

  • show_gui (bool, default: True ) –

    Show gmsh GUI for interactive preview

  • auto_size (bool, default: False ) –

    If True, scale refined_mesh_size down to the smallest conductor feature / cells_per_feature. Off by default. Explicit refined_mesh_size overrides bypass auto-sizing.

  • cells_per_feature (int, default: 2 ) –

    Target cells across the smallest conductor feature for auto-sizing and resolution warnings. Default 2.

  • curve_fit_mode (Literal['line', 'spline', 'bspline'] | None, default: None ) –

    Patterned dielectric boundary mode (line/spline/bspline).

  • curve_fit_layers (list[str] | None, default: None ) –

    Layer names where spline fitting is applied.

  • curve_fit_tolerance_um (float | None, default: None ) –

    Point merge tolerance before fitting.

  • curve_fit_min_points (int | None, default: None ) –

    Min contour points required to fit curves.

  • curve_fit_corner_angle_deg (float | None, default: None ) –

    Turn-angle threshold used to split sharp corners from smooth curve-fit segments.

  • high_order_elements (bool | None, default: None ) –

    Enable high-order geometric mesh elements.

  • high_order_order (int | None, default: None ) –

    Polynomial order for high-order elements.

  • high_order_optimize (bool | None, default: None ) –

    Run gmsh high-order optimization after meshing.

  • algorithm_3d (Literal['delaunay', 'hxt'] | None, default: None ) –

    Gmsh 3D meshing algorithm, "delaunay" or "hxt".

  • threads (int | None, default: None ) –

    Threads for 3D meshing (see MeshConfig).

  • surface_threads (int | None, default: None ) –

    Threads for 1D and 2D meshing. Above 1 the mesh differs from run to run.

  • decimate_tolerance (float | None, default: None ) –

    Relative tolerance for polygon decimation (None = no decimation; typical 0.001-0.01).

Example

sim.preview(preset="fine", planar_conductors=True, show_gui=True)

print_mesh_stats

print_mesh_stats() -> None

Print mesh statistics from the last mesh generation.

Reports node/element counts and input-mesh Field DOF estimates at the configured field order, before Palace preprocessing and refinement.

run

run(
    parent_dir: str | Path | None = None,
    *,
    verbose: Literal["quiet", "status", "full"] = "status",
    wait: bool = True,
    check_cache: bool = False,
    poll_interval: float = 5.0,
) -> dict[str, Path] | str

Run the eigenmode sim on GDSFactory+ cloud.

Thin wrapper over :meth:~gsim.common.cloud.CloudJobMixin.run that narrows the return type: an eigenmode run returns a dict[str, Path] of output files keyed by name (e.g. "eig.csv"), or the job_id string when wait=False.

run_local

run_local(
    *,
    palace_sif_path: str | Path | None = None,
    palace_executable: str | Path | None = None,
    use_apptainer: bool = False,
    num_processes: int | None = None,
    num_threads: int | None = None,
    verbose: bool = True,
    remedy: str | None = None,
) -> SParams | PalaceTextResults | dict[str, Path]

Run simulation locally using Palace.

Requires mesh() and write_config() to be called first. Supports both Apptainer and direct Palace installation.

Parameters:

  • palace_sif_path (str | Path | None, default: None ) –

    Path to Palace Apptainer SIF file. Only used when use_apptainer=True and no executable is selected. If None, tries PALACE_SIF, then local defaults: ./Palace.sif, ./palace.sif, ./bin/Palace.sif, ./bin/palace.sif.

  • palace_executable (str | Path | None, default: None ) –

    Path to Palace executable. If provided, runs Palace directly and overrides use_apptainer. If None, tries PALACE_EXECUTABLE, then ./bin/palace, then palace on PATH.

  • use_apptainer (bool, default: False ) –

    If True (default), run via Apptainer using SIF file. If False, run Palace executable directly. Ignored when palace_executable is explicitly provided.

  • num_processes (int | None, default: None ) –

    Number of MPI processes. If None (default), a problem-size-aware default is chosen: 2D mode-analysis runs use a single MPI rank (SuperLU_DIST's 2D processor grid does not scale on small 2D problems and can effectively hang at 8-16 ranks), while 3D runs are capped to a few ranks by the estimated unknown count. An explicit value is always respected.

  • num_threads (int | None, default: None ) –

    Number of OpenMP threads to use for OpenMP builds. When running with a single MPI rank and num_threads is omitted, defaults to the number of physical CPU cores so shared-memory parallelism is used.

  • verbose (bool, default: True ) –

    Print progress messages and stream Palace output in real time

  • remedy (str | None, default: None ) –

    A second way out of a dead Palace runtime, named at the end of the abort report beyond pointing PALACE_BIN somewhere else. A caller with no other way out gives none.

Returns:

Raises:

  • ValueError –

    If output_dir not set or Palace not configured

  • FileNotFoundError –

    If mesh, config, or Palace not found

  • RuntimeError –

    If the simulation fails. A binary that died on a signal is reported through :func:gsim.palace.runtime.local_abort_report, which says whether the runtime or the model is at fault.

Example

Using Apptainer (default)

import os os.environ["PALACE_SIF"] = "/path/to/Palace.sif" results = sim.run_local()

Using Apptainer with explicit path

results = sim.run_local(palace_sif_path="/path/to/Palace.sif")

Auto-discovery with no options:

prefers local ./bin/palace if present,

otherwise falls back to local SIF or PATH executable

results = sim.run_local()

Using direct Palace with custom executable path

results = sim.run_local(palace_executable="/usr/local/bin/palace")

Using a locally built Palace binary

results = sim.run_local(palace_executable="./bin/palace")

For DrivenSim: results is SParams -> results.s21.db

For eigen / electrostatic: results is dict[str, Path]

set_airbox

set_airbox(
    *,
    margin_x: float | None = None,
    margin_y: float | None = None,
    z_above: float | None = None,
    z_below: float | None = None,
    material: str = "air",
) -> None

Configure an explicit weak-priority airbox for meshing.

This helper centralizes airbox controls that were previously split across mesh margin arguments and stack air thickness parameters. The resulting airbox is created as a dedicated dielectric volume with the weakest boolean-priority in mesh construction.

material sets the material name of the padded background region. It defaults to "air" (eps=1). For a photonic cross-section with a uniform cladding, pass e.g. "sio2" so the region around the device is filled with SiO2 instead of air. The material must be resolvable in the stack's materials (or the built-in database); its permittivity is evaluated at the simulation frequency (e.g. Sellmeier SiO2 at 1550 nm).

Note: the background material currently applies to the native-2D BoundaryMode domain (the region outside the stack/cladding); the 3D airbox region remains air.

Parameters:

  • margin_x (float | None, default: None ) –

    Airbox x-margin around the design (um). Defaults to 0.0 when omitted.

  • margin_y (float | None, default: None ) –

    Airbox y-margin around the design (um). Defaults to 0.0 when omitted.

  • z_above (float | None, default: None ) –

    Airbox extension above the stack top (um). Defaults to 0.0 when omitted.

  • z_below (float | None, default: None ) –

    Airbox extension below the stack bottom (um). Defaults to 0.0 when omitted.

  • material (str, default: 'air' ) –

    Background material name for the padded region (default "air").

set_eigenmode

set_eigenmode(
    *,
    num_modes: int = 10,
    target: float | None = None,
    tolerance: float = 1e-09,
    save: int = 0,
    floquet: bool = False,
    phi_target: float = pi / 2,
    periodic_length: float | None = None,
    n_eff_guess: float | None = None,
) -> None

Configure eigenmode simulation.

Parameters:

  • num_modes (int, default: 10 ) –

    Number of modes to find

  • target (float | None, default: None ) –

    Positive target frequency in Hz for mode search. Required before meshing or exporting the configuration.

  • tolerance (float, default: 1e-09 ) –

    Eigenvalue solver tolerance

  • save (int, default: 0 ) –

    Number of eigenmodes to save as ParaView fields (0 = disabled)

  • floquet (bool, default: False ) –

    Enable Floquet periodic boundary setup in config generation (requires mesh(periodic_axis=...)).

  • phi_target (float, default: pi / 2 ) –

    Signed Bloch phase per cell in radians (Floquet only). Zero and ±pi are valid. The wave vector is phase / mesh period. Palace applies E(receiver) = exp(-i * phi_target) * E(donor).

  • periodic_length (float | None, default: None ) –

    Optional expected period in mesh units (um). Must match the measured mesh translation, including domain padding. Omit to use the measured period directly.

  • n_eff_guess (float | None, default: None ) –

    Deprecated compatibility argument, ignored with a warning. Target frequency controls the eigenvalue search, not the wave vector.

Example

sim.set_eigenmode(num_modes=10, target=50e9)

set_geometry

set_geometry(component: Component) -> None

Set the gdsfactory component for simulation.

Parameters:

  • component (Component) –

    gdsfactory Component to simulate

Example

sim.set_geometry(my_component)

set_material

set_material(
    name: str,
    *,
    material_type: Literal["conductor", "dielectric", "semiconductor"] | None = None,
    conductivity: float | None = None,
    permittivity: float | None = None,
    loss_tangent: float | None = None,
) -> None

Override or add material properties.

Parameters:

  • name (str) –

    Material name

  • material_type (Literal['conductor', 'dielectric', 'semiconductor'] | None, default: None ) –

    Material type (conductor, dielectric, semiconductor)

  • conductivity (float | None, default: None ) –

    Conductivity in S/m (for conductors)

  • permittivity (float | None, default: None ) –

    Relative permittivity (for dielectrics)

  • loss_tangent (float | None, default: None ) –

    Dielectric loss tangent

Example

sim.set_material( ... "aluminum", material_type="conductor", conductivity=3.8e7 ... ) sim.set_material("sio2", material_type="dielectric", permittivity=3.9)

set_numerical

set_numerical(
    *,
    order: int | _UnsetOrder = DEFAULT,
    tolerance: float | None = None,
    max_iterations: int = max_iterations,
    solver_type: Literal["Default", "SuperLU", "STRUMPACK", "MUMPS"] = solver_type,
    preconditioner: Literal["Default", "AMS", "BoomerAMG"] = preconditioner,
    device: Literal["CPU", "GPU"] = device,
    mg_max_levels: int = mg_max_levels,
    pc_mat_real: bool = pc_mat_real,
    complex_coarse_solve: bool = complex_coarse_solve,
) -> None

Deprecated alias for set_solver, with the same order-2 defaults.

Omitting order emits a visible migration warning because this setter previously defaulted to order 1. Pass order=1 to retain that behavior.

set_output_dir

set_output_dir(path: str | Path) -> None

Set the output directory for mesh and config files.

Parameters:

  • path (str | Path) –

    Directory path for output files

Example

sim.set_output_dir("./palace-sim")

set_pn_junction

set_pn_junction(
    junction: Any,
    *,
    layer_p: str,
    layer_n: str,
    length_um: float,
    height_um: float,
    name: str | None = None,
) -> float

Apply the depletion capacitance of a PN junction between two layers.

Capacitance-mode modelling of a PN junction: the depletion width W is computed from the doping concentrations and bias point via :class:gsim.common.stack.pn_junction.PNJunctionConfig (Sze, Physics of Semiconductor Devices, ch. 2), converted to an absolute parallel-plate capacitance C = eps_s * A / W, and applied as a lumped Impedance boundary on the shared P/N interface.

Use this when the depletion strip is too thin to resolve on the mesh; for a well-resolved depletion region prefer drawing it as dielectric geometry of its own instead.

Parameters:

  • junction (Any) –

    PNJunctionConfig or its dict form (doping concentrations, bias, temperature, permittivity).

  • layer_p (str) –

    Name of the P-doped layer.

  • layer_n (str) –

    Name of the N-doped layer.

  • length_um (float) –

    Device length along the propagation direction (um).

  • height_um (float) –

    Junction z-extent (um), e.g. the rib height.

  • name (str | None, default: None ) –

    Optional display name for the boundary.

Returns:

  • float –

    The absolute capacitance applied [F].

Example

sim.set_pn_junction( ... {"na_cm3": 1e19, "nd_cm3": 1e19}, ... layer_p="p_rib", ... layer_n="n_rib", ... length_um=10.0, ... height_um=0.22, ... )

set_refinement

set_refinement(
    *,
    max_its: int = 0,
    tol: float = 0.01,
    uniform_levels: int = 0,
    max_dofs: int | None = None,
    update_fraction: float | None = None,
    nonconformal: bool | None = None,
    max_nc_levels: int | None = None,
    save_adapt_iterations: bool | None = None,
    save_adapt_mesh: bool | None = None,
) -> None

Configure Palace's adaptive mesh refinement (AMR).

Palace refines the elements that carry most of its estimated error and re-solves, until the error norm falls below tol, max_its passes have run, or the problem reaches max_dofs degrees of freedom. See :class:~gsim.palace.models.RefinementConfig.

Parameters:

  • max_its (int, default: 0 ) –

    Maximum number of AMR passes. 0 disables AMR.

  • tol (float, default: 0.01 ) –

    Stop refining when the estimated error norm falls below this.

  • uniform_levels (int, default: 0 ) –

    Uniform refinement levels applied to the input mesh before solving.

  • max_dofs (int | None, default: None ) –

    Maximum degrees of freedom. None means no limit.

  • update_fraction (float | None, default: None ) –

    Dörfler marking fraction, between 0 and 1.

  • nonconformal (bool | None, default: None ) –

    Refine with hanging nodes instead of conformally.

  • max_nc_levels (int | None, default: None ) –

    Maximum nonconformal refinement levels; 0 means no limit.

  • save_adapt_iterations (bool | None, default: None ) –

    Keep the output of every pass in an iterationX subdirectory.

  • save_adapt_mesh (bool | None, default: None ) –

    Save the final adapted mesh.

Example

sim.set_refinement(max_its=5, tol=1e-3, max_dofs=2_000_000)

set_solver

set_solver(
    *,
    order: int = order,
    tolerance: float | None = None,
    max_iterations: int = max_iterations,
    solver_type: Literal["Default", "SuperLU", "STRUMPACK", "MUMPS"] = solver_type,
    preconditioner: Literal["Default", "AMS", "BoomerAMG"] = preconditioner,
    device: Literal["CPU", "GPU"] = device,
    mg_max_levels: int = mg_max_levels,
    pc_mat_real: bool = pc_mat_real,
    complex_coarse_solve: bool = complex_coarse_solve,
) -> None

Set common solver controls, preserving problem-specific settings.

Defaults match the simulation constructor: order 2, complex MUMPS multigrid, 400 iterations, and CPU. Linear tolerance is 1e-9 for eigenmode simulations and 1e-6 otherwise. Set individual controls directly through sim.solver to retain other common values.

Example

sim.set_solver(order=1, tolerance=1e-6) sim.solver.eigenmode.target = 4e9

set_stack

set_stack(
    stack: LayerStack | None = None,
    *,
    yaml_path: str | Path | None = None,
    air_above: float | None = None,
    air_below: float | None = None,
    substrate_thickness: float = 2.0,
    include_substrate: bool = False,
    add_oxide_dielectric: bool = True,
    **kwargs,
) -> None

Configure the layer stack.

Three modes of use:

  1. Active PDK (default — auto-detects IHP, QPDK, etc.)::

    sim.set_stack(substrate_thickness=2.0)

  2. YAML file::

    sim.set_stack(yaml_path="custom_stack.yaml")

  3. Custom stack (advanced — pass a hand-built LayerStack)::

    sim.set_stack(my_layer_stack)

Parameters:

  • stack (LayerStack | None, default: None ) –

    Custom gsim LayerStack (bypasses PDK extraction).

  • yaml_path (str | Path | None, default: None ) –

    Path to custom YAML stack file.

  • air_above (float | None, default: None ) –

    Deprecated and ignored. Use set_airbox().

  • air_below (float | None, default: None ) –

    Deprecated and ignored. Use set_airbox().

  • substrate_thickness (float, default: 2.0 ) –

    Thickness below z=0 in um.

  • include_substrate (bool, default: False ) –

    Include lossy silicon substrate.

  • add_oxide_dielectric (bool, default: True ) –

    Add synthetic oxide background dielectric.

  • **kwargs –

    Additional args passed to extract_layer_stack.

Example

sim.set_stack(substrate_thickness=2.0)

show_stack

show_stack() -> None

Print the layer stack table.

Example

sim.show_stack()

start

start(*, verbose: bool = True) -> None

Start cloud execution for this simulation's uploaded job.

Raises:

  • ValueError –

    If :meth:upload has not been called.

upload

upload(*, verbose: bool = True) -> str

Write the inputs and upload them. Does NOT start execution.

Parameters:

  • verbose (bool, default: True ) –

    Print progress messages.

Returns:

  • str –

    job_id string for use with :meth:start, :meth:get_status,

  • or ( str ) –

    func:gsim.wait_for_results.

validate_config

validate_config() -> ValidationResult

Validate the simulation configuration.

Returns:

validate_mesh

validate_mesh() -> ValidationResult

Validate the generated mesh and config before cloud submission.

Checks that physical groups are correctly assigned after meshing: conductor surfaces, dielectric volumes, ports, and absorbing boundary. Also verifies the generated config.json structure.

Call after mesh() and before run().

Returns:

  • ValidationResult –

    ValidationResult with validation status and messages when valid.

Raises:

Example

sim.mesh(preset="coarse") result = sim.validate_mesh() print(result)

wait_for_results

wait_for_results(
    *,
    verbose: Verbosity = "status",
    parent_dir: str | Path | None = None,
    poll_interval: float = 5.0,
) -> Any

Wait for this simulation's cloud job, then download and parse results.

Parameters:

  • verbose (Verbosity, default: 'status' ) –

    "quiet" no output, "status" status line, "full" stream solver logs.

  • parent_dir (str | Path | None, default: None ) –

    Where to create the sim-data directory.

  • poll_interval (float, default: 5.0 ) –

    Seconds between status polls.

Returns:

  • Any –

    The solver's parsed results.

Raises:

  • ValueError –

    If no job has been submitted yet.

write_config

write_config(
    *,
    validate_mesh: bool = True,
    photonic: bool = False,
    photononic: bool | None = None,
) -> Path

Write Palace config.json after mesh generation.

By default this validates that the generated mesh/config include conductor boundaries required for EM conductor solves. For photonic simulations, pass photonic=True to skip this validation.

Parameters:

  • photonic (bool, default: False ) –

    Skip conductor-oriented mesh validation when True.

  • photononic (bool | None, default: None ) –

    Deprecated alias for photonic.

Returns:

  • Path –

    Path to the generated config.json

Raises:

Example

result = sim.mesh("./sim") config_path = sim.write_config()

Photonic workflow without conductor boundaries

config_path = sim.write_config(photonic=True)