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:
-
prisms(dict[str, list[Prism]]) –Mapping from layer name to list of Prism objects.
-
bbox(tuple[tuple[float, float, float], tuple[float, float, float]]) –Axis-aligned 3D bounding box as ((xmin, ymin, zmin), (xmax, ymax, zmax)).
-
layer_bboxes(dict[str, tuple[tuple[float, float, float], tuple[float, float, float]]]) –Optional per-layer bounding boxes for 2D slice logic.
-
layer_mesh_orders(dict[str, int]) –Optional mapping of layer_name -> mesh_order for z-ordering in 2D plots.
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:
-
GeometryModel–A GeometryModel containing all extracted prisms and the overall
-
GeometryModel–3D bounding box.
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 whengrading="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.
capacitance
¶
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".
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 (seePalaceSimMixin.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:
PNJunctionConfigor 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 toNone, which requestsW / 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 junctionLayeras a numericmesh_resolutionfor the BoundaryMode mesher to consume. -
snap_grid_um(float | None, default:0.001) –Grid (um) the region bounds are snapped to before drawing (
Nonedisables). 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_umwhen 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)ofp_1; datatype increments per strip. Must not collide with other drawn layers. -
n_gds_start(tuple[int, int], default:(20, 1)) –(layer, datatype)ofn_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 (
Nonedisables), keeping adjacent strips on bit-identical shared edges. -
mesh_resolution(str | float, default:'fine') –Mesh resolution assigned to the layers.
Returns:
-
dict[str, dict[str, Any]]–Dict with keys
layer_specs({name: Layer}), -
dict[str, dict[str, Any]]–materials({name: MaterialProperties}with per-strip -
dict[str, dict[str, Any]]–permittivity/conductivity),centres -
dict[str, dict[str, Any]]–(
{name: y_centre}),segments(per-strip geometry plus -
dict[str, dict[str, Any]]–sampled
n/p/eps_prime/sigma_Sm) andjunction -
dict[str, dict[str, Any]]–(depletion metadata plus binning parameters).
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
Layerspec named"{name_prefix}{i}", - a
MaterialPropertiesentry 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) andsign(+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 (
Nonedisables). 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_umwhen 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:
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_nwhen omitted). -
tau_h_s(float | None, default:None) –Hole relaxation time in s (derived from
mu_pwhen 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:
refractive_index
¶
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:
-
ValueError–On non-positive mobilities.
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 whengrading="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.
capacitance
¶
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".
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 (seePalaceSimMixin.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:
PNJunctionConfigor 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 toNone, which requestsW / 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 junctionLayeras a numericmesh_resolutionfor the BoundaryMode mesher to consume. -
snap_grid_um(float | None, default:0.001) –Grid (um) the region bounds are snapped to before drawing (
Nonedisables). 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 forgrading="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:
junction_capacitance_per_area
¶
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.Axeswhen ax was provided, otherwiseNone -
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).