Getting Started

Welcome to GeoDynamo.jl! This guide will get you from zero to running your first simulation.


Prerequisites

What You Need
RequirementVersion
Julia1.10 or 1.11
MPIOpenMPI, MPICH, or Intel MPI
NetCDFC 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-dev

macOS

brew install mpich netcdf

Fedora/RHEL

sudo dnf install mpich netcdf-devel

Verify 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()'     │
│                                                                             │
╰─────────────────────────────────────────────────────────────────────────────╯
Development Mode

For development with a local SHTnsKit checkout at ../SHTnsKit.jl:

julia --project -e 'using Pkg; Pkg.develop(PackageSpec(path="../SHTnsKit.jl"))'
Optional CUDA GPU Backend

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_functions
Missing Features?

Update SHTnsKit with:

using Pkg; Pkg.update("SHTnsKit")

Your 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)                                                      │
│   '                                                                         │
│                                                                             │
╰─────────────────────────────────────────────────────────────────────────────╯
Output

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\]

Toroidal-Poloidal Decomposition

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)

FieldInner (ICB)Outer (CMB)Model keyword
VelocityNo-slipNo-slipvelocity_bcs = BoundaryConditions(inner = NoSlip(), outer = NoSlip())
VelocityStress-freeStress-freevelocity_bcs = BoundaryConditions(inner = StressFree(), outer = StressFree())
TemperatureFixed TFixed Ttemperature_bcs = BoundaryConditions(inner = FixedTemperature(1), outer = FixedTemperature(0))
MagneticInsulatingInsulating(automatic)
CompositionFixed CFixed Ccomposition_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

Where to Go From Here
I want to...Read...
Understand all parametersConfiguration
Learn about time integrationTime Integration
Explore spherical harmonicsSpherical Harmonics
Configure output filesData Output
Add non-spherical boundariesBoundary Topography
Contribute codeDeveloper Guide