Skip to content
Advanced

Reflection, VSWR and return loss

The reflection coefficient of a load \(Z\) against a reference \(Z_0\) (Impedance and admittance):

\[ \Gamma = \frac{Z - Z_0}{Z + Z_0} \]
  • \(\Gamma\) is Complex<Per<Volt, Volt>, One, F>, a ratio of root-power quantities: its to_db is \(20 \cdot \lg|\Gamma|\), and return_loss is \(-20 \cdot \lg|\Gamma|\), a Fixed<Loss<Decibel>, One, F> positive for a passive load.
  • VSWR is \((1 + \lvert \Gamma \rvert)/(1 - \lvert \Gamma \rvert)\), the ratio of the standing wave's largest voltage to its smallest, a Fixed<Per<Volt, Volt>, One, F>; infinite at \(|\Gamma| \ge 1\).
  • Mismatch loss is \(1 - \lvert \Gamma \rvert^2\), the share of the incident power the load takes, a Fixed<Per<Watt, Watt>, One, F>: its to_db is \(10 \lg\), the loss as a negative level (−0.51 dB at VSWR 2).
use exact_units::{Complex, Impedance, Z0, prefix::One, q, units::{Decibel, Loss}};

let z0 = Z0::<One, f64>::bounded(50.0, 0.0);
let gamma = Impedance::<One, f64>::bounded(100.0, 0.0).reflection(z0).finite().unwrap();
assert_eq!(gamma, Complex::<_, _, f64>::bounded(1.0 / 3.0, 0.0));
assert!(gamma.vswr().is_in(q!(2 V/V +- 0.000001 V/V, Inside))); // a hair under 2 in f64
assert!(gamma.return_loss().is_in(q!(9.542425... Loss<Decibel>))); // 20·lg 3
assert!(gamma.mismatch_loss().is_in(q!(0.888... W/W))); // 8/9 of the power, -0.51 dB as its to_db()

Floats only: \(\Gamma\) is a complex quotient, rounded twice in integers. A firmware works \(\Gamma\) out once in floats (a bench tool, a reflectometer's host side), or tests a Q15 \(|\Gamma|^2\) against a db!(norm_sqr ..) threshold without ever forming \(\Gamma\) — see Levels, dBm and cable loss.

On the extended plane

reflection and to_admittance/to_impedance (Impedance and admittance) have a value for every load, the point at infinity included, and no error. \(Z = 0\) (a short) is \(\Gamma = -1\); \(Z = \infty\) (an open) is \(\Gamma = 1\); \(Z = -Z_0\), a negative resistance an oscillator's or a tunnel diode's can reach, is \(\Gamma = \infty\), where the denominator of the formula above is 0:

use exact_units::{Complex, Extended, Impedance, Z0, prefix::One};

let z0 = Z0::<One, f64>::bounded(50.0, 0.0);
let open = Impedance::<One, f64>::bounded(f64::INFINITY, 0.0);
assert_eq!(open.reflection(z0), Extended::Finite(Complex::<_, _, f64>::bounded(1.0, 0.0)));

// a negative resistance of −50 Ω on 50 Ω
let oscillator = Impedance::<One, f64>::bounded(-50.0, 0.0);
assert_eq!(oscillator.reflection(z0), Extended::Infinity);

reflection computes \(\Gamma\) by Smith's division: no part of \(Z\) or \(Z_0\) is squared, so a part past the square root of the float's largest value still gives \(\Gamma\), and the result is never NaN — the larger of the real and imaginary parts of the denominator is nonzero, and the quotient has its sign.

Why no error, ever

A mismatch this bad is still a load a tuner is adjusting toward, not a fault to report: an antenna swept across its band passes through shorts, opens and negative resistances on its way to the match, and a sweep that stops at the first \(\infty\) never finds it. A worked matching example sweeps one.