Cosmic Ray
This example shows how to trace cosmic rays in a background magnetic field. In the original MHD solution, everything is dimensionless. We are following the normalization procedures in Cosmic ray propagation in sub-Alfvénic magnetohydrodynamic turbulence. The Lorentz equation for each particle of charge
Each particle is injected with a Lorentz factor
where
This is measured in cyclotron frequency units, a gyration frequency measured in the particle's own frame. A particle with pitch angle cosine
where
In practice, at least in the interstellar medium, the effect of the electric field over high-energy (multi TeV) cosmic rays can be neglected. Therefore, energy is conserved and we are interested in looking at the scattering and diffusion processes.
Thus, the normalized equations can be further simplified:
By taking
This looks good, but there is still an annoying factor
It simply means that if the original domain length is 1, now it becomes
A standard procedure is as follows:
Obtain the dimensionless MHD solution.
Normalize the magnetic field with its background mean magnitude, such that in the new field,
. This has a clear physical meaning that a particle with velocity 1 has a gyroradii of 1 and a gyroperiod of . Manually choose the spatial extent to be
. For simplicity, we set and the MHD domain extent to be . If we have discrete points along that direction, then the grid size is . If , then is a quarter of the gyroradius. In this way we can control how well we resolve the magnetic field for the gyromotion and diffusion process.
Now let's demonstrate this with trace_normalized!.
using TestParticle, OrdinaryDiffEqVerner, StaticArrays
using CairoMakie
# Number of cells for the field along each dimension
nx, ny, nz = 4, 6, 2
# Unit conversion factors for length
rL0 = 1.0
L = nx / 4
# Set length scales
x = range(-L/2-1e-2, L/2+1e-2, length = nx) # [rL0]
y = range(-L-1e-2, 1e-2, length = ny) # [rL0]
z = range(-10, 10, length = nz) # [rL0]
B = fill(0.0, 3, nx, ny, nz) # [B0]
B[3, :, :, :] .= 1.0
E(x) = SA[0.0, 0.0, 0.0] # [E₀]
# periodic bc = 2
param = prepare(x, y, z, E, B; species = User, bc = 2)
# Initial condition
stateinit = let
x0 = [0.0, 0.0, 0.0] # initial position [l₀]
u0 = [1.0, 0.0, 0.0] # initial velocity [v₀] -> r = 1 * rL0
[x0..., u0...]
end
# Time span
tspan = (0.0, π) # half gyroperiod
prob = ODEProblem(trace_normalized!, stateinit, tspan, param)
sol = solve(prob, Vern9())
### Visualization
f = Figure(fontsize = 18)
ax = Axis(f[1, 1],
title = "Proton trajectory",
xlabel = "X",
ylabel = "Y",
limits = (2*x[1]-0.1, 2*x[end]+0.1, 2*y[1]-0.1, 2*y[end]+0.1),
aspect = DataAspect()
)
lines!(ax, sol, idxs = (1, 2))
xgrid = [i for i in x, _ in y]
ygrid = [j for _ in x, j in y]
scatter!(ax, xgrid[:], ygrid[:], color = :tomato)