Cascade

class pmrf.models.composite.interconnected.cascade.Cascade(cascade: tuple[Model, ...], *, name: str | None = None, metadata: Any = None, flatten: bool = True, method: Literal['s', 'a'] = 's')

Bases: Model

Represents a cascade, or series connection, of two or more Model objects.

This container connects multiple models end-to-end. The output port of one model is connected to the input port of the next.

All models must have 2N-many ports. Ports N to 2*N-1 of the first model are connected to ports 0 to N-1 of the second, and so on.

Any nested Cascade instances are automatically flattened to maintain a simple, linear chain of models.

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

  • method ({'s', 'a'}, default='s') – The underlying mathematical domain to use for the cascade reduction.

  • flatten (bool, default=True) – (experimental) Flattens the cascade into one large cascade if they contain sub-cascades.

Notes

The scattering reduction pins junction modes that are singular and unobservable from the external ports, such as the common mode between floating networks, and inverts everything else exactly, so S and its JAX gradients match Circuit.from_chain. A resonance is observable and never pinned. A lossless model evaluated exactly at a true resonance frequency is still singular; that is physical. See pmrf.rf.cascade_two_s().

Examples

Cascading models is most easily done using the ** operator, which is an alias for creating a Cascade model.

>>> import pmrf as prf
>>> from pmrf.models import Resistor, Capacitor, Inductor

# Create individual component models >>> res = Resistor(50) >>> cap = Capacitor(1e-12) >>> ind = Inductor(1e-9)

# Cascade them together in a series R-L-C configuration # This is equivalent to Cascade(models=(res, ind, cap)) >>> rlc_series = res ** ind ** cap

# Define a frequency axis >>> freq = prf.Frequency(start=1, stop=10, npoints=101, unit=’ghz’)

# Calculate the S-parameters of the cascaded network >>> s_params = rlc_series.s(freq)

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() → Cascade
mna(freq: Frequency) → MNAStamp

Overrides the generic Model.mna() fallback, which prefers .a() over .s() whenever both are overridden.

cascade: tuple[Model, ...]

The models.

flatten: bool = True

(experimental) Flatten the connections if they contain any sub-circuits

method: Literal['s', 'a'] = 's'

The cascade reduction algorithm method.

property number_of_ports

Number of ports.

Return type:

int