Skip to content

Earth Gravity

This example demonstrates tracing a proton motion with only an Earth-like gravity field provided in the external field F.

julia
using TestParticle
using OrdinaryDiffEqVerner
using StaticArrays
using LinearAlgebra
using CairoMakie

# Constants
const G = 6.67430e-11 # [m^3 kg^-1 s^-2]
const M = 5.972e24    # [kg]
const Rₑ = TestParticle.Rₑ

# Analytic fields
B(x) = SA[0.0, 0.0, 0.0]
E(x) = SA[0.0, 0.0, 0.0]

# Earth's gravity
function F(x)
   r = SA[x[1], x[2], x[3]]
   rmag = @views norm(r)
   return -G * M * TestParticle.mᵢ / rmag^3 * r
end

# Initial static particle
# Start with a location in the equatorial plane and circular motion-like velocity.
r0 = 2Rₑ
v0 = sqrt(G * M / r0)
stateinit = let x0 = [r0, 0.0, 0.0], v0 = [0.0, v0, 0.0]
   [x0..., v0...]
end

# Time span
# Orbital period T = 2π * sqrt(r^3 / GM)
T_orbit = * sqrt(r0^3 / (G * M))
tspan = (0, 2T_orbit)

param = prepare(E, B, F, species = Proton)
prob = ODEProblem(trace!, stateinit, tspan, param)
# High accuracy is needed for conservation of energy and angular momentum over long periods,
# though for 2 orbits default tolerances might be acceptable.
sol = solve(prob, Vern9())

# Visualization
f = Figure(size = (800, 800))
ax = Axis3(f[1, 1],
   title = "Proton in Earth Gravity (No EM field)",
   xlabel = "X [Re]", ylabel = "Y [Re]", zlabel = "Z [Re]",
   aspect = :data
)

# Draw Earth
# A simple sphere at the origin
u = LinRange(0, , 50)
v = LinRange(0, π, 50)
x_sphere = Rₑ .* (cos.(u) * sin.(v)')
y_sphere = Rₑ .* (sin.(u) * sin.(v)')
z_sphere = Rₑ .* (ones(length(u)) * cos.(v)')

surface!(ax, x_sphere ./ Rₑ, y_sphere ./ Rₑ, z_sphere ./ Rₑ,
   colormap = (:turbo, 0.5), shading = true, transparency = true)

# Plot trajectory
lines!(ax, sol[1, :] ./ Rₑ, sol[2, :] ./ Rₑ, sol[3, :] ./ Rₑ,
   color = :orangered, linewidth = 2, label = "Trajectory")

If we use lines!(ax, sol, idxs=(1,2,3)), interpolation will automatically be used. However, there is currently a bug in Makie for scale! on the axis.