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.

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=True) – Flattens sub-circuits and sub-cascades to perform a single solve. Defaults to True.

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

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 1
...     [(p1, 0), (C2, 1), (L, 0)],         # Node 1 -> Port 2
...     [(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.

This method is used by graph algorithms (like the solver in Circuit.flattened) to unpack composite models, wrappers, and nested hierarchies into a single flat netlist. This allows global matrix solves to be used, where desired.

Note that expand is automatically implemented if pmrf.Model.build() is overridden and the built model also implements expand. This means that most user-classes do NOT need to manually implement this method, and it is mainly intended for built-in composite models in ParamRF to override e.g. pmrf.models.Cascade or 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

Imagine a custom 2-port model that internally connects an Inductor and Capacitor in series. When asked to expand, it exposes the inner components and their wiring:

>>> def expand(self):
...     # 1. Grab internal components
...     L, C = self.inductor, self.capacitor
...
...     # 2. Map our external ports to the internal components
...     port_mapping = [
...         (L, 0),  # External port 0 maps to Inductor port 0
...         (C, 1)   # External port 1 maps to Capacitor port 1
...     ]
...
...     # 3. Define the internal connections (the netlist)
...     # Connect Inductor port 1 to Capacitor port 0
...     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.

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.

property nodal_representation: NodalRepresentation

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.

property port_representation: PortRepresentation

Generates the static topological map for scattering connection and reduction.

solver: AbstractScatteringCircuitSolver | AbstractAdmittanceCircuitSolver | AbstractMNACircuitSolver

The circuit solver.