A browser-based teaching app that builds up the Pound–Drever–Hall (PDH) laser frequency-stabilization technique one idea at a time, then unlocks a full control-systems simulator. Built with Vite + React + TypeScript; all physics runs client-side from a small, dependency-free simulation engine.
npm install
npm run dev # development server (hot reload)
# or
npm run build && npm run preview # production build + static previewThen open the printed local URL (e.g. http://localhost:5173).
Progress is saved to localStorage, so you can close the tab and pick up where
you left off. Use Reset (top-right) to start over.
Ten guided stages, each introducing exactly one new concept with an interactive Plotly figure and a guided "Try this" experiment:
| Stage | Idea |
|---|---|
| 0 | Why a free-running laser must be locked at all |
| 1 | The Fabry–Pérot cavity and the Airy reflection dip |
| 2 | Why reflected power alone is ambiguous (it is symmetric) |
| 3 | Adding sidebands with an EOM (Bessel-weighted spectrum) |
| 4 | The antisymmetric reflected-phase S-curve |
| 5 | Turning phase into a measurable RF beat note |
| 6 | Demodulation, the demod-phase knob, and RAM |
| 7 | Reading the S-curve: discriminant slope vs. capture range |
| 8 | Closing the loop with a PI controller (lock acquisition) |
| 9 | Real limits: actuator bandwidth and loop delay |
After Stage 9, Free Play unlocks: a four-tab dashboard (S-curve · Bode · live Time Domain · Noise/PSD) with every cavity, modulation, actuator, controller and noise parameter exposed at once, plus named presets. The time-domain simulation streams from a Web Worker so the UI stays responsive.
A Theory & Derivations appendix (top-right) states the actual mathematics the simulator implements, with references.
The engine (src/sim/) is not a cartoon — it computes the real quantities:
- Cavity reflection from the exact two-mirror Fabry–Pérot coefficient
F(ω) = [r₁ − r₂ e^{−iφ}] / [1 − r₁r₂ e^{−iφ}], giving the true Airy dip and the antisymmetric reflected phase. - Sidebands from Bessel functions
Jₙ(β)(series forJ₀,J₁; Miller's downward recurrence for higher orders), validated against reference values. - The PDH error signal as the demodulated beat,
ε ∝ Im{F(ω)F*(ω+Ω) − F*(ω)F(ω−Ω)}·cos φ_LO + …·sin φ_LO, keeping both quadratures so the demod-phase knob behaves like a real lock-in. - Residual Amplitude Modulation (RAM) as a first-class effect. This matters:
for an ideal lossless cavity one can show
D(−δ) = −D(δ), so every demod quadrature is antisymmetric and a 90°-wrong demod phase merely flattens the discriminant. The familiar symmetric dip only appears with RAM present — the app models this explicitly rather than faking the classic textbook cartoon. - A genuine closed loop in the time domain: error → PI (with anti-windup) → finite-bandwidth actuator → transport-delay ring buffer → detuning, with a seeded noise/disturbance model for reproducible runs.
- Open-loop Bode analysis using the same gains as the time-domain loop, with numerically located gain/phase margins — so the "delay collapses the phase margin" lesson is quantitative, not asserted.
src/
sim/ pure simulation modules (no React)
cavity.ts Fabry–Pérot reflection, finesse/linewidth, finesse→R
modulation.ts Bessel functions, sideband powers
errorSignal.ts PDH error signal, quadratures, S-curve analysis
controller.ts PI(D) with anti-windup
plant.ts actuator low-pass + delay line
noise.ts seeded RNG, white + flicker noise, disturbance
integrator.ts time-domain closed-loop engine
loopAnalysis.ts open-loop Bode + margins
fft.ts radix-2 FFT + periodogram (PSD)
presets.ts default params + named Free Play presets
content/ stage text + slider configuration
components/ SignalChainMap, StagePanel, StageVisual, FreePlay, TheoryModal, …
simWorker.ts Web Worker wrapping the integrator for Free Play
store.ts Zustand store + localStorage persistence
- E. D. Black, An introduction to Pound–Drever–Hall laser frequency stabilization, Am. J. Phys. 69, 79 (2001).
- R. W. P. Drever et al., Appl. Phys. B 31, 97 (1983).
- T. Day, E. K. Gustafson, R. L. Byer, IEEE J. Quantum Electron. 28, 1106 (1992).