Problem
The standard VCVS (voltage-controlled voltage source) stamp used for unidirectional optical components has an implicit phase-dependent input reflection coefficient.
A VCVS with V_out = T · V_in is stamped as:
return {
"o1": s.i_fwd, # shared branch current at input
"o2": -s.i_fwd, # shared branch current at output
"i_fwd": V_o2 - T * V_o1, # constraint
}
Converting to S-parameters, this device has:
S11 = (1 - T) / (1 + T) S21 = 2T / (1 + T)
For |T| ≈ 1, |S11| = |tan(φ/2)| — the reflection sweeps from 0 to ∞ as phase rotates. This is not physical for a waveguide or phase shifter, which should have S11 = 0 and S21 = T.
Impact
In a thermal MZI circuit (mmi1x2 → heater → mmi2x2 → detectors), the artificial back-reflection from the heater VCVS propagates backward through the mmi1x2's Y-matrix. Because the mmi1x2 is near-lossless, its Y-matrix is ill-conditioned (det(S+I) = 1 - 2t² ≈ 0.067 for 0.3 dB loss), amplifying the reflected current ~15×. This causes:
- Non-physical power oscillation at intermediate nodes (between mmi1x2 output and heater input)
- Node voltage V(W1) depends on heater phase:
V(W1) ∝ 1 / (T(I) + T_fixed + 2) instead of being constant
- Visible amplitude modulation on what should be a pure phase rotation
Fix
Replace the shared branch current at the input port with a matched input admittance (Y_in = 1/z₀ = 1):
return {
"o1": signals.o1, # matched input: Y_in = 1, gives S11 = 0
"o2": -s.i_fwd, # output current from constraint
"i_fwd": V_o2 - T * V_o1,
}
This decouples the input from the output loading. The KCL at the input node no longer contains T(I), so the node voltage is constant across the sweep. Power conservation holds: input power |V|² equals output power |T|² · |V|².
Scope
This affects any VCVS-based component where T varies during a simulation (e.g., thermal phase shifters, tunable couplers). Components with fixed T are less affected because the reflection coefficient is constant, but still present incorrect S11 values.
The TunableBeamSplitter in circulax/components/photonic.py uses the same shared-branch-current pattern and would have the same issue.
The near-lossless SAX component Y-matrices (via s_to_y) amplify the problem but are not the root cause — the VCVS stamp itself is the source of the artificial reflection.
Problem
The standard VCVS (voltage-controlled voltage source) stamp used for unidirectional optical components has an implicit phase-dependent input reflection coefficient.
A VCVS with
V_out = T · V_inis stamped as:Converting to S-parameters, this device has:
For
|T| ≈ 1,|S11| = |tan(φ/2)|— the reflection sweeps from 0 to ∞ as phase rotates. This is not physical for a waveguide or phase shifter, which should have S11 = 0 and S21 = T.Impact
In a thermal MZI circuit (mmi1x2 → heater → mmi2x2 → detectors), the artificial back-reflection from the heater VCVS propagates backward through the mmi1x2's Y-matrix. Because the mmi1x2 is near-lossless, its Y-matrix is ill-conditioned (
det(S+I) = 1 - 2t² ≈ 0.067for 0.3 dB loss), amplifying the reflected current ~15×. This causes:V(W1) ∝ 1 / (T(I) + T_fixed + 2)instead of being constantFix
Replace the shared branch current at the input port with a matched input admittance (
Y_in = 1/z₀ = 1):This decouples the input from the output loading. The KCL at the input node no longer contains T(I), so the node voltage is constant across the sweep. Power conservation holds: input power
|V|²equals output power|T|² · |V|².Scope
This affects any VCVS-based component where
Tvaries during a simulation (e.g., thermal phase shifters, tunable couplers). Components with fixedTare less affected because the reflection coefficient is constant, but still present incorrect S11 values.The
TunableBeamSplitterincirculax/components/photonic.pyuses the same shared-branch-current pattern and would have the same issue.The near-lossless SAX component Y-matrices (via
s_to_y) amplify the problem but are not the root cause — the VCVS stamp itself is the source of the artificial reflection.