Skip to content

Common API

Geometry

Geometry

Bases: BaseModel

Shared geometry wrapper for gdsfactory Component.

This class wraps a gdsfactory Component and provides computed properties that are useful for simulation setup (bounds, ports, etc.).

Attributes:

  • component (Any) –

    The wrapped gdsfactory Component

Example

from gdsfactory.components import straight c = straight(length=100) geom = Geometry(component=c) print(geom.bounds) (0.0, -0.25, 100.0, 0.25)

GeometryModel dataclass

GeometryModel(
    prisms: dict[str, list[Prism]],
    bbox: tuple[tuple[float, float, float], tuple[float, float, float]],
    layer_bboxes: dict[
        str, tuple[tuple[float, float, float], tuple[float, float, float]]
    ] = dict(),
    layer_mesh_orders: dict[str, int] = dict(),
)

Complete 3D geometry: layers of prisms, ready for visualization.

Attributes:

Prism dataclass

Prism(
    vertices: ndarray,
    z_base: float,
    z_top: float,
    layer_name: str = "",
    material: str = "",
    sidewall_angle: float = 0.0,
    original_polygon: Any = None,
)

A 2D polygon extruded in z. No solver dependency.

Attributes:

  • vertices (ndarray) –

    (N, 2) numpy array of xy coordinates defining the polygon.

  • z_base (float) –

    Bottom z coordinate of the extrusion.

  • z_top (float) –

    Top z coordinate of the extrusion.

  • layer_name (str) –

    Name of the layer this prism belongs to.

  • material (str) –

    Name of the material assigned to this prism.

  • sidewall_angle (float) –

    Sidewall taper angle in degrees (gdsfactory convention).

  • original_polygon (Any) –

    Optional reference to the source Shapely polygon.

extract_geometry_model

extract_geometry_model(layered_component: LayeredComponentBase) -> GeometryModel

Convert a LayeredComponentBase into a GeometryModel with generic Prisms.

For each geometry layer (sorted by mesh_order): 1. Retrieve the merged Shapely polygon from layered_component.polygons. 2. Compute z_base / z_top from get_layer_bbox. 3. Iterate sub-polygons for MultiPolygon geometries. 4. Handle polygons with holes via Delaunay triangulation. 5. Produce Prism objects with (N, 2) numpy vertex arrays.

Parameters:

  • layered_component (LayeredComponentBase) –

    A LayeredComponentBase (or subclass) instance that provides polygons, geometry_layers, and get_layer_bbox.

Returns:

Stack

LayerStack

Bases: BaseModel

Complete layer stack for Palace simulation.

Layer

Bases: BaseModel

Layer information for Palace simulation.

PN Junction

Depletion model after Sze & Ng, Physics of Semiconductor Devices, ch. 2, plus the 1D free-carrier plasma-dispersion model for the complex optical permittivity and the doping-profile geometry builders.

PNJunctionConfig

Bases: BaseModel

Parameters of a PN-junction depletion model (depletion approximation).

Concentrations use the semiconductor-industry convention (cm^-3); derived lengths are exposed in micrometers and capacitances in farads. See module docstring for the underlying formulas (Sze ch. 2).

Attributes:

  • na_cm3 (float) –

    Acceptor concentration on the P side (cm^-3).

  • nd_cm3 (float) –

    Donor concentration on the N side (cm^-3).

  • v_reverse (float) –

    Applied reverse bias in volts (positive = reverse; negative values model forward bias below flat-band).

  • temperature_k (float) –

    Lattice temperature in kelvin.

  • ni_cm3 (float) –

    Intrinsic carrier concentration (cm^-3).

  • permittivity (float) –

    Relative permittivity of the depleted semiconductor.

  • grading (Literal['abrupt', 'linear']) –

    "abrupt" or "linear" junction profile.

  • grade_const_cm4 (float | None) –

    Grade constant a = |dN/dx| in cm^-4, required when grading="linear".

Methods:

  • capacitance –

    Absolute junction capacitance for a rectangular junction face.

  • select_mode –

    Auto-select the representation mode for this junction.

  • to_metadata –

    Return a plain-dict summary of the computed junction quantities.

c_per_area property

c_per_area: float

Junction capacitance per unit area in F/m^2 (eps_s / W).

v_bi property

v_bi: float

Built-in potential in volts.

w_um property

w_um: float

Total depletion width in micrometers at the configured bias.

xn_um property

xn_um: float

Depletion extent spilled into the N side (micrometers).

xp_um property

xp_um: float

Depletion extent spilled into the P side (micrometers).

capacitance

capacitance(length_um: float, height_um: float) -> float

Absolute junction capacitance for a rectangular junction face.

Treats the depletion strip as a parallel-plate capacitor of area length x height filled with the depleted semiconductor: C = eps_s * A / W.

Parameters:

  • length_um (float) –

    Device length along the propagation direction (um).

  • height_um (float) –

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

Returns:

  • float –

    Absolute capacitance in farads.

select_mode

select_mode(
    p_extent_um: float, n_extent_um: float, *, fraction: float = JUNCTION_MODE_FRACTION
) -> JunctionMode

Auto-select the representation mode for this junction.

