Circuits¶
circuits
¶
Photonic circuit simulation: an S-matrix netlist solver and compact models.
Solve a :class:~lightsmith.problems.CircuitProblem with
lightsmith.solve(problem) (backend lightsmith-circuit, method
circuit), or call :func:circuit_sparameters directly to get the S-matrix
as an array (a PyTorch tensor with gradients on device="torch-cpu"/CUDA)::
from lightsmith.circuits import circuit_sparameters
sol = circuit_sparameters(problem, device="torch-cpu", params={"ring": {"neff": neff_tensor}})
power = abs(sol["out", "in"]) ** 2
:func:list_models documents every compact model and its settings. Files
from field solvers (Touchstone .sNp or SParameterResult JSON) enter a
circuit as "component": "sparams:<path>"; :func:waveguide_from_modes
turns an FDE ModeResult into a dispersive waveguide instance.
CircuitSolution
dataclass
¶
CircuitSolution(ports: list[str], wavelengths_nm: ndarray, s: Any, device: Device, info: dict[str, Any] = dict(), warnings: list[str] = list())
NetlistError
¶
Bases: ValueError
The netlist is inconsistent (unknown/duplicate/unconnected ports, unknown models, bad settings).
Ctx
dataclass
¶
Ctx(wl_np: ndarray, device: Device, single: bool = False)
Wavelength grid and array namespace a model is evaluated on.
smatrix
¶
Assemble S[w, out, in] from {(out, in): (W,) array}; reciprocal fills (in, out) too.
check_netlist
¶
check_netlist(problem: CircuitProblem, ports_of: dict[str, list[str]], unconnected: str = 'error') -> tuple[list[tuple[str, str]], dict[str, str], list[str], list[str]]
Validate references; return (connections, external map, ignored ports, warnings).
Raises :class:NetlistError naming every unknown, duplicate or unconnected port.
circuit_sparameters
¶
circuit_sparameters(problem: CircuitProblem | dict | str, *, params: dict[str, dict[str, Any]] | None = None, device: str | Device = 'cpu', wavelengths_nm=None, algorithm: Literal['auto', 'dense', 'reduce'] = 'auto', precision: Literal['double', 'single'] = 'double', unconnected: Literal['error', 'ignore'] = 'error', base_dir: str | Path | None = None) -> CircuitSolution
Solve a circuit and return its external S-matrix as an array on device.
params overrides instance settings, e.g. {"ring": {"neff": t}}; with
device="torch-cpu" (or a CUDA device) and t a tensor with
requires_grad=True, gradients flow from the result back to t.
wavelengths_nm overrides the problem's wavelengths.
interconnect
¶
interconnect(blocks: dict[str, Block], conns: list[tuple[str, str]], ext_refs: list[str], ctx: Ctx, algorithm: Literal['auto', 'dense', 'reduce'] = 'auto') -> tuple[Any, str]
External S-matrix of the connected blocks; returns (S_ext, algorithm used).
compact_model
¶
compact_model(name: str, settings: type[ModelSettings], ports: tuple[str, ...] | None, aliases: tuple[str, ...] = ())
Register a compact model fn(ctx, values) -> (ports, S[w, out, in]) under name.
get_model
¶
Look up a model by name or alias; sparams:<path> loads S-parameters from a file.
list_models
¶
Every registered model: name, aliases, ports, documentation and settings JSON schema.
waveguide_from_modes
¶
waveguide_from_modes(result, length_nm: float, mode: int = 0, wl0_nm: float | None = None, extra_loss_db_per_cm: float = 0.0)
Build a waveguide :class:~lightsmith.problems.Instance from an FDE ModeResult.
With one wavelength the model uses neff, ng (from the mode, or neff if absent)
and the mode loss at that wavelength. With several wavelengths neff and loss are
tabulated (and interpolated, no extrapolation), so the circuit sees the full
dispersion that the mode solver computed. mode indexes modes sorted by
decreasing neff, as in ModeResult.modes[wavelength][mode].
read_sparameters
¶
read_sparameters(path: str | Path, time_convention: TimeConvention = '+iwt') -> tuple[ndarray, list[str], ndarray]
Read S-parameters from a Touchstone (.sNp/.ts) or SParameterResult JSON file.
read_touchstone
¶
read_touchstone(path: str | Path, time_convention: TimeConvention = '+iwt') -> tuple[ndarray, list[str], ndarray]
Read a Touchstone file. Returns (wavelengths_nm ascending, port names, S[wl, out, in]).
S is returned in lightsmith's exp(-i omega t) convention (conjugated when the
file uses time_convention="+iwt", the Touchstone standard).
write_touchstone
¶
write_touchstone(path: str | Path, wavelengths_nm, s, ports: list[str] | None = None, time_convention: TimeConvention = '+iwt') -> Path
Write S[wl, out, in] (exp(-i omega t) convention) as a Touchstone 1.1 RI file in Hz.
The extension should be .sNp with N the port count. Port names go into
! Port[n] = name comments so :func:read_touchstone restores them.