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:
-
geometry(Geometry | None) –Wrapped gdsfactory Component (from common)
-
stack(LayerStack | None) –Layer stack configuration (from common)
-
ports(list[PortConfig]) –List of single-element port configurations
-
cpw_ports(list[CPWPortConfig]) –List of CPW (two-element) port configurations
-
eigenmode(EigenmodeConfig) –Eigenmode simulation configuration
-
materials(dict[str, MaterialConfig]) –Material property overrides
-
solver(EigenmodeSolverConfig) –Grouped numerical and problem-specific solver configuration
- API Guides Palace guide Simulation Classes
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
¶
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).
mesh_groups
property
¶
Physical groups of the generated mesh, once meshed.
Raises:
-
ValueError–When read before
mesh()has run.
numerical
property
writable
¶
numerical: SolverConfig
Compatibility alias for the common controls in solver.
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 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_portfor 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
axisin 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:
-
NotImplementedError–For electrostatic and boundarymode simulations.
-
ValueError–If a plane was already added.
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:
Raises:
-
ValueError–If no job has been submitted yet.
group_legacy_solver_settings
classmethod
¶
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>.mshandoutput/<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:
-
SimulationResult–SimulationResult with mesh path
Raises:
-
ValueError–If output_dir not set, configuration is invalid, or
model_nameis 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"])
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 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=Trueand 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, thenpalaceon PATH. -
use_apptainer(bool, default:False) –If True (default), run via Apptainer using SIF file. If False, run Palace executable directly. Ignored when
palace_executableis 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_threadsis 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_BINsomewhere else. A caller with no other way out gives none.
Returns:
-
SParams | PalaceTextResults | dict[str, Path]–Parsed Palace result object (
SParams) whenport-S.csvis -
SParams | PalaceTextResults | dict[str, Path]–present, matching :meth:
runbehavior. Falls back to parsed -
SParams | PalaceTextResults | dict[str, Path]–PalaceTextResultsfor text-only outputs (for example, -
SParams | PalaceTextResults | dict[str, Path]–BoundaryMode), then to a
dict[str, Path]mapping filenames to -
SParams | PalaceTextResults | dict[str, Path]–local paths when no parser applies.
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:
resultsis SParams -> results.s21.db¶For eigen / electrostatic:
resultsis 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.0when omitted. -
margin_y(float | None, default:None) –Airbox y-margin around the design (um). Defaults to
0.0when omitted. -
z_above(float | None, default:None) –Airbox extension above the stack top (um). Defaults to
0.0when omitted. -
z_below(float | None, default:None) –Airbox extension below the stack bottom (um). Defaults to
0.0when 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 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_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) –PNJunctionConfigor 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
iterationXsubdirectory. -
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:
-
Active PDK (default — auto-detects IHP, QPDK, etc.)::
sim.set_stack(substrate_thickness=2.0)
-
YAML file::
sim.set_stack(yaml_path="custom_stack.yaml")
-
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)
start
¶
start(*, verbose: bool = True) -> None
Start cloud execution for this simulation's uploaded job.
Raises:
-
ValueError–If :meth:
uploadhas not been called.
upload
¶
validate_config
¶
validate_config() -> ValidationResult
Validate the simulation configuration.
Returns:
-
ValidationResult–ValidationResult with validation status and messages
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:
-
RuntimeError–If mesh/config validation fails.
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:
-
ValueError–If mesh() hasn't been called yet
Example
result = sim.mesh("./sim") config_path = sim.write_config()
Photonic workflow without conductor boundaries¶
config_path = sim.write_config(photonic=True)