Thin wrapper around :func:select_junction_mode using this config's computed depletion width.

Parameters:

  • p_extent_um (float) –

    Size of the doped flank on the P side (um).

  • n_extent_um (float) –

    Size of the doped flank on the N side (um).

  • fraction (float, default: JUNCTION_MODE_FRACTION ) –

    Resolvability threshold fraction (~⅕ default).

Returns:

  • JunctionMode –

    "high_res" or "capacitance".

to_metadata

to_metadata() -> dict[str, Any]

Return a plain-dict summary of the computed junction quantities.

make_pn_junction_profile

make_pn_junction_profile(
    comp: Component,
    *,
    length: float,
    center_y: float,
    rib_width: float,
    junction: PNJunctionConfig | dict[str, Any],
    p_region: tuple[str, tuple[int, int], float],
    n_region: tuple[str, tuple[int, int], float],
    junction_region: tuple[str, tuple[int, int]] | None = None,
    zmin: float = 0.0,
    zmax: float | None = None,
    fmax: float = 200000000000.0,
    mode: Literal["auto", "capacitance", "high_res"] = "auto",
    mode_fraction: float = JUNCTION_MODE_FRACTION,
    min_width_um: float = 0.0,
    junction_mesh_size_um: float | None = None,
    snap_grid_um: float | None = 0.001,
    mesh_resolution: str | float = "fine",
) -> dict[str, dict[str, Any]]

Build P / depletion-junction / N rib regions around center_y.

The depletion width W (and its asymmetric split xp/xn into the P and N halves) comes from :class:PNJunctionConfig (the depletion model in this module).

Two representation modes are supported:

  • "high_res": three contiguous rectangles are drawn — N [cy - rib_width/2, cy - xn], depleted-junction dielectric strip [cy - xn, cy + xp], P [cy + xp, cy + rib_width/2]. The junction strip is registered as a patterned dielectric with a real GDS layer so it appears on the simulation mesh.
  • "capacitance": geometry is unchanged from a plain P/N split (adjacent half-rectangles); no junction polygon is drawn and callers apply the computed capacitance as a lumped impedance boundary instead (see PalaceSimMixin.set_pn_junction).

With mode="auto" the choice falls out of :func:select_junction_mode: the strip is meshed only when W >= mode_fraction * min(P flank, N flank), where each flank is rib_width / 2. When min_width_um > 0 the strip is additionally meshed only if every drawn rectangle (the depletion strip and both trimmed P/N flanks) is at least min_width_um wide; otherwise the lumped-capacitance representation is used so the mesher never sees an unresolvable sliver. The drawn strip always spans exactly [center_y - xn, center_y + xp] — widths are never distorted, only the representation choice changes. With mode="high_res" (forced) the true widths are always drawn; a ValueError is raised instead when the partition would violate min_width_um (or produce a non-positive flank, e.g. under strongly asymmetric doping where the depletion spills past a rib half).

Parameters:

  • comp (Component) –

    gdsfactory component the rectangles are added to.

  • length (float) –

    Rectangle length along the propagation direction (um).

  • center_y (float) –

    Y coordinate of the metallurgical junction / rib centre.

  • rib_width (float) –

    Full rib width (um); P occupies the upper half, N the lower half.

  • junction (PNJunctionConfig | dict[str, Any]) –

    Depletion-model parameters (:class:PNJunctionConfig or its dict form).

  • p_region (tuple[str, tuple[int, int], float]) –

    (name, gds_layer, sigma_S_per_m) for the P region.

  • n_region (tuple[str, tuple[int, int], float]) –

    (name, gds_layer, sigma_S_per_m) for the N region.

  • junction_region (tuple[str, tuple[int, int]] | None, default: None ) –

    (name, gds_layer) used to register the depletion strip in high-res mode. Required when the selected mode is "high_res"; ignored in capacitance mode.

  • zmin (float, default: 0.0 ) –

    Bottom z of the regions (um).

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

    Top z of the regions (um); defaults to zmin + 0.22.

  • fmax (float, default: 200000000000.0 ) –

    Upper frequency of the Drude-model validity range (Hz).

  • mode (Literal['auto', 'capacitance', 'high_res'], default: 'auto' ) –

    "auto", "capacitance" or "high_res".

  • mode_fraction (float, default: JUNCTION_MODE_FRACTION ) –

    Auto-mode threshold fraction (~⅕ default).

  • min_width_um (float, default: 0.0 ) –

    Minimum drawn width (um) for the depletion strip and both trimmed P/N flanks in "high_res" mode (default 0.0 = no constraint, preserving prior behaviour). Tie this to the mesh resolution (e.g. ~2x the refined mesh size) so the mesher never sees an unresolvable sliver.

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

    Target mesh size (um) requested for the depletion strip in "high_res" mode. Defaults to None, which requests W / 4 (about four elements across the strip) so the mesher resolves the strip with well-shaped elements instead of slivers. Pass an explicit size to override. Recorded on the junction Layer as a numeric mesh_resolution for the BoundaryMode mesher to consume.

  • snap_grid_um (float | None, default: 0.001 ) –

    Grid (um) the region bounds are snapped to before drawing (None disables). Shared bounds then land on bit-identical vertices, so no 1 nm GDS snap slivers appear between the P / junction / N rectangles.

  • mesh_resolution (str | float, default: 'fine' ) –

    Mesh resolution assigned to the generated layers.

