|
1 | 1 | module IonizationRates
|
2 | 2 | using SpecialFunctions
|
3 | 3 | using HCubature
|
| 4 | +using ElectricFields |
4 | 5 |
|
5 | 6 | # * Common
|
6 | 7 |
|
@@ -241,4 +242,65 @@ function PPT(Iₚ, I, ω, ℓ, m, Z=1)
|
241 | 242 | isnan(w) ? zero(w) : w
|
242 | 243 | end
|
243 | 244 |
|
| 245 | +function ionization_yield(F::ElectricFields.LinearField, tmin::Number, tmax::Number, Iₚ, ℓ, m, Z; model=:ppt) |
| 246 | + model == :ppt || throw(ArgumentError("Unknown ionization model $(model)")) |
| 247 | + |
| 248 | + s = span(F) |
| 249 | + a = max(tmin, s.left) |
| 250 | + b = min(tmax, s.right) |
| 251 | + |
| 252 | + ω = photon_energy(F) |
| 253 | + |
| 254 | + f(t) = PPT(Iₚ, abs2(field_amplitude(F, t)), ω, ℓ, m, Z) |
| 255 | + |
| 256 | + first(hquadrature(f, a, b)) |
| 257 | +end |
| 258 | + |
| 259 | +function ionization_yield(F::ElectricFields.LinearField, Iₚ, ℓ, m, Z=1; kwargs...) |
| 260 | + s = span(F) |
| 261 | + ionization_yield(F, s.left, s.right, Iₚ, ℓ, m, Z; kwargs...) |
| 262 | +end |
| 263 | + |
| 264 | +""" |
| 265 | + cumulative_integral!(v, f, t) |
| 266 | +
|
| 267 | +Compute the cumulative integral, such that at exit, |
| 268 | +
|
| 269 | +v[i] = ∫_{t[1]}^{t[i]} dt f(t). |
| 270 | +
|
| 271 | +We do this by recursively halving the interval until it is small |
| 272 | +enough for brute force quadrature. |
| 273 | +""" |
| 274 | +function cumulative_integral!(v, f, t; min_length=3, kwargs...) |
| 275 | + @assert min_length > 2 |
| 276 | + n = length(t) |
| 277 | + if n ≤ min_length |
| 278 | + # @info "Base case" |
| 279 | + # We may not write to v[1], since it is v[end] in the left |
| 280 | + # neighbouring interval, and the contribution from this |
| 281 | + # interval is zero anyway. |
| 282 | + for i = 2:n |
| 283 | + v[i] = f(t[1],t[i]) |
| 284 | + end |
| 285 | + else |
| 286 | + s = n ÷ 2 |
| 287 | + sel1 = 1:s |
| 288 | + sel2 = s:n |
| 289 | + # @info "Subdividing integral" n s sel1 sel2 |
| 290 | + v1 = |
| 291 | + @sync begin |
| 292 | + Threads.@spawn cumulative_integral!(view(v, sel1), f, view(t, sel1); min_length=min_length, kwargs...) |
| 293 | + Threads.@spawn cumulative_integral!(view(v, sel2), f, view(t, sel2); min_length=min_length, kwargs...) |
| 294 | + end |
| 295 | + v[s+1:n] .+= v[s] |
| 296 | + end |
| 297 | + v |
| 298 | +end |
| 299 | + |
| 300 | +function ionization_yield(F::ElectricFields.LinearField, t::AbstractVector{T}, args...; kwargs...) where T |
| 301 | + f(a,b) = ionization_yield(F, a, b, args...; kwargs...) |
| 302 | + a,b = length(t) > 1 ? (t[1],t[2]) : (one(T),one(T)+eps(T)) |
| 303 | + cumulative_integral!(zeros(typeof(f(a,b)), length(t)), f, t; kwargs...) |
| 304 | +end |
| 305 | + |
244 | 306 | end
|
0 commit comments