β: This English translation is in beta — the Traditional-Chinese original is the authoritative version.
Lab 05 — ISF Fourier coefficients and Parseval
The ISF is a -periodic function, so it can be decomposed into a Fourier series. Why decompose? Because what appears in the phase-noise formulas is the ISF's Fourier coefficients , not itself: (the DC coefficient) decides whether 1/f noise gets upconverted into close-in phase noise; sets the weight with which noise near is moved to the carrier; and by Parseval (Parseval's theorem — time-domain energy = frequency-domain energy) the sum of squares of all coefficients equals , where directly sets the 1/f² phase-noise magnitude.
This lab does three things: (1) compute the of one ISF and reconstruct it with 1, 2, 4 harmonics; (2) plot the coefficient spectrum and numerically verify the Parseval relation; (3) put a symmetric () and an asymmetric () ISF side by side to show that only upconverts 1/f noise.
Physical intuition: think of the ISF as "the local-oscillator (LO) waveform of the mixer that the oscillator is." Noise does not enter the phase directly; it is first comb-sampled by the ISF in the frequency domain — noise near each is weighted by and downconverted to near the carrier. So the ISF's shape (its harmonic content) is the knob the designer can actually turn: make the waveform symmetric (suppress ) to suppress 1/f³; make the overall small to suppress 1/f².
1. Learning objectives
- Write the ISF as the Fourier series , and understand the physical role of each coefficient.
- Compute the of a given ISF by numerical integration, and demonstrate "more harmonics, closer reconstruction."
- Use the Parseval relation to connect "frequency-domain coefficients" with "time-domain rms," and face honestly the DC-term bookkeeping trap under the half-amplitude convention.
- Understand why (= the ISF's mean value × 2) is the "gate" for 1/f noise upconversion: a symmetric waveform gives → the 1/f³ corner is pushed very low.
- Maps to [P1] Eq.(12),(20),(24).
2. Mathematical model
ISF Fourier series ([P1] Eq.(12), p.183):
- is the mean (DC value) of the ISF. Note the factor of 2: the Fourier coefficient is called , but the ISF's DC value is . This factor is extremely easy to get wrong when computing the 1/f³ corner (see the notation pitfalls in notation).
- are the amplitude and phase of the -th harmonic; , , where are the standard cos/sin coefficients.
- dimension check: is dimensionless, cos is dimensionless, so every is dimensionless ✓.
Parseval / rms ISF ([P1] Eq.(20), p.185):
It links "the sum of squares of all harmonics" to "the ISF's mean square × 2." Physically: white-noise phase noise is proportional to ([P1] Eq.(19) → Eq.(21)), so knowing is enough to compute the 1/f² phase noise without tracking every harmonic individually.
The half-amplitude-convention bookkeeping trap (you will see it with your own eyes in this lab): the on the left side of Eq.(20) must use the same definition as the of Eq.(12). This lab's
compute_fourier_coefficientsreturnsc[0] = |a0|, where , i.e. . For an ISF with a non-zero DC value, throwingc[0]**2straight into counts the DC energy once too many (because the cos terms enter at half amplitude while the DC term enters at full amplitude, so their squared weights differ). This is exactly why the Parseval numbers below disagree by ~10% — we choose to show it as is rather than hide it.
1/f³ corner ([P1] Eq.(24), p.185, which explains why matters):
(symmetric waveform) the 1/f³ corner , and the close-in phase noise is clean.
3. Block diagram
4. Core Python code
The Fourier coefficients are computed directly by trapezoidal integration
(simulations/common/isf_utils.py, quoted verbatim):
def compute_fourier_coefficients(theta, gamma, n_harmonics):
theta = np.asarray(theta, dtype=float)
gamma = np.asarray(gamma, dtype=float)
a0 = (1 / np.pi) * _trapz(gamma, theta)
a = np.zeros(n_harmonics + 1)
b = np.zeros(n_harmonics + 1)
for n in range(1, n_harmonics + 1):
a[n] = (1 / np.pi) * _trapz(gamma * np.cos(n * theta), theta)
b[n] = (1 / np.pi) * _trapz(gamma * np.sin(n * theta), theta)
c = np.sqrt(a ** 2 + b ** 2)
c[0] = abs(a0) # c0 magnitude (the DC coefficient)
phase = np.arctan2(-b, a)
return a0, a, b, c, phase
rms and the Parseval check (fig_coefficients in simulations/lab_05_fourier_isf.py):
a0, a, b, c, ph = compute_fourier_coefficients(theta, g, n_harmonics=8)
# check Parseval: sum c_n^2 ?= 2 Gamma_rms^2
parseval_lhs = c[0] ** 2 + np.sum(c[1:] ** 2)
grms = gamma_rms(theta, g)
The example ISF used in this lab (deliberately made asymmetric so several harmonics are non-zero;
the +0.25 creates the non-zero ):
def make_isf(theta):
"""A richer asymmetric ISF so several harmonics are non-trivial."""
return (-np.sin(theta) + 0.35 * np.sin(2 * theta)
+ 0.18 * np.cos(3 * theta) + 0.25) # the +0.25 sets a non-zero c0
Symmetric vs asymmetric comparison (fig_symmetric_vs_asymmetric):
g_sym = np.cos(theta) # c0 = 0 (symmetric)
g_asym = gamma_asymmetric(theta, alpha=0.4) # c0 = 2*alpha = 0.8
- Why
thetamust include the endpoint (endpoint=True) across the full : the trapezoidal rule must integrate