Circuit

class pmrf.models.composite.interconnected.circuit.circuit.Circuit(connections: dataclasses.InitVar[list[list[tuple[pmrf.models.base.Model, int]]]]=None, *, name: str | None = None, metadata: Any = None, flatten: bool = False, solver: AbstractScatteringCircuitSolver | AbstractAdmittanceCircuitSolver | AbstractMNACircuitSolver = <factory>, circuit: list[Model] = None, indexed_connections: list[list[tuple[int, int]]]=None)

Bases: Model

Represents an arbitrary interconnection of multiple models.

This container connects multiple models together based on a specified list of nodes. Each node connects one or more ports of the constituent models to form a composite network.

The external ports follow Port declaration order: scanning connections node by node, left to right, the first Port found is port 0. This holds for every solver, nested or flattened. ports returns them in that order.

Each Port’s z0 is the circuit’s native reference impedance at that port (ADR-0006): s() and to_skrf() report S-parameters at the Ports’ z0 unless an explicit z0 is passed. A parent model, such as a Cascade or another Circuit, always passes an explicit z0, so the Ports’ z0 of a nested circuit do not affect the parent.

Parameters:
  • connections (list[list[tuple[Model, int]]]) – A list representing the nodes of the circuit. Each node is a list of tuples, where each tuple contains a model and the integer index of the port to connect to that node.

  • flatten (bool, default=False) – Flattens sub-circuits and sub-cascades to perform a single solve.

  • solver (AbstractCircuitSolver, default=GlobalMNACircuitSolver()) – The circuit solver to use. Available solvers can be found in pmrf.models.

Raises:

ValueError – If two Ports share a net, or a Port shares a net with a Ground.

Examples

Create a two-port PI-CLC network. External nodes are defined using Port, and common nodes using Ground.

>>> import pmrf as prf
>>> from pmrf.models import Capacitor, Inductor, Circuit, Port, Ground
>>>
>>> # Instantiate the elements, ports, and ground
>>> C1, C2 = Capacitor(C=2e-12), Capacitor(C=1.5e-12)
>>> L = Inductor(L=3e-9)
>>> p0, p1, ground = Port(), Port(), Ground()
>>>
>>> # Create the connections list
>>> connections = [
...     [(p0, 0), (C1, 1), (L, 1)],         # Node 0 -> Port 0
...     [(p1, 0), (C2, 1), (L, 0)],         # Node 1 -> Port 1
...     [(ground, 0), (C1, 0), (C2, 0)],    # Node 2 -> Ground
... ]
>>>
>>> # Create the circuit model
>>> pi_clc = Circuit(connections)
classmethod from_chain(models: tuple[Model, ...], **kwargs)

Creates a flattened Circuit from a chain of models connected in cascade. The final model may act as a termination by having N ports instead of 2N ports.

Parameters:
  • models (tuple[Model, ...]) – The sequence of models to connect end-to-end.

  • **kwargs – Additional keyword arguments to pass to the Circuit constructor.

classmethod from_connection(model_a: Model, port_a: int, model_b: Model, port_b: int, solver: AbstractScatteringCircuitSolver | AbstractAdmittanceCircuitSolver | AbstractMNACircuitSolver = None, **kwargs)

Creates a Circuit representing a direct port-to-port connection between one or two models.

This handles both standard connections (connecting port a on model_a to port b on model_b) and inner connections (closing a loop by connecting two ports on the same model instance).

The resultant external ports maintain the expected order: the unconnected ports of model_a followed by the unconnected ports of model_b.

Parameters:
  • model_a (Model) – The first model.

  • port_a (int) – The integer index of the port on model_a to connect.

  • model_b (Model) – The second model. If model_a and model_b are the exact same instance, an inner-connection is performed.

  • port_b (int) – The integer index of the port on model_b to connect.

  • solver (AbstractCircuitSolver, optional) – The solver to use. Defaults to SequentialScatteringCircuitSolver.

  • **kwargs – Additional keyword arguments passed to the Circuit constructor.

Examples

Connect port 1 of a 2-port attenuator to port 0 of a 2-port amplifier:

>>> atten, amp = Attenuator(loss=3.0), Amplifier(gain=10.0)
>>> chain = Circuit.from_connected(atten, 1, amp, 0)
classmethod from_parallel(models: tuple[Model, ...], solver: AbstractScatteringCircuitSolver | AbstractAdmittanceCircuitSolver | AbstractMNACircuitSolver = None, **kwargs)

Creates a Circuit representing a parallel connection of two or more Model objects.

Port i of every model is connected to port i of every other model, forming a single composite network with the same number of ports as the individual models. All models must have the exact same number of ports.

Parameters:
  • models (tuple[Model, ...]) – The sequence of models in parallel.

  • solver (AbstractCircuitSolver, optional) – The solver to use. Defaults to HierarchicalScatteringCircuitSolver.

  • **kwargs – Additional keyword arguments passed to the Circuit constructor.

Examples

Create a parallel RLC tank circuit:

>>> res, cap, ind = Resistor(50.0), Capacitor(1e-12), Inductor(1e-9)
>>> rlc_tank = Circuit.from_parallel((res, cap, ind))
expand()

Expands this model into its internal graph representation for circuit flattening.

Used by Circuit.flattened to unpack composite models into a single flat netlist for a global matrix solve.

pmrf.models.AbstractBuilder delegates this to its built model, as does a direct Model.build() override, so user classes rarely need it. It is mainly for built-in composites such as pmrf.models.Cascade and pmrf.models.Renumbered.

Returns:

If the model is a composite or routing container, it returns a tuple of: - port_mapping: A list of length nports mapping each external port index

of this model to an internal (Model, port_index) tuple.

  • internal_connections: A list of sub-nodes (connections) to add to the netlist. Each node is a list of (Model, port_index) tuples.

If the model is a fundamental leaf component, it returns None.

Return type:

tuple or None

Examples

A 2-port model holding an inductor and capacitor in series:

>>> def expand(self):
...     L, C = self.inductor, self.capacitor
...     port_mapping = [(L, 0), (C, 1)]
...     internal_connections = [[(L, 1), (C, 0)]]
...     return port_mapping, internal_connections
flattened() → Circuit

Returns a newly compiled Circuit instance where all sub-circuits, cascades, and builder models have been fully unwrapped into a flat netlist.

mna(freq: Frequency) → MNAStamp

The MNA stamp of S at the hub reference, which stays finite when ports are shorted together.

circuit: list[Model] = None

The models in the connections.

connections: dataclasses.InitVar[list[list[tuple[pmrf.models.base.Model, int]]]] = None

The connections.

flatten: bool = False

Flatten sub-circuits.

indexed_connections: list[list[tuple[int, int]]] = None

The collated indices of the connections.

property mna_representation: MNARepresentation

Generates the static topological map for MNA assembly and reduction.

nodal_representation

Generates the static topological map for nodal admittance assembly and reduction.

property number_of_ports: int

Computes the number of external ports exposed by this circuit.

port_representation

Generates the static topological map for scattering connection and reduction.

property ports: list[Port]

The circuit’s external Ports, in port order.

solver: AbstractScatteringCircuitSolver | AbstractAdmittanceCircuitSolver | AbstractMNACircuitSolver

The circuit solver.

supports_native_z0: ClassVar[bool] = True

Whether the model has a native reference impedance, so that s() accepts z0=None (ADR-0006). A model that sets it defaults to z0=None.