|
| 1 | +# Trajectory access (wraps ODE solution for CPU) |
| 2 | +struct TrajectoryInterpolant{S,I} |
| 3 | + sol::S |
| 4 | + r_idxs::I |
| 5 | + u_idxs::I |
| 6 | +end |
| 7 | +(t::TrajectoryInterpolant)(τ) = (t.sol(τ, idxs = t.r_idxs[2:4]), t.sol(τ, idxs = t.u_idxs[2:4])) |
| 8 | + |
| 9 | +# Convenience: extract all trajectories from ensemble solution |
| 10 | +# trajectories(ensemble_sol, sys) → Vector{TrajectoryInterpolant} |
| 11 | +function trajectories(ensemble_sol::EnsembleSolution) |
| 12 | + sys = ensemble_sol.u[1].prob.f.sys # sys is the same across the ensemble |
| 13 | + [TrajectoryInterpolant(ensemble_sol.u[i], r_idxs=sys.x, u_idxs=sys.u) for i in ensemble_sol.trajectories] |
| 14 | +end |
| 15 | + |
| 16 | +# Observer geometry + temporal sampling |
| 17 | +struct ObserverScreen{G,T} |
| 18 | + x_grid::G # e.g., LinRange for x |
| 19 | + y_grid::G # e.g., LinRange for y |
| 20 | + z::T # screen distance |
| 21 | + x⁰_start::T |
| 22 | + δt::T |
| 23 | + N_samples::Int |
| 24 | +end |
| 25 | + |
| 26 | +# dτᵣ/dt = 1/(u⁰(τᵣ) - u⃗(τᵣ)·n̂(τᵣ, r_obs)) |
| 27 | +function retarded_time_rhs(τᵣ, p, t) |
| 28 | + traj, r_obs = p |
| 29 | + rⁱ, uⁱ = traj(τᵣ) |
| 30 | + n̂ = (r_obs - rⁱ) * inv(norm(r_obs - rⁱ)) |
| 31 | + inv(u⁰ - uⁱ ⋅ n̂) |
| 32 | +end |
| 33 | + |
| 34 | +advanced_time(traj, τ, x_obs) = traj.sol(τ, idxs=traj.r_idxs[1]) + norm(x_obs - traj.sol(τ, idxs=traj.u_idxs[1])) |
| 35 | + |
| 36 | +function retarded_time_problem(e_trajectories::Vector{TrajectoryInterpolant}, screen::ObserverScreen) |
| 37 | + dims = (N_electrons, length(screen.x_grid), length(screen.y_grid)) |
| 38 | + CI = CartesianIndices(dims) |
| 39 | + |
| 40 | + j, ix, iy = Tuple(CI[1]) |
| 41 | + traj = e_trajectories[j] |
| 42 | + r_obs = SVector{3}(screen.x_grid[ix], screen.y_grid[iy], screen.z) |
| 43 | + |
| 44 | + (x⁰_i, x⁰_f) = advanced_time(traj, τi, x), advanced_time(traj, τf, x) |
| 45 | + prob = ODEProblem{false,SciMLBase.FullSpecialize}( |
| 46 | + retarded_time_rhs, |
| 47 | + τi, |
| 48 | + (x⁰_i, x⁰_f), |
| 49 | + (traj, r_obs), |
| 50 | + ) |
| 51 | + |
| 52 | + function set_traj_and_pixel(prob, i, repeat) |
| 53 | + j, ix, iy = Tuple(CI[i]) |
| 54 | + traj = e_trajectories[j] |
| 55 | + r_obs = SVector{3}(screen.x_grid[ix], screen.y_grid[iy], screen.z) |
| 56 | + |
| 57 | + x⁰_i, x⁰_f = advanced_time(traj, τ_span, r_obs) |
| 58 | + remake(prob; p=(traj, r_obs), tspan=(x⁰_i, x⁰_f)) |
| 59 | + end |
| 60 | + |
| 61 | + EnsembleProblem(prob; prob_func = set_traj_and_pixel, safetycopy=false) |
| 62 | +end |
| 63 | + |
| 64 | +function accumulate_potential(rt_sol, trajs, screen, K) |
| 65 | + # (N_samples, 4, Nx, Ny) |
| 66 | +end |
0 commit comments