Source code for pmrf.models.lumped

import jax.numpy as jnp

from pmrf.parameters import Parameter
from pmrf.models.model import Model
from pmrf.frequency import Frequency

[docs] class Load(Model): """ An abstract base class for N-port loads defined by their reflection coefficient. """ gamma: float nports: int = 1
[docs] def s(self, freq: Frequency) -> jnp.ndarray: gamma, nports = self.gamma, self.nports # Create a frequency-dependent 1x1 matrix from the scalar gamma s = jnp.array(gamma).reshape(-1, 1, 1) * \ jnp.eye(nports, dtype=jnp.complex128).reshape((-1, nports, nports)).\ repeat(freq.npoints, 0) return s
[docs] class Capacitor(Model): """ A 2-port model of a series capacitor. """ C: Parameter = 1.0
[docs] def s(self, freq: Frequency) -> jnp.ndarray: w = freq.w C = self.C z0_0 = z0_1 = self.z0 denom = 1.0 + 1j * w * C * (z0_0 + z0_1) s11 = (1.0 - 1j * w * C * (jnp.conj(z0_0) - z0_1) ) / denom s22 = (1.0 - 1j * w * C * (jnp.conj(z0_1) - z0_0) ) / denom s12 = s21 = (2j * w * C * (z0_0.real * z0_1.real)**0.5) / denom s = jnp.array([ [s11, s12], [s21, s22] ]).transpose(2, 0, 1) return s
[docs] class Inductor(Model): """ A 2-port model of a series inductor. """ L: Parameter = 1.0
[docs] def s(self, freq: Frequency) -> jnp.ndarray: L = self.L w = freq.w z0_0 = z0_1 = self.z0 denom = (1j * w * L) + (z0_0 + z0_1) s11 = (1j * w * L - jnp.conj(z0_0) + z0_1) / denom s22 = (1j * w * L + z0_0 - jnp.conj(z0_1)) / denom s12 = s21 = 2 * (z0_0.real * z0_1.real)**0.5 / denom s = jnp.array([ [s11, s12], [s21, s22] ]).transpose(2, 0, 1) return s
[docs] class Resistor(Model): """ **Overview** A 2-port model of a series resistor. """ R: Parameter = 1.0
[docs] def s(self, freq: Frequency) -> jnp.ndarray: R = self.R z0_0 = z0_1 = self.z0 ones = jnp.ones(freq.npoints, dtype=jnp.complex128) denom = R + (z0_0 + z0_1) s11 = ((R - jnp.conj(z0_0) + z0_1) / denom) * ones s22 = ((R + z0_0 - jnp.conj(z0_1)) / denom) * ones s12 = (2 * (z0_0.real * z0_1.real)**0.5 / denom) * ones s21 = s12 s = jnp.array([ [s11, s12], [s21, s22] ]).transpose(2, 0, 1) return s
[docs] class ShuntCapacitor(Model): """ A 2-port model of a shunt capacitor. This model represents a capacitor connected from the signal path to the ground reference, placed between port 1 and port 2. """ C: Parameter = 1.0
[docs] def s(self, freq: Frequency) -> jnp.ndarray: w = freq.w C = self.C z0 = self.z0 yn = 1j * w * C * z0 denom = 2.0 + yn s11 = -yn / denom s22 = s11 s21 = 2.0 / denom s12 = s21 # Construct the S-parameter matrix s = jnp.array([ [s11, s12], [s21, s22] ]).transpose(2, 0, 1) # Transpose to (num_freq_points, 2, 2) return s
[docs] class ShuntResistor(Model): """ A 2-port model of a shunt resistor. This model represents a resistor connected from the signal path to the ground reference, placed between port 1 and port 2. """ nports = 2 R: Parameter = 50.0
[docs] def s(self, freq: Frequency) -> jnp.ndarray: R = self.R z0 = self.z0 yn = z0 / R denom = 2.0 + yn s11 = -yn / denom s22 = s11 s21 = 2.0 / denom s12 = s21 s11_freq = jnp.full(freq.w.shape, s11) s21_freq = jnp.full(freq.w.shape, s21) s = jnp.array([ [s11_freq, s21_freq], [s21_freq, s11_freq] ]).transpose(2, 0, 1) return s
[docs] class ShuntInductor(Model): """ A 2-port model of a shunt inductor. """ nports = 2 L: Parameter = 1e-9
[docs] def s(self, freq: Frequency) -> jnp.ndarray: w = freq.w L = self.L z0 = self.z0 yn = z0 / (1j * w * L) denom = 2.0 + yn s11 = -yn / denom s22 = s11 s21 = 2.0 / denom s12 = s21 s = jnp.array([ [s11, s12], [s21, s22] ]).transpose(2, 0, 1) return s
SHORT = Load(-1.0) OPEN = Load(1.0) MATCH = Load(0.0)