models
¶
SAX Models.
Modules:
| Name | Description |
|---|---|
bends |
SAX Bend Models. |
couplers |
SAX Coupler Models. |
crossings |
SAX Crossing Models. |
factories |
SAX Default Models. |
isolators |
SAX Isolator and Circulator Models. |
mmis |
SAX MMI Models. |
probes |
SAX Probe Models. |
reflectors |
SAX Reflector Models. |
rf |
Sax generic RF models. |
splitters |
SAX Default Models. |
straight |
SAX Default Models. |
terminators |
SAX Terminator Models. |
Functions:
| Name | Description |
|---|---|
admittance |
Generalized two-port admittance element. |
attenuator |
Simple optical attenuator model. |
bend |
Simple waveguide bend model. |
capacitor |
Ideal two-port capacitor model. |
circulator |
Optical circulator model (non-reciprocal 3-port device). |
copier |
Copy 100% of the power at the input ports to all output ports. |
coplanar_waveguide |
S-parameter model for a straight coplanar waveguide. |
coupler |
Dispersive directional coupler model. |
coupler_ideal |
Ideal 2x2 directional coupler model. |
cpw_epsilon_eff |
Effective permittivity of a CPW on a finite-height substrate. |
cpw_thickness_correction |
Apply conductor thickness correction to CPW ε_eff and Z₀. |
cpw_z0 |
Characteristic impedance of a CPW. |
crossing_ideal |
Ideal waveguide crossing model. |
electrical_open |
Electrical open connection Sax model. |
electrical_short |
Electrical short connection Sax model. |
ellipk_ratio |
Ratio of complete elliptic integrals of the first kind K(m) / K(1-m). |
gamma_0_load |
Connection with given reflection coefficient. |
grating_coupler |
Grating coupler model for fiber-chip coupling. |
ideal_probe |
Ideal 4-port measurement probe with 100% transmission and 100% tap coupling. |
impedance |
Generalized two-port impedance element. |
inductor |
Ideal two-port inductor model. |
isolator |
Optical isolator model (non-reciprocal). |
lc_shunt_component |
SAX component for a 1-port shunted LC resonator. |
microstrip |
S-parameter model for a straight microstrip transmission line. |
microstrip_epsilon_eff |
Effective permittivity of a microstrip line. |
microstrip_thickness_correction |
Conductor thickness correction for a microstrip line. |
microstrip_z0 |
Characteristic impedance of a microstrip line. |
mirror |
Ideal mirror model (reflector with default 100% reflection). |
mmi1x2 |
Realistic 1x2 MMI splitter model with dispersion and loss. |
mmi1x2_ideal |
Ideal 1x2 multimode interference (MMI) splitter model. |
mmi2x2 |
Realistic 2x2 MMI coupler model with dispersion and asymmetry. |
mmi2x2_ideal |
Ideal 2x2 multimode interference (MMI) coupler model. |
model_2port |
Generate a general 2-port model with 100% transmission. |
model_3port |
Generate a general 3-port model (1x2 splitter). |
model_4port |
Generate a general 4-port model (2x2 coupler). |
passthru |
Copy 100% of the power at each input port to its corresponding output port. |
phase_shifter |
Simple voltage-controlled phase shifter model. |
propagation_constant |
Complex propagation constant of a quasi-TEM transmission line. |
reflector |
Partial reflector / mirror model. |
resistor |
Ideal two-port resistor model. |
splitter_ideal |
Ideal 1x2 power splitter model. |
tee |
Ideal three-port RF power divider/combiner (T-junction). |
terminator |
Optical terminator / absorber model. |
transmission_line_s_params |
S-parameters of a uniform transmission line (ABCD→S conversion). |
unitary |
Generate a unitary N×M optical device model. |
admittance
¶
admittance(*, f: FloatArrayLike = DEFAULT_FREQUENCY, y: ComplexLike = 1 / 50) -> SDict
Generalized two-port admittance element.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Frequency in Hz |
DEFAULT_FREQUENCY
|
y
|
ComplexLike
|
Admittance in siemens |
1 / 50
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary representing the admittance element |
References
Pozar
Examples:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
import jaxellip # pyright: ignore[reportMissingImports]
import scipy.constants
sax.set_port_naming_strategy("optical")
f = np.linspace(1e9, 10e9, 500)
s = sax.models.rf.admittance(f=f, y=1 / 75)
plt.figure()
plt.plot(f / 1e9, np.abs(s[("o1", "o1")]), label="|S11|")
plt.plot(f / 1e9, np.abs(s[("o1", "o2")]), label="|S12|")
plt.plot(f / 1e9, np.abs(s[("o2", "o2")]), label="|S22|")
plt.xlabel("Frequency [GHz]")
plt.ylabel("Magnitude")
plt.legend()
Source code in src/sax/models/rf.py
attenuator
¶
attenuator(*, wl: FloatArrayLike = WL_C, loss: FloatArrayLike = 0.0) -> SDict
Simple optical attenuator model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
The wavelength in micrometers. |
WL_C
|
loss
|
FloatArrayLike
|
Attenuation in decibels (dB). |
0.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary containing the complex transmission coefficient. |
Examples:
Attenuator:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.attenuator(wl=wl, loss=3.0)
thru = np.abs(s[("o1", "o2")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/straight.py
bend
¶
bend(
wl: FloatArrayLike = WL_C,
wl0: FloatArrayLike = WL_C,
neff: FloatArrayLike = 2.34,
ng: FloatArrayLike = 3.4,
length: FloatArrayLike = 10.0,
loss_dB_cm: FloatArrayLike = 0.1,
) -> SDict
Simple waveguide bend model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Operating wavelength in micrometers. Can be a scalar or array for multi-wavelength simulations. Defaults to 1.55 μm. |
WL_C
|
wl0
|
FloatArrayLike
|
Reference wavelength in micrometers used for dispersion calculation. This is typically the design wavelength where neff is specified. Defaults to 1.55 μm. |
WL_C
|
neff
|
FloatArrayLike
|
Effective refractive index at the reference wavelength. This value represents the fundamental mode effective index and determines the phase velocity. Defaults to 2.34 (typical for silicon). |
2.34
|
ng
|
FloatArrayLike
|
Group refractive index at the reference wavelength. Used to calculate chromatic dispersion: ng = neff - lambda * d(neff)/d(lambda). Typically ng > neff for normal dispersion. Defaults to 3.4. |
3.4
|
length
|
FloatArrayLike
|
Physical length of the waveguide in micrometers. Determines both the total phase accumulation and loss. Defaults to 10.0 μm. |
10.0
|
loss_dB_cm
|
FloatArrayLike
|
Propagation loss in dB/cm. Includes material absorption, scattering losses, and other loss mechanisms. Set to 0.0 for lossless modeling. Defaults to 0.0 dB/cm. |
0.1
|
Returns:
| Type | Description |
|---|---|
SDict
|
The bend s-matrix |
Examples:
Basic bend simulation:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.bend(wl=wl, length=50.0, loss_dB_cm=0.1, neff=2.35, ng=3.5)
thru = np.abs(s[("o1", "o2")]) ** 2
plt.plot(wl, thru)
plt.xlabel("Wavelength (μm)")
plt.ylabel("thru")
Note
This model treats the bend as an equivalent straight waveguide and does not account for:
- Mode coupling between bend eigenmodes
- Radiation losses due to bending
- Polarization effects in bends
- Non-linear dispersion effects
For more accurate bend modeling, consider using dedicated bend models that account for these physical effects.
Source code in src/sax/models/bends.py
capacitor
¶
capacitor(
*,
f: FloatArrayLike = DEFAULT_FREQUENCY,
capacitance: FloatLike = 1e-15,
z0: ComplexLike = 50,
) -> SDict
Ideal two-port capacitor model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Frequency in Hz |
DEFAULT_FREQUENCY
|
capacitance
|
FloatLike
|
Capacitance in Farads |
1e-15
|
z0
|
ComplexLike
|
Reference impedance in Ω. |
50
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary representing the capacitor element |
References
Pozar
Examples:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
import jaxellip # pyright: ignore[reportMissingImports]
import scipy.constants
sax.set_port_naming_strategy("optical")
f = np.linspace(1e9, 10e9, 500)
s = sax.models.rf.capacitor(f=f, capacitance=1e-12, z0=50)
plt.figure()
plt.plot(f / 1e9, np.abs(s[("o1", "o1")]), label="|S11|")
plt.plot(f / 1e9, np.abs(s[("o1", "o2")]), label="|S12|")
plt.plot(f / 1e9, np.abs(s[("o2", "o2")]), label="|S22|")
plt.xlabel("Frequency [GHz]")
plt.ylabel("Magnitude")
plt.legend()
Source code in src/sax/models/rf.py
circulator
¶
circulator(
*,
wl: FloatArrayLike = WL_C,
insertion_loss_dB: FloatArrayLike = 0.0,
isolation_dB: FloatArrayLike = 40.0,
) -> SDict
Optical circulator model (non-reciprocal 3-port device).
Routes light in a circular fashion: port 1 -> port 2 -> port 3 -> port 1. Light traveling in the reverse direction is strongly attenuated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. |
WL_C
|
insertion_loss_dB
|
FloatArrayLike
|
Insertion loss in dB for the forward circulation path. Defaults to 0.0 dB. |
0.0
|
isolation_dB
|
FloatArrayLike
|
Isolation in dB between non-adjacent ports (reverse direction). Defaults to 40.0 dB. |
40.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary for the circulator. |
Examples:
3-port circulator:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.circulator(
wl=wl,
insertion_loss_dB=0.5,
isolation_dB=30.0,
)
fwd_12 = np.abs(s[("o1", "o2")]) ** 2
fwd_23 = np.abs(s[("o2", "o3")]) ** 2
iso_21 = np.abs(s[("o2", "o1")]) ** 2
plt.figure()
plt.plot(wl, 10 * np.log10(fwd_12), label="o1→o2")
plt.plot(wl, 10 * np.log10(fwd_23), label="o2→o3")
plt.plot(wl, 10 * np.log10(iso_21 + 1e-10), label="o2→o1 (isolated)")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Transmission [dB]")
plt.legend()
Source code in src/sax/models/isolators.py
copier
¶
copier(
num_inputs: int,
num_outputs: int,
*,
reciprocal: bool = True,
diagonal: bool = False,
) -> SCooModel
Copy 100% of the power at the input ports to all output ports.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_inputs
|
int
|
Number of input ports for the device. |
required |
num_outputs
|
int
|
Number of output ports for the device. |
required |
reciprocal
|
bool
|
If True, the device exhibits reciprocal behavior where forward and reverse transmissions are equal. Defaults to True. |
True
|
diagonal
|
bool
|
If True, creates diagonal coupling (each input couples to only one output). If False, creates full coupling between all input-output pairs. Defaults to False. |
False
|
Returns:
| Type | Description |
|---|---|
SCooModel
|
A copier model |
Examples:
A 1×4 optical amplifier/splitter:
import sax
amp_splitter = sax.models.copier(1, 4, reciprocal=False)
Si, Sj, Sx, port_map = amp_splitter(wl=1.55)
# Single input amplified and split to 4 outputs
Source code in src/sax/models/factories.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | |
coplanar_waveguide
¶
coplanar_waveguide(
f: FloatArrayLike = DEFAULT_FREQUENCY,
length: FloatLike = 1000.0,
width: FloatLike = 10.0,
gap: FloatLike = 5.0,
thickness: FloatLike = 0.0,
substrate_thickness: FloatLike = 500.0,
ep_r: FloatLike = 11.45,
tand: FloatLike = 0.0,
) -> SDict
S-parameter model for a straight coplanar waveguide.
Computes S-parameters analytically using conformal-mapping CPW theory following Simons and the Qucs-S CPW model. Conductor thickness corrections use the first-order model of Gupta, Garg, Bahl, and Bhartia.
References
Simons, ch. 2; Gupta, Garg, Bahl & Bhartia; Qucs technical documentation, §12.4
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Array of frequency points in Hz |
DEFAULT_FREQUENCY
|
length
|
FloatLike
|
Physical length in µm |
1000.0
|
width
|
FloatLike
|
Centre-conductor width in µm |
10.0
|
gap
|
FloatLike
|
Gap between centre conductor and ground plane in µm |
5.0
|
thickness
|
FloatLike
|
Conductor thickness in µm |
0.0
|
substrate_thickness
|
FloatLike
|
Substrate height in µm |
500.0
|
ep_r
|
FloatLike
|
Relative permittivity of the substrate |
11.45
|
tand
|
FloatLike
|
Dielectric loss tangent |
0.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
sax.SDict: S-parameters dictionary |
Source code in src/sax/models/rf.py
coupler
¶
coupler(
*,
wl: FloatArrayLike = WL_C,
wl0: FloatArrayLike = WL_C,
length: FloatArrayLike = 0.0,
coupling0: FloatArrayLike = 0.2,
dk1: FloatArrayLike = 1.2435,
dk2: FloatArrayLike = 5.3022,
dn: FloatArrayLike = 0.02,
dn1: FloatArrayLike = 0.1169,
dn2: FloatArrayLike = 0.4821,
) -> SDict
Dispersive directional coupler model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Operating wavelength in micrometers. Can be a scalar or array for multi-wavelength simulations. Defaults to 1.55 μm. |
WL_C
|
wl0
|
FloatArrayLike
|
Reference wavelength in micrometers for dispersion expansion. Typically the center design wavelength. Defaults to 1.55 μm. |
WL_C
|
length
|
FloatArrayLike
|
Coupling length in micrometers. This is the length over which the two waveguides are in close proximity. Defaults to 0.0 μm. |
0.0
|
coupling0
|
FloatArrayLike
|
Base coupling coefficient at the reference wavelength from bend regions or other coupling mechanisms. Obtained from FDTD simulations or measurements. Defaults to 0.2. |
0.2
|
dk1
|
FloatArrayLike
|
First-order derivative of coupling coefficient with respect to wavelength (∂κ/∂λ). Units: μm⁻¹. Defaults to 1.2435. |
1.2435
|
dk2
|
FloatArrayLike
|
Second-order derivative of coupling coefficient with respect to wavelength (∂²κ/∂λ²). Units: μm⁻². Defaults to 5.3022. |
5.3022
|
dn
|
FloatArrayLike
|
Effective index difference between even and odd supermodes at the reference wavelength. Determines beating length. Defaults to 0.02. |
0.02
|
dn1
|
FloatArrayLike
|
First-order derivative of effective index difference with respect to wavelength (∂Δn/∂λ). Units: μm⁻¹. Defaults to 0.1169. |
0.1169
|
dn2
|
FloatArrayLike
|
Second-order derivative of effective index difference with respect to wavelength (∂²Δn/∂λ²). Units: μm⁻². Defaults to 0.4821. |
0.4821
|
Returns:
| Type | Description |
|---|---|
SDict
|
The coupler s-matrix |
Examples:
Basic dispersive coupler:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.coupler(
wl=wl,
length=15.7,
coupling0=0.0,
dn=0.02,
)
thru = np.abs(s[("o1", "o4")]) ** 2
cross = np.abs(s[("o1", "o3")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Note
The coupling strength follows the formula:
κ_total = κ₀ + κ₁ + κ_length
Where:
- κ₀ = coupling0 + dk1(λ-λ₀) + 0.5dk2*(λ-λ₀)²
- κ₁ = π*Δn(λ)/λ
- κ_length represents the distributed coupling over the interaction length
Source code in src/sax/models/couplers.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
coupler_ideal
¶
coupler_ideal(*, wl: FloatArrayLike = WL_C, coupling: FloatArrayLike = 0.5) -> SDict
Ideal 2x2 directional coupler model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
the wavelength of the simulation in micrometers. |
WL_C
|
coupling
|
FloatArrayLike
|
Power coupling coefficient between 0 and 1. Defaults to 0.5. |
0.5
|
Returns:
| Type | Description |
|---|---|
SDict
|
The coupler s-matrix |
Examples:
Ideal coupler:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.coupler_ideal(
wl=wl,
coupling=0.3,
)
thru = np.abs(s[("o1", "o4")]) ** 2
cross = np.abs(s[("o1", "o3")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/couplers.py
cpw_epsilon_eff
¶
cpw_epsilon_eff(
w: FloatArrayLike, s: FloatArrayLike, h: FloatArrayLike, ep_r: FloatArrayLike
) -> Array
Effective permittivity of a CPW on a finite-height substrate.
where \(K\) is the complete elliptic integral of the first kind in the parameter convention (\(m = k^2\)).
References
Simoons, Eq. 2.37; Ghione & Naldi
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
w
|
FloatArrayLike
|
Centre-conductor width (m). |
required |
s
|
FloatArrayLike
|
Gap to ground plane (m). |
required |
h
|
FloatArrayLike
|
Substrate height (m). |
required |
ep_r
|
FloatArrayLike
|
Relative permittivity of the substrate. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Effective permittivity (dimensionless). |
Source code in src/sax/models/rf.py
cpw_thickness_correction
¶
cpw_thickness_correction(
w: FloatArrayLike, s: FloatArrayLike, t: FloatArrayLike, ep_eff: FloatArrayLike
) -> tuple[Any, Any]
Apply conductor thickness correction to CPW ε_eff and Z₀.
First-order correction from Gupta, Garg, Bahl & Bhartia
References
Gupta, Garg, Bahl & Bhartia, §7.3, Eqs. 7.98-7.100
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
w
|
FloatArrayLike
|
Centre-conductor width (m). |
required |
s
|
FloatArrayLike
|
Gap to ground plane (m). |
required |
t
|
FloatArrayLike
|
Conductor thickness (m). |
required |
ep_eff
|
FloatArrayLike
|
Uncorrected effective permittivity. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
|
Any
|
and characteristic impedance (Ω). |
Source code in src/sax/models/rf.py
cpw_z0
¶
cpw_z0(w: FloatArrayLike, s: FloatArrayLike, ep_eff: FloatArrayLike) -> Array
Characteristic impedance of a CPW.
References
Simons, Eq. 2.38. Note that our \(w\) and \(s\) correspond to Simons' \(s\) and \(w\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
w
|
FloatArrayLike
|
Centre-conductor width (m). |
required |
s
|
FloatArrayLike
|
Gap to ground plane (m). |
required |
ep_eff
|
FloatArrayLike
|
Effective permittivity (see :func: |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Characteristic impedance (Ω). |
Source code in src/sax/models/rf.py
crossing_ideal
¶
crossing_ideal(wl: FloatArrayLike = WL_C) -> SDict
Ideal waveguide crossing model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. |
WL_C
|
Returns:
| Type | Description |
|---|---|
SDict
|
The crossing s-matrix |
Examples:
Ideal crossing:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import jax.numpy as jnp
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.crossing_ideal(wl=wl)
thru = np.abs(s[("o1", "o3")]) ** 2
cross = np.abs(s.get(("o1", "o2"), jnp.zeros_like(wl))) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/crossings.py
electrical_open
¶
electrical_open(*, f: FloatArrayLike = DEFAULT_FREQUENCY, n_ports: int = 1) -> SDict
Electrical open connection Sax model.
Useful for specifying some ports to remain open while not exposing them for connections in circuits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Array of frequency points in Hz |
DEFAULT_FREQUENCY
|
n_ports
|
int
|
Number of ports to set as opened |
1
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary where \(S = I_\text{n_ports}\) |
References
Pozar
Source code in src/sax/models/rf.py
electrical_short
¶
electrical_short(*, f: FloatArrayLike = DEFAULT_FREQUENCY, n_ports: int = 1) -> SDict
Electrical short connection Sax model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Array of frequency points in Hz |
DEFAULT_FREQUENCY
|
n_ports
|
int
|
Number of ports to set as shorted |
1
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary where \(S = -I_\text{n_ports}\) |
References
Pozar
Source code in src/sax/models/rf.py
ellipk_ratio
¶
ellipk_ratio(m: FloatArrayLike) -> Array
Ratio of complete elliptic integrals of the first kind K(m) / K(1-m).
Source code in src/sax/models/rf.py
gamma_0_load
¶
gamma_0_load(
*, f: FloatArrayLike = DEFAULT_FREQUENCY, gamma_0: Complex = 0, n_ports: int = 1
) -> SType
Connection with given reflection coefficient.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Array of frequency points in Hz |
DEFAULT_FREQUENCY
|
gamma_0
|
Complex
|
Reflection coefficient Γ₀ of connection |
0
|
n_ports
|
int
|
Number of ports in component. The diagonal ports of the matrix are set to Γ₀ and the off-diagonal ports to 0. |
1
|
Returns:
| Type | Description |
|---|---|
SType
|
sax.SType: S-parameters dictionary where \(S = \Gamma_0I_\text{n_ports}\) |
Examples:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
import jaxellip # pyright: ignore[reportMissingImports]
import scipy.constants
sax.set_port_naming_strategy("optical")
f = np.linspace(1e9, 10e9, 500)
gamma_0 = 0.5 * np.exp(1j * np.pi / 4)
s = sax.models.rf.gamma_0_load(f=f, gamma_0=gamma_0, n_ports=2)
plt.figure()
plt.plot(f / 1e9, np.abs(s[("o1", "o1")]), label="|S11|")
plt.plot(f / 1e9, np.abs(s[("o2", "o2")]), label="|S22|")
plt.plot(f / 1e9, np.abs(s[("o1", "o2")]), label="|S12|")
plt.plot(f / 1e9, np.abs(s[("o2", "o1")]), label="|S21|")
plt.xlabel("Frequency [GHz]")
plt.ylabel("Magnitude")
plt.legend()
Source code in src/sax/models/rf.py
grating_coupler
¶
grating_coupler(
*,
wl: FloatArrayLike = WL_C,
wl0: FloatArrayLike = WL_C,
loss: FloatArrayLike = 0.0,
reflection: FloatArrayLike = 0.0,
reflection_fiber: FloatArrayLike = 0.0,
bandwidth: FloatArrayLike = 0.04,
) -> SDict
Grating coupler model for fiber-chip coupling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Operating wavelength in micrometers. Can be a scalar or array for spectral analysis. Defaults to 1.55 μm. |
WL_C
|
wl0
|
FloatArrayLike
|
Center wavelength in micrometers where peak transmission occurs. This is the design wavelength of the grating. Defaults to 1.55 μm. |
WL_C
|
loss
|
FloatArrayLike
|
Insertion loss in dB at the center wavelength. Includes coupling efficiency losses, scattering, and mode mismatch. Defaults to 0.0 dB. |
0.0
|
reflection
|
FloatArrayLike
|
Reflection coefficient from the waveguide side (chip interface). Represents reflections back into the waveguide from grating discontinuities. Range: 0 to 1. Defaults to 0.0. |
0.0
|
reflection_fiber
|
FloatArrayLike
|
Reflection coefficient from the fiber side (top interface). Represents reflections back toward the fiber from the grating surface. Range: 0 to 1. Defaults to 0.0. |
0.0
|
bandwidth
|
FloatArrayLike
|
3dB bandwidth in micrometers. Determines the spectral width of the Gaussian transmission profile. Typical values: 20-50 nm. Defaults to 40e-3 μm (40 nm). |
0.04
|
Returns:
| Type | Description |
|---|---|
SDict
|
The grating coupler s-matrix |
Examples:
Basic grating coupler:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = np.linspace(1.5, 1.6, 101)
s = sax.models.grating_coupler(
wl=wl,
loss=3.0,
bandwidth=0.035,
)
plt.figure()
plt.plot(wl, np.abs(s[("o1", "o2")]) ** 2, label="Transmission")
plt.xlabel("Wavelength (μm)")
plt.ylabel("Power")
plt.legend()
Note
The transmission power profile follows a Gaussian shape: P(λ) = P₀ * exp(-((λ-λ₀)/σ)²)
The amplitude transmission is: A(λ) = A₀ * exp(-((λ-λ₀)/σ)²/2)
Where σ = bandwidth / (2√(2ln(2))) converts FWHM to Gaussian width.
This model assumes:
- Gaussian spectral response (typical for uniform gratings)
- Wavelength-independent loss coefficient
- Linear polarization (TE or TM)
- Single-mode fiber coupling
- No higher-order diffraction effects
Source code in src/sax/models/couplers.py
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
ideal_probe
¶
ideal_probe(wl: FloatArrayLike = WL_C) -> SDict
Ideal 4-port measurement probe with 100% transmission and 100% tap coupling.
This is an unphysical component designed for debugging and measurement purposes. It intercepts a connection and provides access to both forward and backward traveling waves without affecting the signal propagation.
The probe has the following behavior:
- Full transmission from in to out (and vice versa)
- Forward tap (tap_fwd) copies the signal traveling from in toward out
- Backward tap (tap_bwd) copies the signal traveling from out toward in
- No reflections at any port
- No cross-coupling between tap ports
Note
This S-matrix is NOT unitary (violates energy conservation). This is intentional—it's a measurement tool, not a physical device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. Defaults to 1.55 μm. |
WL_C
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-parameter dictionary for the ideal probe. |
Example
Probes are typically not used directly, but via the probes argument
to sax.circuit():
Source code in src/sax/models/probes.py
impedance
¶
impedance(
*, f: FloatArrayLike = DEFAULT_FREQUENCY, z: ComplexLike = 50, z0: ComplexLike = 50
) -> SDict
Generalized two-port impedance element.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Frequency in Hz |
DEFAULT_FREQUENCY
|
z
|
ComplexLike
|
Impedance in Ω |
50
|
z0
|
ComplexLike
|
Reference impedance in Ω. |
50
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary representing the impedance element |
References
Pozar
Examples:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
import jaxellip # pyright: ignore[reportMissingImports]
import scipy.constants
sax.set_port_naming_strategy("optical")
f = np.linspace(1e9, 10e9, 500)
s = sax.models.rf.impedance(f=f, z=75, z0=50)
plt.figure()
plt.plot(f / 1e9, np.abs(s[("o1", "o1")]), label="|S11|")
plt.plot(f / 1e9, np.abs(s[("o1", "o2")]), label="|S12|")
plt.plot(f / 1e9, np.abs(s[("o2", "o2")]), label="|S22|")
plt.xlabel("Frequency [GHz]")
plt.ylabel("Magnitude")
plt.legend()
Source code in src/sax/models/rf.py
inductor
¶
inductor(
*,
f: FloatArrayLike = DEFAULT_FREQUENCY,
inductance: FloatLike = 1e-12,
z0: ComplexLike = 50,
) -> SDict
Ideal two-port inductor model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Frequency in Hz |
DEFAULT_FREQUENCY
|
inductance
|
FloatLike
|
Inductance in Henries |
1e-12
|
z0
|
ComplexLike
|
Reference impedance in Ω. |
50
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary representing the inductor element |
References
Pozar
Examples:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
import jaxellip # pyright: ignore[reportMissingImports]
import scipy.constants
sax.set_port_naming_strategy("optical")
f = np.linspace(1e9, 10e9, 500)
s = sax.models.rf.inductor(f=f, inductance=1e-9, z0=50)
plt.figure()
plt.plot(f / 1e9, np.abs(s[("o1", "o1")]), label="|S11|")
plt.plot(f / 1e9, np.abs(s[("o1", "o2")]), label="|S12|")
plt.plot(f / 1e9, np.abs(s[("o2", "o2")]), label="|S22|")
plt.xlabel("Frequency [GHz]")
plt.ylabel("Magnitude")
plt.legend()
Source code in src/sax/models/rf.py
isolator
¶
isolator(
*,
wl: FloatArrayLike = WL_C,
insertion_loss_dB: FloatArrayLike = 0.0,
isolation_dB: FloatArrayLike = 40.0,
) -> SDict
Optical isolator model (non-reciprocal).
Transmits light in the forward direction (in0 -> out0) with low loss while blocking the reverse direction (out0 -> in0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. |
WL_C
|
insertion_loss_dB
|
FloatArrayLike
|
Forward insertion loss in dB. Defaults to 0.0 dB. |
0.0
|
isolation_dB
|
FloatArrayLike
|
Reverse isolation in dB. Higher values mean better blocking of backward-propagating light. Defaults to 40.0 dB. |
40.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary for the isolator. |
Examples:
Isolator with 1 dB insertion loss and 30 dB isolation:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.isolator(
wl=wl,
insertion_loss_dB=1.0,
isolation_dB=30.0,
)
fwd = np.abs(s[("o1", "o2")]) ** 2
bwd = np.abs(s[("o2", "o1")]) ** 2
plt.figure()
plt.plot(wl, 10 * np.log10(fwd), label="forward")
plt.plot(wl, 10 * np.log10(bwd + 1e-10), label="backward")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Transmission [dB]")
plt.legend()
Source code in src/sax/models/isolators.py
lc_shunt_component
¶
lc_shunt_component(
f: FloatArrayLike = 5000000000.0,
inductance: FloatLike = 1e-09,
capacitance: FloatLike = 1e-12,
z0: FloatLike = 50,
) -> SDict
SAX component for a 1-port shunted LC resonator.
Source code in src/sax/models/rf.py
microstrip
¶
microstrip(
f: FloatArrayLike = DEFAULT_FREQUENCY,
length: FloatLike = 1000.0,
width: FloatLike = 10.0,
substrate_thickness: FloatLike = 500.0,
thickness: FloatLike = 0.2,
ep_r: FloatLike = 11.45,
tand: FloatLike = 0.0,
) -> SDict
S-parameter model for a straight microstrip transmission line.
Computes S-parameters analytically using the Hammerstad-Jensen closed-form expressions for effective permittivity and characteristic impedance, as described in Pozar. Conductor thickness corrections follow Gupta et al.
References
Hammerstad & Jensen; Pozar, ch. 3, §3.8; Gupta, Garg, Bahl & Bhartia, §2.2.4
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Array of frequency points in Hz. |
DEFAULT_FREQUENCY
|
length
|
FloatLike
|
Physical length in µm. |
1000.0
|
width
|
FloatLike
|
Strip width in µm. |
10.0
|
substrate_thickness
|
FloatLike
|
Substrate height in µm. |
500.0
|
thickness
|
FloatLike
|
Conductor thickness in µm (default 0.2 µm = 200 nm). |
0.2
|
ep_r
|
FloatLike
|
Relative permittivity of the substrate (default 11.45 for Si). |
11.45
|
tand
|
FloatLike
|
Dielectric loss tangent (default 0 — lossless). |
0.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
sax.SDict: S-parameters dictionary. |
Source code in src/sax/models/rf.py
microstrip_epsilon_eff
¶
microstrip_epsilon_eff(
w: FloatArrayLike, h: FloatArrayLike, ep_r: FloatArrayLike
) -> Array
Effective permittivity of a microstrip line.
Uses the Hammerstad-Jensen formula as given in Pozar.
where the last term contributes only for narrow strips (\(w/h < 1\)).
References
Hammerstad & Jensen; Pozar, Eqs. 3.195-3.196.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
w
|
FloatArrayLike
|
Strip width (m). |
required |
h
|
FloatArrayLike
|
Substrate height (m). |
required |
ep_r
|
FloatArrayLike
|
Relative permittivity of the substrate. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Effective permittivity (dimensionless). |
Source code in src/sax/models/rf.py
microstrip_thickness_correction
¶
microstrip_thickness_correction(
w: FloatArrayLike,
h: FloatArrayLike,
t: FloatArrayLike,
ep_r: FloatArrayLike,
ep_eff: FloatArrayLike,
) -> tuple[Array, Array, Array]
Conductor thickness correction for a microstrip line.
Uses the widely-adopted Schneider correction as presented in Pozar and Gupta et al.
Then the corrected \(Z_0\) is computed with the effective width \(w_e\) and corrected \(\varepsilon_{\mathrm{eff},t}\).
References
Pozar, §3.8; Gupta, Garg, Bahl & Bhartia
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
w
|
FloatArrayLike
|
Strip width (m). |
required |
h
|
FloatArrayLike
|
Substrate height (m). |
required |
t
|
FloatArrayLike
|
Conductor thickness (m). |
required |
ep_r
|
FloatArrayLike
|
Relative permittivity of the substrate. |
required |
ep_eff
|
FloatArrayLike
|
Uncorrected effective permittivity. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
|
Array
|
thickness-corrected effective permittivity, |
Array
|
and characteristic impedance (Ω). |
Source code in src/sax/models/rf.py
microstrip_z0
¶
microstrip_z0(w: FloatArrayLike, h: FloatArrayLike, ep_eff: FloatArrayLike) -> Array
Characteristic impedance of a microstrip line.
Uses the Hammerstad-Jensen approximation as given in Pozar.
References
Hammerstad & Jensen; Pozar, Eqs. 3.197-3.198.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
w
|
FloatArrayLike
|
Strip width (m). |
required |
h
|
FloatArrayLike
|
Substrate height (m). |
required |
ep_eff
|
FloatArrayLike
|
Effective permittivity (see :func: |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Characteristic impedance (Ω). |
Source code in src/sax/models/rf.py
mirror
¶
mirror(
*,
wl: FloatArrayLike = WL_C,
reflection: FloatArrayLike = 1.0,
loss_dB: FloatArrayLike = 0.0,
) -> SDict
Ideal mirror model (reflector with default 100% reflection).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. |
WL_C
|
reflection
|
FloatArrayLike
|
Power reflection coefficient between 0 and 1. Defaults to 1.0 (perfect mirror). |
1.0
|
loss_dB
|
FloatArrayLike
|
Insertion loss in dB. Defaults to 0.0 dB. |
0.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary for the mirror. |
Examples:
Perfect mirror:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.mirror(wl=wl)
refl = np.abs(s[("o1", "o1")]) ** 2
plt.figure()
plt.plot(wl, refl, label="reflection")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/reflectors.py
mmi1x2
¶
mmi1x2(
wl: FloatArrayLike = WL_C,
wl0: FloatArrayLike = WL_C,
fwhm: FloatArrayLike = 0.2,
loss_dB: FloatArrayLike = 0.3,
) -> SDict
Realistic 1x2 MMI splitter model with dispersion and loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
The wavelength in micrometers. |
WL_C
|
wl0
|
FloatArrayLike
|
The Center wavelength of the MMI |
WL_C
|
fwhm
|
FloatArrayLike
|
The Full width at half maximum or the MMI. |
0.2
|
loss_dB
|
FloatArrayLike
|
Insertion loss in dB at the center wavelength. |
0.3
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary representing the dispersive MMI splitter behavior. |
Examples:
Basic 1x2 MMI:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.mmi1x2(wl=wl)
thru = np.abs(s[("o1", "o3")]) ** 2
cross = np.abs(s[("o1", "o2")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/mmis.py
mmi1x2_ideal
¶
mmi1x2_ideal(wl: FloatArrayLike = WL_C) -> SDict
Ideal 1x2 multimode interference (MMI) splitter model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
The wavelength in micrometers. |
WL_C
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary representing the ideal MMI splitter behavior. |
Examples:
Ideal 1x2 MMI:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.mmi1x2_ideal(wl=wl)
thru = np.abs(s[("o1", "o3")]) ** 2
cross = np.abs(s[("o1", "o2")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/mmis.py
mmi2x2
¶
mmi2x2(
wl: FloatArrayLike = WL_C,
wl0: FloatArrayLike = WL_C,
fwhm: FloatArrayLike = 0.2,
loss_dB: FloatArrayLike = 0.3,
shift: FloatArrayLike = 0.0,
loss_dB_cross: FloatArrayLike | None = None,
loss_dB_thru: FloatArrayLike | None = None,
splitting_ratio_cross: FloatArrayLike = 0.5,
splitting_ratio_thru: FloatArrayLike = 0.5,
) -> SDict
Realistic 2x2 MMI coupler model with dispersion and asymmetry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
wavelength in micrometers. |
WL_C
|
wl0
|
FloatArrayLike
|
Center wavelength of the MMI in micrometers. |
WL_C
|
fwhm
|
FloatArrayLike
|
Full width at half maximum bandwidth in micrometers. |
0.2
|
loss_dB
|
FloatArrayLike
|
Insertion loss of the MMI at center wavelength. |
0.3
|
shift
|
FloatArrayLike
|
The peak shift of the cross-transmission in micrometers. |
0.0
|
loss_dB_cross
|
FloatArrayLike | None
|
Optional separate insertion loss in dB for cross ports. If None, uses loss_dB. Allows modeling of asymmetric loss. |
None
|
loss_dB_thru
|
FloatArrayLike | None
|
Optional separate insertion loss in dB for bar (through) ports. If None, uses loss_dB. Allows modeling of asymmetric loss. |
None
|
splitting_ratio_cross
|
FloatArrayLike
|
Power splitting ratio for cross ports (0 to 1). Allows modeling of imbalanced coupling. Defaults to 0.5. |
0.5
|
splitting_ratio_thru
|
FloatArrayLike
|
Power splitting ratio for bar ports (0 to 1). Allows modeling of imbalanced transmission. Defaults to 0.5. |
0.5
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary representing the realistic MMI coupler behavior. |
Examples:
Basic 2x2 MMI:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.mmi2x2(wl=wl, shift=0.001)
thru = np.abs(s[("o1", "o4")]) ** 2
cross = np.abs(s[("o1", "o3")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
```
Source code in src/sax/models/mmis.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | |
mmi2x2_ideal
¶
mmi2x2_ideal(*, wl: FloatArrayLike = WL_C) -> SDict
Ideal 2x2 multimode interference (MMI) coupler model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
The wavelength in micrometers. |
WL_C
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary representing the ideal MMI coupler behavior. |
Examples:
Ideal 2x2 MMI:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.mmi2x2_ideal(wl=wl)
thru = np.abs(s[("o1", "o4")]) ** 2
cross = np.abs(s[("o1", "o3")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/mmis.py
model_2port
¶
model_2port(p1: Name, p2: Name) -> SDictModel
Generate a general 2-port model with 100% transmission.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p1
|
Name
|
Name of the first port (typically in0 or o1). |
required |
p2
|
Name
|
Name of the second port (typically out0 or o2). |
required |
Returns:
| Type | Description |
|---|---|
SDictModel
|
A 2-port model |
Source code in src/sax/models/factories.py
model_3port
¶
model_3port(p1: Name, p2: Name, p3: Name) -> SDictModel
Generate a general 3-port model (1x2 splitter).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p1
|
Name
|
Name of the input port (typically o1 or in0). |
required |
p2
|
Name
|
Name of the first output port (typically o2 or out1). |
required |
p3
|
Name
|
Name of the second output port (typically o3 or out0). |
required |
Returns:
| Type | Description |
|---|---|
SDictModel
|
A 3-port model |
Source code in src/sax/models/factories.py
model_4port
¶
model_4port(p1: Name, p2: Name, p3: Name, p4: Name) -> SDictModel
Generate a general 4-port model (2x2 coupler).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p1
|
Name
|
Name of the first input port (typically o1 or in0). |
required |
p2
|
Name
|
Name of the second input port (typically o2 or in1). |
required |
p3
|
Name
|
Name of the first output port (typically o3 or out1). |
required |
p4
|
Name
|
Name of the second output port (typicall o4 or out0). |
required |
Returns:
| Type | Description |
|---|---|
SDictModel
|
A 4-port model |
Source code in src/sax/models/factories.py
passthru
¶
Copy 100% of the power at each input port to its corresponding output port.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_links
|
int
|
Number of independent pass-through links (input-output pairs). This creates a device with num_links inputs and num_links outputs. |
required |
reciprocal
|
bool
|
If True, the device exhibits reciprocal behavior where transmission is identical in both directions. This is typical for passive devices like fibers and waveguides. Defaults to True. |
True
|
Returns:
| Type | Description |
|---|---|
SCooModel
|
A passthru model |
Examples:
Create an 8×8 optical switch (straight-through state):
switch_thru = sax.models.passthru(8, reciprocal=True)
Si, Sj, Sx, port_map = switch_thru(wl=1.55)
# Each input passes straight to corresponding output
Source code in src/sax/models/factories.py
phase_shifter
¶
phase_shifter(
wl: FloatArrayLike = WL_C,
neff: FloatArrayLike = 2.34,
voltage: FloatArrayLike = 0,
length: FloatArrayLike = 10,
loss: FloatArrayLike = 0.0,
) -> SDict
Simple voltage-controlled phase shifter model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
The wavelength in micrometers. |
WL_C
|
neff
|
FloatArrayLike
|
The Effective index of the unperturbed waveguide mode. |
2.34
|
voltage
|
FloatArrayLike
|
The Applied voltage in volts. The phase shift is assumed to be linearly proportional to voltage with a coefficient of π rad/V. Positive voltage increases the phase. Defaults to 0 V. |
0
|
length
|
FloatArrayLike
|
The length of the phase shifter in micrometers. |
10
|
loss
|
FloatArrayLike
|
Additional loss in dB introduced by the active region. |
0.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary containing the complex-valued transmission coefficient. |
Examples:
Phase shifter:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.phase_shifter(wl=wl, loss=3.0)
thru = np.abs(s[("o1", "o2")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/straight.py
propagation_constant
¶
propagation_constant(
f: FloatArrayLike,
ep_eff: FloatArrayLike,
tand: FloatArrayLike = 0.0,
ep_r: FloatArrayLike = 1.0,
) -> Array
Complex propagation constant of a quasi-TEM transmission line.
For the general lossy case
where the dielectric attenuation is
and the phase constant is
For a superconducting line (\(\tan\delta = 0\)) the propagation is purely imaginary: \(\gamma = j\beta\).
References
Pozar, §3.8
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Frequency (Hz). |
required |
ep_eff
|
FloatArrayLike
|
Effective permittivity. |
required |
tand
|
FloatArrayLike
|
Dielectric loss tangent (default 0 — lossless). |
0.0
|
ep_r
|
FloatArrayLike
|
Substrate relative permittivity (only needed when |
1.0
|
Returns:
| Type | Description |
|---|---|
Array
|
Complex propagation constant \(\gamma\) (1/m). |
Source code in src/sax/models/rf.py
reflector
¶
reflector(
*,
wl: FloatArrayLike = WL_C,
reflection: FloatArrayLike = 0.5,
loss_dB: FloatArrayLike = 0.0,
) -> SDict
Partial reflector / mirror model.
A 2-port component that reflects a fraction of the input power and transmits the rest (minus any loss).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. |
WL_C
|
reflection
|
FloatArrayLike
|
Power reflection coefficient between 0 and 1. 0 means full transmission, 1 means full reflection. Defaults to 0.5. |
0.5
|
loss_dB
|
FloatArrayLike
|
Insertion loss in dB applied to both reflected and transmitted amplitudes. Defaults to 0.0 dB. |
0.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary for the reflector. |
Examples:
50% reflector:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.reflector(wl=wl, reflection=0.5)
thru = np.abs(s[("o1", "o2")]) ** 2
refl = np.abs(s[("o1", "o1")]) ** 2
plt.figure()
plt.plot(wl, thru, label="transmission")
plt.plot(wl, refl, label="reflection")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/reflectors.py
resistor
¶
resistor(
*,
f: FloatArrayLike = DEFAULT_FREQUENCY,
resistance: FloatLike = 50,
z0: ComplexLike = 50,
) -> SDict
Ideal two-port resistor model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Frequency in Hz |
DEFAULT_FREQUENCY
|
resistance
|
FloatLike
|
Resistance in Ohms |
50
|
z0
|
ComplexLike
|
Reference impedance in Ω. |
50
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary representing the resistor element |
References
[@pozar2012]
Examples:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
f = np.linspace(1e9, 10e9, 500)
s = sax.models.rf.resistor(f=f, resistance=100, z0=50)
plt.figure()
plt.plot(f / 1e9, np.abs(s[("o1", "o1")]), label="|S11|")
plt.plot(f / 1e9, np.abs(s[("o1", "o2")]), label="|S12|")
plt.plot(f / 1e9, np.abs(s[("o2", "o2")]), label="|S22|")
plt.xlabel("Frequency [GHz]")
plt.ylabel("Magnitude")
plt.legend()
Source code in src/sax/models/rf.py
splitter_ideal
¶
splitter_ideal(*, wl: FloatArrayLike = WL_C, coupling: FloatArrayLike = 0.5) -> SDict
Ideal 1x2 power splitter model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. |
WL_C
|
coupling
|
FloatArrayLike
|
Power coupling ratio between 0 and 1. |
0.5
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary containing the complex-valued cross/thru coefficients. |
Examples:
Ideal 1x2 splitter:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.splitter_ideal(wl=wl, coupling=0.3)
thru = np.abs(s[("o1", "o3")]) ** 2
cross = np.abs(s[("o1", "o2")]) ** 2
plt.figure()
plt.plot(wl, thru, label="thru")
plt.plot(wl, cross, label="cross")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/splitters.py
tee
¶
tee(*, f: FloatArrayLike = DEFAULT_FREQUENCY) -> SDict
Ideal three-port RF power divider/combiner (T-junction).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
FloatArrayLike
|
Array of frequency points in Hz |
DEFAULT_FREQUENCY
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-dictionary representing ideal RF T-junction behavior |
Examples:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
import jaxellip # pyright: ignore[reportMissingImports]
import scipy.constants
sax.set_port_naming_strategy("optical")
f = np.linspace(1e9, 10e9, 500)
s = sax.models.rf.tee(f=f)
plt.figure()
plt.plot(f / 1e9, np.abs(s[("o1", "o2")]) ** 2, label="|S12|^2")
plt.plot(f / 1e9, np.abs(s[("o1", "o3")]) ** 2, label="|S13|^2")
plt.plot(f / 1e9, np.abs(s[("o2", "o3")]) ** 2, label="|S23|^2")
plt.xlabel("Frequency [GHz]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/rf.py
terminator
¶
terminator(*, wl: FloatArrayLike = WL_C, reflection: FloatArrayLike = 0.0) -> SDict
Optical terminator / absorber model.
A 1-port device that absorbs all incoming light with minimal reflection. Used to terminate unused ports and prevent back-reflections.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wl
|
FloatArrayLike
|
Wavelength in micrometers. |
WL_C
|
reflection
|
FloatArrayLike
|
Residual power reflection coefficient between 0 and 1. Defaults to 0.0 (perfect absorber). |
0.0
|
Returns:
| Type | Description |
|---|---|
SDict
|
S-matrix dictionary for the terminator. |
Examples:
Ideal terminator:
# mkdocs: render
import matplotlib.pyplot as plt
import numpy as np
import sax
sax.set_port_naming_strategy("optical")
wl = sax.wl_c()
s = sax.models.terminator(wl=wl, reflection=0.01)
refl = np.abs(s[("o1", "o1")]) ** 2
plt.figure()
plt.plot(wl, refl, label="reflection")
plt.xlabel("Wavelength [μm]")
plt.ylabel("Power")
plt.legend()
Source code in src/sax/models/terminators.py
transmission_line_s_params
¶
transmission_line_s_params(
gamma: ComplexLike,
z0: ComplexLike,
length: FloatArrayLike,
z_ref: ComplexLike | None = None,
) -> tuple[Array, Array]
S-parameters of a uniform transmission line (ABCD→S conversion).
The ABCD matrix of a line with characteristic impedance \(Z_0\), propagation constant \(\gamma\), and length \(\ell\) is:
Converting to S-parameters referenced to \(Z_{\mathrm{ref}}\)
When z_ref is None the reference impedance defaults to z0
(matched case), giving \(S_{11} = 0\) and
\(S_{21} = e^{-\gamma\ell}\).
References
Pozar, Table 4.2
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gamma
|
ComplexLike
|
Complex propagation constant (1/m). |
required |
z0
|
ComplexLike
|
Characteristic impedance (Ω). |
required |
length
|
FloatArrayLike
|
Physical length (m). |
required |
z_ref
|
ComplexLike | None
|
Reference (port) impedance (Ω). Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
tuple[Array, Array]
|
|
Source code in src/sax/models/rf.py
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 | |
unitary
¶
unitary(
num_inputs: int,
num_outputs: int,
*,
reciprocal: bool = True,
diagonal: bool = False,
) -> SCooModel
Generate a unitary N×M optical device model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_inputs
|
int
|
Number of input ports for the device. |
required |
num_outputs
|
int
|
Number of output ports for the device. |
required |
reciprocal
|
bool
|
If True, the device exhibits reciprocal behavior (S = S^T). This is typical for passive optical devices. Defaults to True. |
True
|
diagonal
|
bool
|
If True, creates a diagonal coupling matrix (each input couples to only one output). If False, creates full coupling between all input-output pairs. Defaults to False. |
False
|
Returns:
| Type | Description |
|---|---|
SCooModel
|
A unitary model |
Source code in src/sax/models/factories.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | |