Tutorial
What makes plasmas particularly difficult to analyze is the fact that the densities fall in an intermediate range. Fluids like water are so dense that the motions of individual molecules do not have to be considered. Collisions dominate, and the simple equations of ordinary fluid dynamics suffice. At the other extreme in very low-density devices, only single-particle trajectories need to be considered; collective effects are often unimportant. Plasma behaves sometimes like fluids, and sometimes like a collection of individual particles. The first step in learning how to deal with this schizophrenic personality is to understand how single particles behave in electric and magnetic fields.
Here we assume that the EM fields are prescribed and not affected by the charged particles. References can be found in classic textbooks like Introduction to Plasma Physics and Controlled Fusion by F.F.Chen, and Fundamentals of Plasma Physics by Paul Bellan. For more complete notes corresponding to the derivation online, please check out Single-Particle Motions.
Choice of numerical algorithms
By default DifferentialEquations.jl applies Tsit5
to an ODE problem. If only OrdinaryDiffEq.jl is imported, then we need to explicitly select a solver. However, not all solvers are guaranteed to work. For example, the demo case of electron tracing in the magnetic bottle with strong magnetic field is tested to work only with fixed timestep algorithms like Euler
and the Adams-Bashforth family.
Currently we recommend Vern9
as a starting point for adaptive timestepping, with additional fine tuning by changing reltol
if needed. You can also try out the native implementation of the Boris method in TestParticle.jl, with a constraint of using a fixed time step.
Take you some time to figure out which algorithm works for your problem!
Unit conversions
By default SI units are applied within the package. However, users can also define their own units by setting the particle mass and charge (2 constants) and providing the basic scales of magnetic field, length, time, or velocity (3 reference scales required; length, time and velocity are interchangable).
In the dimensionless natural unit system, we have the most number of ones which in turn gives the simplest form for computation. Check out the demos on unit conversions for more details.
Tracing backwards in time
It is easy to trace a charged particle backwards in time. In a forward tracing problem, we set tspan = (t1, t2)
where t1 < t2
. In a backward tracing problem, we simply set t1 > t2
, e.g. tspan = (0.0, -1.0)
. Note that tracing backwards in time is different from inversing the velocity because of the cross product in the Lorentz force. More specifically, the drift velocities will not change sign if one inverses velocity.
Multiple particles tracing
There are two ways to trace multiple particles simultaneously:
- Extracting the solution in a loop with varying initial conditions. See the example demo_ensemble.
- Constructing the Ensemble Simulations. One example can be found here. However, note that by default the ensemble type replicates the parameters for each solution, which is very memory inefficient for tracing in a numeric field. We need to set
safetycopy=false
to make the field as a reference in the parameter of each trajectory.
The Boris pusher follows a similar interface for multithreading.
Guiding center drifts
By solving the trajectories of particles, we can calculate the actual guiding center orbits by following the definition. This is supported directly via get_gc
. In theoretical treatments, all kinds of drifts have been derived with analytical formulas listed below (see trace_gc_drifts!
). With additional ODEs for solving the drifts, we can separate the different effects or check the deviation of actual orbits from the low order analytical formulas.
An alternative approach is to solve the guiding center approximation equations. In TestParticle.jl, we provide tracing via solving the equations derived from Hamiltonian mechanics and their 1st order approximation.
Summary of guiding center drifts
General force:
\[\mathbf{v}_f = \frac{1}{q}\frac{\mathbf{F}\times\mathbf{B}}{B^2}\]
Electric field:
\[\mathbf{v}_E = \frac{\mathbf{E}\times\mathbf{B}}{B^2}\]
Gravitational field:
\[\mathbf{v}_g = \frac{m}{q}\frac{\mathbf{g}\times\mathbf{B}}{B^2}\]
Nonuniform electric field:
\[\mathbf{v}_E = \Big( 1+\frac{1}{4}r_L^2 \nabla^2 \Big)\frac{\mathbf{E}\times\mathbf{B}}{B^2}\]
Nonuniform magnetic field:
Grad-B:
\[\begin{aligned} \mathbf{v}_{\nabla B} &= \pm \frac{1}{2}v_\perp r_L\frac{\mathbf{B}\times\nabla B}{B^2} \\ &=\frac{mv_\perp^2}{2qB^3}\mathbf{B}\times\nabla B \end{aligned}\]
Curvature drift:
\[\begin{aligned} \mathbf{v}_c &= \frac{mv_\parallel^2}{q}\frac{\mathbf{R}_c \times\mathbf{B}}{R_c^2 B^2} \\ &= \frac{mv_\parallel^2}{qB^4}\mathbf{B}\times\left[ \mathbf{B}\cdot\nabla\mathbf{B} \right] \\ &= \frac{m v_\parallel^2}{qB^3}\mathbf{B}\times\nabla B\,\text{(current-free)} \end{aligned}\]
Curved vacuum field:
\[\begin{aligned} \mathbf{v}_c + \mathbf{v}_{\nabla B} &= \frac{m}{q}\Big( v_\parallel^2 + \frac{1}{2}v_\perp^2 \Big) \frac{\mathbf{R}_c \times\mathbf{B}}{R_c^2 B^2} \\ &= \frac{m}{q}\frac{\mathbf{B}\times\nabla B}{B^3}\Big( v_\parallel^2 + \frac{1}{2}v_\perp^2 \Big) \end{aligned}\]
Polarization drift:[2]
\[\mathbf{v}_p = \pm \frac{1}{\omega_c B}\frac{d\mathbf{E}}{dt}\]
Adiabatic Invariants
See more thorough notes on the adiabatic invariants.
Solution Interpolations
All the tracing solutions come with an interpolation method to make them continuous. Depending on the order of the scheme, different orders of interpolations are applied.
Note that if the scheme comes with an "lazy" interpolation (e.g. Vern family), you can either output the full solution (default) and interpolate
sol = solve(prob, Vern9())
or turn off the lazy interpolation and select part of the solution
sol = solve(prob, Vern9(lazy=false), save_idxs=[1,2,3])
The interpolated solution would be wrong if lazy=true
and save_idxs!=[1,2,3,4,5,6]
.
Presentations
Please checkout:
- 2In common test particle models, we assume static EM fields, so the polarization drift as well as adiabatic heating is not present. However, it is easily achieveable here in this package.