Returns:

  • dict[str, dict[str, Any]] –

    Dict with keys:

  • dict[str, dict[str, Any]] –
    • layer_specs: {name: Layer} for every drawn region.
  • dict[str, dict[str, Any]] –
    • materials: {name: MaterialProperties} (Drude models for P/N, plain dielectric for the junction strip).
  • dict[str, dict[str, Any]] –
    • centres: {role: y_centre} for drawn regions.
  • dict[str, dict[str, Any]] –
    • junction: computed quantities (widths, capacitance, chosen mode and selection reason).

make_segmented_junction_profile

make_segmented_junction_profile(
    comp: Component,
    *,
    length: float,
    center_y: float,
    rib_width: float,
    junction: PNJunctionConfig | dict[str, Any],
    n_p: int,
    n_n: int,
    wavelength_um: float = 1.55,
    eps_bg_rel: float | None = None,
    mu_n_cm2_vs: float = MU_N_CM2_VS,
    mu_p_cm2_vs: float = MU_P_CM2_VS,
    p_prefix: str = "p_",
    n_prefix: str = "n_",
    p_gds_start: tuple[int, int] = (21, 1),
    n_gds_start: tuple[int, int] = (20, 1),
    zmin: float = 0.0,
    zmax: float | None = None,
    snap_grid_um: float | None = 0.001,
    mesh_resolution: str | float = "fine",
) -> dict[str, dict[str, Any]]

Bin the rib into fine strips sampling the 1D Sze permittivity.

