Skip to content

circuit ¤

High-level callable circuit interface.

Classes:

Name Description
Circuit

A compiled, callable circuit with SAX-like parameter API.

Functions:

Name Description
compile_circuit

Compile a netlist into a callable :class:Circuit.

Circuit ¤

Circuit(
    solver: CircuitLinearSolver, groups: dict, sys_size: int, port_map: dict[str, int]
)

A compiled, callable circuit with SAX-like parameter API.

Wraps the output of :func:compile_netlist and :func:analyze_circuit into a single callable. Global parameters (e.g. wavelength_nm) are forwarded to every component group that declares them. When array-valued parameters are passed, :meth:__call__ applies jax.vmap over the batch dimension automatically.

Attributes:

Name Type Description
solver

The configured linear solver strategy.

groups

Compiled component groups dict.

sys_size

Number of scalar unknowns in the real-valued system.

port_map

Maps "Instance,port" strings to indices in the flat solution vector y.

Methods:

Name Description
get_port_field

Extract the (possibly complex) field at a named port.

with_groups

Return a new Circuit with replaced component groups.

Source code in circulax/circuit.py
def __init__(  # noqa: D107
    self,
    solver: CircuitLinearSolver,
    groups: dict,
    sys_size: int,
    port_map: dict[str, int],
) -> None:
    self.solver = solver
    self.groups = groups
    self.sys_size = sys_size
    self.port_map = port_map

get_port_field ¤

get_port_field(y: Array, port: str) -> Array

Extract the (possibly complex) field at a named port.

Parameters:

Name Type Description Default
y Array

Solution array of shape (n,) or (batch, n).

required
port str

Port key as "InstanceName,port_name".

required

Returns:

Type Description
Array

Real or complex scalar/array. For complex circuits, reconstructs

Array

the field from the unrolled block format.

Source code in circulax/circuit.py
def get_port_field(self, y: jax.Array, port: str) -> jax.Array:
    """Extract the (possibly complex) field at a named port.

    Args:
        y: Solution array of shape ``(n,)`` or ``(batch, n)``.
        port: Port key as ``"InstanceName,port_name"``.

    Returns:
        Real or complex scalar/array. For complex circuits, reconstructs
        the field from the unrolled block format.

    """
    idx = self.port_map[port]
    if self.solver.is_complex:
        return y[..., idx] + 1j * y[..., idx + self.sys_size]
    return y[..., idx]

with_groups ¤

with_groups(groups: dict) -> Circuit

Return a new Circuit with replaced component groups.

Use together with :func:~circulax.utils.update_params_dict for instance-specific parameter changes before solving.

Parameters:

Name Type Description Default
groups dict

New groups dict.

required

Returns:

Type Description
Circuit

A new :class:Circuit with the updated groups.

Source code in circulax/circuit.py
def with_groups(self, groups: dict) -> Circuit:
    """Return a new Circuit with replaced component groups.

    Use together with :func:`~circulax.utils.update_params_dict` for
    instance-specific parameter changes before solving.

    Args:
        groups: New groups dict.

    Returns:
        A new :class:`Circuit` with the updated groups.

    """
    return Circuit(self.solver, groups, self.sys_size, self.port_map)

compile_circuit ¤

compile_circuit(
    net_dict: dict,
    models_map: dict,
    *,
    backend: str = "default",
    is_complex: bool = False,
    g_leak: float = 1e-09
) -> Circuit

Compile a netlist into a callable :class:Circuit.

Convenience wrapper that runs :func:~circulax.compiler.compile_netlist and :func:~circulax.solvers.linear.analyze_circuit in one call.

Parameters:

Name Type Description Default
net_dict dict

SAX-format netlist dict with instances, connections, and optionally ports keys.

required
models_map dict

Mapping from component type name strings to :class:~circulax.components.base_component.CircuitComponent subclasses.

required
backend str

Linear solver backend. One of "default", "dense", "sparse", "klu", "klu_split". Defaults to "default" (klu_split).

'default'
is_complex bool

If True, treat the circuit as complex-valued (photonic). The solution vector will have length 2 * sys_size.

False
g_leak float

Leakage conductance for regularisation. Defaults to 1e-9.

1e-09

Returns:

Name Type Description
A Circuit

class:Circuit ready to call with circuit(**params).

Example::

circuit = compile_circuit(net_dict, models_map, is_complex=True)
solutions = jax.jit(circuit)(wavelength_nm=jnp.linspace(1260, 1360, 2000))
field_out = circuit.get_port_field(solutions, "Detector,p1")
Source code in circulax/circuit.py
def compile_circuit(
    net_dict: dict,
    models_map: dict,
    *,
    backend: str = "default",
    is_complex: bool = False,
    g_leak: float = 1e-9,
) -> Circuit:
    """Compile a netlist into a callable :class:`Circuit`.

    Convenience wrapper that runs :func:`~circulax.compiler.compile_netlist`
    and :func:`~circulax.solvers.linear.analyze_circuit` in one call.

    Args:
        net_dict: SAX-format netlist dict with ``instances``, ``connections``,
            and optionally ``ports`` keys.
        models_map: Mapping from component type name strings to
            :class:`~circulax.components.base_component.CircuitComponent`
            subclasses.
        backend: Linear solver backend. One of ``"default"``, ``"dense"``,
            ``"sparse"``, ``"klu"``, ``"klu_split"``. Defaults to
            ``"default"`` (``klu_split``).
        is_complex: If ``True``, treat the circuit as complex-valued (photonic).
            The solution vector will have length ``2 * sys_size``.
        g_leak: Leakage conductance for regularisation. Defaults to ``1e-9``.

    Returns:
        A :class:`Circuit` ready to call with ``circuit(**params)``.

    Example::

        circuit = compile_circuit(net_dict, models_map, is_complex=True)
        solutions = jax.jit(circuit)(wavelength_nm=jnp.linspace(1260, 1360, 2000))
        field_out = circuit.get_port_field(solutions, "Detector,p1")

    """
    from circulax.compiler import compile_netlist
    from circulax.solvers.linear import analyze_circuit

    groups, sys_size, port_map = compile_netlist(net_dict, models_map)
    solver = analyze_circuit(groups, sys_size, backend=backend, is_complex=is_complex, g_leak=g_leak)
    return Circuit(solver=solver, groups=groups, sys_size=sys_size, port_map=port_map)