-
Notifications
You must be signed in to change notification settings - Fork 42
preionfrac as a function of z #417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,7 +23,7 @@ end | |||||||||||||||
| "Kerr response for real field" | ||||||||||||||||
| function Kerr_field(γ3) | ||||||||||||||||
| Kerr = let γ3 = γ3 | ||||||||||||||||
| function Kerr(out, E, ρ) | ||||||||||||||||
| function Kerr(out, E, ρ; z=0.0) | ||||||||||||||||
| if size(E,2) == 1 | ||||||||||||||||
| KerrScalar!(out, E, ρ*ε_0*γ3) | ||||||||||||||||
| else | ||||||||||||||||
|
|
@@ -38,7 +38,7 @@ function Kerr_field_nothg(γ3, n) | |||||||||||||||
| E = Array{Float64}(undef, n) | ||||||||||||||||
| hilbert = Maths.plan_hilbert(E) | ||||||||||||||||
| Kerr = let γ3 = γ3, hilbert = hilbert | ||||||||||||||||
| function Kerr(out, E, ρ) | ||||||||||||||||
| function Kerr(out, E, ρ; z=0.0) | ||||||||||||||||
| out .+= ρ*3/4*ε_0*γ3.*abs2.(hilbert(E)).*E | ||||||||||||||||
| end | ||||||||||||||||
| end | ||||||||||||||||
|
|
@@ -62,7 +62,7 @@ end | |||||||||||||||
| "Kerr response for envelope" | ||||||||||||||||
| function Kerr_env(γ3) | ||||||||||||||||
| Kerr = let γ3 = γ3 | ||||||||||||||||
| function Kerr(out, E, ρ) | ||||||||||||||||
| function Kerr(out, E, ρ; z=0.0) | ||||||||||||||||
| if size(E,2) == 1 | ||||||||||||||||
| KerrScalarEnv!(out, E, ρ*ε_0*γ3) | ||||||||||||||||
| else | ||||||||||||||||
|
|
@@ -77,15 +77,15 @@ end | |||||||||||||||
| function Kerr_env_thg(γ3, ω0, t) | ||||||||||||||||
| C = exp.(2im*ω0.*t) | ||||||||||||||||
| Kerr = let γ3 = γ3, C = C | ||||||||||||||||
| function Kerr(out, E, ρ) | ||||||||||||||||
| function Kerr(out, E, ρ; z=0.0) | ||||||||||||||||
| @. out += ρ*ε_0*γ3/4*(3*abs2(E) + C*E^2)*E | ||||||||||||||||
| end | ||||||||||||||||
| end | ||||||||||||||||
| end | ||||||||||||||||
|
|
||||||||||||||||
| "Response type for cumtrapz-based plasma polarisation, adapted from: | ||||||||||||||||
| M. Geissler, G. Tempea, A. Scrinzi, M. Schnürer, F. Krausz, and T. Brabec, Physical Review Letters 83, 2930 (1999)." | ||||||||||||||||
| struct PlasmaCumtrapz{R, EType, tType} | ||||||||||||||||
| struct PlasmaCumtrapz{R, EType, tType, PType} | ||||||||||||||||
| ratefunc::R # the ionization rate function | ||||||||||||||||
| ionpot::Float64 # the ionization potential (for calculation of ionization loss) | ||||||||||||||||
| rate::tType # buffer to hold the rate | ||||||||||||||||
|
|
@@ -94,34 +94,62 @@ struct PlasmaCumtrapz{R, EType, tType} | |||||||||||||||
| J::EType # buffer to hold the plasma current | ||||||||||||||||
| P::EType # buffer to hold the plasma polarisation | ||||||||||||||||
| δt::Float64 # the time step | ||||||||||||||||
| preionfrac::Float64 # the pre-ionisation fraction | ||||||||||||||||
| preionfrac::PType # the pre-ionisation fraction (Float64 or callable function of z) | ||||||||||||||||
| end | ||||||||||||||||
|
|
||||||||||||||||
| """ | ||||||||||||||||
| PlasmaCumtrapz(t, E, ratefunc, ionpot) | ||||||||||||||||
| PlasmaCumtrapz(t, E, ratefunc, ionpot; preionfrac=0.0) | ||||||||||||||||
|
|
||||||||||||||||
| Construct the Plasma polarisation response for a field on time grid `t` | ||||||||||||||||
| with example electric field like `E`, an ionization rate callable | ||||||||||||||||
| `ratefunc` and ionization potential `ionpot`. | ||||||||||||||||
|
|
||||||||||||||||
| The `preionfrac` can be either: | ||||||||||||||||
| - A `Float64` constant value (default: 0.0) | ||||||||||||||||
| - A callable (function or interpolation) that takes `z` (position) as input and returns the pre-ionization fraction | ||||||||||||||||
|
|
||||||||||||||||
| For z-dependent pre-ionization, you can use an interpolation object from Interpolations.jl | ||||||||||||||||
| or a custom function that maps z to the pre-ionization fraction. | ||||||||||||||||
| """ | ||||||||||||||||
| function PlasmaCumtrapz(t, E, ratefunc, ionpot; preionfrac=0.0) | ||||||||||||||||
| rate = similar(t) | ||||||||||||||||
| fraction = similar(t) | ||||||||||||||||
| phase = similar(E) | ||||||||||||||||
| J = similar(E) | ||||||||||||||||
| P = similar(E) | ||||||||||||||||
| !(0.0 <= preionfrac <= 1.0) && throw(DomainError(preionfrac, "preionfrac must be between 0 and 1")) | ||||||||||||||||
| if preionfrac > 0.0 | ||||||||||||||||
| @warn("Using preionfrac > 0.0 is not a well founded physical model. Use only after careful consideration.") | ||||||||||||||||
| # Validate preionfrac | ||||||||||||||||
| if preionfrac isa Number | ||||||||||||||||
| !(0.0 <= preionfrac <= 1.0) && throw(DomainError(preionfrac, "preionfrac must be between 0 and 1")) | ||||||||||||||||
| if preionfrac > 0.0 | ||||||||||||||||
| @warn("Using preionfrac > 0.0 is not a well founded physical model. Use only after careful consideration.") | ||||||||||||||||
| end | ||||||||||||||||
| else # preionfrac is a callable | ||||||||||||||||
|
||||||||||||||||
| else # preionfrac is a callable | |
| else # preionfrac is intended to be a callable | |
| if !applicable(preionfrac, 0.0) | |
| throw(ArgumentError("preionfrac must be either a Number in [0, 1] or a callable that accepts a single Float64 argument (z).")) | |
| end |
Copilot
AI
Mar 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getpreionfrac returns Plas.preionfrac(z) without validating the result. Unlike the constant Number path, this means out-of-range values (<0 or >1) (or non-numeric returns) will silently propagate and can produce unphysical ionisation fractions and downstream computations (e.g. (1 - Plas.fraction[ii]) becoming negative). Consider validating the evaluated value (and throwing DomainError like the constant case) at least once per call site (e.g. inside getpreionfrac).
| return Plas.preionfrac(z) | |
| val = Plas.preionfrac(z) | |
| if !(val isa Number) | |
| throw(DomainError(val, "preionfrac(z) must return a numeric value between 0 and 1")) | |
| end | |
| !(0.0 <= val <= 1.0) && throw(DomainError(val, "preionfrac must be between 0 and 1")) | |
| return val |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -114,29 +114,29 @@ function _cpscb_core(dest, source, N, scale, idcs) | |
| end | ||
|
|
||
| """ | ||
| Et_to_Pt!(Pt, Et, responses, density) | ||
| Et_to_Pt!(Pt, Et, responses, density; z=0.0) | ||
|
|
||
| Accumulate responses induced by Et in Pt. | ||
| """ | ||
| function Et_to_Pt!(Pt, Et, responses, density::Number) | ||
| function Et_to_Pt!(Pt, Et, responses, density::Number; z=0.0) | ||
| fill!(Pt, 0) | ||
| for resp! in responses | ||
| resp!(Pt, Et, density) | ||
| resp!(Pt, Et, density; z=z) | ||
| end | ||
|
Comment on lines
+121
to
125
|
||
| end | ||
|
|
||
| function Et_to_Pt!(Pt, Et, responses, density::AbstractVector) | ||
| function Et_to_Pt!(Pt, Et, responses, density::AbstractVector; z=0.0) | ||
| fill!(Pt, 0) | ||
| for ii in eachindex(density) | ||
| for resp! in responses[ii] | ||
| resp!(Pt, Et, density[ii]) | ||
| resp!(Pt, Et, density[ii]; z=z) | ||
| end | ||
| end | ||
| end | ||
|
|
||
| function Et_to_Pt!(Pt, Et, responses, density, idcs) | ||
| function Et_to_Pt!(Pt, Et, responses, density, idcs; z=0.0) | ||
| for i in idcs | ||
| Et_to_Pt!(view(Pt, :, i), view(Et, :, i), responses, density) | ||
| Et_to_Pt!(view(Pt, :, i), view(Et, :, i), responses, density; z=z) | ||
| end | ||
| end | ||
|
|
||
|
|
@@ -274,7 +274,7 @@ function Erω_to_Prω!(t, x) | |
| Modes.to_space!(t.Erω, t.Emω, x, t.ts, z=t.z) | ||
| to_time!(t.Er, t.Erω, t.Erωo, inv(t.FT)) | ||
| # get nonlinear pol at r,θ | ||
| Et_to_Pt!(t.Pr, t.Er, t.resp, t.density) | ||
| Et_to_Pt!(t.Pr, t.Er, t.resp, t.density; z=t.z) | ||
| @. t.Pr *= t.grid.towin | ||
| to_freq!(t.Prω, t.Prωo, t.Pr, t.FT) | ||
| @. t.Prω *= t.grid.ωwin | ||
|
|
@@ -362,7 +362,7 @@ const nlscale = sqrt(PhysData.ε_0*PhysData.c/2) | |
| function (t::TransModeAvg)(nl, Eω, z) | ||
| to_time!(t.Eto, Eω, t.Eωo, inv(t.FT)) | ||
| @. t.Eto /= nlscale*sqrt(t.aeff(z)) | ||
| Et_to_Pt!(t.Pto, t.Eto, t.resp, t.densityfun(z)) | ||
| Et_to_Pt!(t.Pto, t.Eto, t.resp, t.densityfun(z); z=z) | ||
| @. t.Pto *= t.grid.towin | ||
| to_freq!(nl, t.Pωo, t.Pto, t.FT) | ||
| t.norm!(nl, z) | ||
|
|
@@ -466,7 +466,7 @@ place the result in `nl` | |
| function (t::TransRadial)(nl, Eω, z) | ||
| to_time!(t.Eto, Eω, t.Eωo, inv(t.FT)) # transform ω -> t | ||
| ldiv!(t.Eto, t.QDHT, t.Eto) # transform k -> r | ||
| Et_to_Pt!(t.Pto, t.Eto, t.resp, t.densityfun(z), t.idcs) # add up responses | ||
| Et_to_Pt!(t.Pto, t.Eto, t.resp, t.densityfun(z), t.idcs; z=z) # add up responses | ||
| @. t.Pto *= t.grid.towin # apodisation | ||
| mul!(t.Pto, t.QDHT, t.Pto) # transform r -> k | ||
| to_freq!(nl, t.Pωo, t.Pto, t.FT) # transform t -> ω | ||
|
|
@@ -597,7 +597,7 @@ function (t::TransFree)(nl, Eωk, z) | |
| fill!(t.Eωo, 0) | ||
| copy_scale!(t.Eωo, Eωk, length(t.grid.ω), t.scale) | ||
| ldiv!(t.Eto, t.FT, t.Eωo) # transform (ω, ky, kx) -> (t, y, x) | ||
| Et_to_Pt!(t.Pto, t.Eto, t.resp, t.densityfun(z), t.idcs) # add up responses | ||
| Et_to_Pt!(t.Pto, t.Eto, t.resp, t.densityfun(z), t.idcs; z=z) # add up responses | ||
| @. t.Pto *= t.grid.towin # apodisation | ||
| mul!(t.Pωo, t.FT, t.Pto) # transform (t, y, x) -> (ω, ky, kx) | ||
| copy_scale!(nl, t.Pωo, length(t.grid.ω), 1/t.scale) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change introduces new behavior where
preionfracmay be a z-dependent callable. There are existing tests covering constantpreionfracdomain validation (seetest/test_ionisation.jl), but there is no coverage for (1) callablepreionfracbeing accepted and applied at different z values, and (2) callable returns outside [0,1] producing a clear error. Adding tests for these cases would help prevent regressions.