Internal
using TestParticle imports the tracing setup and execution APIs, end-to-end VDF tracers, main result accessors, and plotting entry points. Diagnostics, conversions, sampling and distribution APIs, interpolation policies, and storage types are public but not exported. Access them through the module or an explicit import:
using TestParticle
using TestParticle: get_energy, Maxwellian, ClampExtrap
# Alternatively, use TestParticle.get_energy, TestParticle.Maxwellian, etc.Both exported and public-only names are supported API. If an unqualified name from an earlier release is no longer imported, qualify it with TestParticle. or add an explicit import; its implementation remains available.
Public APIs
TestParticle.AdaptiveHybrid Type
AdaptiveHybrid{T, A}Hybrid algorithm that switches between adaptive Boris (FO) and a guiding-center ODE solver gc_alg (defaulting to Vern7() when OrdinaryDiffEqVerner is loaded), used as solve(TraceProblem(u0, tspan, p), alg) with the full-orbit state u0.
Mode switching uses hysteresis with two adiabaticity thresholds to avoid rapid GC ↔ FO chattering near a single bound:
threshold_gc_to_fo(α): switch GC → FO whenε ≥ α.threshold_fo_to_gc(β): switch FO → GC whenε < β.
With α ≥ β the band β ≤ ε < α forms a buffer where the current mode is retained, so a particle hovering near the boundary does not oscillate.
The adiabaticity parameter ε compared against the thresholds is selected by the adiabaticity field, which may be:
:curvature(default) →ε_curv = ρ_L / R_c(curvature drift; reproduces the legacyget_adiabaticitybehavior exactly),:gradB→ε_gradB = ρ_L / L_B, withL_B = |B| / |∇B|,:both→ OR of the two criteria: the solver switches to the full orbit whenever eitherε_curv ≥ αorε_gradB ≥ α(equivalentlymax(ε_curv, ε_gradB) ≥ α),:jacobian→ε_jac = ρ_L · ‖JB‖_F / |B|, CHIMP's original all-in-one criterion (Bates & Fuentes, 2020), whereJBis the Jacobian ofBand‖JB‖_Fits Frobenius norm. It captures curvature, grad-B, torsion and shear at once, so it switches to full orbit in non-adiabatic regions that:curvature/:gradBmiss (e.g. a field whose direction rotates in space while keeping constant magnitude).
Both modes adapt their step size to the local field. The full-orbit mode uses a Boris step dt = 2π * safety_fo / (|q/m| * |B|) clipped to [dtmin, dtmax] and recomputed after every accepted step; when the step changes, the staggered velocity is re-centered on the new step so that the leapfrog scheme stays time-reversible. The guiding-center mode steps with gc_alg, so its steps may span many gyroperiods.
Because a guiding-center step can be long compared with the scale on which ε varies, the adiabaticity check is triggered by whichever comes first: check_interval accepted steps, or check_dt in simulation time since the previous check. A step is also clipped so that it never crosses the next check deadline, which makes check_dt a hard bound on the simulated time a particle can travel between examinations rather than a bound that a long step could overshoot. check_dt defaults to 100 * dtmax: small enough to catch a transition that a long guiding-center step would otherwise jump over, and large enough that the clamp does not turn check_dt into a step-size cap that costs more than the monitoring saves. Lower it where ε changes on a shorter scale.
While the solver is in the full-orbit mode, check_margin_max > 1 lengthens both bounds by up to that factor in proportion to how far ε sits above threshold_fo_to_gc: ε changes by O(ε) over one curvature radius, so an ε that is a factor k above the exit threshold needs of order k such excursions before the mode can flip, and checking in between only costs time. The interval collapses back to its nominal value as ε approaches the threshold, and the guiding-center mode always uses the nominal interval, so a transition into a non-adiabatic region is detected as early as with a uniform interval.
It is off by default (check_margin_max = 1). Stretching reorders the mode history enough to matter: on the magnetic-bottle benchmark 4 makes the run about 40% faster but the RMS position error 50% larger, because the full-orbit excursions become fewer and longer and the full-orbit step is the coarser one. Raise it only where the full-orbit mode is cheap relative to the guiding-center mode.
On the switch to the guiding center, the state is refined by up to switch_correction fixed-point iterations of X = x - ρ(X) instead of the zeroth-order X = x - ρ(x) map, which removes the O(ε) jump that the switch would otherwise introduce. That map is the exact inverse of the reconstruction back to the full orbit, so the round trip through a switch returns the particle where it was. Set switch_correction = 0 for the legacy behavior.
Each check point records only the adiabaticity value used by the selected adiabaticity mode (a single scalar per check) together with the active mode in sol.stats.adiabaticity. This diagnostic is only saved when save_adiabaticity = true (the default); set it to false to skip the buffers and reduce memory/allocation overhead.
TestParticle.ErasedField Type
ErasedField{itd}Type alias for a Field wrapping an ErasedFunction.
TestParticle.ErasedFunction Type
ErasedFunctionType-erased callable for 3D vector fields wrapping arbitrary user functions or interpolators. Holds precompiled FunctionWrapper handles for both Float64 and Float32 inputs (supporting both 3-component and full 6-component state inputs), along with the raw callable for autodiff (ForwardDiff.Dual) and custom types.
TestParticle.Field Type
Field(f; time_dependent=is_time_dependent(f))Wrap f(x) or f(x, t) as a field. Automatic detection prefers the two-argument signature; set time_dependent explicitly for ambiguous or input-type-specific callables.
TestParticle.FullOrbit Type
FullOrbit, RelativisticOrbit, Canonical, RelativisticCanonical, GuidingCenterModel of a TraceProblem: the equations that its state u0 and parameters p follow, and thereby the solvers and diagnostics that apply to it. RelativisticOrbit states hold γv in place of v.
TestParticle.GPUGrid Type
GPUGrid{N, C, X, V, A<:AbstractArray{V, N}} <: AbstractFieldInterpolatorMultilinear interpolator over an N-dimensional grid of V values that can be evaluated inside a device kernel. Each axis is a GPUUniformAxis or a GPUNonUniformAxis carrying its boundary condition; queries outside a filling axis return fill. With CartesianCoords{D}, the grid spans the location components D; with SphericalCoords, it spans (r, θ, ϕ) and rotates a vector result back into the Cartesian basis.
TestParticle.GPUNonUniformAxis Type
GPUNonUniformAxis{T, V<:AbstractVector{T}, B}Non-uniformly spaced grid axis of a GPUGrid; a cell is bracketed with a binary search.
TestParticle.GPUUniformAxis Type
GPUUniformAxis{T, B}Uniformly spaced grid axis of a GPUGrid; a cell is located with a multiply.
TestParticle.LazyTimeInterpolator Type
LazyTimeInterpolator{T, F, L}A callable struct for handling time-dependent fields with lazy loading and linear time interpolation.
Fields
times::Vector{T}: Sorted vector of time points.loader::L: Functioni -> fieldthat loads the field at indexi.buffer::Dict{Int, F}: Cache for loaded fields.lock::ReentrantLock: Lock for thread safety.
TestParticle.PotentialField Type
PotentialField{TP, TA, TGP, TGA}A representation of scalar potential phi and vector potential A, along with optional spatial gradient functions grad_phi and grad_A.
TestParticle.TraceCanonicalProblem Type
TraceCanonicalProblem(u0, tspan, p; prob_func)TraceProblem in canonical coordinates: u0 = [x..., p...] and p = (; q, m, c, pf) from prepare_canonical. The relativistic variant is TraceProblem{RelativisticCanonical}.
TestParticle.TraceGCProblem Type
TraceGCProblem(u0, tspan, p; prob_func)TraceProblem of a guiding center: u0 = [X..., vpar] and p = (; q, q2m, μ, E, B) from prepare_gc.
TestParticle.TraceProblem Method
TraceProblem(u0, tspan, p; prob_func = DEFAULT_PROB_FUNC)
TraceProblem(f, u0, tspan, p; prob_func = DEFAULT_PROB_FUNC)
TraceProblem{M}(...)Problem specification for particle tracing in the model M: FullOrbit (the default), RelativisticOrbit, Canonical, RelativisticCanonical or GuidingCenter, also written TraceCanonicalProblem and TraceGCProblem. Supports the native solvers of each model and standard ODE solvers (e.g. Tsit5, Vern7). RelativisticOrbit states hold γv in place of v. Boris and hybrid solvers accept only the default FullOrbit equations without F.
When f is not provided, the model's equations are used: in-place for mutable arrays, out-of-place for StaticArrays. The default equations of a model imply it, and TraceProblem{M} throws on those of another. Custom f keeps M.
Normalized units need no separate equations: prepare p with q = 1, m = 1, and c = 1 for the relativistic case.
TestParticle.BiKappa Function
BiKappa(args...; kw...)Construct a BiKappa distribution. Forwards to VelocityDistributionFunctions.BiKappa.
BiKappa(B, u0, ppar, pperp, n, kappa; m=mᵢ)Construct a BiKappa distribution with magnetic field B, bulk velocity u0, parallel thermal pressure ppar, perpendicular thermal pressure pperp, number density n, and spectral index kappa in SI units. The default particle is proton.
TestParticle.BiMaxwellian Function
BiMaxwellian(args...; kw...)Construct a BiMaxwellian distribution. Forwards to VelocityDistributionFunctions.BiMaxwellian.
BiMaxwellian(B, u0, ppar, pperp, n; m=mᵢ)Construct a BiMaxwellian distribution with magnetic field B, bulk velocity u0, parallel thermal pressure ppar, perpendicular thermal pressure pperp, and number density n in SI units. The default particle is proton.
TestParticle.Kappa Function
Kappa(args...; kw...)Construct a Kappa distribution. Forwards to VelocityDistributionFunctions.Kappa.
Kappa(u0, p, n, kappa; m=mᵢ)Construct a Kappa distribution with bulk velocity u0, thermal pressure p, number density n, and spectral index kappa in SI units. The default particle is proton.
TestParticle.Maxwellian Function
Maxwellian(args...; kw...)Construct a Maxwellian distribution. Forwards to VelocityDistributionFunctions.Maxwellian.
Maxwellian(u0, p, n; m=mᵢ)Construct a Maxwellian distribution with bulk velocity u0, thermal pressure p, and number density n in SI units. The default particle is proton.
TestParticle.TerminateOutside Method
TerminateOutside(isoutofdomain)Create a DiscreteCallback that terminates the simulation if isoutofdomain(u, p, t) is true. The condition follows the same (u, p, t) convention as the isoutside keyword, and is adapted here to the (u, t, integrator) signature that SciML callbacks use.
TestParticle.adiabaticity_components Function
adiabaticity_components(x, Bfunc, q, m, μ, t = 0.0)
adiabaticity_components(x, Bfunc, μ, t = 0.0; species = Proton)Return the tuple (ε_curv, ε_gradB, ε_jac) of first-order adiabaticity parameters at position x and time t:
ε_curv = ρ / R_c(curvature drift; the definition used byget_adiabaticity),ε_gradB = ρ / L_B(grad-B drift; CHIMP'seGC), withL_B = |B| / |∇B|the magnetic-field length scale,ε_jac = ρ · ‖JB‖_F / |B|(CHIMP's all-in-one criterion;JBis the Jacobian ofBand‖JB‖_Fits Frobenius norm). Because‖JB‖_F² = |∇B|² + |B|²|κ|² + |B|²τ² + shear, this folds curvature, grad-B, torsion and shear into one number, so it switches to full orbit in non-adiabatic regions thatε_curv/ε_gradBmiss (e.g. a field whose direction rotates in space with constant magnitude). It always satisfiesε_jac ≥ max(ε_curv, ε_gradB).
ρ = √(2 μ m / |B|) / |q| is the gyroradius. When |B| = 0 all three components are Inf.
TestParticle.analytic_projection Method
analytic_projection(f, k, vi, vj, vk, dvk) -> MatrixAnalytic 2-D projection f(vᵢ, vⱼ) = ∫ f dvₖ in [s²/km⁵] of a 3-D phase-space density, evaluated on the velocity grids vi and vj in [km/s] while the k-th axis is integrated over vk in [km/s] with the midpoint rule at spacing dvk. The two remaining axes follow from k as i < j: k = 3 projects onto Vx–Vy, k = 2 onto Vx–Vz and k = 1 onto Vy–Vz.
f takes a velocity in [m/s] and returns f in [s³/m⁶].
TestParticle.bin_centers Method
bin_centers(edges)Centers of the 1-D bins delimited by edges, in the same unit as edges.
TestParticle.bin_velocity_space Method
bin_velocity_space(vs, weights, edges; vx_source = nothing, average = false)Accumulate velocity-space samples into a 3-D grid.
vs are sample velocities in [m/s] as returned by get_particle_crossings and weights the weight of each sample. edges are the bin edges in [km/s], shared by all three velocity axes. Samples outside the binned range are discarded, and the returned array carries the unit of weights. Empty bins are zero.
Two estimators are available, and they differ in how the samples that land in a bin are combined:
average = false(default) sums the weights, which is the histogram estimator of the bin-averagedf: feedingf·ΔV/dv³withfin [s³/km⁶] returnsfin [s³/km⁶], and feeding the constantn/(N·dv³)turns binned counts into a Monte-Carlo estimate off. Its error carries the counting noise∝ 1/√nof the samples per bin.average = truetakes the mean of the weights, a ratio estimator of the localfthat divides out the counting noise. It is the better choice when the sampling spreads only a handful of samples over each bin, e.g. forward Liouville tracking of a uniformly sampled velocity sphere onto a fine detector grid.
Either way project_vdf turns the result into 2-D projections in [s²/km⁵].
If vx_source is given, each sample is rescaled by |vx_source| / |vx|. A trajectory maps a source velocity-space volume onto a detector volume that differs by exactly that ratio, so the rescale turns a source-referred weight into the detector-referred one. This is what makes a flux-weighted launch ensemble consistent with the crossing flux recorded at the detector.
TestParticle.build_interpolator Function
build_interpolator(A, grids::Tuple; bc, order=1, gridtype=CartesianGrid, kwargs...)
build_interpolator([gridtype,] A, grids..., order=1, bc=FillExtrap(NaN); kwargs...)Build a callable field for prepare. Vector data has shape (3, length.(grids)...) or contains SVector{3} values. Orders are 0, 1, and 3. The tuple API requires bc: one policy for all axes or a tuple of per-axis policies. FillExtrap values must agree across axes.
PeriodicBC(endpoint=:inclusive) repeats the endpoint; :exclusive omits it (uniform-grid period NΔx). WrapExtrap() wraps over the grid span without imposing spline periodicity. FillExtrap(NaN) fills outside; ClampExtrap() extends constantly. Field lookup neither wraps particle state nor terminates trajectories.
gridtype=StructuredGrid uses spherical (r, θ, ϕ) grids and (Br, Bθ, Bϕ) components; queries and outputs are Cartesian. Supply fill/clamp for radius and colatitude and PeriodicBC with period 2π for longitude. Its positional default is (FillExtrap(NaN), FillExtrap(NaN), PeriodicBC(check = false)).
coeffs selects cubic coefficient storage. store=StorePolicy(copy=false) may alias inputs, which must remain unchanged. Device conversion requires order 1 and fill, clamp, wrap, or inclusive periodic policies; exclusive periodic fields are CPU-only.
TestParticle.cart2sph Method
cart2sph(x, y, z)Convert from Cartesian to spherical coordinates vector.
sourceTestParticle.cart2sphvec Method
cart2sphvec(vx, vy, vz, x, y, z)Convert a vector from Cartesian to spherical coordinates at the Cartesian position (x, y, z).
TestParticle.embed_vdf Method
embed_vdf(g1, g2, full_centers, M) -> MatrixEmbed a 2-D sub-grid projection M onto a canvas defined by full_centers. g1 and g2 are bin centers along the two axes in [km/s], and full_centers is the target full grid of bin centers.
TestParticle.full_to_gc Function
full_to_gc(xu, param)Convert full particle state xu to guiding center state state_gc and magnetic moment μ. Returns (state_gc, μ), where state_gc = [R..., vpar].
TestParticle.gc_to_full Function
gc_to_full(state_gc, param, μ, phase=0)Convert guiding center state state_gc to full particle state xu. Returns xu = [x, y, z, vx, vy, vz].
TestParticle.generate_sphere Function
generate_sphere(nθ=64, nϕ=64, radius=1.0)Generate a sphere with radius and matching grid points nθ and nϕ. Returns a tuple of (x, y, z) matrices.
TestParticle.get_adiabaticity Function
get_adiabaticity(r, Bfunc, q, m, μ, t=0.0)
get_adiabaticity(r, Bfunc, μ, t=0.0; species = Proton)Calculate the adiabaticity parameter ϵ = ρ / Rc at position r and time t. ρ is the gyroradius and Rc is the radius of curvature of the magnetic field.
TestParticle.get_adiabaticity Method
get_adiabaticity(sol::AbstractODESolution, t)Calculate the adiabaticity parameter ϵ from a solution sol at time t. t must be a scalar.
TestParticle.get_adiabaticity Method
get_adiabaticity(sol::AbstractODESolution)Calculate the adiabaticity parameter ϵ from a solution sol at all time steps. The model, parameters q, m and Bfunc are extracted from sol.prob.
TestParticle.get_curvature_radius Method
get_curvature_radius(x, t, Bfunc)Calculate the radius of curvature of the magnetic field at position x and time t. Returns Inf if the field is zero or the field lines are straight.
TestParticle.get_dv! Method
get_dv!(dv, v, x, p, t)In-place solver components for DynamicalODEProblem (velocity).
TestParticle.get_dx! Method
get_dx!(dx, v, x, p, t)In-place solver components for DynamicalODEProblem (location).
TestParticle.get_energy Method
get_energy(sol::AbstractODESolution) -> VectorKinetic energy per unit charge [eV for |q| = e] at every saved state of sol, from the model and the particle of sol.prob.
TestParticle.get_fields Method
get_fields(sol::AbstractODESolution)Return the electric and magnetic fields at the saved states of sol, in the element type of the state.
TestParticle.get_first_crossing Function
get_first_crossing(sol, surface) -> SVector{6}
get_first_crossing(sols, surface) -> Vector{SVector{6}}State [x, y, z, vx, vy, vz] at the first crossing of surface, linearly interpolated between the two bracketing saved points. Returns a state filled with NaN for trajectories that never reach surface, which is how unreachable velocities are flagged when tracing a detector grid backward to a source. Requires Meshes.jl to be loaded.
TestParticle.get_gc Method
get_gc(xu, param; use_vE = false)
get_gc(x, y, z, vx, vy, vz, bx, by, bz, q2m)Calculate the coordinates of the guiding center according to the phase space coordinates of a particle. Reference: wiki
Nonrelativistic definition:
If use_vE=true, it calculates the guiding center relative to the E × B drift frame:
which is essential for correctly identifying the polarization drift in time-varying fields.
sourceTestParticle.get_gc_velocity Method
get_gc_velocity(y, p, t)Get the guiding center velocity.
sourceTestParticle.get_gyrofrequency Function
get_gyrofrequency(B=5e-9; q=qᵢ, m=mᵢ)Return the gyrofrequency [rad/s].
Arguments
B: Magnetic field magnitude [T]. Default is 5 nT.q: Charge [C]. Default is proton charge.m: Mass [kg]. Default is proton mass.
TestParticle.get_gyroperiod Function
get_gyroperiod(B=5e-9; q=qᵢ, m=mᵢ)Return the gyroperiod [s].
Arguments
B: Magnetic field magnitude [T]. Default is 5 nT.q: Charge [C]. Default is proton charge.m: Mass [kg]. Default is proton mass.
TestParticle.get_gyroradius Method
get_gyroradius(V, B; q=qᵢ, m=mᵢ)Return the gyroradius [m].
Arguments
V: Velocity magnitude [m/s] (usually perpendicular to the magnetic field).B: Magnetic field magnitude [T].q: Charge [C]. Default is proton charge.m: Mass [kg]. Default is proton mass.
TestParticle.get_gyroradius Method
get_gyroradius(sol::AbstractODESolution, t)Return the gyroradius [m] from the solution sol at time t. The interpolated magnetic field function is obtained from sol.prob.p.
TestParticle.get_magnetic_properties Method
get_magnetic_properties(x, t, Bfunc)Calculate magnetic field properties at position x and time t. Returns the NamedTuple (; B, ∇B, κ, b̂, Bmag, JB):
B: Magnetic field vector∇B: Gradient of magnetic field magnitudeκ: Curvature vector(b̂ ⋅ ∇) b̂b̂: Unit magnetic field vectorBmag: Magnitude of BJB: Jacobian of B,JB[i, j] = ∂Bᵢ/∂xⱼ
∇B, κ and b̂ are zero in a magnetic null.
TestParticle.get_particle_crossings Function
get_particle_crossings(sol, surface, weight = 1.0) -> (velocities, weights)
get_particle_crossings(sols, surface, weights = 1.0) -> (velocities, weights)
get_particle_crossings(sols, surfaces, weights = 1.0) -> (velocities, weights)Detect every crossing of a virtual detector surface and return the velocity [m/s] at each crossing together with the corresponding weight.
A trajectory can cross the same detector more than once, so a crossing carries the weight of its trajectory rather than of the trajectory set: passing a scalar weight applies it to every trajectory of the ensemble. With a vector of surfaces the two returned vectors hold one vector per surface. Requires Meshes.jl to be loaded.
TestParticle.get_particle_flux Function
get_particle_flux(sol, surface, weight = 1.0) -> (number_flux, velocity_flux)
get_particle_flux(sols, surface, weights = 1.0) -> (number_flux, velocity_flux)
get_particle_flux(sols, surfaces, weights = 1.0) -> (number_fluxes, velocity_fluxes)Number flux density and velocity flux density through surface, or through each of surfaces, obtained by summing the crossing weights of a single trajectory or of an ensemble of trajectories sols and dividing by the surface area. Requires Meshes.jl to be loaded.
TestParticle.get_work_channels Method
get_work_channels(xv, p, t; kwargs...) -> SVector{3}Group the work rates into the three physical acceleration channels (P_parallel, P_fermi, P_betatron) [W].
The mapping between the four leading-order terms of get_work_rates and the channels is:
P_parallel = P_par: direct acceleration byE∥;P_fermi = P_fermi: work byEon the curvature drift;P_betatron = P_betatron + P_grad: perpendicular heating under conservation ofμ. Grad-B drift work is not a separate mechanism; since(μ/B)(b̂×∇B)⋅E = μ v_E⋅∇B, it is the convective (spatial) part of the betatron channel, whileμ ∂B/∂tis its local (temporal) part.
The state and the keywords are as in get_work_rates.
TestParticle.get_work_rates Method
get_work_rates(xv, p, t; model = _param_model(p), magnetic_properties = nothing, E = nothing)
-> SVector{4}Calculate the leading-order adiabatic work rates [W] (P_par, P_fermi, P_grad, P_betatron) acting on a full-orbit particle or a guiding center:
| Term | Formula | Physics |
|---|---|---|
P_par | q v∥ (E⋅b̂) | direct acceleration by E∥ |
P_fermi | (m v∥²/B) (b̂×κ)⋅E | work by E on the curvature drift |
P_grad | (μ/B) (b̂×∇B)⋅E | convective part of the betatron channel, μ v_E⋅∇B |
P_betatron | μ ∂B/∂t | local part of the betatron channel |
Here v_E = (E×b̂)/B is the ExB drift, so P_grad is the perpendicular heating a particle picks up by being convected across ∇B at fixed μ, while P_betatron is the heating from the local change of |B|. Together they are μ (∂_t + v_E⋅∇) B. See get_work_channels for the grouping into physical acceleration channels.
model defaults to GuidingCenter() when p carries a magnetic moment μ and to FullOrbit() otherwise. Full-orbit μ uses the gyration velocity v⊥ - v_E. For RelativisticOrbit(), the state holds γv and the drifts use the mass γm.
magnetic_properties and E are optional precomputed values of get_magnetic_properties and of the electric field at (get_x(xv), t), used to avoid recomputing the field Jacobian when the caller already has them.
For a full-orbit state these are gyro-averaged quantities: they do not reproduce the instantaneous q v⋅E, which oscillates at the gyrofrequency. They are therefore best compared against the energy change accumulated over many gyroperiods.
For the guiding-center equations solved by trace_gc!, the four terms sum to dK/dt with K = ½ m v∥² + μB up to O(ε) corrections. The sum is exact when b̂⋅(∇×b̂) = 0, as in axisymmetric fields without a B_φ component. In this case B*_∥ = |B| and the residual twist term vanishes. Planar field lines or translation invariance alone do not imply this condition. When it holds, any remaining mismatch is numerical (e.g. time-integration or quadrature error).
All four terms are zero in a magnetic null.
Reference: Northrop, T. G. (1963), The Adiabatic Motion of Charged Particles.
sourceTestParticle.get_work_rates Method
get_work_rates(sol::AbstractODESolution) -> Vector{SVector{4}}Work rates at every saved state of sol, in the element type of the state.
TestParticle.prepare Method
prepare(pf::PotentialField; species = Proton, q = nothing, m = nothing, c = c, type = nothing)Return parameters (; q, m, c, pf) for TraceCanonicalProblem.
TestParticle.prepare Method
prepare(; E=nothing, B=nothing, F=nothing, species=Proton, q, m, c, type, erased=false)Build particle parameters from callable electric, magnetic, and external force fields. Omitted fields are zero. Each callable accepts x or (x, t) and returns three components. Construct numerical fields with build_interpolator before calling prepare. See Field to select the calling convention. q and m override species; c sets the relativistic speed of light. type converts particle constants.
TestParticle.prepare_canonical Method
prepare_canonical(; phi = nothing, A = nothing, grad_phi = nothing, grad_A = nothing, kwargs...)PotentialField and prepare in one call, for TraceCanonicalProblem.
TestParticle.prepare_erased Method
prepare_erased(; E = nothing, B = nothing, F = nothing, kwargs...)Tracing parameters with type-erased fields for uniform dispatch and static compilation. Equivalent to prepare(; erased = true, kwargs...).
TestParticle.prepare_gc Method
prepare_gc(xv; E = nothing, B = nothing, kw...) -> (state_gc, param_gc)Initial guiding-center state [X..., vpar] from full-orbit state xv and parameters (; q, q2m, μ, E, B) for tracing it. Omitted fields are zero. xv is [x, y, z, vx, vy, vz]. Field arguments and keywords mirror prepare.
TODO: support external forces
sourceTestParticle.project_vdf Method
project_vdf(f3d, dv) -> (f_xy, f_xz, f_yz)Integrate a 3-D phase-space density f3d in [s³/km⁶] over each velocity axis in turn, returning the projections f(vᵢ, vⱼ) = ∫ f dvₖ in [s²/km⁵]. dv is the bin width in [km/s]. The array axes are ordered (v₁, v₂, v₃), so the projections come out as (v₁, v₂), (v₁, v₃) and (v₂, v₃).
TestParticle.refine_vdf_window Method
refine_vdf_window(f, vx, vy, vz, v0, dv; margin = 0.0, relthresh = 1.0e-5,
bounds = nothing)Refine a coarse velocity grid down to the spacing dv, keeping only the populated part of f. This is the second pass of the adaptive backward Liouville method: a cheap coarse pass locates the region of velocity space that the detector can actually see, and only that region is retraced on the fine grid.
Returns (vx_new, vy_new, vz_new) in the same unit as the inputs: the smallest box enclosing every grid point where f exceeds relthresh times its maximum, expanded by margin and clamped to bounds. The box bounds are snapped onto v0 + k·dv so that the refined grid shares bin centers with the full grid starting at v0. v0, dv and margin may be scalars or 3-tuples for per-axis values.
bounds is a (lo, hi) pair, or one such pair per axis. It defaults to the extent of the coarse grid, which is the range the coarse pass actually probed; pass the extent of the full display grid instead when the refined result has to live on that grid.
TestParticle.relative_l2 Method
relative_l2(rec, ref; thresh = 1.0e-4)Relative L2 difference ‖rec − ref‖ / ‖ref‖, evaluated over the entries where ref is above thresh times its own maximum and rec is finite. Restricting to the populated cells keeps the metric from being dominated by the empty tails of a reconstruction.
TestParticle.sample_maxwellian Function
sample_maxwellian([rng], Tn, m; offset=0.0, u0=SA[0.0, 0.0, 0.0])
sample_maxwellian([rng], Tn, species::String; offset=0.0, u0=SA[0.0, 0.0, 0.0])Sample a velocity [m/s] from a Maxwellian distribution with temperature Tn [K], mass m [kg], energy offset offset [J], and bulk velocity u0 [m/s]. This function requires VelocityDistributionFunctions.jl to be loaded.
TestParticle.sample_unit_sphere Function
sample_unit_sphere(rng::AbstractRNG=default_rng())Sample a unit vector on a sphere uniformly.
sourceTestParticle.sample_velocity_ball Method
sample_velocity_ball([rng], radius; center = SA[0.0, 0.0, 0.0]) -> SVector{3}Sample a velocity [m/s] uniformly from the ball of radius [m/s] centered on center [m/s].
Uniformity is what makes the sample usable as a quadrature rule in velocity space: each draw stands for the same volume 4πR³ / (3N), which forward Liouville tracking needs in order to convert a sampled f into a contribution to a detector bin.
TestParticle.sph2cart Method
sph2cart(r, θ, ϕ)Convert from spherical to Cartesian coordinates vector.
sourceTestParticle.sph2cartvec Method
sph2cartvec(vr, vθ, vϕ, θ, ϕ)Convert a vector from spherical to Cartesian coordinates. θ and ϕ define the position (polar and azimuthal angles in radians) where the spherical components (vr, vθ, vϕ) are defined.
TestParticle.trace! Method
trace!(dy, y, p, t)ODE equations for charged particle moving in EM field and external force field with in-place form.
sourceTestParticle.trace Method
trace(y, p, t)::SVector{6}ODE equations for charged particle moving in EM field and external force field with out-of-place form.
sourceTestParticle.trace_gc! Method
trace_gc!(dy, y, p, t)Guiding center equations for nonrelativistic charged particle moving in EM field with in-place form. Variable y = (x, y, z, u), where u is the velocity along the magnetic field at (x,y,z).
TestParticle.trace_gc_drifts! Method
trace_gc_drifts!(dx, x, p, t)Equations for tracing the guiding center using analytical drifts, including the grad-B drift, curvature drift, and ExB drift. Parallel velocity is also added. This expression requires the full particle trajectory p.sol.
TestParticle.trace_gc_exb! Method
trace_gc_exb!(dx, x, p, t)Equations for tracing the guiding center using the ExB drift and parallel velocity from a reference trajectory.
sourceTestParticle.trace_gc_flr! Method
trace_gc_flr!(dx, x, p, t)Equations for tracing the guiding center using the ExB drift with FLR corrections and parallel velocity.
sourceTestParticle.trace_relativistic! Method
trace_relativistic!(dy, y, p, t)ODE equations for relativistic charged particle (x, γv) moving in EM field with in-place form. The speed of light is p.c when present, c in SI otherwise.
TestParticle.trace_relativistic Method
trace_relativistic(y, p, t) -> SVector{6}ODE equations for relativistic charged particle (x, γv) moving in EM field with out-of-place form.
sourceTestParticle.vdf_backward Method
vdf_backward(sols, source, f_src, dims) -> Array{T, 3}Phase-space density [s³/km⁶] on a velocity grid of size dims = (nx, ny, nz), obtained by tracing that grid backward in time and evaluating the source distribution on the traced-back states, as prescribed by Liouville's theorem.
Each trajectory of sols is followed back to the surface source with get_first_crossing and f_src is evaluated on the velocity there; grid points whose trajectory never reaches source are left at zero. f_src takes a velocity in [m/s] and returns f in [s³/m⁶].
TestParticle.vdf_backward_trace Method
vdf_backward_trace(
param, detector, source, f_src;
v_range = 1000.0e3, vy_range = v_range, vz_range = v_range,
dv = 20.0e3, dt, alg, tspan = (0.0, -20.0),
adaptive = true, dv_coarse = 3 * dv, margin = 3 * dv,
relthresh = 1.0e-5, bounds = nothing, isoutside = nothing,
ensemblealg = EnsembleThreads()
) -> (f_3d, (vx_grid, vy_grid, vz_grid))Reconstruct the 3-D phase-space density [s³/km⁶] at detector by tracing a velocity grid backward in time to source and evaluating f_src on the traced-back states.
TestParticle.vdf_forward_trace Method
vdf_forward_trace(
param, source, detector, f_src;
nparticles = 50000, vradius, tspan = (0.0, 20.0), dt, alg,
center = SA[0.0, 0.0, 0.0], dv_km = 20.0,
v_edges = -1000.0:dv_km:1000.0,
isoutside = nothing, ensemblealg = EnsembleThreads(),
seed = 42
) -> (f_3d, (f_xy, f_xz, f_yz))Reconstruct the 3-D phase-space density [s³/km⁶] at detector using forward Liouville tracking from a uniformly sampled velocity ball at source.
TestParticle.vdf_grid_problem Method
vdf_grid_problem(vx, vy, vz, x0, param, tspan) -> TraceProblemBuild a TraceProblem that traces a velocity-space grid: trajectory i starts at position x0 [m] with the grid velocity (vx[ix], vy[iy], vz[iz]) [m/s], the z index varying fastest. This is the setup of the backward Liouville method, where the grid sits at the detector and tspan runs backward in time.
TestParticle.velocity_moments Method
velocity_moments(v, A; dv)
velocity_moments(proj::Tuple; dv)Density n [m⁻³] and momentum density n·V [m⁻³·km/s] of a 2-D velocity distribution A in [s²/km⁵], sampled on the first-axis bin centers v in [km/s] with bin width dv in [km/s]. Since the momentum is taken along the first axis, pass the Vx–Vy or the Vx–Vz projection to obtain n·Vx.
Private types and methods
TestParticle.AbstractFieldInterpolator Type
AbstractFieldInterpolatorAbstract type for all field interpolators.
sourceTestParticle.FieldInterpolator Type
FieldInterpolator{T, S}A callable struct that wraps a 3D interpolation object.
sourceTestParticle.FieldInterpolator1D Type
FieldInterpolator1D{T, S}A callable struct that wraps a 1D interpolation object.
sourceTestParticle.FieldInterpolator2D Type
FieldInterpolator2D{T, S}A callable struct that wraps a 2D interpolation object.
sourceTestParticle.SphericalFieldInterpolator Type
SphericalFieldInterpolator{T, S}A callable struct for spherical grid interpolation (scalar or combined vector).
sourceTestParticle._adiabaticity_components Method
_adiabaticity_components(mp, q, m, μ)Same as adiabaticity_components but taking the get_magnetic_properties output mp instead of recomputing it, for callers that already have the field derivatives in hand.
TestParticle._foreach_chunk Method
_foreach_chunk(f, ensemblealg, n)Call f(irange) on chunks of the trajectory indices 1:n, all at once for EnsembleSerial and one chunk per thread for EnsembleThreads.
TestParticle._gc_adia_parameters Method
_gc_adia_parameters(xv, E, B, q, m, t) -> (X, μ)Guiding-center position and magnetic moment of the full-orbit state xv — the two quantities an adiabaticity estimate needs. The gyrophase (get_perp_vector and an atan2) is skipped because the estimate never uses it; the values match those of _get_gc_parameters.
TestParticle._gc_frame Method
_gc_frame(x, v, E, B, m, t) -> (; b̂, w, vpar, μ)Field-aligned frame at position x: unit field b̂, gyration velocity w = v - vpar b̂ - v_E, parallel velocity vpar = b̂ ⋅ v and magnetic moment μ = m|w|² / (2|B|).
TestParticle._gc_position Method
_gc_position(x, v, B, q, m, t)Guiding-center position X = x - ρ(x), with the Larmor radius ρ evaluated at the particle: the zeroth-order map.
TestParticle._gc_state_at_switch Method
_gc_state_at_switch(xv, E, B, q, m, t, niter) -> (X, vpar, μ, phase)Guiding-center state of the full-orbit state xv, refined by up to niter fixed-point iterations of X = x - ρ(X): the Larmor radius is evaluated at the guiding center instead of at the particle, which is the first-order correction that removes the O(ε) error of the zeroth-order map. niter = 0 recovers the zeroth-order map.
This map is the exact inverse of _gc_to_full, so a switch to the guiding center and back returns the particle where it was; the reverse conversion needs no correction of its own.
An iteration is kept only if it reduces the residual ‖x - (X + ρ(X))‖, so a strongly non-adiabatic crossing, where the fixed-point map stops contracting, cannot make the conversion worse than the zeroth-order one.
TestParticle._gc_to_full Function
_gc_to_full(state_gc, E_field, B_field, q, m, μ, t, phase = 0)Internal GC → full-orbit conversion taking the field functions and charges directly, so it can be shared by the GC and hybrid solvers. E_field and B_field must be callable as E_field(x, t) / B_field(x, t); static fields simply ignore t.
Returns an SVector{6} so that it can be used in a hot loop and stored in a Vector{SVector{6}} without allocating; gc_to_full converts it to a Vector for the public API.
TestParticle._get_gc_parameters Method
_get_gc_parameters(xv, E, B, q, m, t) -> (X, vpar, q, q / m, μ, phase)Extract the guiding-center position X, parallel velocity vpar, magnetic moment μ, and gyrophase phase from a full-particle state xv at time t. E and B must be callable as E(x, t) / B(x, t); static fields simply ignore t.
#TODO : support external forces
sourceTestParticle._lorentz_factor Method
_lorentz_factor(u, model, p)Lorentz factor of the velocity part u of a full-orbit state; relativistic states store γv in place of v. Other models have no velocity part, so they have no method.
TestParticle._model Method
_model(prob)Model of prob. A plain ODEProblem has none of its own, so it follows from the equations and the parameters.
TestParticle._param_model Method
_param_model(p)Model that the parameters p are written for: the default where neither a problem nor the equations name the model.
TestParticle._prepare_potential_scalar Method
PotentialField(;
phi = nothing, A = nothing, grad_phi = nothing, grad_A = nothing, erased = false
)Scalar potential phi(x[, t]) and vector potential A(x[, t]) for canonical tracing; nothing is an absent potential. Gradients that are not given are computed with ForwardDiff. grad_A(x[, t])[i, j] is grad_A * v is
TestParticle._rng_seed Method
_rng_seed(seed::Integer, i::Integer)Combine the ensemble seed and the trajectory index i into a well-mixed UInt64 used to seed a per-trajectory RNG.
A naive seed + i couples the two linearly: incrementing seed merely rotates which RNG each trajectory index draws from, so two nearby seeds (e.g. 1 and 2) produce ensembles that share almost all trajectories and are therefore not independent. The SplitMix64-style finalizer below is a bijection on UInt64, so any distinct seed decorrelates every trajectory while remaining deterministic and reproducible (no reliance on hash, which is salted per Julia session).
Note: Julia's multi-argument Xoshiro(seed, i, …) constructor does not mix — it embeds the integers directly into the 4×UInt64 state (Xoshiro(s0,s1,s2,s3) → initstate!). Because xoshiro256++'s first output depends only on s0 and s3, seeding with Xoshiro(seed, i, 0, 0) yields the same first draw for every trajectory index i and does not decorrelate adjacent seeds. Robust mixing in Xoshiro only happens via the single-argument constructor (SHA2-256 hash_seed), so seed and i must be folded into one well-mixed integer first — which is what this function does.
TestParticle.get_cell_centers Function
get_cell_centers(grid::Union{CartesianGrid, RectilinearGrid})Return the cell center coordinates of a Meshes.jl grid, one range per dimension. Requires Meshes.jl to be loaded.
sourceTestParticle.get_mean_magnitude Method
get_mean_magnitude(B)Calculate the Root Mean Square (RMS) magnitude of a vector field B. It is assumed that the first dimension of B represents the vector components. This function is compatible with any spatial dimension.
TestParticle.get_perp_vector Method
get_perp_vector(b::AbstractVector)Obtain two unit vectors e1 and e2 such that (e1, e2, b) form a right-handed orthonormal system.
TestParticle.get_velocity Method
get_velocity(sol) -> MatrixVelocity of a full-orbit sol at every saved state, as a 3 × n matrix.
TestParticle.is_time_dependent Method
is_time_dependent(f::Function)Judge whether the field function is time dependent.
sourceTestParticle.makegrid Function
makegrid(grid::Union{CartesianGrid, RectilinearGrid})Return the coordinate ranges of a Meshes.jl grid, one range per dimension, e.g. (x, y, z) for a 3-D grid. Requires Meshes.jl to be loaded.
TestParticle.trace_gc Method
trace_gc(y, p, t)Guiding center equations for nonrelativistic charged particle moving in EM field with out-of-place form.
source