Getting Started
Welcome to GeoDynamo.jl! This guide will get you from zero to running your first simulation.
Prerequisites
| Requirement | Version |
|---|---|
| Julia | 1.10 or 1.11 |
| MPI | OpenMPI, MPICH, or Intel MPI |
| NetCDF | C libraries for output |
Installation
Step 1: Install Julia
Download from julialang.org/downloads and ensure it's on your PATH.
Step 2: Install MPI & NetCDF
Ubuntu/Debian
sudo apt install mpich libnetcdf-devmacOS
brew install mpich netcdfFedora/RHEL
sudo dnf install mpich netcdf-develVerify MPI is working:
╭─────────────────────────────────────────────────────────────────────────────╮
│ Verify MPI │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ $ mpiexec --version │
│ │
╰─────────────────────────────────────────────────────────────────────────────╯Step 3: Clone GeoDynamo.jl
╭─────────────────────────────────────────────────────────────────────────────╮
│ Clone repository │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ $ git clone https://github.com/subhk/GeoDynamo.jl │
│ $ cd GeoDynamo.jl │
│ │
╰─────────────────────────────────────────────────────────────────────────────╯Step 4: Install Dependencies
╭─────────────────────────────────────────────────────────────────────────────╮
│ Install Julia packages │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ $ julia --project -e 'using Pkg; Pkg.instantiate(); Pkg.precompile()' │
│ │
╰─────────────────────────────────────────────────────────────────────────────╯For development with a local SHTnsKit checkout at ../SHTnsKit.jl:
julia --project -e 'using Pkg; Pkg.develop(PackageSpec(path="../SHTnsKit.jl"))'The rewritten solver includes a single-device GPU path with CUDA-backed SHTnsKit transforms when CUDA is available. To use it, add CUDA to your environment and load it before building the solver:
using GeoDynamo
using CUDA
grid = SphericalShellGrid(GPU(); nr = 64, lmax = 31)
model = GeodynamoModel(grid; include_magnetic = true)
simulation = Simulation(model; Δt = 1e-5, stop_time = 0.02)Verification
Test the Installation
╭─────────────────────────────────────────────────────────────────────────────╮
│ Quick test │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ $ julia --project test/shtnskit_roundtrip.jl │
│ │
╰─────────────────────────────────────────────────────────────────────────────╯╭─────────────────────────────────────────────────────────────────────────────╮
│ Full test suite │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ $ julia --project -e 'using Pkg; Pkg.test("GeoDynamo")' │
│ │
╰─────────────────────────────────────────────────────────────────────────────╯Check SHTnsKit Features
julia> using GeoDynamo
julia> info = get_shtnskit_version_info()
julia> @show info.version
julia> @show info.has_qst_transforms
julia> @show info.has_energy_functionsYour First Simulation
Minimal Example
using GeoDynamo
grid = SphericalShellGrid(CPU(); lmax=32, nr=64, nr_inner=16)
model = GeodynamoModel(grid; Ek=1e-4, Ra=1e6, include_magnetic=true)
set!(model; temperature = RandomPerturbation(amplitude=0.1, lmax=10),
magnetic = AnalyticIC(:dipole; amplitude=1.0))
sim = Simulation(model; Δt=1e-5, stop_time=0.1, stop_iteration=10_000)
add_callback!(sim, sim -> @info("step", n=sim.model.clock.iteration);
schedule=IterationInterval(100))
run!(sim)Running with MPI
╭─────────────────────────────────────────────────────────────────────────────╮
│ MPI execution (4 processes) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ $ mpiexec -n 4 julia --project -e ' │
│ using GeoDynamo │
│ grid = SphericalShellGrid(nr = 64, lmax = 31) │
│ model = GeodynamoModel(grid; Ek = 1e-4, Ra = 1e6) │
│ simulation = Simulation(model; Δt = 1e-5, stop_time = 0.02) │
│ run!(simulation) │
│ ' │
│ │
╰─────────────────────────────────────────────────────────────────────────────╯NetCDF files are written to ./output/ by default. See Data Output for details.
Understanding the Physics
GeoDynamo.jl solves the Boussinesq MHD equations in a rotating spherical shell:
\[E \frac{\partial \boldsymbol{u}}{\partial t} = E\nabla^2\boldsymbol{u} + \boldsymbol{N}_u(\boldsymbol{u}, \boldsymbol{B}, T, C)\]
\[\frac{\partial T}{\partial t} = \frac{Pm}{Pr}\nabla^2T + N_T(\boldsymbol{u}, T), \qquad N_T = -\boldsymbol{u}\cdot\nabla T + Q_T\]
\[\frac{\partial \boldsymbol{B}}{\partial t} = \nabla^2\boldsymbol{B} + \nabla\times(\boldsymbol{u}\times\boldsymbol{B})\]
The velocity forcing N_u contains the explicit advection, Coriolis, buoyancy, and optional Lorentz terms. Temperature uses diffusivity Pm/Pr; composition, when enabled, uses Pm/Sc. Magnetic diffusion has coefficient 1 in the magnetic-diffusion time scaling used by the solver.
\[\nabla\cdot\boldsymbol{u}=0, \qquad \nabla\cdot\boldsymbol{B}=0\]
Fields are represented as:
\[\boldsymbol{u} = \nabla \times (T \hat{r}) + \nabla \times \nabla \times (P \hat{r})\]
This automatically satisfies the divergence-free constraint.
Boundary Conditions
Default Setup (Shell Geometry)
| Field | Inner (ICB) | Outer (CMB) | Model keyword |
|---|---|---|---|
| Velocity | No-slip | No-slip | velocity_bcs = BoundaryConditions(inner = NoSlip(), outer = NoSlip()) |
| Velocity | Stress-free | Stress-free | velocity_bcs = BoundaryConditions(inner = StressFree(), outer = StressFree()) |
| Temperature | Fixed T | Fixed T | temperature_bcs = BoundaryConditions(inner = FixedTemperature(1), outer = FixedTemperature(0)) |
| Magnetic | Insulating | Insulating | (automatic) |
| Composition | Fixed C | Fixed C | composition_bcs = BoundaryConditions(inner = FixedTemperature(1), outer = FixedTemperature(0)) |
Custom Boundaries
using GeoDynamo
grid = SphericalShellGrid(nr = 64, lmax = 31)
model = GeodynamoModel(
grid;
temperature_bcs = BoundaryConditions(
inner = FixedTemperature(1.0),
outer = FixedTemperature(0.0),
),
velocity_bcs = BoundaryConditions(
inner = NoSlip(),
outer = StressFree(),
),
)
simulation = Simulation(model; Δt = 1e-5, stop_time = 0.02)Initial Conditions
Setting Up Fields
Use the high-level set! interface to apply initial conditions by field name:
using GeoDynamo
grid = SphericalShellGrid(CPU(); lmax=32, nr=64, nr_inner=16)
model = GeodynamoModel(grid; include_magnetic = true)
# Oceananigans-style: set! dispatches to set_initial_condition! per field
set!(model;
temperature = RandomPerturbation(amplitude=0.1, lmax=10),
magnetic = AnalyticIC(:dipole; amplitude=1.0))
simulation = Simulation(model; Δt = 1e-5, stop_time = 0.02)Equivalent descriptor calls are also accepted at model construction:
model = GeodynamoModel(grid;
include_magnetic = true,
initial_conditions = (
temperature = AnalyticIC(:conductive),
velocity = RandomPerturbation(amplitude = 1e-4, lmax = 8),
magnetic = AnalyticIC(:dipole; amplitude = 1.0),
),
)Loading from Files
# Continue from a restart directory. The restart reader is collective, so call
# this under MPI after MPI.Init().
simulation = Simulation(model; Δt = 1e-5, stop_time = 0.1,
restart_from = "output")
# Fresh initial condition from a compatible IC file
set!(model; temperature = FileIC("path/to/temperature_ic.nc"))Workflow Overview
┌─────────────────────────────────────────────────────────┐
│ 1. GRID │
│ SphericalShellGrid(...) │
└───────────────────────────┬─────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ 2. BOUNDARIES (optional) │
│ BoundaryConditions(inner = ..., outer = ...) │
└───────────────────────────┬─────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ 3. MODEL + SIMULATION │
│ GeodynamoModel(grid; ...) │
│ Simulation(model; Δt, stop_time) │
│ set!(model; temperature = ..., magnetic = ...) │
└───────────────────────────┬─────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ 4. RUN │
│ run!(simulation) │
└───────────────────────────┬─────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ 5. ANALYZE │
│ Inspect NetCDF output in ./output/ │
└───────────────────────────┬─────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ 6. RESTART (optional) │
│ Simulation(model; restart_from = "output") │
└─────────────────────────────────────────────────────────┘Next Steps
| I want to... | Read... |
|---|---|
| Understand all parameters | Configuration |
| Learn about time integration | Time Integration |
| Explore spherical harmonics | Spherical Harmonics |
| Configure output files | Data Output |
| Add non-spherical boundaries | Boundary Topography |
| Contribute code | Developer Guide |