|
| 1 | +using ElectronDynamicsModels |
| 2 | +using ModelingToolkit |
| 3 | +using OrdinaryDiffEqVerner, OrdinaryDiffEqTsit5 |
| 4 | +using StaticArrays |
| 5 | +using Test |
| 6 | +using SciMLBase |
| 7 | +using LinearAlgebra |
| 8 | +using FFTW |
| 9 | + |
| 10 | +@testset "Thomson Scattering — Dipole Pattern" begin |
| 11 | + # Non-relativistic Thomson scattering from a single electron in a weak plane wave. |
| 12 | + # For a₀ ≪ 1 (linear polarization along x), the scattered radiation at the |
| 13 | + # fundamental frequency follows the dipole pattern: |A_ω|² ∝ sin²(θ) / R² |
| 14 | + # where θ is the angle from the polarization (x) axis. |
| 15 | + # Higher harmonics should be negligible. |
| 16 | + |
| 17 | + # Use natural units (c = 1) |
| 18 | + @named ref_frame = ProperFrame(:natural) |
| 19 | + |
| 20 | + a₀ = 0.01 |
| 21 | + @named laser = PlaneWave(; amplitude = a₀, frequency = 1.0, ref_frame) |
| 22 | + @named elec = ClassicalElectron(; laser) |
| 23 | + sys = mtkcompile(elec) |
| 24 | + |
| 25 | + ω = 1.0 |
| 26 | + T = 2π / ω |
| 27 | + c = 1.0 |
| 28 | + |
| 29 | + # Simulate for several periods to get a clean FFT |
| 30 | + n_periods = 20 |
| 31 | + τi = -n_periods * T / 2 |
| 32 | + τf = n_periods * T / 2 |
| 33 | + tspan = (τi, τf) |
| 34 | + |
| 35 | + x⁰ = [τi * c, 0.0, 0.0, 0.0] |
| 36 | + u⁰ = [c, 0.0, 0.0, 0.0] # electron at rest |
| 37 | + |
| 38 | + u0 = [sys.x => x⁰, sys.u => u⁰] |
| 39 | + prob = ODEProblem{false, SciMLBase.FullSpecialize}( |
| 40 | + sys, u0, tspan, u0_constructor = SVector{8}, fully_determined = true |
| 41 | + ) |
| 42 | + sol = solve(prob, Vern9(), reltol = 1.0e-14, abstol = 1.0e-14) |
| 43 | + |
| 44 | + @test SciMLBase.successful_retcode(sol) |
| 45 | + |
| 46 | + # Build trajectory interpolant |
| 47 | + trajs = [TrajectoryInterpolant(sol, sys.x, sys.u)] |
| 48 | + |
| 49 | + # Screen setup: observe from far field at distance Z along z |
| 50 | + Z = 1.0e4 # far field: Z ≫ λ = 2π |
| 51 | + δt = T / 8 # 8 samples per period (Nyquist up to 4th harmonic) |
| 52 | + |
| 53 | + Nx, Ny = 15, 15 |
| 54 | + L = Z * 0.1 # small screen so all pixels have similar arrival times |
| 55 | + |
| 56 | + # Cover the full range: earliest signal (center pixel) to latest end (corner pixel) |
| 57 | + x⁰_earliest = c * τi + Z |
| 58 | + x⁰_latest = c * τf + hypot(Z, L * sqrt(2)) |
| 59 | + N_samples = ceil(Int, (x⁰_latest - x⁰_earliest) / (c * δt)) |
| 60 | + x⁰_samples = range(start = x⁰_earliest, step = c * δt, length = N_samples) |
| 61 | + |
| 62 | + screen = ObserverScreen( |
| 63 | + LinRange(-L, L, Nx), |
| 64 | + LinRange(-L, L, Ny), |
| 65 | + Z, |
| 66 | + x⁰_samples |
| 67 | + ) |
| 68 | + |
| 69 | + A_s = accumulate_potential(trajs, screen, Tsit5()) |
| 70 | + A_ω = rfft(A_s, 1) |
| 71 | + |
| 72 | + # Find fundamental frequency bin |
| 73 | + freqs = rfftfreq(N_samples, 1 / δt) |
| 74 | + idx_f1 = findmin(f -> abs(f - ω / 2π), freqs)[2] |
| 75 | + |
| 76 | + # Extract |A_ω|² at fundamental frequency (all 3 spatial components) |
| 77 | + intensity = zeros(Nx, Ny) |
| 78 | + A_ω_expected = zeros(Nx, Ny) |
| 79 | + for ix in 1:Nx, iy in 1:Ny |
| 80 | + intensity[ix, iy] = sum(abs2, A_ω[idx_f1, 2:4, ix, iy]) |
| 81 | + r_obs = [screen.x_grid[ix], screen.y_grid[iy], Z] |
| 82 | + R = norm(r_obs) |
| 83 | + n̂ = r_obs / norm(r_obs) |
| 84 | + A_ω_expected[ix, iy] = (1 - n̂[1]^2) / R^2 |
| 85 | + end |
| 86 | + |
| 87 | + @testset "Dipole angular pattern" begin |
| 88 | + for ix in 1:Nx, iy in 1:Ny |
| 89 | + expected = A_ω_expected[ix, iy] / maximum(A_ω_expected) |
| 90 | + @test intensity[ix, iy] / maximum(intensity) ≈ expected rtol = 0.05 |
| 91 | + end |
| 92 | + end |
| 93 | + |
| 94 | + @testset "Higher harmonics suppressed" begin |
| 95 | + # For a₀ ≪ 1, the 2nd harmonic should be much weaker than fundamental |
| 96 | + idx_f2 = findmin(f -> abs(f - 2ω / 2π), freqs)[2] |
| 97 | + power_f1 = sum(abs2, A_ω[idx_f1, 2:4, :, :]) |
| 98 | + power_f2 = sum(abs2, A_ω[idx_f2, 2:4, :, :]) |
| 99 | + |
| 100 | + @test power_f2 / power_f1 < 1.0e-4 |
| 101 | + end |
| 102 | +end |
0 commit comments