1 minute read

The traps that wouldn’t equalize

Two symmetric optical traps. Same target intensity. The Gerchberg-Saxton algorithm running for 100 iterations. And yet one trap was bright, the other dim, oscillating back and forth forever without converging.

GS algorithm and phase scaling

The problem

The standard weight update rule from Di Leonardo et al. (2007) is aggressive:

Original weight update (undamped):
w_j(n+1) = w_j(n) × ⟨|V|⟩ / |V_j(n)|
If trap j is too bright → weight decreases. Too dim → weight increases.

The issue: with only two traps, the correction overshoots. Trap A gets too much weight, trap B too little. Next iteration, the opposite happens. The uniformity metric oscillates around 0.85 without improving.

The fix

A damping exponent γ ∈ (0, 1] that controls the correction rate:

Damped weight update (γ = 0.5):
w_j(n+1) = w_j(n) × (⟨|V|⟩ / |V_j(n)|)γ
γ=1.0 → original (aggressive, oscillates)
γ=0.5 → half-strength corrections (stable, monotonic convergence)

With γ=0.5, uniformity converges monotonically from ~0.85 to ~0.97 over 30+ iterations instead of oscillating. The key insight: making half-strength corrections each step prevents the overshoot-undershoot cycle.

The phase_scale sweet spot

Also found the right value for the phase_scale parameter. Three regimes:

phase_scaleFringesResult
π< 1Mask looks flat, no visible pattern
10 × 2π ≈ 638-15Clear, beautiful blazed grating patterns
2π × N/4 ≈ 800100+Mask looks like noise, unresolvable

The sweet spot at 10 × 2π gives enough spatial frequency to see the holographic structure while keeping patterns visually interpretable. Also tightened tolerance to 10⁻⁸ and enforced minimum 30 iterations before checking convergence.

Fourier optics principles

Small changes, big difference. Three numbers: γ=0.5, phase_scale=10×2π, min_iterations=30. Optical tweezers on GitHub.