The P half [center_y, center_y + rib_width/2] is split into n_p uniform strips (p_1 at the metallurgical junction, p_{n_p} at the rib edge) and the N half mirrored into n_n strips (n_1 at the junction). Each strip gets its own GDS layer and material whose (eps', sigma) comes from :func:junction_epsilon_profile sampled at the strip centre, so an optical eigenmode sees the laterally varying free-carrier permittivity instead of a homogeneous body. Strips whose centres fall inside the depletion slice sample ~ni and stay pure dielectrics (conductivity=None).

Unlike :func:make_pn_junction_profile there is no capacitance mode: the bins always resolve whatever depletion width the bias point gives.

Parameters:

  • comp (Component) –

    gdsfactory component the rectangles are added to.

  • length (float) –

    Rectangle length along the propagation direction (um).

  • center_y (float) –

    Y coordinate of the metallurgical junction / rib centre.

  • rib_width (float) –

    Full rib width (um).

  • junction (PNJunctionConfig | dict[str, Any]) –

    Depletion-model parameters (config or its dict form).

  • n_p (int) –

    Strip count on the P side (>= 1).

  • n_n (int) –

    Strip count on the N side (>= 1).

  • wavelength_um (float, default: 1.55 ) –

    Optical wavelength in micrometers (> 0).

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

    Lattice background (resolved from the Si Sellmeier model at wavelength_um when omitted).

  • mu_n_cm2_vs (float, default: MU_N_CM2_VS ) –

    Electron mobility in cm^2/(V s).

  • mu_p_cm2_vs (float, default: MU_P_CM2_VS ) –

    Hole mobility in cm^2/(V s).

  • p_prefix (str, default: 'p_' ) –

    Name prefix for P-side strips.

  • n_prefix (str, default: 'n_' ) –

    Name prefix for N-side strips.

  • p_gds_start (tuple[int, int], default: (21, 1) ) –

    (layer, datatype) of p_1; datatype increments per strip. Must not collide with other drawn layers.

  • n_gds_start (tuple[int, int], default: (20, 1) ) –

    (layer, datatype) of n_1.

  • zmin (float, default: 0.0 ) –

    Bottom z of the strips (um).

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

    Top z of the strips (um); defaults to zmin + 0.22.

  • snap_grid_um (float | None, default: 0.001 ) –

    Grid (um) the strip edges are snapped to before drawing (None disables), keeping adjacent strips on bit-identical shared edges.

  • mesh_resolution (str | float, default: 'fine' ) –

    Mesh resolution assigned to the layers.

Returns:

Raises:

  • ValueError –

    On invalid counts, geometry, or a depletion width wider than the rib.

make_doping_profile

make_doping_profile(
    comp: Component,
    *,
    length: float,
    rib_center_y: float,
    rib_width: float,
    profile: dict[str, list[tuple[float, float]]],
    sides: _SideConfig,
    zmin: float,
    zmax: float,
    permittivity: float = 11.9,
    fmax: float = 200000000000.0,
    snap_grid_um: float | None = 0.001,
    mesh_resolution: str | float = "fine",
) -> dict[str, dict[str, Any]]

Add contiguous doping regions beside a rib and build layer/material specs.

For each side (e.g. "upper" / "lower") the regions listed in profile are placed as adjacent rectangles starting at the rib edge and extending outward, so the doping is contiguous with no gaps. Each region i on a side gets:

  • a gdsfactory rectangle of size (length, width) on the GDS layer (base_layer[0], base_layer[1] + i),
  • a Layer spec named "{name_prefix}{i}",
  • a MaterialProperties entry with the region's Drude conductivity.

Parameters:

  • comp (Component) –

    gdsfactory component the rectangles are added to.

  • length (float) –

    Rectangle length along the propagation direction (um).

  • rib_center_y (float) –

    Y coordinate of the rib centre (um).

  • rib_width (float) –

    Rib width (um); regions start at the rib edges.

  • profile (dict[str, list[tuple[float, float]]]) –

    Per-side region list {side: [(width_um, sigma_S_per_m), ...]}.

  • sides (_SideConfig) –

    Per-side configuration: each value is a dict with keys base_layer ((layer, datatype) tuple for the first region), name_prefix (region-name prefix) and sign (+1 extends in +y, -1 in -y).

  • zmin (float) –

    Bottom z of the doping regions (um).

  • zmax (float) –

    Top z of the doping regions (um).

  • permittivity (float, default: 11.9 ) –

    Relative permittivity shared by all regions (e.g. 11.9).

  • fmax (float, default: 200000000000.0 ) –

    Upper frequency of the dispersion-model validity range (Hz).

  • snap_grid_um (float | None, default: 0.001 ) –

    Grid (um) the strip bounds are snapped to before drawing (None disables). Snapped explicit polygons keep adjacent strips on bit-identical shared edges so no 1 nm GDS snap slivers appear between them.

  • mesh_resolution (str | float, default: 'fine' ) –

    Mesh resolution assigned to the generated Layer.

Returns:

junction_epsilon_profile

junction_epsilon_profile(
    y_um: ndarray | list[float],
    junction: PNJunctionConfig | dict[str, Any],
    *,
    center_um: float = 0.0,
    wavelength_um: float = 1.55,
    eps_bg_rel: float | None = None,
    mu_n_cm2_vs: float = MU_N_CM2_VS,
    mu_p_cm2_vs: float = MU_P_CM2_VS,
) -> dict[str, Any]

1D Sze-based complex permittivity across a PN junction.

Combines the depletion model (:class:PNJunctionConfig gives xp/xn) with the 1D carrier profile and Drude dispersion, so a single call maps positions to the complex permittivity that each slice of a segmented waveguide should carry.

Parameters:

  • y_um (ndarray | list[float]) –

    Sample positions in micrometers (list or array).

  • junction (PNJunctionConfig | dict[str, Any]) –

    Depletion-model parameters (config or its dict form).

  • center_um (float, default: 0.0 ) –

    Metallurgical-junction position in micrometers.

  • wavelength_um (float, default: 1.55 ) –

    Optical wavelength in micrometers (> 0).

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

    Lattice background (resolved from the Si Sellmeier model at wavelength_um when omitted).

  • mu_n_cm2_vs (float, default: MU_N_CM2_VS ) –

    Electron mobility in cm^2/(V s).

  • mu_p_cm2_vs (float, default: MU_P_CM2_VS ) –

    Hole mobility in cm^2/(V s).

Returns:

  • dict[str, Any] –

    Dict with y_um, n_cm3, p_cm3, eps_rel,

  • dict[str, Any] –

    eps_prime, sigma_Sm, n_index, k_index,

  • dict[str, Any] –

    eps_bg_rel and the junction metadata.

carrier_profile_1d

carrier_profile_1d(
    y_um: ndarray | list[float] | float,
    *,
    center_um: float,
    xp_um: float,
    xn_um: float,
    na_cm3: float,
    nd_cm3: float,
    ni_cm3: float = NI_SI_300K_CM3,
) -> tuple[ndarray, ndarray]

Free-carrier densities along a 1D cut through an abrupt PN junction.

Depletion approximation: outside [center - xn, center + xp] each side is quasi-neutral with the local-equilibrium densities for the net doping C (n0 = (C + sqrt(C^2 + 4 ni^2))/2, p0 = (-C + sqrt(C^2 + 4 ni^2))/2 with C = +Nd / -Na, evaluated in the n*p = ni^2 form for float64 safety); inside the strip the carriers are swept out (C = 0 gives ni). This is the 1D counterpart of the notebook's C_Sze charge profile.

Parameters:

  • y_um (ndarray | list[float] | float) –

    Sample positions in micrometers (scalar, list or array).

  • center_um (float) –

    Metallurgical-junction position in micrometers.

  • xp_um (float) –

    Depletion extent into the P side (>= 0).

  • xn_um (float) –

    Depletion extent into the N side (>= 0).

  • na_cm3 (float) –

    Acceptor concentration on the P side in cm^-3 (> 0).

  • nd_cm3 (float) –

    Donor concentration on the N side in cm^-3 (> 0).

  • ni_cm3 (float, default: NI_SI_300K_CM3 ) –

    Intrinsic carrier concentration in cm^-3 (> 0).

Returns:

  • ndarray –

    (n_cm3, p_cm3) electron/hole density arrays in cm^-3 with the

  • ndarray –

    broadcast shape of y_um.

Raises:

  • ValueError –

    On non-positive concentrations or negative extents.

epsilon_eff_relative

epsilon_eff_relative(
    n_cm3: ndarray | list[float] | float,
    p_cm3: ndarray | list[float] | float,
    *,
    wavelength_um: float,
    eps_bg_rel: float,
    mu_n_cm2_vs: float = MU_N_CM2_VS,
    mu_p_cm2_vs: float = MU_P_CM2_VS,
    tau_e_s: float | None = None,
    tau_h_s: float | None = None,
) -> ndarray

Complex relative permittivity from free-carrier plasma dispersion.

Full Drude-Sommerfeld form (notebook effective_eps, SI-corrected)::

eps_r = eps_bg - [n q mu_n / (tau_e eps0) (1 - j/(w tau_e))
                + p q mu_p / (tau_h eps0) (1 - j/(w tau_h))] / w^2

with densities converted from cm^-3 to m^-3. At 1550 nm w tau >> 1 (relaxation regime), so the real part carries the plasma shift and the imaginary part the free-carrier absorption.

Parameters:

  • n_cm3 (ndarray | list[float] | float) –

    Electron density in cm^-3 (scalar or array).

  • p_cm3 (ndarray | list[float] | float) –

    Hole density in cm^-3 (scalar or array, broadcastable).

  • wavelength_um (float) –

    Optical wavelength in micrometers (> 0).

  • eps_bg_rel (float) –

    Relative permittivity of the undoped lattice at the target wavelength (e.g. Si Sellmeier, see :func:default_eps_bg_rel).

  • mu_n_cm2_vs (float, default: MU_N_CM2_VS ) –

    Electron mobility in cm^2/(V s).

  • mu_p_cm2_vs (float, default: MU_P_CM2_VS ) –

    Hole mobility in cm^2/(V s).

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

    Electron relaxation time in s (derived from mu_n when omitted).

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

    Hole relaxation time in s (derived from mu_p when omitted).

Returns:

  • ndarray –

    Complex relative-permittivity array.

Raises:

  • ValueError –

    On non-positive wavelength or background permittivity.

optical_params

optical_params(
    eps_rel: ndarray | list[float] | complex, wavelength_um: float
) -> tuple[ndarray | float, ndarray | float]

Split a complex relative permittivity for Palace material entry.

Palace carries a real Permittivity plus a Conductivity, so eps'' is mapped through sigma = omega eps0 eps''.

Parameters:

  • eps_rel (ndarray | list[float] | complex) –

    Complex relative permittivity (scalar or array).

  • wavelength_um (float) –

    Optical wavelength in micrometers (> 0).

Returns:

  • ndarray | float –

    (eps_prime, sigma_Sm) real part and conductivity in S/m

  • ndarray | float –

    (Python floats for scalar input, arrays otherwise).

refractive_index

refractive_index(
    eps_rel: ndarray | list[float] | complex,
) -> tuple[ndarray | float, ndarray | float]

Refractive index and extinction coefficient from n + jk = sqrt(eps).

Parameters:

  • eps_rel (ndarray | list[float] | complex) –

    Complex relative permittivity (scalar or array).

Returns:

  • tuple[ndarray | float, ndarray | float] –

    (n, k) index and extinction (floats for scalar input).

drude_relaxation_times

drude_relaxation_times(
    mu_n_cm2_vs: float = MU_N_CM2_VS, mu_p_cm2_vs: float = MU_P_CM2_VS
) -> tuple[float, float]

Drude momentum-relaxation times from mobilities (tau = m* mu / q).

Parameters:

  • mu_n_cm2_vs (float, default: MU_N_CM2_VS ) –

    Electron mobility in cm^2/(V s) (> 0).

  • mu_p_cm2_vs (float, default: MU_P_CM2_VS ) –

    Hole mobility in cm^2/(V s) (> 0).

Returns:

Raises:

PNJunctionConfig

Bases: BaseModel

Parameters of a PN-junction depletion model (depletion approximation).

Concentrations use the semiconductor-industry convention (cm^-3); derived lengths are exposed in micrometers and capacitances in farads. See module docstring for the underlying formulas (Sze ch. 2).

Attributes:

  • na_cm3 (float) –

    Acceptor concentration on the P side (cm^-3).

  • nd_cm3 (float) –

    Donor concentration on the N side (cm^-3).

  • v_reverse (float) –

    Applied reverse bias in volts (positive = reverse; negative values model forward bias below flat-band).

  • temperature_k (float) –

    Lattice temperature in kelvin.

  • ni_cm3 (float) –

    Intrinsic carrier concentration (cm^-3).

  • permittivity (float) –

    Relative permittivity of the depleted semiconductor.

  • grading (Literal['abrupt', 'linear']) –

    "abrupt" or "linear" junction profile.

  • grade_const_cm4 (float | None) –

    Grade constant a = |dN/dx| in cm^-4, required when grading="linear".

Methods:

  • capacitance –

    Absolute junction capacitance for a rectangular junction face.

  • select_mode –

    Auto-select the representation mode for this junction.

  • to_metadata –

    Return a plain-dict summary of the computed junction quantities.

c_per_area property

c_per_area: float

Junction capacitance per unit area in F/m^2 (eps_s / W).

v_bi property

v_bi: float

Built-in potential in volts.

w_um property

w_um: float

Total depletion width in micrometers at the configured bias.

xn_um property

xn_um: float

Depletion extent spilled into the N side (micrometers).

xp_um property

xp_um: float

Depletion extent spilled into the P side (micrometers).

capacitance

capacitance(length_um: float, height_um: float) -> float

Absolute junction capacitance for a rectangular junction face.

Treats the depletion strip as a parallel-plate capacitor of area length x height filled with the depleted semiconductor: C = eps_s * A / W.

Parameters:

  • length_um (float) –

    Device length along the propagation direction (um).

  • height_um (float) –

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

Returns:

  • float –

    Absolute capacitance in farads.

select_mode

select_mode(
    p_extent_um: float, n_extent_um: float, *, fraction: float = JUNCTION_MODE_FRACTION
) -> JunctionMode

Auto-select the representation mode for this junction.

Thin wrapper around :func:select_junction_mode using this config's computed depletion width.

Parameters:

  • p_extent_um (float) –

    Size of the doped flank on the P side (um).

  • n_extent_um (float) –

    Size of the doped flank on the N side (um).

  • fraction (float, default: JUNCTION_MODE_FRACTION ) –

    Resolvability threshold fraction (~⅕ default).

Returns:

  • JunctionMode –

    "high_res" or "capacitance".

to_metadata

to_metadata() -> dict[str, Any]

Return a plain-dict summary of the computed junction quantities.

make_pn_junction_profile

make_pn_junction_profile(
    comp: Component,
    *,
    length: float,
    center_y: float,
    rib_width: float,
    junction: PNJunctionConfig | dict[str, Any],
    p_region: tuple[str, tuple[int, int], float],
    n_region: tuple[str, tuple[int, int], float],
    junction_region: tuple[str, tuple[int, int]] | None = None,
    zmin: float = 0.0,
    zmax: float | None = None,
    fmax: float = 200000000000.0,
    mode: Literal["auto", "capacitance", "high_res"] = "auto",
    mode_fraction: float = JUNCTION_MODE_FRACTION,
    min_width_um: float = 0.0,
    junction_mesh_size_um: float | None = None,
    snap_grid_um: float | None = 0.001,
    mesh_resolution: str | float = "fine",
) -> dict[str, dict[str, Any]]

Build P / depletion-junction / N rib regions around center_y.

The depletion width W (and its asymmetric split xp/xn into the P and N halves) comes from :class:PNJunctionConfig (the depletion model in this module).

Two representation modes are supported:

  • "high_res": three contiguous rectangles are drawn — N [cy - rib_width/2, cy - xn], depleted-junction dielectric strip [cy - xn, cy + xp], P [cy + xp, cy + rib_width/2]. The junction strip is registered as a patterned dielectric with a real GDS layer so it appears on the simulation mesh.
  • "capacitance": geometry is unchanged from a plain P/N split (adjacent half-rectangles); no junction polygon is drawn and callers apply the computed capacitance as a lumped impedance boundary instead (see PalaceSimMixin.set_pn_junction).

With mode="auto" the choice falls out of :func:select_junction_mode: the strip is meshed only when W >= mode_fraction * min(P flank, N flank), where each flank is rib_width / 2. When min_width_um > 0 the strip is additionally meshed only if every drawn rectangle (the depletion strip and both trimmed P/N flanks) is at least min_width_um wide; otherwise the lumped-capacitance representation is used so the mesher never sees an unresolvable sliver. The drawn strip always spans exactly [center_y - xn, center_y + xp] — widths are never distorted, only the representation choice changes. With mode="high_res" (forced) the true widths are always drawn; a ValueError is raised instead when the partition would violate min_width_um (or produce a non-positive flank, e.g. under strongly asymmetric doping where the depletion spills past a rib half).

Parameters:

  • comp (Component) –

    gdsfactory component the rectangles are added to.

  • length (float) –

    Rectangle length along the propagation direction (um).

  • center_y (float) –

    Y coordinate of the metallurgical junction / rib centre.

  • rib_width (float) –

    Full rib width (um); P occupies the upper half, N the lower half.

  • junction (PNJunctionConfig | dict[str, Any]) –

    Depletion-model parameters (:class:PNJunctionConfig or its dict form).

  • p_region (tuple[str, tuple[int, int], float]) –

    (name, gds_layer, sigma_S_per_m) for the P region.

  • n_region (tuple[str, tuple[int, int], float]) –

    (name, gds_layer, sigma_S_per_m) for the N region.

  • junction_region (tuple[str, tuple[int, int]] | None, default: None ) –

    (name, gds_layer) used to register the depletion strip in high-res mode. Required when the selected mode is "high_res"; ignored in capacitance mode.

  • zmin (float, default: 0.0 ) –

    Bottom z of the regions (um).

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

    Top z of the regions (um); defaults to zmin + 0.22.

  • fmax (float, default: 200000000000.0 ) –

    Upper frequency of the Drude-model validity range (Hz).

  • mode (Literal['auto', 'capacitance', 'high_res'], default: 'auto' ) –

    "auto", "capacitance" or "high_res".

  • mode_fraction (float, default: JUNCTION_MODE_FRACTION ) –

    Auto-mode threshold fraction (~⅕ default).

  • min_width_um (float, default: 0.0 ) –

    Minimum drawn width (um) for the depletion strip and both trimmed P/N flanks in "high_res" mode (default 0.0 = no constraint, preserving prior behaviour). Tie this to the mesh resolution (e.g. ~2x the refined mesh size) so the mesher never sees an unresolvable sliver.

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

    Target mesh size (um) requested for the depletion strip in "high_res" mode. Defaults to None, which requests W / 4 (about four elements across the strip) so the mesher resolves the strip with well-shaped elements instead of slivers. Pass an explicit size to override. Recorded on the junction Layer as a numeric mesh_resolution for the BoundaryMode mesher to consume.

  • snap_grid_um (float | None, default: 0.001 ) –

    Grid (um) the region bounds are snapped to before drawing (None disables). Shared bounds then land on bit-identical vertices, so no 1 nm GDS snap slivers appear between the P / junction / N rectangles.

  • mesh_resolution (str | float, default: 'fine' ) –

    Mesh resolution assigned to the generated layers.

Returns:

  • dict[str, dict[str, Any]] –

    Dict with keys:

  • dict[str, dict[str, Any]] –
    • layer_specs: {name: Layer} for every drawn region.
  • dict[str, dict[str, Any]] –
    • materials: {name: MaterialProperties} (Drude models for P/N, plain dielectric for the junction strip).
  • dict[str, dict[str, Any]] –
    • centres: {role: y_centre} for drawn regions.
  • dict[str, dict[str, Any]] –
    • junction: computed quantities (widths, capacitance, chosen mode and selection reason).

built_in_voltage

built_in_voltage(
    na_cm3: float,
    nd_cm3: float,
    *,
    temperature_k: float = 300.0,
    ni_cm3: float = NI_SI_300K_CM3,
) -> float

Compute the built-in potential V_bi of a PN junction in volts.

Implements V_bi = (k_B T / q) ln(Na Nd / ni^2) (Sze ch. 2).

Parameters:

  • na_cm3 (float) –

    Acceptor concentration on the P side in cm^-3 (> 0).

  • nd_cm3 (float) –

    Donor concentration on the N side in cm^-3 (> 0).

  • temperature_k (float, default: 300.0 ) –

    Lattice temperature in kelvin (> 0).

  • ni_cm3 (float, default: NI_SI_300K_CM3 ) –

    Intrinsic carrier concentration in cm^-3 (> 0).

Returns:

  • float –

    Built-in potential in volts.

Raises:

  • ValueError –

    If any input is non-positive or Na*Nd <= ni**2.

depletion_width

depletion_width(
    na_cm3: float,
    nd_cm3: float,
    *,
    v_reverse: float = 0.0,
    temperature_k: float = 300.0,
    ni_cm3: float = NI_SI_300K_CM3,
    permittivity: float = DEFAULT_SI_PERMITTIVITY,
    grading: Literal["abrupt", "linear"] = "abrupt",
    grade_const_cm4: float | None = None,
) -> float

Compute the total depletion width W in micrometers.

Parameters:

  • na_cm3 (float) –

    Acceptor concentration in cm^-3 (> 0).

  • nd_cm3 (float) –

    Donor concentration in cm^-3 (> 0).

  • v_reverse (float, default: 0.0 ) –

    Applied reverse-bias voltage in volts (positive = reverse). Negative values model forward bias down to (but excluding) flat-band.

  • temperature_k (float, default: 300.0 ) –

    Lattice temperature in kelvin.

  • ni_cm3 (float, default: NI_SI_300K_CM3 ) –

    Intrinsic carrier concentration in cm^-3.

  • permittivity (float, default: DEFAULT_SI_PERMITTIVITY ) –

    Relative permittivity of the semiconductor.

  • grading (Literal['abrupt', 'linear'], default: 'abrupt' ) –

    "abrupt" (step junction) or "linear" (linearly graded).

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

    Grade constant a = |dN/dx| in cm^-4 for grading="linear".

Returns:

  • float –

    Total depletion width in micrometers.

Raises:

  • ValueError –

    On non-positive inputs, missing grade constant, or bias beyond flat-band.

depletion_extents

depletion_extents(
    na_cm3: float,
    nd_cm3: float,
    *,
    w_um: float,
    grading: Literal["abrupt", "linear"] = "abrupt",
) -> tuple[float, float]

Split a total depletion width into P-side/N-side extents in micrometers.

For an abrupt junction the depletion spills asymmetrically::

x_p = W Nd / (Na + Nd),    x_n = W Na / (Na + Nd)

A linearly graded junction is symmetric around the metallurgical junction, so x_p = x_n = W/2.

Parameters:

  • na_cm3 (float) –

    Acceptor concentration in cm^-3 (> 0).

  • nd_cm3 (float) –

    Donor concentration in cm^-3 (> 0).

  • w_um (float) –

    Total depletion width in micrometers (from :func:depletion_width).

  • grading (Literal['abrupt', 'linear'], default: 'abrupt' ) –

    Junction grading type.

Returns:

  • tuple[float, float] –

    (xp_um, xn_um) — extents spilled into the P and N sides.

junction_capacitance_per_area

junction_capacitance_per_area(permittivity: float, w_um: float) -> float

Depletion capacitance per unit area C_j = eps_s / W in F/m^2.

Parameters:

  • permittivity (float) –

    Relative permittivity of the semiconductor.

  • w_um (float) –

    Total depletion width in micrometers (> 0).

Returns:

  • float –

    Capacitance per unit area in F/m^2.

select_junction_mode

select_junction_mode(
    w_um: float,
    p_extent_um: float,
    n_extent_um: float,
    *,
    fraction: float = JUNCTION_MODE_FRACTION,
) -> JunctionMode

Choose how to represent the depletion region in a simulation.

The depletion strip is meshed explicitly ("high_res") when its width is comparable to the doped sections flanking it — specifically when w_um >= fraction * min(p_extent, n_extent). Otherwise the region is far thinner than its neighbours and meshing it would only bloat the model, so a lumped capacitance boundary is used instead ("capacitance").

Parameters:

  • w_um (float) –

    Total depletion width in micrometers (> 0).

  • p_extent_um (float) –

    Size of the doped section flanking the junction on the P side (micrometers, > 0).

  • n_extent_um (float) –

    Size of the doped section flanking the junction on the N side (micrometers, > 0).

  • fraction (float, default: JUNCTION_MODE_FRACTION ) –

    Resolvability threshold as a fraction of the smaller flank (default ~⅕).

Returns:

  • JunctionMode –

    "high_res" when the geometry should carry the depletion strip,

  • JunctionMode –

    "capacitance" otherwise.

Visualization

plot_prisms_3d

plot_prisms_3d(
    geometry_model: GeometryModel,
    *,
    show_edges: bool = True,
    opacity: float = 0.8,
    color_by_layer: bool = True,
    show_simulation_box: bool = True,
    camera_position: str | None = "isometric",
    notebook: bool = True,
    theme: str = "default",
    **kwargs: Any,
) -> Any | None

Create interactive 3D visualisation of prisms using PyVista.

Parameters:

  • geometry_model (GeometryModel) –

    A GeometryModel with prisms and bbox.

  • show_edges (bool, default: True ) –

    Whether to show edges of the prisms.

  • opacity (float, default: 0.8 ) –

    Base opacity (0.0-1.0). Core layer forced opaque.

  • color_by_layer (bool, default: True ) –

    Colour by layer name.

  • show_simulation_box (bool, default: True ) –

    Draw the simulation bounding box.

  • camera_position (str | None, default: 'isometric' ) –

    "isometric", "xy", "xz", "yz", or custom tuple.

  • notebook (bool, default: True ) –

    Whether running inside Jupyter.

  • theme (str, default: 'default' ) –

    PyVista theme ("default", "dark", "document").

  • **kwargs (Any, default: {} ) –

    Extra args forwarded to pv.Plotter.

Returns:

  • Any | None –

    PyVista plotter object for further customisation.

plot_prism_slices

plot_prism_slices(
    geometry_model: GeometryModel,
    x: float | str | None = None,
    y: float | str | None = None,
    z: float | str = "core",
    ax: Axes | None = None,
    legend: bool = True,
    slices: str = "z",
    *,
    aspect: Literal["equal", "auto"] = "equal",
    overlay: Any | None = None,
) -> Axes | None

Plot cross sections of a GeometryModel with multi-view support.

Parameters:

  • geometry_model (GeometryModel) –

    GeometryModel with prisms and bbox.

  • x (float | str | None, default: None ) –

    X-coordinate (or layer name) for the slice plane.

  • y (float | str | None, default: None ) –

    Y-coordinate (or layer name) for the slice plane.

  • z (float | str, default: 'core' ) –

    Z-coordinate (or layer name) for the slice plane.

  • ax (Axes | None, default: None ) –

    Axes to draw on. If None, one figure is created for each requested slice.

  • legend (bool, default: True ) –

    Whether to show the legend.

  • slices (str, default: 'z' ) –

    Which slice(s) to plot -- "x", "y", "z", or combinations like "xy", "xz", "yz", "xyz".

  • aspect (Literal['equal', 'auto'], default: 'equal' ) –

    Axis aspect ratio. Use "equal" to preserve physical proportions or "auto" to fill the available plotting area.

  • overlay (Any | None, default: None ) –

    Optional SimOverlay with sim cell / PML / port metadata.

Returns:

  • Axes | None –

    plt.Axes when ax was provided, otherwise None

  • Axes | None –

    (the figure is shown directly).

create_web_export

create_web_export(
    geometry_model: GeometryModel,
    filename: str = "geometry_3d.html",
    title: str = "3D Geometry Visualization",
) -> str

Export 3D visualisation as standalone HTML (via PyVista).

export_3d_mesh

export_3d_mesh(geometry_model: GeometryModel, filename: str, fmt: str = 'auto') -> None

Export 3D geometry to mesh file (STL, PLY, OBJ, VTK, glTF).