API Reference
┌─────────────────────────────────────────────────────────────────────────┐
│ GeoDynamo.jl API │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ GeoDynamo │
│ ├── Core Types & Functions │
│ ├── bcs (Boundary Conditions) │
│ │ └── topography │
│ ├── InitialConditions │
│ ├── GeoDynamoShell │
│ └── GeoDynamoBall │
│ │
└─────────────────────────────────────────────────────────────────────────┘This page provides a comprehensive reference for all exported types and functions.
Module Index
Main Module
The main GeoDynamo module exports core types, simulation drivers, and utilities.
At a Glance
GeoDynamo
├── Types
│ ├── GeoDynamoParameters # Simulation configuration
│ ├── SimulationState # Runtime state container
│ └── SHTnsKitConfig # Transform configuration
│
├── Simulation
│ ├── initialize_simulation # Create initial state
│ ├── run_simulation! # Main time loop
│ └── set_parameters! # Apply configuration
│
├── I/O
│ ├── write_fields! # Output to NetCDF
│ ├── read_restart! # Load checkpoint
│ └── save_parameters # Save configuration
│
└── Transforms
├── shtnskit_synthesis! # Spectral → Physical
├── shtnskit_analysis! # Physical → Spectral
└── get_shtnskit_version_infoGeoDynamo._BUFFER_CACHE_LOCK — Constant
_BUFFER_CACHE_LOCKGlobal ReentrantLock for thread-safe access to SHTnsKitConfig buffer caches. All access to config.buffercache should be protected by this lock.
GeoDynamo.AbstractScalarField — Type
Abstract type for scalar fields (temperature, composition, etc.)
GeoDynamo.AdvancedThreadManager — Type
AdvancedThreadManagerAdvanced thread management with CPU affinity, NUMA awareness, and work-stealing.
GeoDynamo.AsyncCommManager — Type
AsyncCommManager{T}Advanced asynchronous communication manager for overlapping computation and communication.
GeoDynamo.CPUParallelizer — Type
CPUParallelizer{T}Advanced CPU parallelization system with SIMD, NUMA, and task-based parallelism.
GeoDynamo.CombinerConfig — Type
CombinerConfigConfiguration structure for field combination process.
GeoDynamo.DynamicLoadBalancer — Type
DynamicLoadBalancerDynamic load balancing system that adapts to computational heterogeneity.
GeoDynamo.EAB2ALUCacheEntry — Type
EAB2ALUCacheEntry{T}Type-stable cache entry for EAB2 (Exponential Adams-Bashforth 2) method. Stores banded matrices and their LU factorizations for each spherical harmonic degree l.
GeoDynamo.ERK2BoundarySide — Type
ERK2BoundarySide{T}Encodes how to enforce a boundary condition at one boundary (inner or outer) for the ERK2 exponential integrator.
All BC types are expressed as a linear constraint: sumj stencil[j] * u[j] + lcorrection * u[b] = value
which is solved for u[b]: u[b] = (value - sum{j≠b} stencil[j] * u[j]) / (stencil[b] + lcorrection)
BC types and their encoding:
- :dirichlet → stencil = delta{b}, value = BCval (u[b] = BC_val)
- :neumann → stencil = d1[b,:], value = q (du/dr = q)
- :stressfreetor → stencil = d1[b,:], lcorrection = -1/rb (dT/dr - T/r = 0)
- :noslip_pol → stencil = d1[b,:], value = 0 (dP/dr = 0)
- :stressfreepol → stencil = d2[b,:], value = 0 (d²P/dr² = 0)
- :insulatinginner → stencil = d1[b,:], lcorrection = -l/r_b (d/dr - l/r)P = 0
- :insulatingouter → stencil = d1[b,:], lcorrection = +(l+1)/r_b (d/dr + (l+1)/r)P = 0
GeoDynamo.ERK2BoundarySpec — Type
ERK2BoundarySpec{T}Complete boundary condition specification for both boundaries.
inner_mode_values and outer_mode_values are optional per-mode value overrides (indexed by lmidx). When provided, they override `bcside.value` for specific modes. Used e.g. for rotating inner core: T(l=1,m=0) = rotomega * rinner.
GeoDynamo.ERK2Cache — Type
ERK2Cache{T}Cached data structure for Exponential 2nd Order Runge-Kutta method. Stores precomputed matrix exponentials and φ functions for each spherical harmonic mode.
GeoDynamo.ERK2InfluenceMatrix — Type
ERK2InfluenceMatrix{T}Precomputed influence matrix data for enforcing P = 0 at boundaries while using derivative boundary conditions in the exponential operator.
This matches the Fortran DD_2DCODE influence matrix method for poloidal velocity.
GeoDynamo.EnergyTracker — Type
EnergyTrackerStructure for tracking energy conservation during simulation.
GeoDynamo.FieldCombiner — Type
FieldCombiner{T}Structure for combining distributed GeoDynamo.jl output files using the consistent field structures and parameter system.
GeoDynamo.GradientWorkspace — Type
GradientWorkspace{T}Shared workspace for transient gradient spectral fields. Reused across scalar field computations that run sequentially (temperature, composition). These arrays are zeroed and recomputed every timestep, so sharing is safe.
GeoDynamo.MasterParallelizer — Type
MasterParallelizer{T}Comprehensive parallelization system combining all techniques.
GeoDynamo.MemoryOptimizer — Type
MemoryOptimizer{T}Advanced memory management with cache optimization and NUMA awareness.
GeoDynamo.NaNDetectionConfig — Type
NaNDetectionConfigConfiguration for NaN/Inf detection during simulation.
GeoDynamo.ParallelIOOptimizer — Type
ParallelIOOptimizer{T}Advanced parallel I/O optimization with asynchronous writes and data staging.
GeoDynamo.PerformanceMonitor — Type
PerformanceMonitorComprehensive performance monitoring for parallel efficiency analysis.
GeoDynamo.Phi2ConditioningMonitor — Type
Phi2ConditioningMonitorGlobal structure for monitoring φ₂ function conditioning during ERK2 integration. Tracks worst conditioning, series expansion usage, and numerical issues.
GeoDynamo.RadialDomain — Type
RadialDomainSpecification of the radial discretization for the spherical shell.
Radial Grid
The simulation domain is a spherical shell between inner radius ri (e.g., inner core boundary) and outer radius ro (e.g., core-mantle boundary). The radial direction is discretized using Chebyshev collocation for spectral accuracy.
Fields
N: Number of radial pointslocal_range: Indices of radial points local to this MPI processr: Radial coordinate values [1, N]dr_matrices: Radial derivative matrices (1st, 2nd order, etc.)radial_laplacian: Matrix for radial part of Laplacianintegration_weights: Quadrature weights for radial integration
GeoDynamo.SHTnsKitConfig — Type
SHTnsKitConfig <: AbstractSHTnsConfigMain configuration structure for spherical harmonic transforms using SHTnsKit. This struct encapsulates all parameters needed for transforms and parallelization.
Fields
Core SHTnsKit Configuration
sht_config: The underlying SHTnsKit.SHTConfig object
Grid Parameters
nlat::Int: Number of latitude (theta) points (Gauss-Legendre grid)nlon::Int: Number of longitude (phi) points (uniform grid)lmax::Int: Maximum spherical harmonic degreemmax::Int: Maximum spherical harmonic order (≤ lmax)nlm::Int: Total number of (l,m) spectral mode pairs
Parallelization Infrastructure
pencils::NamedTuple: Collection of PencilArrays Pencil objects for different data orientations (:theta, :phi, :r, :spec, :mixed)fft_plans::Dict{Symbol,Any}: Precomputed FFTW plans for FFT operationstranspose_plans::Dict{Symbol,Any}: Plans for data redistribution between pencils
Auxiliary Data
memory_estimate::String: Human-readable memory usage estimatel_values::Vector{Int}: Spherical harmonic degree for each spectral indexm_values::Vector{Int}: Spherical harmonic order for each spectral indextheta_grid::Vector{Float64}: Latitude values (Gauss-Legendre nodes)phi_grid::Vector{Float64}: Longitude values (uniform spacing)gauss_weights::Vector{Float64}: Gauss-Legendre quadrature weights
Internal
_buffer_cache::Dict{Symbol,Any}: Reusable work arrays to reduce allocations
Usage
config = create_shtnskit_config(lmax=32, mmax=32, nlat=64, nlon=128)GeoDynamo.SHTnsPhysField — Type
SHTnsPhysField{T}A scalar field represented on the physical (θ, φ, r) grid.
Storage Layout
Field values stored in a 3D array:
- Dimension 1: Latitude index (1 to nlat), Gauss-Legendre points
- Dimension 2: Longitude index (1 to nlon), uniform spacing
- Dimension 3: Radial level index
Pencil Orientation
The pencil field specifies how data is distributed across MPI processes. Different pencil orientations are optimal for different operations:
- phi pencil: Optimal for FFTs (all longitudes local)
- theta pencil: Optimal for Legendre transforms (all latitudes local)
- r pencil: Optimal for radial operations (all radii local)
GeoDynamo.SHTnsSpecField — Type
SHTnsSpecField{T}A scalar field represented in spectral space as spherical harmonic coefficients.
Storage Layout
Coefficients are stored as separate real and imaginary parts in 3D arrays:
- Dimension 1: Combined (l,m) spectral index (1 to nlm)
- Dimension 2: Dummy dimension (size 1) for PencilArrays compatibility
- Dimension 3: Radial level index
Boundary Conditions
Each (l,m) mode can have independent boundary conditions at the inner and outer radial boundaries. Common types:
- DIRICHLET: Specified value at boundary
- NEUMANN: Specified derivative at boundary
Fields
config: SHTnsKit configuration (grid and transform parameters)nlm: Total number of spectral modesdata_real,data_imag: Real/imaginary parts of coefficientspencil: PencilArrays pencil defining data distributionbc_type_inner/outer: Boundary condition type for each modeboundary_values: Boundary values [2, nlm] for inner/outer
GeoDynamo.SHTnsTorPolField — Type
SHTnsTorPolField{T}Vector field in toroidal-poloidal spectral representation.
The Toroidal-Poloidal Decomposition
Any solenoidal (divergence-free) vector field can be written as: v = ∇ × (T r̂) + ∇ × ∇ × (P r̂)
where T and P are scalar functions called the toroidal and poloidal potentials.
Why This Representation?
- Automatically satisfies ∇·v = 0 (mass conservation for incompressible flow)
- Decouples certain physical processes in the equations
- Reduces storage: 2 scalars instead of 3 vector components
- Natural for spherical geometry and spectral methods
Fields
toroidal: Toroidal potential T(l,m,r) in spectral spacepoloidal: Poloidal potential P(l,m,r) in spectral space
GeoDynamo.SHTnsVectorField — Type
SHTnsVectorField{T}A vector field represented by its three spherical components in physical space.
Components:
r_component: Radial component v_r(θ, φ, r)θ_component: Latitudinal component v_θ(θ, φ, r)φ_component: Longitudinal component v_φ(θ, φ, r)
Each component is a SHTnsPhysField, potentially with different pencil orientations for optimal computation of different operations.
GeoDynamo.SIMDOptimizer — Type
SIMDOptimizer{T}Advanced SIMD vectorization for mathematical operations with AVX/NEON support.
GeoDynamo.SimulationState — Type
SimulationState{T}Unified simulation state with comprehensive parallelization and diagnostics. Type-stable version with concrete cache types for optimal performance.
GeoDynamo.SolenoidalMonitor — Type
SolenoidalMonitorStructure for monitoring solenoidal constraint ∇·v = 0 for velocity and magnetic fields.
GeoDynamo.SpectralToPhysicalConverter — Type
SpectralToPhysicalConverter{T}Structure for converting spectral field data to physical space using the GeoDynamo.jl infrastructure (PencilArrays + SHTns).
GeoDynamo.TaskGraph — Type
TaskGraphRepresents computation as a directed acyclic graph for optimal scheduling.
GeoDynamo.TaskNode — Type
TaskNodeRepresents a computation task in a dependency graph.
GeoDynamo.ThreadingAccelerator — Type
ThreadingAccelerator{T} (Backward Compatibility)Basic CPU threading acceleration for existing code.
GeoDynamo._copy_spectral_to_field! — Method
_copy_spectral_to_field!(field::SHTnsSpecField{T}, real_data::AbstractArray, imag_data::AbstractArray)Copy restart spectral data into a SHTnsSpecField. Handles the dimension mismatch between the restart file format [nlm, nr] and the field storage format [nlm, 1, nr].
GeoDynamo._get_influence_cache — Method
_get_influence_cache(domain::RadialDomain, ∂r)Get or create cached influence functions and matrix for given domain. Note: ∂r should be a BandedMatrix (defined in linear_algebra.jl)
GeoDynamo._get_tau_cache — Method
_get_tau_cache(domain::RadialDomain)Get or create cached tau polynomials and derivatives for given domain.
GeoDynamo._load_file_bcs! — Method
_load_file_bcs!(state::SimulationState)Load file-based boundary conditions from paths specified in parameters. Modifies the field's mutable boundaryinterpolationcache in place.
GeoDynamo._load_restart_file — Method
_load_restart_file(filepath, tracker, config; pencils=nothing)Load simulation state from a specific restart NetCDF file path using parallel I/O. All ranks open the file collectively and read their local slices.
GeoDynamo._shtns_make_transpose — Method
_shtns_make_transpose(pair)Create a PencilArrays transpose plan between two pencil configurations. Used internally to set up efficient data redistribution operations.
Arguments
pair: A Pair of source and destination Pencil objects (src => dest)
Returns
- A Transposition object that can be used with
mul!for data redistribution
GeoDynamo._spectral_curl_torpol! — Method
_spectral_curl_torpol!(dst_tor_r, dst_tor_i, dst_pol_r, dst_pol_i,
src_tor_r, src_tor_i, src_pol_r, src_pol_i,
ℓ_factors, d1_matrix, d²_matrix, domain, config, T)Shared spectral curl for toroidal-poloidal fields: (∇×V)tor = [l(l+1)/r² - d²/dr² - 2/r d/dr] Vpol (∇×V)pol = -l(l+1)/r² Vtor
Used by both current density (j = ∇×B) and induction curl (∇×(u×B)).
GeoDynamo.add_internal_sources_local! — Method
add_internal_sources_local!(𝔽::AbstractScalarField{T}, domain::RadialDomain) where TAdd volumetric sources (completely local operation). This works for any scalar field with radial source profile.
GeoDynamo.analyze_load_balance — Method
analyze_load_balance(pencil::Pencil)Analyze and report load balance for a given pencil decomposition.
GeoDynamo.apply_banded_full! — Method
apply_banded_full!(out, B, v)Apply banded matrix to full vector.
GeoDynamo.apply_exponential_filter! — Method
apply_exponential_filter!(config::SHTnsKitConfig, alm::Matrix{ComplexF64};
order::Int=16, cutoff::Float64=0.65,
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Apply an exponential spectral filter for dealiasing. filter(l) = exp(-α * (l/lmax)^order) where α is chosen so filter(cutoff*lmax) = 0.5
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsorder: Filter order (higher = sharper cutoff, default 16)cutoff: Fraction of lmax where filter = 0.5 (default 0.65)alm_out: Optional output array
GeoDynamo.apply_flux_bc_direct! — Method
apply_flux_bc_direct!(spec_real, spec_imag, local_lm, lm_idx,
𝔽::AbstractScalarField, domain, r_range)Direct modification of boundary values to approximately satisfy flux BC. This is the simplest but least accurate method.
GeoDynamo.apply_flux_bc_influence_matrix! — Method
apply_flux_bc_influence_matrix!(spec_real, spec_imag, local_lm, lm_idx,
apply_inner, apply_outer, 𝔽::AbstractScalarField,
domain, r_range, owns_mode::Bool)Apply flux boundary conditions using the influence matrix method.
MPI Safety
The owns_mode parameter indicates whether this process owns the lm mode. All processes must call this function for each mode to ensure Allreduce is called the same number of times by all processes (prevents deadlock).
GeoDynamo.apply_flux_bc_tau! — Method
apply_flux_bc_tau!(spec_real, spec_imag, local_lm, lm_idx,
apply_inner, apply_outer, 𝔽::AbstractScalarField,
domain, r_range, owns_mode::Bool)Apply flux boundary conditions using the tau method. This is the generalized version that works with any scalar field.
MPI Safety
The owns_mode parameter indicates whether this process owns the lm mode. All processes must call this function for each mode to ensure Allreduce is called the same number of times by all processes (prevents deadlock).
GeoDynamo.apply_geometric_factors_spectral! — Method
apply_geometric_factors_spectral!(ws::GradientWorkspace{T}, 𝔽::AbstractScalarField{T}, domain::RadialDomain) where TApply geometric factors (1/r, 1/(r sin θ)) in spectral space. For gradients in spherical coordinates. This is generic.
GeoDynamo.apply_horizontal_laplacian! — Method
apply_horizontal_laplacian!(config::SHTnsKitConfig, alm::Matrix{ComplexF64};
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Apply the horizontal (angular) Laplacian to spectral coefficients. ∇²h Yl^m = -l(l+1) Y_l^m
This scales each coefficient by -l(l+1), which is the eigenvalue of the horizontal Laplacian on the unit sphere.
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsalm_out: Optional output array (if nothing, modifies alm in-place)
Returns
The Laplacian-transformed coefficients
GeoDynamo.apply_influence_matrix_correction! — Method
apply_influence_matrix_correction!(result, influence, bc_inner_val, bc_outer_val)Apply influence matrix correction to enforce P = 0 at boundaries. This subtracts the Green's function response that would give non-zero boundary values.
After this correction, result[1] ≈ bcinnerval and result[nr] ≈ bcouterval (typically both zero for no-penetration).
GeoDynamo.apply_inverse_horizontal_laplacian! — Method
apply_inverse_horizontal_laplacian!(config::SHTnsKitConfig, alm::Matrix{ComplexF64};
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing,
regularize_l0::Bool=true)Apply the inverse horizontal Laplacian to spectral coefficients. This scales each coefficient by -1/(l(l+1)), which is useful for solving Poisson equations.
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsalm_out: Optional output arrayregularize_l0: If true, set l=0 mode to zero (since 1/0 is undefined)
Returns
The inverse-Laplacian-transformed coefficients
GeoDynamo.apply_scalar_flux_bc_spectral! — Method
apply_scalar_flux_bc_spectral!(𝔽::AbstractScalarField{T}, domain::RadialDomain;
method::Symbol=:tau) where TApply flux boundary conditions to a scalar field in spectral space. Methods available: :tau (most robust), :influence_matrix, :direct (simplest).
MPI Safety
Uses global loop bounds (1:nlm) to ensure all processes call MPI collectives the same number of times, preventing deadlock with uneven lm distribution.
GeoDynamo.apply_spectral_filter! — Method
apply_spectral_filter!(config::SHTnsKitConfig, alm::Matrix{ComplexF64},
filter_func::Function;
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Apply a custom spectral filter to coefficients. The filter function takes (l, m) and returns a scaling factor.
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsfilter_func: Function (l, m) -> scale_factoralm_out: Optional output array
Example
# Exponential filter for dealiasing
exp_filter(l, m) = exp(-(l/lmax)^16)
apply_spectral_filter!(config, alm, exp_filter)GeoDynamo.apply_tau_correction! — Method
apply_tau_correction!(profile::Vector{T}, tau_coeffs, domain::RadialDomain) where TAdd tau correction to the radial profile.
GeoDynamo.apply_velocity_poloidal_influence_correction! — Method
apply_velocity_poloidal_influence_correction!(field, influence_matrices, config)Apply influence matrix correction to enforce P = 0 at boundaries for velocity poloidal. This is called after erk2finalizefield! to enforce the no-penetration condition while preserving the derivative BC constraints used in the exponential operator.
Matches DD_2DCODE's influence matrix method for velocity poloidal.
GeoDynamo.batch_convert_directory — Method
batch_convert_directory(input_dir::String, output_dir::String = "";
pattern::String = "combined_global_time_",
precision::Type{T} = Float64,
compute_diagnostics::Bool = true) where TConvert all spectral files matching a pattern in a directory.
GeoDynamo.batch_magnetic_transforms! — Method
batch_magnetic_transforms!(ℬ::SHTnsMagneticFields{T}) where TPerform batched transforms for better cache efficiency using shtnskit_transforms.jl
GeoDynamo.batch_shtnskit_transforms! — Method
batch_shtnskit_transforms!(specs::Vector{SHTnsSpecField{T}},
physs::Vector{SHTnsPhysField{T}}) where TBatch process multiple transforms using SHTnsKit with PencilArrays.
MPI Safety
This function processes transforms sequentially to avoid calling MPI collectives (Barrier) from multiple threads simultaneously. MPI collective operations must be called from the same thread on all processes to avoid deadlock.
Note: The individual transforms themselves are still efficient as SHTnsKit performs optimized Legendre transforms and FFTs internally.
GeoDynamo.batch_spectral_to_physical! — Method
batch_spectral_to_physical!(specs, physs)Compatibility wrapper that calls batch_shtnskit_transforms! for batched spectral→physical transforms using SHTnsKit with PencilArrays/MPI.
GeoDynamo.batch_velocity_transforms! — Method
batch_velocity_transforms!(𝒰::SHTnsVelocityFields{T}) where TPerform batched transforms for better cache efficiency using shtnskit_transforms.jl
GeoDynamo.build_banded_A — Method
build_banded_A(T, domain, diffusivity, l) -> BandedMatrix{T}Construct banded A = ν*(d²/dr² + (2/r)d/dr − l(l+1)/r²) in banded storage.
GeoDynamo.build_erk2_bc_spec_magnetic_pol — Method
build_erk2_bc_spec_magnetic_pol(T, domain) -> ERK2BoundarySpec{T}Build ERK2 boundary spec for magnetic poloidal field (insulating BCs, l-dependent). Inner: (d/dr - l/r)P = 0. Outer: (d/dr + (l+1)/r)P = 0.
GeoDynamo.build_erk2_bc_spec_magnetic_tor — Method
build_erk2_bc_spec_magnetic_tor(T, nr) -> ERK2BoundarySpec{T}Build ERK2 boundary spec for magnetic toroidal field (insulating: BT = 0 at both).
GeoDynamo.build_erk2_bc_spec_scalar — Method
build_erk2_bc_spec_scalar(T, domain, i_bc) -> ERK2BoundarySpec{T}Build ERK2 boundary spec for a scalar field (temperature or composition). i_bc encoding: 1=DD, 2=DN, 3=ND, 4=NN.
GeoDynamo.build_erk2_bc_spec_velocity_pol — Method
build_erk2_bc_spec_velocity_pol(T, domain, i_vel_bc) -> ERK2BoundarySpec{T}Build ERK2 boundary spec for the velocity poloidal component.
Uses proper derivative boundary conditions matching DD_2DCODE:
- No-slip: ∂P/∂r = 0 (first derivative)
- Stress-free: ∂²P/∂r² = 0 (second derivative)
The no-penetration condition (P = 0 at boundaries) is enforced separately via the influence matrix method, which is applied after the exponential operator in erk2finalizevelocity_poloidal!.
ivelbc: 1=no-slip both, 2=no-slip inner/stress-free outer, 3=stress-free inner/no-slip outer, 4=stress-free both.
GeoDynamo.build_erk2_bc_spec_velocity_tor — Method
build_erk2_bc_spec_velocity_tor(T, domain, i_vel_bc; config=nothing, rot_omega=0.0) -> ERK2BoundarySpec{T}Build ERK2 boundary spec for the velocity toroidal component. ivelbc: 1=no-slip both, 2=no-slip inner/stress-free outer, 3=stress-free inner/no-slip outer, 4=stress-free both.
If rot_omega ≠ 0 and inner BC is no-slip, the inner boundary value for (l=1, m=0) is set to rot_omega * r_inner (rotating inner core).
GeoDynamo.build_influence_matrix — Method
build_influence_matrix(G_inner, G_outer, ∂r, domain)Construct a 2×2 matrix mapping influence amplitudes to boundary flux errors. Rows correspond to (inner, outer) boundaries; columns to (inner, outer) influence functions.
GeoDynamo.build_lm_lookup_tables — Method
build_lm_lookup_tables(lmax, mmax) -> (l_values, m_values)Build precomputed lookup tables for converting linear indices to (l, m).
Returns
l_values: Vector where l_values[idx] gives the degree l for linear index idxm_values: Vector where m_values[idx] gives the order m for linear index idx
GeoDynamo.build_rhs_cnab2! — Method
build_rhs_cnab2!(rhs, un, nl, nl_prev, dt, matrices)Build RHS for CNAB2 IMEX: rhs = un/dt + (1-θ)·L·un + (3/2)·nl − (1/2)·nl_prev, where θ = matrices.theta and L is the diffusivity-scaled linear operator.
MPI Safety
Uses global loop bounds (1:nlm) to ensure all processes call Allreduce the same number of times, preventing deadlock with uneven lm distribution.
GeoDynamo.build_∂θ — Method
build_∂θ(::Type{T}, config::SHTnsKitConfig) where TBuild sparse matrix for θ-derivatives in spectral space. This matrix couples different l modes with the same m.
GeoDynamo.calculate_linear_neighbors — Method
calculate_linear_neighbors(rank::Int, dim::Int, proc_dims::Tuple, boundaries::Symbol)Calculate neighbor ranks for non-Cartesian topologies.
GeoDynamo.check_field_for_nan — Method
check_field_for_nan(field_data::AbstractArray, field_name::String, config::NaNDetectionConfig, step::Int)Check a field for NaN or Inf values. Returns (hasnan, hasinf, nancount, infcount).
GeoDynamo.check_parallel_netcdf_support — Method
check_parallel_netcdf_support(comm)Verify that parallel NetCDF (MPI-IO via HDF5) is available at runtime. Called once at initialization. Errors immediately if not supported.
GeoDynamo.check_simulation_state_for_nan — Method
check_simulation_state_for_nan(state::SimulationState, step::Int;
config::NaNDetectionConfig=DEFAULT_NAN_CONFIG)Comprehensive NaN/Inf check across all simulation fields. Returns true if any NaN/Inf detected.
GeoDynamo.check_solenoidal_constraint! — Method
check_solenoidal_constraint!(state::SimulationState)Check and record solenoidal constraint for velocity and magnetic fields.
GeoDynamo.check_spectral_field_for_nan — Method
check_spectral_field_for_nan(field::SHTnsSpecField, field_name::String,
config::NaNDetectionConfig, step::Int)Check both real and imaginary parts of a spectral field.
GeoDynamo.check_transform_synchronization — Method
check_transform_synchronization(config; strict::Bool=false) -> BoolVerify that the SHTnsKit transform configuration is safe for parallel execution.
Checks:
- All processes have same number of local radial levels
- Spectral mode distribution is valid
- FFT plans are properly initialized
Arguments
config: SHTnsKit configuration object with pencil informationstrict: If true, throw an error on invalid configuration (recommended for production)
Returns
true if configuration is safe for parallel transforms.
Example
# Validate before running transforms
check_transform_synchronization(config; strict=true)GeoDynamo.clear_buffer_cache! — Method
clear_buffer_cache!(config)Thread-safe clearing of all cached buffers. Useful when changing configurations or to free memory.
GeoDynamo.combine_distributed_time — Method
combine_distributed_time(output_dir::String, time::Float64;
config::CombinerConfig = create_combiner_config(),
precision::Type{T} = Float64) where TMain function to combine distributed files for a specific time.
GeoDynamo.combine_magnetic_spectral! — Method
combine_magnetic_spectral!(combiner::FieldCombiner{T}, lm_mapping::Dict) where TCombine magnetic spectral coefficients from all distributed files.
GeoDynamo.combine_physical_fields! — Method
combine_physical_fields!(combiner::FieldCombiner{T}) where TCombine physical space temperature field from distributed files.
GeoDynamo.combine_spectral_fields! — Method
combine_spectral_fields!(combiner::FieldCombiner{T}) where TCombine spectral field data from distributed files.
GeoDynamo.combine_time_series — Method
combine_time_series(output_dir::String, time_range::Tuple{Float64,Float64};
config::CombinerConfig = create_combiner_config(),
precision::Type{T} = Float64) where TCombine multiple time points into a time series.
GeoDynamo.combine_to_global! — Method
combine_to_global!(combiner::FieldCombiner{T}) where TCombine distributed field data into global field structures.
GeoDynamo.combine_velocity_spectral! — Method
combine_velocity_spectral!(combiner::FieldCombiner{T}, lm_mapping::Dict) where TCombine velocity spectral coefficients from all distributed files.
GeoDynamo.compute_all_gradients_spectral! — Method
compute_all_gradients_spectral!(𝔽::AbstractScalarField{T}, domain::RadialDomain, ws::GradientWorkspace{T}) where TCompute all gradient components (θ, φ, r) in spectral space. This is the main driver function that works for any scalar field.
GeoDynamo.compute_all_nonlinear_terms! — Method
compute_all_nonlinear_terms!(𝒰, temp_field, comp_field, mag_field, domain)Compute all nonlinear forcing terms for the momentum equation.
Governing Equation (Dimensional)
In a rotating reference frame with angular velocity Ω:
∂u/∂t = -u×ω - ∇p/ρ + 2Ω(ẑ×u) + ν∇²u + (αg/ρ)T·r̂ + (Δρg/ρ)C·r̂ + (1/μ₀ρ)(∇×B)×B
where:
- u: velocity, ζ = ∇×u: vorticity
- Ω: rotation rate, ẑ: rotation axis
- ν: kinematic viscosity
- α: thermal expansion coefficient, g: gravity
- T: temperature perturbation, C: composition perturbation
- B: magnetic field, μ₀: permeability
Non-Dimensionalization (Magnetic Diffusion Time Scaling)
Length scale: d (shell thickness or ball radius) Time scale: τ = d²/η (magnetic diffusion time) Velocity scale: U = η/d Magnetic field scale: B₀ Temperature scale: ΔT
Dimensionless parameters:
- E = ν/(Ω d²): Ekman number
- Pm = ν/η: Magnetic Prandtl number
- Pr = ν/κ: Prandtl number
- Sc = ν/D: Schmidt number
- Ra = (αgΔT d³)/(νκ): Rayleigh number
- Ra_C = (Δρg d³)/(ρνD): Compositional Rayleigh number
Non-Dimensional Momentum Equation (magnetic diffusion time scaling)
E·Pm⁻¹[∂ũ/∂τ + (∇×ũ)×ũ] + ẑ×ũ = -∇p̃* + (Pm/Pr)·Ra·T̃·r·r̂ + (Pm/Sc)·Ra_C·C̃·r·r̂ + (∇×B̃)×B̃ + E∇²ũ
where:
- τ = L²/η (magnetic diffusion time scaling)
- E = ν/(2ΩL²) is the Ekman number
- r factor in buoyancy represents linear gravity profile g(r) ∝ r
Implementation Notes
The explicit RHS entering the time integrator is: RHS = -(E/Pm)·(∇×ũ)×ũ - (ẑ×ũ) + (Pm/Pr)·Ra·T̃·r·r̂ + (Pm/Sc)·Ra_C·C̃·r·r̂ + (∇×B̃)×B̃
Coefficients (Fortran DD_2DCODE convention, mass coeff = E on du/dt):
- Advection: E (= d_Ro = Rossby number, equals E for magnetic diffusion time)
- Coriolis: 1 (no scaling)
- Thermal buoyancy: (Pm/Pr) * Ra * r (with radial factor)
- Compositional buoyancy: (Pm/Sc) * Ra_C * r (with radial factor)
- Lorentz: 1/Pm
Viscous diffusion is treated implicitly with coefficient E (Ekman number). Mass coefficient E is applied in the time-stepping matrices.
GeoDynamo.compute_boundary_fluxes — Method
compute_boundary_fluxes(profile::Vector{T}, ∂r, domain::RadialDomain) where TCompute flux (dT/dr) at both boundaries using the derivative matrix. Note: ∂r should be a BandedMatrix{T} (defined in linear_algebra.jl)
GeoDynamo.compute_chebyshev_polynomial — Method
compute_chebyshev_polynomial(n::Int, domain::RadialDomain)Compute Chebyshev polynomial T_n on the radial grid.
GeoDynamo.compute_composition_nonlinear! — Method
compute_composition_nonlinear!(𝔽::SHTnsCompositionField{T},
vel_fields, 𝒟ᵒᶜ::RadialDomain;
geometry::Symbol = get_parameters().geometry) where TCompute the nonlinear advection term -u·∇C for the composition equation.
This function implements the EXPLICIT part of the composition equation: ∂C/∂t + u·∇C = (Pm/Sc) ∇²C
The advection term -u·∇C is computed using the following optimized workflow:
- Compute ∇C in spectral space (no MPI communication required)
- Batched transform of C and ∇C to physical space
- Compute advection -u·∇C locally in physical space
- Transform result back to spectral space
- Apply boundary conditions
Arguments
𝔽: Composition field structure to updatevel_fields: Velocity field structure (provides u for advection)𝒟ᵒᶜ: Radial domain informationgeometry: Geometry type (:shell or :ball) for transform selection
Side Effects
- Updates
𝔽.nonlinearwith the computed advection term - Updates
𝔽.gradientwith ∇C in physical space - Applies boundary conditions to spectral representation
Performance Notes
- Gradients computed in spectral space avoid MPI communication
- Batched transforms minimize data transfer overhead
- Physical space operations are embarrassingly parallel
GeoDynamo.compute_divergence_spectral — Method
compute_divergence_spectral(tor_spec::SHTnsSpecField, pol_spec::SHTnsSpecField,
domain::RadialDomain) where TCheck solenoidal constraint for toroidal-poloidal decomposition. For v = ∇×(T r̂) + ∇×∇×(P r̂), the divergence ∇·v = 0 is satisfied analytically by construction (divergence of a curl is identically zero). Therefore this function always returns (0.0, 0.0) — the solenoidal constraint is guaranteed by the representation, not by numerical accident.
GeoDynamo.compute_enstrophy — Method
compute_enstrophy(config::SHTnsKitConfig, Tlm::Matrix{ComplexF64}; real_field::Bool=true)Compute enstrophy (mean square vorticity) from toroidal coefficients. Enstrophy is related to the rotational part of the kinetic energy.
GeoDynamo.compute_field_energy — Method
compute_field_energy(field_data::Array{T,3}) where TCompute L2 energy of a 3D field: E = ½ ∫ |f|² dV ≈ ½ Σ |f_ijk|²
GeoDynamo.compute_global_diagnostics — Method
compute_global_diagnostics(combiner::FieldCombiner{T}) where TCompute global diagnostics for the combined fields.
GeoDynamo.compute_global_diagnostics — Method
compute_global_diagnostics(converter::SpectralToPhysicalConverter{T}) where TCompute global field diagnostics using MPI reductions.
GeoDynamo.compute_horizontal_gradient_magnitude — Method
compute_horizontal_gradient_magnitude(config::SHTnsKitConfig, alm::Matrix{ComplexF64})Compute the magnitude of the horizontal gradient |∇h f|² in spectral space. |∇h f|² = l(l+1) |f_lm|² (summed over all modes)
This is useful for computing gradient energy or penalty terms.
Arguments
config: SHTnsKit configurationalm: Spectral coefficients
Returns
Scalar value of the integrated horizontal gradient magnitude squared
GeoDynamo.compute_influence_functions_flux — Method
compute_influence_functions_flux(𝒟ᵒᶜ::RadialDomain)Compute influence functions for flux BCs. These are solutions to the homogeneous equation with specific BCs.
GeoDynamo.compute_inner_tau_function — Method
compute_inner_tau_function(domain::RadialDomain)Compute tau function for inner boundary only (zero derivative at outer).
GeoDynamo.compute_magnetic_helicity — Method
compute_magnetic_helicity(ℬ::SHTnsMagneticFields{T}) where TCompute magnetic helicity using enhanced spectral integration
GeoDynamo.compute_outer_tau_function — Method
compute_outer_tau_function(domain::RadialDomain)Compute tau function for outer boundary only (zero derivative at inner).
GeoDynamo.compute_phi1_function — Method
compute_phi1_function(A, expA)Compute φ1(A) = (exp(A) - I) / A efficiently with comprehensive error handling. Uses series expansion for small ||A|| to avoid numerical issues.
GeoDynamo.compute_phi2_function — Method
compute_phi2_function(A, expA; l=0)Compute φ2(A) = (exp(A) - I - A) / A² efficiently with comprehensive error handling. Uses series expansion for small ||A|| to avoid numerical issues. Tracks conditioning statistics when monitoring is enabled.
GeoDynamo.compute_phi_gradient_spectral! — Method
compute_phi_gradient_spectral!(𝔽::AbstractScalarField{T}, ws::GradientWorkspace{T}) where TCompute ∂field/∂φ using spherical harmonic properties (local operation). This is generic and works for any scalar field.
GeoDynamo.compute_radial_gradient_spectral! — Method
compute_radial_gradient_spectral!(𝔽::AbstractScalarField{T}, domain::RadialDomain, ws::GradientWorkspace{T}) where TCompute ∂field/∂r using banded matrix derivative operator in spectral space. This uses the pre-computed derivative matrices from the field for optimal accuracy and efficiency.
Note: Radial data is always local (not MPI distributed). Only spectral (lm) modes are distributed across MPI processes.
GeoDynamo.compute_scalar_advection_local! — Method
compute_scalar_advection_local!(𝔽::AbstractScalarField{T}, vel_fields) where TCompute -u·∇field in physical space (completely local operation). This works for any scalar field.
GeoDynamo.compute_scalar_energy — Method
compute_scalar_energy(𝔽::AbstractScalarField{T}, 𝒟ᵒᶜ::RadialDomain) where TCompute energy ∫ field² dV
GeoDynamo.compute_scalar_energy_spectrum — Method
compute_scalar_energy_spectrum(config::SHTnsKitConfig, alm::Matrix{ComplexF64}; real_field::Bool=true)Compute the energy spectrum per spherical harmonic degree l using SHTnsKit v1.1.15.
Returns
Vector of length lmax+1 with energy at each degree l.
GeoDynamo.compute_scalar_rms — Method
compute_scalar_rms(𝔽::AbstractScalarField{T}, 𝒟ᵒᶜ::RadialDomain) where TCompute RMS value of scalar field.
GeoDynamo.compute_tau_coefficients_both — Method
compute_tau_coefficients_both(flux_error_inner::T, flux_error_outer::T, domain::RadialDomain) where TCompute tau polynomial coefficients for both boundaries. Uses highest two Chebyshev modes as tau functions.
GeoDynamo.compute_tau_coefficients_inner — Method
compute_tau_coefficients_inner(flux_error::T, domain::RadialDomain) where TCompute tau coefficient for inner boundary only. Uses a single tau function that doesn't affect outer boundary.
GeoDynamo.compute_tau_coefficients_outer — Method
compute_tau_coefficients_outer(flux_error::T, domain::RadialDomain) where TCompute tau coefficient for outer boundary only. Uses a single tau function that doesn't affect inner boundary.
GeoDynamo.compute_theta_gradient_spectral! — Method
compute_theta_gradient_spectral!(𝔽::AbstractScalarField{T}, ws::GradientWorkspace{T}) where TCompute ∂field/∂θ using spherical harmonic recurrence relations (local operation). This is generic and works for any scalar field.
GeoDynamo.compute_theta_recurrence_coefficients — Method
compute_theta_recurrence_coefficients(::Type{T}, config::SHTnsKitConfig) where TPre-compute recurrence coefficients for θ-derivatives. Store as [nlm, 2] matrix: [:, 1] for l-1 coupling, [:, 2] for l+1 coupling
GeoDynamo.compute_total_energy! — Method
compute_total_energy!(state::SimulationState)Compute and record total energy of the simulation state.
GeoDynamo.compute_total_scalar_energy — Method
compute_total_scalar_energy(config::SHTnsKitConfig, alm::Matrix{ComplexF64}; real_field::Bool=true)Compute total energy of a scalar field from its spectral coefficients.
GeoDynamo.compute_total_vector_energy — Method
compute_total_vector_energy(config::SHTnsKitConfig, Slm::Matrix{ComplexF64}, Tlm::Matrix{ComplexF64}; real_field::Bool=true)Compute total kinetic energy of a vector field from spheroidal/toroidal coefficients.
GeoDynamo.compute_vector_energy — Method
compute_vector_energy(v_r::Array{T,3}, v_theta::Array{T,3}, v_phi::Array{T,3}) where TCompute kinetic/magnetic energy: E = ½ ∫ |v|² dV = ½ ∫ (vr² + vθ² + v_φ²) dV
GeoDynamo.compute_vector_energy_spectrum — Method
compute_vector_energy_spectrum(config::SHTnsKitConfig, Slm::Matrix{ComplexF64}, Tlm::Matrix{ComplexF64}; real_field::Bool=true)Compute the kinetic energy spectrum per spherical harmonic degree l for a vector field decomposed into spheroidal (Slm) and toroidal (Tlm) components.
Returns
Vector of length lmax+1 with kinetic energy at each degree l.
GeoDynamo.convert_spectral_file — Method
convert_spectral_file(input_filename::String, output_filename::String = "";
precision::Type{T} = Float64,
compute_diagnostics::Bool = true) where TMain function to convert a single spectral data file to physical space.
GeoDynamo.convert_to_physical! — Method
convert_to_physical!(converter::SpectralToPhysicalConverter{T}) where TConvert all loaded spectral data to physical space using SHTns transforms.
GeoDynamo.create_boundary_slice — Method
create_boundary_slice(size_arr::Tuple, dim::Int, side::Symbol, width::Int)Create array slice for boundary data extraction.
GeoDynamo.create_combiner_config — Method
create_combiner_config(; kwargs...)Create combiner configuration with keyword arguments.
GeoDynamo.create_composition_matrices — Method
create_composition_matrices(config, domain, diffusivity, dt;
i_cmp_bc, theta, T)Create implicit time-stepping matrices for the composition equation with boundary conditions embedded in the matrix rows (matching Fortran cmpbcC).
Arguments
config: SHTnsKitConfig with l_valuesdomain: RadialDomain with derivative matrices and griddiffusivity: Compositional diffusivity (Pm/Sc in magnetic diffusion time)dt: Timestepi_cmp_bc: BC type (1=DD, 2=DN, 3=ND, 4=NN)theta: Implicit parameter (default d_implicit)T: Numeric type (default Float64)
Returns
SHTnsImplicitMatrices{T}with BCs embedded in system matrices
GeoDynamo.create_computation_pencils — Method
create_computation_pencils(topology, dims, config)Create specialized pencils for different stages of computation.
GeoDynamo.create_dirichlet_bc — Method
create_dirichlet_bc(T, nr, value) -> ERK2BoundarySide{T}Create a Dirichlet BC side (u = value at boundary).
GeoDynamo.create_enhanced_output_config — Method
create_enhanced_output_config(state)Create output configuration with enhanced I/O settings.
GeoDynamo.create_erk2_cache — Method
create_erk2_cache(config, domain, diffusivity, dt; use_krylov=false, m=20, tol=1e-8, bc_spec=nothing)Create ERK2 cache with precomputed matrix functions for all spherical harmonic modes.
Boundary rows of A are zeroed only for l=0 (where the spherical Laplacian has a null space, making A singular). For l≥1, the full operator is retained (non-singular due to the -l(l+1)/r² term), enabling accurate LU-based phi1/phi2 computation and O(h³) enforcement corrections per step.
GeoDynamo.create_erk2_cache_composition — Method
create_erk2_cache_composition(T, config, domain, diffusivity, dt, i_cmp_bc; kwargs...)Create ERK2 cache for composition field with embedded BCs. Wrapper around createerk2cache_scalar with composition-specific defaults.
GeoDynamo.create_erk2_cache_magnetic_poloidal — Method
create_erk2_cache_magnetic_poloidal(T, config, domain, diffusivity, dt; use_krylov=false, m=20, tol=1e-8)Create ERK2 cache for magnetic poloidal field with insulating BCs embedded in the matrix A.
This matches DD_2DCODE's approach where the matrix has:
- Inner boundary row: (∂/∂r - l/r) operator → insulating interior
- Outer boundary row: (∂/∂r + (l+1)/r) operator → insulating exterior
Embedding BCs in A ensures exp(dt*A) automatically preserves solutions satisfying the insulating constraints, rather than requiring post-evolution correction.
GeoDynamo.create_erk2_cache_magnetic_toroidal — Method
create_erk2_cache_magnetic_toroidal(T, config, domain, diffusivity, dt; use_krylov=false, m=20, tol=1e-8)Create ERK2 cache for magnetic toroidal field with insulating BCs embedded in the matrix A.
This matches DD_2DCODE's approach where the matrix has:
- Inner boundary row: identity → BT = 0
- Outer boundary row: identity → BT = 0
For Dirichlet BCs (BT = 0), we zero the boundary rows except for the diagonal (identity), which makes exp(dt*A)|_boundary = identity, preserving BT = 0.
GeoDynamo.create_erk2_cache_scalar — Method
create_erk2_cache_scalar(T, config, domain, diffusivity, dt, i_bc; use_krylov=false, m=20, tol=1e-8)Create ERK2 cache for scalar fields (temperature or composition) with boundary rows zeroed in the matrix A.
Boundary condition types (matching DD2DCODE tmpbcT / cmpbc_C):
- i_bc = 1: Dirichlet-Dirichlet (fixed value both boundaries)
- i_bc = 2: Dirichlet-Neumann (fixed value inner, fixed flux outer)
- i_bc = 3: Neumann-Dirichlet (fixed flux inner, fixed value outer)
- i_bc = 4: Neumann-Neumann (fixed flux both, l=0 inner uses Dirichlet)
For exponential integrators, boundary rows are always zeroed:
- exp(dt*A)[boundary,:] = [1, 0, ..., 0] → preserves boundary value
- Actual BC enforcement (Dirichlet/Neumann) is done via post-processing in erk2preparefield! and erk2finalizefield! using enforceerk2bc!
GeoDynamo.create_erk2_cache_temperature — Method
create_erk2_cache_temperature(T, config, domain, diffusivity, dt, i_tmp_bc; kwargs...)Create ERK2 cache for temperature field with embedded BCs. Wrapper around createerk2cache_scalar with temperature-specific defaults.
GeoDynamo.create_erk2_config — Method
create_erk2_config(; lmax, mmax, nlat, nlon, optimize_for_erk2=true)Create an SHTnsKit configuration for ERK2 timestepping.
GeoDynamo.create_etd_cache — Method
create_etd_cache(config, domain, diffusivity, dt) -> ETDCacheBuild per-l exponential cache for the linear operator Al = diffusivity*(d²/dr² + (2/r)d/dr − l(l+1)/r²). Computes exp(dt Al) and phi1(dt A_l) via dense methods. Single-rank recommended.
GeoDynamo.create_field_combiner — Method
create_field_combiner(output_dir::String, time::Float64;
precision::Type{T} = Float64) where TCreate a field combiner by reading configuration from distributed files.
GeoDynamo.create_halo_slice — Method
create_halo_slice(size_arr::Tuple, dim::Int, side::Symbol, width::Int)Create array slice for halo region insertion.
GeoDynamo.create_insulating_inner_bc — Method
create_insulating_inner_bc(T, d1_row, r_inv) -> ERK2BoundarySide{T}Create an insulating magnetic poloidal inner BC: (d/dr - l/r)P = 0. The l-factor is applied dynamically during enforcement.
GeoDynamo.create_insulating_outer_bc — Method
create_insulating_outer_bc(T, d1_row, r_inv) -> ERK2BoundarySide{T}Create an insulating magnetic poloidal outer BC: (d/dr + (l+1)/r)P = 0. The (l+1) factor is split: fixedcorrection = +1/r (the "+1" part), and lsign = +1 with uselcorrection = true (the "l" part). Total correction = lsignlrinv + fixed_correction = (l+1)/r.
GeoDynamo.create_magnetic_poloidal_matrices — Method
create_magnetic_poloidal_matrices(config, domain, diffusivity, dt;
theta, T)Create implicit time-stepping matrices for the poloidal magnetic component with insulating boundary conditions embedded in the matrix rows (matching Fortran magbcPol).
Boundary conditions (l-dependent):
- Inner: (∂/∂r - l/r) BP = 0 (field matches r^l interior solution)
- Outer: (∂/∂r + (l+1)/r) BP = 0 (field matches r^{-(l+1)} exterior decay)
GeoDynamo.create_magnetic_toroidal_matrices — Method
create_magnetic_toroidal_matrices(config, domain, diffusivity, dt;
theta, T)Create implicit time-stepping matrices for the toroidal magnetic component with insulating boundary conditions embedded in the matrix rows (matching Fortran magbcTor).
Both boundary rows use identity (BT = 0) for insulating exterior/interior.
GeoDynamo.create_neumann_bc — Method
create_neumann_bc(T, d1_row, value) -> ERK2BoundarySide{T}Create a Neumann BC side (du/dr = value at boundary).
GeoDynamo.create_noslip_pol_bc — Method
create_noslip_pol_bc(T, d1_row) -> ERK2BoundarySide{T}Create a no-slip poloidal BC side: dP/dr = 0.
GeoDynamo.create_parallel_netcdf — Method
create_parallel_netcdf(filename, config, field_info, metadata, comm)Open a new NetCDF file in parallel mode. All ranks call this collectively. Defines global dimensions and variables based on field_info.
GeoDynamo.create_parameter_template — Method
create_parameter_template(filename::String)Create a template parameter file for users to customize.
GeoDynamo.create_pencil_array — Method
create_pencil_array(::Type{T}, pencil::Pencil; init=:zero) where TCreate a PencilArray with specified initialization.
GeoDynamo.create_pencil_decomposition_shtnskit — Function
create_pencil_decomposition_shtnskit(nlat, nlon, nr, sht_config, comm, optimize)Create PencilArrays decomposition optimized for spherical harmonic transforms.
The Pencil Decomposition Strategy
In a pencil decomposition, 3D data is distributed across MPI processes such that one dimension is always fully local (not split across processes). This enables efficient operations along that dimension without MPI communication.
Physical Space Pencils (nlat × nlon × nr)
theta pencil: [θ local] × [φ distributed] × [r distributed]
→ Best for operations along latitude (Legendre transforms)
phi pencil: [θ distributed] × [φ local] × [r distributed]
→ Best for FFTs along longitude
r pencil: [θ distributed] × [φ distributed] × [r local]
→ Best for radial operations (derivatives, boundary conditions)Spectral Space Pencil (nlm × 1 × nr)
The spectral pencil stores spherical harmonic coefficients indexed by a combined (l,m) index. The middle dimension is 1 (dummy) for compatibility.
Arguments
nlat, nlon, nr: Grid dimensionssht_config: SHTnsKit configuration (provides nlm)comm: MPI communicatoroptimize: Whether to optimize process topology for load balance
Returns
NamedTuple with pencil configurations: (:theta, :θ, :phi, :φ, :r, :spec, :mixed)
GeoDynamo.create_pencil_fft_plans — Method
create_pencil_fft_plans(pencils, dims) -> Dict{Symbol,Any}Create precomputed FFTW plans for efficient FFT operations.
Why Precomputed Plans?
FFTW achieves best performance when FFT plans are created once and reused. Plan creation involves:
- Analyzing the input size and memory layout
- Choosing optimal algorithm (Cooley-Tukey, Bluestein, etc.)
- Possibly benchmarking different strategies
Plan Types Created
:phi_forward/:phi_backward: FFT/IFFT along longitude (dimension 2):theta_forward/:theta_backward: FFT/IFFT for theta pencil orientation
Technical Notes
- Plans operate on the
parent()array of PencilArrays (the underlying Julia array) - We use FFTW directly rather than PencilFFTPlan because we need single-dimension transforms, not full multi-dimensional distributed FFTs
- The plans are tied to specific array sizes and memory layouts
Arguments
pencils: NamedTuple of Pencil configurationsdims: Tuple (nlat, nlon, nr) of grid dimensions
Returns
Dict mapping plan names to FFTW plan objects. Contains :fallback => true on error.
GeoDynamo.create_pencil_topology — Method
create_pencil_topology(shtns_config; nr=i_N, optimize=true)Create enhanced pencil decomposition for SHTns grids. Supports both 1D and 2D decompositions with automatic optimization. Accepts an object with fields nlat, nlon, and nlm (e.g., SHTnsKitConfig).
GeoDynamo.create_radial_domain — Function
create_radial_domain(nr=nothing; rratio=nothing, kl=nothing) -> RadialDomainCreate a radial domain for a spherical shell geometry.
Arguments
nr: Number of radial points (defaults toget_parameters().i_N)rratio: Inner/outer radius ratio (defaults toget_parameters().d_rratio)kl: Bandwidth for finite differences (defaults toget_parameters().i_KL)
Returns
A RadialDomain with Chebyshev-like radial spacing optimized for spectral accuracy.
GeoDynamo.create_shtns_composition_field — Method
create_shtns_composition_field(::Type{T}, config::SHTnsKitConfig,
𝒟ᵒᶜ::RadialDomain,
pencils=nothing, pencil_spec=nothing) where TCreate a composition field structure with all necessary arrays for spectral computation.
Arguments
T: Numeric type (e.g., Float64)config: SHTnsKitConfig with transform parameters (lmax, mmax, nlat, nlon)𝒟ᵒᶜ: Radial domain information for outer corepencils: Optional pencil decomposition (defaults to config.pencils)pencil_spec: Optional spectral pencil (defaults to pencils.spec)
Returns
SHTnsCompositionField{T}: Fully initialized composition field structure
Example
config = create_shtns_config(lmax=32, mmax=32, nlat=64, nlon=128)
domain = create_radial_domain(nr=64, ri=0.35, ro=1.0)
𝔽 = create_shtns_composition_field(Float64, config, domain)Notes
Default boundary conditions are no-flux (NEUMANN) at both boundaries, appropriate for typical compositional convection problems.
GeoDynamo.create_shtns_physical_field — Method
create_shtns_physical_field(T, config, 𝒟ᵒᶜ, pencil) -> SHTnsPhysField{T}Create a new physical space field initialized to zero.
Arguments
T: Element type (typically Float64)config: SHTnsKit configuration providing grid dimensions𝒟ᵒᶜ: RadialDomain (for consistency with spectral field API)pencil: PencilArrays Pencil defining the data distribution
Returns
A new SHTnsPhysField with all grid values initialized to zero.
GeoDynamo.create_shtns_spectral_field — Method
create_shtns_spectral_field(T, config, 𝒟ᵒᶜ, pencil_spec) -> SHTnsSpecField{T}Create a new spectral field initialized to zero with default Dirichlet BCs.
Arguments
T: Element type (typically Float64)config: SHTnsKit configuration providing nlm and other parameters𝒟ᵒᶜ: RadialDomain specifying the radial discretizationpencil_spec: PencilArrays Pencil defining the data distribution
Returns
A new SHTnsSpecField with:
- All spectral coefficients initialized to zero
- Dirichlet boundary conditions on all modes
- Zero boundary values
GeoDynamo.create_shtns_vector_field — Method
create_shtns_vector_field(T, config, 𝒟ᵒᶜ, pencils) -> SHTnsVectorField{T}Create a new vector field with three physical space components.
Arguments
T: Element typeconfig: SHTnsKit configuration𝒟ᵒᶜ: RadialDomain specificationpencils: Either a NamedTuple with :theta/:θ, :phi/:φ, :r keys, or a tuple (pencilθ, pencilφ, pencil_r)
Returns
A new SHTnsVectorField with all components initialized to zero. Each component uses a potentially different pencil orientation for optimal computation of different operations.
GeoDynamo.create_shtnskit_config — Method
create_shtnskit_config(; lmax, mmax, nlat, nlon, nr, optimize_decomp) -> SHTnsKitConfigCreate and initialize a complete SHTnsKit configuration for spherical harmonic transforms with MPI parallelization.
Keyword Arguments
lmax::Int: Maximum spherical harmonic degree (required)mmax::Int=lmax: Maximum spherical harmonic order (≤ lmax)nlat::Int: Number of latitude points. Must be ≥ lmax+1 for numerical accuracy. Defaults to max(lmax+2, parameter system value)nlon::Int: Number of longitude points. Must be ≥ 2*mmax+1 for alias-free transforms. Powers of 2 are preferred for FFT efficiency.nr::Int=i_N: Number of radial points (from parameter system)optimize_decomp::Bool=true: Whether to optimize MPI process topology
Returns
SHTnsKitConfig: Fully initialized configuration ready for transforms
Algorithm
- Create base SHTnsKit configuration with Gauss-Legendre grid
- Set up pencil decomposition for MPI parallelization
- Create FFT plans for longitude transforms
- Create transpose plans for data redistribution
- Initialize grid coordinates and quadrature weights
Example
# Create config for lmax=63 simulation
config = create_shtnskit_config(lmax=63, nlat=96, nlon=192)GeoDynamo.create_shtnskit_transpose_plans — Method
create_shtnskit_transpose_plans(pencils) -> Dict{Symbol,Any}Create transpose plans for redistributing data between pencil orientations.
What is a Transpose?
In pencil decomposition, a "transpose" is an MPI all-to-all communication that redistributes data so a different dimension becomes local. For example:
- theta → phi transpose: makes longitude local (for FFTs)
- phi → r transpose: makes radius local (for radial derivatives)
Why Plans?
Like FFT plans, transpose plans encode the communication pattern and can optimize buffer allocation and MPI operations.
Transpose Constraints
PencilArrays requires that source and destination pencils differ in at most one distributed dimension. If they differ in two dimensions, we need a multi-step transpose (e.g., phi → theta → r).
Plan Keys Created
:theta_to_phi,:phi_to_theta: Switch between theta and phi local:theta_to_r,:r_to_theta: Switch between theta and r local:phi_to_r,:r_to_phi: May be direct or marked as:multi_step
Usage
# Transpose data from theta-local to phi-local orientation
mul!(dest_array, transpose_plans[:theta_to_phi], src_array)GeoDynamo.create_spectral_converter — Method
create_spectral_converter(filename::String; precision::Type{T} = Float64) where TCreate a spectral to physical converter by reading configuration from a NetCDF file.
GeoDynamo.create_stress_free_pol_bc — Method
create_stress_free_pol_bc(T, d2_row) -> ERK2BoundarySide{T}Create a stress-free poloidal BC side: d²P/dr² = 0.
GeoDynamo.create_stress_free_tor_bc — Method
create_stress_free_tor_bc(T, d1_row, r_inv) -> ERK2BoundarySide{T}Create a stress-free toroidal BC side: dT/dr - T/r = 0.
GeoDynamo.create_temperature_matrices — Method
create_temperature_matrices(config, domain, diffusivity, dt;
i_tmp_bc, theta, T)Create implicit time-stepping matrices for the temperature equation with boundary conditions embedded in the matrix rows (matching Fortran tmpbcT).
Arguments
config: SHTnsKitConfig with l_valuesdomain: RadialDomain with derivative matrices and griddiffusivity: Thermal diffusivity (Pm/Pr in magnetic diffusion time)dt: Timestepi_tmp_bc: BC type (1=DD, 2=DN, 3=ND, 4=NN)theta: Implicit parameter (default d_implicit)T: Numeric type (default Float64)
Returns
SHTnsImplicitMatrices{T}with BCs embedded in system matrices
GeoDynamo.create_transpose_plans — Method
create_transpose_plans(pencils)Create enhanced transpose plans between pencil orientations. Includes caching and communication optimization.
GeoDynamo.create_velocity_green_matrices — Method
create_velocity_green_matrices(config, domain, diffusivity;
theta, T)Create Green's function matrices for the influence matrix method (poloidal pressure). These use Dirichlet BCs (identity rows) at both boundaries, matching Fortran velbcGre.
GeoDynamo.create_velocity_poloidal_influence_matrices — Method
create_velocity_poloidal_influence_matrices(T, config, domain, diffusivity, dt, i_vel_bc; theta)Create influence matrices for poloidal velocity to enforce P = 0 at boundaries while using derivative BCs (∂P/∂r = 0 or ∂²P/∂r² = 0) in the implicit/exponential system.
This matches DD2DCODE's velmatrices routine.
GeoDynamo.create_velocity_poloidal_matrices — Method
create_velocity_poloidal_matrices(config, domain, diffusivity, dt;
theta, i_vel_bc, T)Create implicit time-stepping matrices for the poloidal velocity component with boundary conditions embedded in the matrix rows.
The boundary rows of the system matrix are replaced with the BC equations:
- No-slip: first derivative row (∂P/∂r = value)
- Stress-free: second derivative row (∂²P/∂r² = value)
GeoDynamo.create_velocity_toroidal_matrices — Method
create_velocity_toroidal_matrices(config, domain, diffusivity, dt;
theta, i_vel_bc, T)Create implicit time-stepping matrices for the toroidal velocity component with boundary conditions embedded in the matrix rows.
The boundary rows of the system matrix are replaced with the BC equations:
- No-slip: identity row (T = value)
- Stress-free: ∂T/∂r - T/r = 0
This ensures the implicit solve enforces BCs exactly rather than applying them as post-processing.
GeoDynamo.eab2_update! — Method
eab2_update!(u, nl, nl_prev, etd, config)Apply EAB2 update per (l,m): u^{n+1} = E u^n + dtphi1(3/2 nl^n − 1/2 nl^{n−1}).
MPI Safety
Uses global loop bounds (1:nlm) to ensure all processes call Allreduce the same number of times, preventing deadlock with uneven lm distribution.
GeoDynamo.eab2_update_krylov! — Method
eab2_update_krylov!(u, nl, nl_prev, domain, diffusivity, config, dt; m=20, tol=1e-8)EAB2 update using Krylov exp/φ1 actions and banded LU for φ1.
MPI Safety
Uses global loop bounds (1:nlm) to ensure all processes call Allreduce the same number of times, preventing deadlock with uneven lm distribution.
GeoDynamo.eab2_update_krylov_cached! — Method
eab2_update_krylov_cached!(u, nl, nl_prev, alu_map, domain, ν, config, dt; m=20, tol=1e-8, mass_coeff=1.0)Same as eab2updatekrylov!, but reuses cached banded A and LU per l.
Mass Coefficient
For equations of the form c * du/dt = ν*L*u + NL (e.g. velocity with c=dE), pass `masscoeff=c. The operator becomesA = (ν/c)*Land NL is scaled by1/c`.
MPI Safety
Uses global loop bounds (1:nlm) to ensure all processes call Allreduce the same number of times, preventing deadlock with uneven lm distribution.
GeoDynamo.enforce_erk2_bc! — Method
enforce_erk2_bc!(result, bc_side, boundary_idx, l, nr)Enforce a boundary condition on the result vector at the given boundary index. Modifies result[boundary_idx] to satisfy the linear constraint encoded in bc_side.
GeoDynamo.enforce_velocity_boundary_values! — Method
enforce_velocity_boundary_values!(𝒰)Anchor toroidal and poloidal spectral coefficients to the currently cached Dirichlet boundary values on the inner and outer radial surfaces.
GeoDynamo.erk2_finalize_field! — Method
erk2_finalize_field!(buffers, u, cache, config, dt)Finalize ERK2 second stage by applying phi2 correction.
MPI Safety
Uses global loop bounds (1:nlm) to ensure all processes call Allreduce the same number of times, preventing deadlock with uneven lm distribution.
GeoDynamo.erk2_prepare_field! — Method
erk2_prepare_field!(buffers, u, nl, cache, config, dt)Prepare ERK2 first stage by computing linear evolution and k1 terms.
MPI Safety
Uses global loop bounds (1:nlm) to ensure all processes call Allreduce the same number of times, preventing deadlock with uneven lm distribution.
GeoDynamo.erk2_stage_residual_stats — Method
erk2_stage_residual_stats(buffers) -> NamedTupleCompute diagnostic statistics for the difference between stage nonlinear terms and the base-step nonlinear terms.
GeoDynamo.estimate_field_count — Method
estimate_field_count() -> IntEstimate the number of field arrays typically allocated simultaneously. Used for memory usage estimation. Returns 6 as a reasonable default covering velocity (3 components), temperature, composition, and magnetic field.
GeoDynamo.estimate_memory_usage — Method
estimate_memory_usage(pencils, field_count::Int, precision::Type)Estimate memory usage for given pencil configuration.
GeoDynamo.estimate_memory_usage_shtnskit — Method
estimate_memory_usage_shtnskit(nlat, nlon, nr, lmax, field_count, T)Estimate memory usage for SHTnsKit-based transforms with PencilArrays.
Arguments
nlat: Number of latitude pointsnlon: Number of longitude pointsnr: Number of radial pointslmax: Maximum spherical harmonic degreefield_count: Number of fields to estimate forT: Element type (e.g., Float64)
GeoDynamo.evaluate_chebyshev_derivative — Method
evaluate_chebyshev_derivative(n::Int, r::T, domain::RadialDomain) where TEvaluate derivative of Chebyshev polynomial at a point.
GeoDynamo.evaluate_tau_derivative_inner — Method
evaluate_tau_derivative_inner(tau::Vector, domain::RadialDomain)Evaluate tau function derivative at inner boundary.
GeoDynamo.evaluate_tau_derivative_outer — Method
evaluate_tau_derivative_outer(tau::Vector, domain::RadialDomain)Evaluate tau function derivative at outer boundary.
GeoDynamo.exchange_dimension_halos! — Method
exchange_dimension_halos!(data::Array, pencil::Pencil, dim::Int,
halo_width::Int, boundaries::Symbol, comm::MPI.Comm)Perform halo exchange along a specific dimension using MPI point-to-point communication.
GeoDynamo.exp_action_krylov — Method
exp_action_krylov(Aop!, v, dt; m=20, tol=1e-8) -> y ≈ exp(dt A) vSimple Arnoldi-based approximation of the exponential action.
GeoDynamo.extract_all_fields — Method
extract_all_fields(state::SimulationState)Extract all field data from the simulation state for output/restart writing. Returns a Dict with spectral field data (real/imag parts) for velocity, magnetic, temperature, and composition fields.
GeoDynamo.extract_coefficients_for_shtnskit! — Method
extract_coefficients_for_shtnskit!(coeffs_buffer, spec_real, spec_imag, r_local, config)Extract spectral coefficients into SHTnsKit's expected matrix format.
Data Format Conversion
Our internal format: Linear array indexed by combined (l,m) index SHTnsKit format: Matrix indexed by [l+1, m+1]
Arguments
coeffs_buffer: Pre-allocated (lmax+1) × (mmax+1) complex matrix (output)spec_real,spec_imag: Real and imaginary parts of spectral coefficientsr_local: Radial level index (1-based)config: SHTnsKit configuration
Threading
Uses @threads for parallel filling of the coefficient matrix.
GeoDynamo.extract_coefficients_for_shtnskit — Method
extract_coefficients_for_shtnskit(spec_real, spec_imag, r_local, config) -> Matrix{ComplexF64}High-level coefficient extraction with automatic buffer management and MPI gathering.
This is the main entry point for preparing spectral coefficients for SHTnsKit. It handles:
- Buffer allocation/reuse from cache
- Local coefficient extraction
- MPI Allreduce to combine coefficients from all processes
Why MPI Gathering?
Spectral coefficients may be distributed across MPI processes. SHTnsKit needs the complete coefficient matrix, so we sum partial contributions from all processes.
Returns
A complete (lmax+1) × (mmax+1) coefficient matrix ready for SHTnsKit.synthesis()
GeoDynamo.extract_coefficients_pair_for_shtnskit — Method
extract_coefficients_pair_for_shtnskit(spec1_real, spec1_imag, spec2_real, spec2_imag, r_local, config)Extract two spectral coefficient matrices efficiently for vector transforms.
This is optimized for the common case in vector synthesis/analysis where we need both toroidal and poloidal coefficients. It avoids one copy operation compared to calling extract_coefficients_for_shtnskit twice.
Returns
Tuple (coeffs1, coeffs2) of coefficient matrices.
GeoDynamo.extract_dense_row — Method
extract_dense_row(banded::BandedMatrix{T}, row::Int) -> Vector{T}Extract a full dense row from a banded matrix.
GeoDynamo.extract_divergence_coefficients — Method
extract_divergence_coefficients(config::SHTnsKitConfig, Slm::Matrix{ComplexF64})Extract divergence spectral coefficients from spheroidal potential. The divergence field in spectral space is related to Slm by the horizontal Laplacian.
Returns
Matrix of divergence coefficients.
GeoDynamo.extract_local_radial_profile! — Method
extract_local_radial_profile!(profile, data, local_lm, nr, r_range)In-place version to avoid allocations; writes the local radial line into profile for the given local_lm using the provided r_range.
GeoDynamo.extract_physical_slice_generic! — Method
extract_physical_slice_generic!(slice_buffer, phys_data, r_local, config)Generic extraction for any pencil orientation using pre-allocated buffer.
WARNING: MPI Synchronization
This function contains MPI.Allreduce! which is a collective operation. When called inside a per-radial loop, ALL MPI processes must call this function the same number of times, otherwise deadlock will occur. Ensure even radial distribution or use global loop bounds.
GeoDynamo.extract_physical_slice_phi_local! — Method
extract_physical_slice_phi_local!(slice_buffer, phys_data, r_local, config)Extract physical slice when in phi-local pencil using pre-allocated buffer.
WARNING: MPI Synchronization
This function contains MPI.Allreduce! which is a collective operation. When called inside a per-radial loop, ALL MPI processes must call this function the same number of times, otherwise deadlock will occur. Ensure even radial distribution or use global loop bounds.
GeoDynamo.extract_spectral_subset — Method
extract_spectral_subset(field::SHTnsSpecField{T}; l_max::Int = 10) where TExtract a subset of spectral modes for analysis.
GeoDynamo.extract_vector_component_generic! — Method
extract_vector_component_generic!(component_buffer, v_data, r_local, config)Generic extraction for vector components using pre-allocated buffer.
WARNING: MPI Synchronization
This function contains MPI.Allreduce! which is a collective operation. When called inside a per-radial loop, ALL MPI processes must call this function the same number of times, otherwise deadlock will occur. Ensure even radial distribution or use global loop bounds.
GeoDynamo.extract_vorticity_coefficients — Method
extract_vorticity_coefficients(config::SHTnsKitConfig, Tlm::Matrix{ComplexF64})Extract vorticity spectral coefficients from toroidal potential. The vorticity field in spectral space is related to Tlm by the horizontal Laplacian.
Returns
Matrix of vorticity coefficients.
GeoDynamo.find_distributed_files — Function
find_distributed_files(output_dir::String, time::Float64, filename_prefix::String = "geodynamo")Find all distributed files for a specific simulation time.
GeoDynamo.find_package_root — Method
find_package_root()Find the root directory of the GeoDynamo.jl package.
GeoDynamo.get_cached_buffer! — Method
get_cached_buffer!(create_func::Function, config, key::Symbol)
get_cached_buffer!(config, key::Symbol) do ... endThread-safe accessor for buffer cache. Returns existing buffer if present, otherwise creates a new one using create_func() and caches it.
Note: The function parameter comes FIRST to support Julia's do block syntax. When using do block, Julia desugars it to pass the closure as the first argument.
Arguments
create_func::Function: Zero-argument function to create buffer if not cachedconfig: SHTnsKitConfig object containing the buffer cachekey::Symbol: Key to look up in the buffer cache
Returns
The cached or newly created buffer.
Example
buffer = get_cached_buffer!(config, :my_buffer) do
zeros(Float64, nlat, nlon)
endGeoDynamo.get_comm — Method
get_comm()Get MPI communicator, initializing MPI if needed. Thread-safe via double-checked locking with _MPI_INIT_LOCK.
GeoDynamo.get_default_nlat — Method
get_default_nlat() -> IntGet the default number of latitude points for the grid. Tries to read from the parameter system first, falls back to 64. Used during precompilation when parameters may not be available.
GeoDynamo.get_default_nlon — Method
get_default_nlon() -> IntGet the default number of longitude points for the grid. Tries to read from the parameter system first, falls back to 128. Power of 2 is preferred for efficient FFT operations.
GeoDynamo.get_dimension_neighbors — Method
get_dimension_neighbors(pencil::Pencil, dim::Int, boundaries::Symbol) -> (Int, Int)Get left and right neighbor process ranks for a given dimension. Returns (leftneighbor, rightneighbor) where MPI.MPIPROCNULL indicates no neighbor.
GeoDynamo.get_eab2_alu_cache! — Method
get_eab2_alu_cache!(caches, key, ν, T, domain) -> Dict{Int,Tuple{BandedMatrix{T},BandedLU{T}}}Retrieve or initialize a cache mapping l -> (Abanded, LU(Abanded)) for EAB2. Reinitializes if ν or nr changed. Type-stable version using EAB2ALUCacheEntry.
GeoDynamo.get_erk2_cache! — Method
get_erk2_cache!(caches, key, diffusivity, config, domain, dt; use_krylov=false)Retrieve or create ERK2 cache with automatic invalidation when parameters change. Type-stable version using concrete ERK2Cache{T} type.
GeoDynamo.get_erk2_composition_cache! — Method
get_erk2_composition_cache!(caches, diffusivity, T, config, domain, dt, i_cmp_bc; use_krylov=false, m=20, tol=1e-8)Retrieve or create ERK2 cache for composition field with embedded BCs. Uses BC type specified by icmpbc (1=DD, 2=DN, 3=ND, 4=NN), matching DD2DCODE's cmpbc_C.
GeoDynamo.get_erk2_influence_matrices! — Method
get_erk2_influence_matrices!(cache, key, T, config, domain, diffusivity, dt, i_vel_bc; theta)Get or create ERK2 influence matrices for poloidal velocity. Caches matrices by key for reuse across timesteps. Invalidates and recomputes when dt changes.
GeoDynamo.get_erk2_magnetic_poloidal_cache! — Method
get_erk2_magnetic_poloidal_cache!(caches, diffusivity, T, config, domain, dt; use_krylov=false, m=20, tol=1e-8)Retrieve or create ERK2 cache for magnetic poloidal field with embedded insulating BCs. Uses l-dependent insulating BCs matching DD2DCODE's magbc_Pol:
- Inner boundary: (∂/∂r - l/r)P = 0
- Outer boundary: (∂/∂r + (l+1)/r)P = 0
GeoDynamo.get_erk2_magnetic_toroidal_cache! — Method
get_erk2_magnetic_toroidal_cache!(caches, diffusivity, T, config, domain, dt; use_krylov=false, m=20, tol=1e-8)Retrieve or create ERK2 cache for magnetic toroidal field with embedded insulating BCs. Uses Dirichlet BCs (BT = 0) at both boundaries, matching DD2DCODE's magbc_Tor.
GeoDynamo.get_erk2_temperature_cache! — Method
get_erk2_temperature_cache!(caches, diffusivity, T, config, domain, dt, i_tmp_bc; use_krylov=false, m=20, tol=1e-8)Retrieve or create ERK2 cache for temperature field with embedded BCs. Uses BC type specified by itmpbc (1=DD, 2=DN, 3=ND, 4=NN), matching DD2DCODE's tmpbc_T.
GeoDynamo.get_flux_value — Method
get_flux_value(lm_idx::Int, boundary::Int, 𝔽::AbstractScalarField)Get prescribed flux value for given mode and boundary from scalar field. This is a generic version that works with any scalar field.
GeoDynamo.get_nprocs — Method
get_nprocs()Get total number of MPI processes.
GeoDynamo.get_parameters — Method
get_parameters()Get the current global parameters. If not set, loads default parameters. Thread-safe lazy initialization with type-stable return.
GeoDynamo.get_pencil_orientation — Method
get_pencil_orientation(pencil) -> SymbolDetermine which dimension(s) are fully local in a pencil decomposition.
Returns
:theta_phi: Both angular dimensions local (serial or single-node):theta: Latitude (θ) dimension is local:phi: Longitude (φ) dimension is local:r: Radial dimension is local
Usage
Used to choose optimal transform strategies based on data layout.
GeoDynamo.get_process_dimensions — Method
get_process_dimensions(topology) -> TupleExtract process grid dimensions from topology.
GeoDynamo.get_rank — Method
get_rank()Get MPI rank of current process.
GeoDynamo.get_shtnskit_performance_stats — Method
get_shtnskit_performance_stats()Get performance statistics for SHTnsKit transforms with PencilArrays. Returns information about the v1.1.15+ features being used.
GeoDynamo.get_shtnskit_version_info — Method
get_shtnskit_version_info()Get version and capability information about the SHTnsKit installation.
GeoDynamo.get_velocity_workspace — Method
get_velocity_workspace(::Type{T})::Union{VelocityWorkspace{T}, Nothing} where TGet the global velocity workspace if available and matches type T. Returns nothing if not set or type mismatch.
GeoDynamo.index_to_lm_fast — Method
index_to_lm_fast(idx, config) -> (l, m)Fast O(1) conversion from linear spectral index to (l, m) using precomputed tables.
Uses the lvalues and mvalues arrays stored in SHTnsKitConfig during initialization. This is significantly faster than index_to_lm_shtnskit for repeated lookups.
Arguments
idx: Linear spectral index (1-based)config: SHTnsKitConfig containing precomputed lvalues and mvalues
Returns
Tuple (l, m) for the spherical harmonic degree and order.
GeoDynamo.index_to_lm_shtnskit — Method
index_to_lm_shtnskit(idx, lmax, mmax) -> (l, m)Convert linear spectral index to spherical harmonic degree (l) and order (m).
Index Ordering
The linear index follows the SHTnsKit m-major convention (m varies slowest, l fastest):
- idx=1: (l=0, m=0)
- idx=2: (l=1, m=0)
- idx=3: (l=2, m=0)
- ...
- idx=lmax+1: (l=lmax, m=0)
- idx=lmax+2: (l=1, m=1)
- idx=lmax+3: (l=2, m=1)
- ...
Performance Note
This function uses a linear search. For performance-critical code with many lookups, use index_to_lm_fast with precomputed lookup tables from SHTnsKitConfig.
GeoDynamo.infer_pencils_from_transpose_name — Method
infer_pencils_from_transpose_name(name::Symbol, plan) -> (src_pencil, dest_pencil)Infer source and destination pencils from transpose operation name and plan. For TransposeOperator, we need to extract pencil info from context since the operator itself doesn't expose src/dest pencils directly.
GeoDynamo.initialize_parameters — Function
initialize_parameters(config_file::String = "")Initialize the global parameter system.
GeoDynamo.initialize_simulation — Method
initialize_simulation(::Type{T}=Float64; kwargs...)Initialize simulation with comprehensive CPU parallelization.
GeoDynamo.install_erk2_cache_bundle! — Method
install_erk2_cache_bundle!(target, bundle)Copy ERK2 caches from bundle into the target cache dictionary.
GeoDynamo.list_available_times — Function
list_available_times(output_dir::String, filename_prefix::String = "geodynamo")List all available simulation times in the output directory.
GeoDynamo.load_distributed_fields! — Method
load_distributed_fields!(combiner::FieldCombiner{T}) where TLoad field data from all distributed files into the combiner structure.
GeoDynamo.load_erk2_cache_bundle! — Method
load_erk2_cache_bundle!(target, path) -> metadataLoad caches from path and install them into target, returning metadata.
GeoDynamo.load_erk2_cache_bundle — Method
load_erk2_cache_bundle(path) -> (caches, metadata)Load ERK2 caches and associated metadata from disk.
GeoDynamo.load_parameters — Function
load_parameters(config_file::String = "")Load parameters from a configuration file. If no file is specified, loads from the default config/default_params.jl file.
Arguments
config_file::String: Path to parameter file (optional)
Returns
GeoDynamoParameters: Loaded parameters
GeoDynamo.load_parameters_from_file — Method
load_parameters_from_file(config_file::String)Load parameters from a Julia file containing parameter definitions.
GeoDynamo.load_physical_temperature! — Method
load_physical_temperature!(field::SHTnsPhysField{T}, nc_file, var_name::String) where TLoad physical space temperature data from NetCDF file.
GeoDynamo.load_single_file! — Method
load_single_file!(combiner::FieldCombiner{T}, filename::String) where TLoad data from a single file (no combination needed).
GeoDynamo.load_single_spectral_field! — Method
load_single_spectral_field!(field::SHTnsSpecField{T}, nc_file,
real_var::String, imag_var::String) where TLoad a single spectral field from NetCDF file.
GeoDynamo.load_spectral_coefficients! — Method
load_spectral_coefficients!(field::SHTnsSpecField{T}, nc_file,
real_var_name::String, imag_var_name::String,
l_values::Vector{Int}, m_values::Vector{Int},
r_spectral::Vector{Float64}) where TLoad spectral coefficients from NetCDF file into a spectral field structure.
GeoDynamo.load_spectral_data! — Method
load_spectral_data!(converter::SpectralToPhysicalConverter{T}, filename::String) where TLoad spectral field data from NetCDF file into GeoDynamo field structures.
GeoDynamo.main_batch_convert — Method
main_batch_convert(input_dir::String; kwargs...)Main entry point for batch conversion of files.
GeoDynamo.main_combine_time — Method
main_combine_time(output_dir::String, time::Float64; kwargs...)Main entry point for combining distributed files for a single time.
GeoDynamo.main_combine_time_series — Method
main_combine_time_series(output_dir::String, time_range::Tuple{Float64,Float64}; kwargs...)Main entry point for combining time series.
GeoDynamo.main_convert_file — Method
main_convert_file(filename::String; kwargs...)Main entry point for converting a single file.
GeoDynamo.map_spectral_coefficients! — Method
map_spectral_coefficients!(global_tor_real, global_tor_imag, global_pol_real, global_pol_imag,
local_tor_real, local_tor_imag, local_pol_real, local_pol_imag,
local_l, local_m, lm_mapping)Map local spectral coefficients to global arrays using (l,m) index mapping.
GeoDynamo.maybe_log_erk2_stage_residual! — Method
maybe_log_erk2_stage_residual!(label, buffers, step)Emit a diagnostic log entry when ERK2 diagnostics are enabled.
GeoDynamo.modify_for_flux_inner! — Method
modify_for_flux_inner!(spec_real, spec_imag, local_lm, prescribed_flux,
∂r, domain, r_range)Modify coefficients near inner boundary to approximate flux condition. Uses low-order extrapolation.
GeoDynamo.modify_for_flux_outer! — Method
modify_for_flux_outer!(spec_real, spec_imag, local_lm, prescribed_flux,
∂r, domain, r_range)Modify coefficients near outer boundary to approximate flux condition. Uses low-order extrapolation.
GeoDynamo.normalize_influence_function! — Method
normalize_influence_function!(G::Vector{T}, domain::RadialDomain, which_boundary::Int) where TNormalize influence function to have unit flux at the specified boundary.
GeoDynamo.optimize_communication_order — Method
optimize_communication_order(plans::Dict)Determine optimal order for transpose operations to minimize communication.
GeoDynamo.optimize_erk2_transforms! — Method
optimize_erk2_transforms!(config::SHTnsKitConfig)Optimize SHTnsKit transforms for ERK2 timestepping with PencilFFTs. This function pre-warms transform plans and optimizes memory layout.
GeoDynamo.optimize_fft_performance! — Method
optimize_fft_performance!(config::SHTnsKitConfig)Optimize FFT performance by warming up FFTW plans and checking efficiency.
GeoDynamo.optimize_magnetic_memory_layout! — Method
optimize_magnetic_memory_layout!(ℬ::SHTnsMagneticFields{T}) where TOptimize memory layout for better cache performance using pencil topology
GeoDynamo.optimize_process_topology — Method
optimize_process_topology(nprocs::Int, dims::Tuple{Int,Int,Int})Find optimal 2D process grid for given number of processes and problem dimensions. Minimizes communication volume.
GeoDynamo.optimize_process_topology_shtnskit — Method
optimize_process_topology_shtnskit(nprocs, nlat, nlon) -> Tuple{Int,Int}Find optimal 2D MPI process grid for theta-phi parallelization.
The Optimization Problem
Given nprocs MPI processes, we need to factor it as nprocs = p_theta × p_phi such that:
- Each process gets at least 2 grid points in each direction
- Load imbalance (due to non-divisibility) is minimized
- The decomposition is valid (exact factorization)
Algorithm
Iterates through all valid factorizations and scores them by load imbalance. The load imbalance for a dimension is: |gridsize mod processes| / gridsize
Example
For nprocs=12, nlat=64, nlon=128:
- Possible factorizations: (1,12), (2,6), (3,4), (4,3), (6,2), (12,1)
- (4,3) gives nlat/4=16 points/proc in θ, nlon/3≈43 points/proc in φ
- This might be optimal if it minimizes total imbalance
Arguments
nprocs: Total number of MPI processesnlat: Number of latitude pointsnlon: Number of longitude points
Returns
(p_theta, p_phi): Optimal process grid dimensions
GeoDynamo.optimize_velocity_memory_layout! — Method
optimize_velocity_memory_layout!(𝒰::SHTnsVelocityFields{T}) where TOptimize memory layout for better cache performance using pencil topology
GeoDynamo.perform_analysis_direct! — Method
perform_analysis_direct!(phys, spec, config)Direct analysis without transpose (fallback).
GeoDynamo.perform_analysis_from_phi_pencil! — Method
perform_analysis_from_phi_pencil!(phys_phi, spec, config)Perform analysis from phi-pencil data.
GeoDynamo.perform_analysis_phi_local! — Method
perform_analysis_phi_local!(phys, spec, config)Perform analysis when physical field is in phi-pencil orientation.
This is the most efficient analysis path because:
- The phi (longitude) dimension is fully local on each process
- SHTnsKit's FFT operates entirely in local memory
- No MPI communication needed during the transform itself
GeoDynamo.perform_analysis_with_transpose! — Method
perform_analysis_with_transpose!(phys, spec, config, to_phi_plan)Perform analysis with transpose to phi-pencil.
GeoDynamo.perform_synthesis_direct! — Method
perform_synthesis_direct!(spec, phys, config)Direct synthesis method that handles any pencil orientation.
This is the default/fallback method. It works regardless of the physical field's pencil orientation by using a generic storage function that handles the index mapping appropriately.
Note
For phi-pencil physical fields, perform_synthesis_phi_local! is more efficient as it can use optimized storage.
GeoDynamo.perform_synthesis_phi_local! — Method
perform_synthesis_phi_local!(spec, phys, config)Perform synthesis when physical field is in phi-pencil orientation.
This is the most efficient synthesis path because:
- The phi (longitude) dimension is fully local on each process
- SHTnsKit's FFT operates entirely in local memory
- No MPI communication needed during the transform itself
Algorithm for each radial level:
- Extract spectral coefficients into SHTnsKit's (lmax+1, mmax+1) matrix format
- Call SHTnsKit.synthesis() which does Legendre transform + FFT
- Store the resulting (nlat, nlon) physical field slice
GeoDynamo.perform_synthesis_to_phi_pencil! — Method
perform_synthesis_to_phi_pencil!(spec, phys_phi, config)Core synthesis routine that writes directly to a phi-pencil array.
This is the workhorse function called by other synthesis routines. It assumes the destination array is already in phi-pencil orientation.
GeoDynamo.perform_synthesis_with_transpose! — Method
perform_synthesis_with_transpose!(spec, phys, config, back_plan)Perform synthesis when physical field is NOT in phi-pencil orientation.
Strategy
When the target physical field is in a non-phi pencil (e.g., theta or r pencil), we can't directly use SHTnsKit because it requires all longitude points to be local.
Solution:
- Create a temporary phi-pencil array
- Perform synthesis to the temporary array (longitude local)
- Transpose the result to the target pencil orientation
This involves one extra MPI all-to-all communication (the transpose) but ensures the FFT can operate on contiguous local data.
GeoDynamo.phi1_action_krylov — Method
phi1_action_krylov(BA, LU_A, v, dt; m=20, tol=1e-8) -> y ≈ φ1(dt A) vCompute φ1(dt A) v = A^{-1}[(exp(dt A) − I) v]/dt using Krylov exp(action) and banded solve.
GeoDynamo.pivot_tol — Method
Pivot singularity threshold: abs(pivot) < eps(T) * PIVOT_SINGULARITY_FACTOR
GeoDynamo.print_geodynamo_banner — Method
print_geodynamo_banner(config, nprocs::Int, nthreads::Int)Print the GeoDynamo startup banner with configuration information.
GeoDynamo.print_pencil_axes — Method
print_pencil_axes(pencils)Print the axes_local tuple for each pencil, showing the local index ranges for all three axes. This helps verify which axes are distributed (those with nontrivial subranges across ranks) and which axis is contiguous locally.
GeoDynamo.print_pencil_info — Method
print_pencil_info(pencils)Print detailed information about pencil decomposition.
GeoDynamo.print_shtnskit_config_summary — Method
print_shtnskit_config_summary(nlat, nlon, nr, lmax, mmax, nlm, nprocs, memory_estimate)Print configuration summary for SHTnsKit setup.
GeoDynamo.print_transpose_statistics — Method
print_transpose_statistics()Print accumulated transpose timing statistics.
GeoDynamo.rcond_fallback_tol — Method
Reciprocal condition number threshold for matrix function fallback
GeoDynamo.read_distributed_metadata — Method
read_distributed_metadata(filename::String)Read metadata from a distributed NetCDF file to determine global configuration.
GeoDynamo.read_file_metadata — Method
read_file_metadata(filename::String)Read metadata from NetCDF file to determine grid configuration.
GeoDynamo.report_energy_conservation — Method
report_energy_conservation(step::Int; interval::Int=100)Report energy conservation statistics periodically.
GeoDynamo.report_phi2_conditioning — Method
report_phi2_conditioning(step::Int; interval::Int=100)Report φ₂ conditioning statistics periodically during simulation.
GeoDynamo.report_solenoidal_constraint — Method
report_solenoidal_constraint(step::Int; interval::Int=100)Report solenoidal constraint violations periodically.
GeoDynamo.reset_energy_tracker! — Method
reset_energy_tracker!()Reset energy tracking data.
GeoDynamo.reset_phi2_monitor! — Method
reset_phi2_monitor!()Reset φ₂ conditioning monitor statistics.
GeoDynamo.reset_solenoidal_monitor! — Method
reset_solenoidal_monitor!()Reset solenoidal constraint monitoring data.
GeoDynamo.restore_fields_from_restart! — Method
restore_fields_from_restart!(state::SimulationState{T}, restart_data::Dict{String,Any})Restore simulation state fields from restart data loaded by read_restart!. Copies spectral coefficients from the restart data Dict into the state's field arrays.
GeoDynamo.rotate_field_90x! — Method
rotate_field_90x!(config::SHTnsKitConfig, alm::Matrix{ComplexF64};
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Rotate a scalar field by 90 degrees around the x-axis. Equivalent to: Z(-π/2) * Y(π/2) * Z(π/2)
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsalm_out: Optional output array
Returns
The rotated coefficients
GeoDynamo.rotate_field_90y! — Method
rotate_field_90y!(config::SHTnsKitConfig, alm::Matrix{ComplexF64};
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Rotate a scalar field by 90 degrees around the y-axis. This is a special case with optimized Wigner d-matrix values.
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsalm_out: Optional output array
Returns
The rotated coefficients
GeoDynamo.rotate_field_euler! — Method
rotate_field_euler!(config::SHTnsKitConfig, alm::Matrix{ComplexF64},
alpha::Real, beta::Real, gamma::Real;
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Rotate a scalar field by Euler angles (ZYZ convention) in spectral space. The rotation is: R = Rz(gamma) * Ry(beta) * Rz(alpha)
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsalpha, beta, gamma: Euler angles in radians (ZYZ convention)alm_out: Optional output array
Returns
The rotated coefficients
GeoDynamo.rotate_field_y! — Method
rotate_field_y!(config::SHTnsKitConfig, alm::Matrix{ComplexF64}, beta::Real;
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Rotate a scalar field around the y-axis by angle beta in spectral space. Uses Wigner d-matrices (small Wigner rotation matrices).
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientsbeta: Rotation angle in radiansalm_out: Optional output array
Returns
The rotated coefficients
GeoDynamo.rotate_field_z! — Method
rotate_field_z!(config::SHTnsKitConfig, alm::Matrix{ComplexF64}, alpha::Real;
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Rotate a scalar field around the z-axis by angle alpha in spectral space. This is a pure phase rotation: alm[l,m] -> alm[l,m] * exp(-imalpha)
Arguments
config: SHTnsKit configurationalm: Input spectral coefficients (modified in-place if alm_out is nothing)alpha: Rotation angle in radiansalm_out: Optional output array (if nothing, modifies alm in-place)
Returns
The rotated coefficients (alm_out if provided, otherwise alm)
GeoDynamo.run_simulation! — Method
run_simulation!(state::SimulationState{T}; restart_file::String="", restart_dir::String="", restart_time::Float64=0.0)Run geodynamo simulation with all parallelization optimizations. Supports restarting from a saved NetCDF restart file.
GeoDynamo.safe_eval_expr — Method
safe_eval_expr(expr, param_dict::Dict{Symbol, Any})Evaluate a parsed expression using only safe arithmetic operations and known parameter values. No arbitrary code execution is possible.
GeoDynamo.safe_parse_value — Method
safe_parse_value(value_str::AbstractString, param_dict::Dict{Symbol, Any})Parse a parameter value string without using eval. Supports:
- Integer and float literals (including scientific notation)
- Boolean literals (
true,false) - Symbol literals (
:name) - String literals (
"...") - Mathematical constants (
π) - Simple arithmetic expressions referencing previously-defined parameters
GeoDynamo.save_combined_fields — Method
save_combined_fields(combiner::FieldCombiner{T}, output_filename::String;
config::CombinerConfig = create_combiner_config()) where TSave combined fields to NetCDF file using GeoDynamo I/O system.
GeoDynamo.save_combined_time_series — Method
save_combined_time_series(combiners::Vector{FieldCombiner{T}}, output_dir::String,
filename_prefix::String;
config::CombinerConfig = create_combiner_config()) where TSave combined time series to a single NetCDF file.
GeoDynamo.save_erk2_cache_bundle — Method
save_erk2_cache_bundle(path, caches; metadata=Dict())Persist a dictionary of ERK2 caches to disk along with optional metadata.
GeoDynamo.save_parameters — Method
save_parameters(params::GeoDynamoParameters, filename::String)Save parameters to a Julia file.
GeoDynamo.save_physical_fields — Method
save_physical_fields(converter::SpectralToPhysicalConverter{T}, output_filename::String) where TSave converted physical space fields to NetCDF file using parallel I/O.
GeoDynamo.series_tol — Method
Series term convergence: opnorm(term) < eps(T) * SERIES_CONVERGENCE_FACTOR
GeoDynamo.set_composition_rhs_bc! — Method
set_composition_rhs_bc!(rhs_real, rhs_imag, local_lm, nr;
inner_value=0.0, outer_value=0.0,
inner_value_imag=0.0, outer_value_imag=0.0)Set boundary values in the RHS vector for the composition solve. Matches Fortran cmp_setbc: sets RHS boundary rows to prescribed values.
For standard compositional convection, boundary values are typically zero (homogeneous Neumann: ∂C/∂r=0, or homogeneous Dirichlet: C=0). Non-zero imaginary parts are used when file-based spectral BCs are loaded.
GeoDynamo.set_magnetic_rhs_bc! — Method
set_magnetic_rhs_bc!(rhs_real, rhs_imag, local_lm, nr;
inner_value=0.0, outer_value=0.0)Set boundary values in the RHS vector for the magnetic field solve. Matches Fortran magsetbcTor / tim_zerobc: sets RHS boundary rows to zero.
For insulating BCs, all boundary values are zero (homogeneous conditions).
GeoDynamo.set_parameters! — Method
set_parameters!(params::GeoDynamoParameters; validate::Bool=true, strict::Bool=false)Set the global parameters (thread-safe) with optional validation.
Arguments
params::GeoDynamoParameters: Parameters to setvalidate::Bool=true: Whether to validate parameters before settingstrict::Bool=false: If true, throw error on invalid parameters; if false, proceed with warnings
GeoDynamo.set_shtnskit_threads — Method
set_shtnskit_threads(num_threads::Int)Configure the number of threads used by SHTnsKit transforms. Uses SHTnsKit.shtnsusethreads when available.
GeoDynamo.set_temperature_rhs_bc! — Method
set_temperature_rhs_bc!(rhs_real, rhs_imag, local_lm, nr;
inner_value=0.0, outer_value=0.0,
inner_value_imag=0.0, outer_value_imag=0.0)Set boundary values in the RHS vector for the temperature solve. Matches Fortran tmp_setbc: sets RHS boundary rows to prescribed values.
For standard geodynamo simulations, boundary values are typically zero (homogeneous Dirichlet: T=0, or homogeneous Neumann: ∂T/∂r=0). Non-zero imaginary parts are used when file-based spectral BCs are loaded.
GeoDynamo.set_velocity_rhs_bc_poloidal! — Method
set_velocity_rhs_bc_poloidal!(rhs_real, rhs_imag, local_lm, nr;
inner_value=0.0, outer_value=0.0)Set boundary values in the RHS vector for the poloidal velocity solve. Matches Fortran: sets RHS boundary rows to zero for homogeneous BCs.
For no-slip: RHS boundary = 0 (∂P/∂r = 0) For stress-free: RHS boundary = 0 (∂²P/∂r² = 0)
GeoDynamo.set_velocity_rhs_bc_toroidal! — Method
set_velocity_rhs_bc_toroidal!(rhs_real, rhs_imag, local_lm, nr;
inner_value=0.0, outer_value=0.0)Set boundary values in the RHS vector for the toroidal velocity solve. Matches Fortran velsetbcTor: sets RHS boundary rows to zero (or prescribed value).
For no-slip: RHS boundary = 0 (or prescribed velocity, e.g., rotating inner core) For stress-free: RHS boundary = 0 (homogeneous condition ∂T/∂r - T/r = 0)
GeoDynamo.set_velocity_workspace! — Method
set_velocity_workspace!(ws::Union{VelocityWorkspace{T}, Nothing}) where TRegister a global VelocityWorkspace to be used by velocity kernels when available. Pass nothing to disable and fall back to internal buffers. Type-stable version that only accepts VelocityWorkspace or nothing.
GeoDynamo.shtnskit_analysis_inplace! — Method
shtnskit_analysis_inplace!(config::SHTnsKitConfig, f::Matrix{Float64},
alm_out::Matrix{ComplexF64})In-place physical-to-spectral analysis using SHTnsKit v1.1.15. Writes result directly to alm_out, avoiding allocation of temporary arrays.
Arguments
config: SHTnsKit configurationf: Input physical field (nlat × nlon)alm_out: Output spectral coefficients (lmax+1 × mmax+1), modified in-place
GeoDynamo.shtnskit_physical_to_spectral! — Method
shtnskit_physical_to_spectral!(phys, spec)Transform physical space values to spectral coefficients (analysis).
The Analysis Operation
Given physical field values f(θ,φ), compute spherical harmonic coefficients: fl^m = ∫∫ f(θ,φ) × Yl^m*(θ,φ) sin(θ) dθ dφ
The integral is computed numerically using:
- Gauss-Legendre quadrature for the θ integral
- FFT for the φ integral (exploiting periodicity)
Implementation
Uses SHTnsKit's analysis function which:
- Performs the FFT along longitude (extracting Fourier modes)
- Performs the Legendre transform (computing l coefficients for each m)
Arguments
phys::SHTnsPhysField: Source physical field valuesspec::SHTnsSpecField: Destination spectral field (modified in-place)
Side Effects
Modifies spec.data_real and spec.data_imag with the computed coefficients
GeoDynamo.shtnskit_qst_to_spatial! — Method
shtnskit_qst_to_spatial!(config::SHTnsKitConfig, Qlm, Slm, Tlm, vr, vtheta, vphi)Convert QST spectral coefficients to full 3D spatial vector field using SHTnsKit v1.1.15.
This is more efficient than separate scalar + vector synthesis as it handles all three components in a single call.
Arguments
Qlm: Q (radial) spectral coefficientsSlm: S (spheroidal/poloidal) spectral coefficientsTlm: T (toroidal) spectral coefficientsvr,vtheta,vphi: Output spatial components (modified in-place)
GeoDynamo.shtnskit_spatial_to_qst! — Method
shtnskit_spatial_to_qst!(config::SHTnsKitConfig, vr, vtheta, vphi, Qlm, Slm, Tlm)Convert full 3D spatial vector field to QST spectral coefficients using SHTnsKit v1.1.15.
Arguments
vr,vtheta,vphi: Input spatial componentsQlm: Output Q (radial) spectral coefficients (modified in-place)Slm: Output S (spheroidal/poloidal) spectral coefficients (modified in-place)Tlm: Output T (toroidal) spectral coefficients (modified in-place)
GeoDynamo.shtnskit_spectral_to_physical! — Method
shtnskit_spectral_to_physical!(spec, phys)Transform spectral coefficients to physical space values (synthesis).
The Synthesis Operation
Given spherical harmonic coefficients fl^m, compute the physical field: f(θ,φ) = Σ{l,m} fl^m × Yl^m(θ,φ)
where Y_l^m are the spherical harmonics.
Implementation
Uses SHTnsKit's synthesis function which:
- Performs the Legendre transform (summing over l for each m)
- Performs the FFT along longitude (summing over m)
Arguments
spec::SHTnsSpecField: Source spectral field with coefficientsphys::SHTnsPhysField: Destination physical field (modified in-place)
Side Effects
Modifies phys.data with the synthesized field values
GeoDynamo.shtnskit_synthesis_inplace! — Method
shtnskit_synthesis_inplace!(config::SHTnsKitConfig, alm::Matrix{ComplexF64},
f_out::Matrix{Float64})In-place spectral-to-physical synthesis using SHTnsKit v1.1.15. Writes result directly to f_out, avoiding allocation of temporary arrays.
Arguments
config: SHTnsKit configurationalm: Input spectral coefficients (lmax+1 × mmax+1)f_out: Output physical field (nlat × nlon), modified in-place
GeoDynamo.shtnskit_vector_analysis! — Method
shtnskit_vector_analysis!(vec_phys::SHTnsVectorField{T},
tor_spec::SHTnsSpecField{T},
pol_spec::SHTnsSpecField{T}) where TVector analysis using SHTnsKit with PencilArrays.
Toroidal-Poloidal Analysis
Decomposes a 3D velocity field into toroidal and poloidal scalars.
For a solenoidal vector field v (∇·v = 0): v = ∇×(T r̂) + ∇×∇×(P r̂)
Mathematical Note on Analysis
SHTnsKit.spattoSHsphtor takes (vθ, vφ) and returns (P, T).
This is mathematically valid for solenoidal fields because:
- The solenoidal constraint ∇·v = 0 couples vr to (vθ, v_φ)
- The decomposition into T (rotational) and P (potential) parts is unique
- The radial component v_r = l(l+1)/r * P is implicitly determined
However, this assumes EXACT solenoidality. In numerical simulations with finite precision, v_r may not exactly satisfy ∇·v = 0.
Alternative: Use Full 3-Component Analysis
For better numerical accuracy, one could use: Qcoeffs = analysis(vr * r / l(l+1)) # Recover P from vr S, T = spattoSHsphtor(vθ, v_φ) # Decompose tangential
Then check: Qcoeffs ≈ Scoeffs (should match for solenoidal field)
Current implementation uses 2-component analysis which is standard practice for solenoidal MHD simulations.
GeoDynamo.shtnskit_vector_synthesis! — Method
shtnskit_vector_synthesis!(tor_spec::SHTnsSpecField{T},
pol_spec::SHTnsSpecField{T},
vec_phys::SHTnsVectorField{T};
domain::Union{RadialDomain,Nothing}=nothing) where TVector synthesis using SHTnsKit spheroidal-toroidal decomposition with PencilArrays.
Toroidal-Poloidal Decomposition
For a solenoidal vector field v (∇·v = 0): v = ∇×(T r̂) + ∇×∇×(P r̂)
where T = toroidal scalar, P = poloidal scalar.
In spherical components: vr = l(l+1)/r * P * Ylm (from poloidal only) vθ, vφ from both T and P (computed by SHTnsKit.SHsphtortospat)
CRITICAL: SHTnsKit.SHsphtortospat returns ONLY tangential components. The radial component v_r MUST be computed separately from the poloidal scalar.
Parameters
domain: Optional RadialDomain needed for computing vr with correct radial scaling. If not provided, vr will be set to zero (suitable for tests).
GeoDynamo.solve_banded! — Method
solve_banded!(x, lu, b)Solve the banded linear system lu * x = b in-place.
In-place aliasing x === b is explicitly supported and safe. The forward substitution sweep processes rows in ascending order: at step i, it reads x[j] for j < i (already holding the intermediate result y[j]) and b[i] (not yet overwritten when aliased). The back substitution sweep processes rows in descending order with the same safe access pattern.
WARNING: Do not change the loop ordering without verifying aliasing safety.
GeoDynamo.solve_composition_implicit_step! — Method
solve_composition_implicit_step!(solution, rhs, matrices;
bc_inner, bc_outer, bc_inner_imag, bc_outer_imag)Solve the implicit composition system with boundary conditions embedded in the matrix. Before solving, sets the RHS boundary values appropriately.
This matches the Fortran DD_2DCODE approach where each rank has full radial profiles for its subset of (l,m) modes:
- Loop over local lm modes
- Set RHS boundary rows to prescribed values (cmp_setbc)
- Solve banded system with BC rows in matrix
- Solution automatically satisfies BCs
Arguments
solution: Output spectral fieldrhs: Input RHS spectral field (modified in place for BCs)matrices: SHTnsImplicitMatrices with composition BCs embeddedbc_inner: Optional vector of inner boundary values (real part) per mode (default: zeros)bc_outer: Optional vector of outer boundary values (real part) per mode (default: zeros)bc_inner_imag: Optional vector of inner boundary values (imag part) per mode (default: zeros)bc_outer_imag: Optional vector of outer boundary values (imag part) per mode (default: zeros)
GeoDynamo.solve_magnetic_implicit_step! — Method
solve_magnetic_implicit_step!(solution, rhs, matrices, component;
mag_bc_inner=nothing, prev_bc_inner=nothing)Solve the implicit magnetic system with boundary conditions embedded in the matrix. Before solving, sets the RHS boundary values appropriately.
This matches the Fortran DD_2DCODE approach where each rank has full radial profiles for its subset of (l,m) modes:
- Loop over local lm modes
- Set RHS boundary rows to 0 (insulating BCs)
- Solve banded system with BC rows in matrix
- Solution automatically satisfies BCs
Arguments
solution: Output spectral fieldrhs: Input RHS spectral field (modified in place for BCs)matrices: SHTnsImplicitMatrices with BCs embeddedcomponent::toroidalor:poloidalmag_bc_inner: Optional inner boundary values for toroidal (conducting IC case)prev_bc_inner: Previous step inner BC values (for incremental form)
GeoDynamo.solve_temperature_implicit_step! — Method
solve_temperature_implicit_step!(solution, rhs, matrices;
bc_inner, bc_outer, bc_inner_imag, bc_outer_imag)Solve the implicit temperature system with boundary conditions embedded in the matrix. Before solving, sets the RHS boundary values appropriately.
This matches the Fortran DD_2DCODE approach where each rank has full radial profiles for its subset of (l,m) modes:
- Loop over local lm modes
- Set RHS boundary rows to prescribed values (tmp_setbc)
- Solve banded system with BC rows in matrix
- Solution automatically satisfies BCs
Arguments
solution: Output spectral fieldrhs: Input RHS spectral field (modified in place for BCs)matrices: SHTnsImplicitMatrices with temperature BCs embeddedbc_inner: Optional vector of inner boundary values (real part) per mode (default: zeros)bc_outer: Optional vector of outer boundary values (real part) per mode (default: zeros)bc_inner_imag: Optional vector of inner boundary values (imag part) per mode (default: zeros)bc_outer_imag: Optional vector of outer boundary values (imag part) per mode (default: zeros)
GeoDynamo.solve_velocity_implicit_step! — Method
solve_velocity_implicit_step!(solution, rhs, matrices, component;
i_vel_bc=1, domain=nothing,
rot_omega=0.0, current_field=nothing)Solve the implicit velocity system with boundary conditions embedded in the matrix. Before solving, sets the RHS boundary values appropriately.
This matches the Fortran DD_2DCODE approach where each rank has full radial profiles for its subset of (l,m) modes:
- Loop over local lm modes
- Set RHS boundary rows to BC values (typically 0)
- Solve banded system with BC rows in matrix
- Solution automatically satisfies BCs
Arguments
solution: Output spectral fieldrhs: Input RHS spectral field (modified in place for BCs)matrices: SHTnsImplicitMatrices with BCs embeddedcomponent::toroidalor:poloidali_vel_bc: Velocity BC type (1-4)domain: RadialDomain (needed for rotating IC boundary)rot_omega: Inner core rotation rate (for no-slip toroidal l=1,m=0)current_field: Current velocity field (for incremental form of rotating IC BC)
GeoDynamo.spectral_gradient! — Method
spectral_gradient!(config::SHTnsKitConfig, Slm::Matrix{ComplexF64},
grad_theta::Matrix{Float64}, grad_phi::Matrix{Float64})Compute the horizontal gradient of a scalar field in spectral space. Uses SHTnsKit.SHtograd_spat for efficient computation.
Arguments
Slm: Spectral coefficients of the scalar fieldgrad_theta: Output θ-component of gradient (modified in-place)grad_phi: Output φ-component of gradient (modified in-place)
GeoDynamo.store_coefficients_from_shtnskit! — Method
store_coefficients_from_shtnskit!(spec_real, spec_imag, coeffs_matrix, r_local, config)Convert SHTnsKit coefficient matrix format back to our linear spectral storage.
This is the inverse of extract_coefficients_for_shtnskit!:
- Input: SHTnsKit's (lmax+1) × (mmax+1) coefficient matrix
- Output: Our linear-indexed spectral arrays (real and imaginary parts separate)
Physical Constraint
For real-valued physical fields, the m=0 coefficients must be purely real. This function enforces this by zeroing the imaginary part for m=0 modes.
GeoDynamo.store_physical_slice_generic! — Method
store_physical_slice_generic!(phys_data, phys_slice, r_local, config)Generic storage for any pencil orientation.
GeoDynamo.store_physical_slice_phi_local! — Method
store_physical_slice_phi_local!(phys_data, phys_slice, r_local, config)Copy a 2D physical field slice into a 3D array at a specific radial level.
Optimized for Phi-Local Layout
When the physical field is in phi-pencil orientation, the (θ, φ) indices correspond directly to the array's first two dimensions, making this a straightforward copy operation.
Arguments
phys_data: 3D destination array (θ × φ × r)phys_slice: 2D source array from SHTnsKit (θ × φ)r_local: Radial index to write toconfig: Configuration for grid dimensions
GeoDynamo.store_scalar_component_generic! — Method
store_scalar_component_generic!(v_component, field, r_local, config)Store a scalar field into a component array for any pencil orientation. Used for storing the radial component v_r from synthesized field.
GeoDynamo.store_vector_components_generic! — Method
store_vector_components_generic!(v_theta, v_phi, vt_field, vp_field, r_local, config)Store vector components for any pencil orientation.
GeoDynamo.store_zero_component_generic! — Method
store_zero_component_generic!(v_component, r_local, config)Set a component to zero at a given radial level. Used at r=0 (ball geometry) where v_r must be zero for regularity.
GeoDynamo.synchronize_halos! — Method
synchronize_halos!(arr::PencilArray; halo_width::Int=1, boundaries::Symbol=:all)Synchronize ghost/halo regions for parallel finite difference computations.
Parameters
arr: PencilArray to synchronizehalo_width: Width of halo region (number of ghost cells), default 1boundaries: Boundary handling (:all, :periodic, :nonperiodic), default :all
Notes
This function implements MPI point-to-point communication to exchange boundary data between neighboring processes in each decomposed dimension. It's essential for maintaining accuracy in finite difference stencil operations near subdomain boundaries.
For spectral methods, explicit halo exchange may not be needed as the global nature of spectral transforms handles boundary coupling through transpose operations.
GeoDynamo.synchronize_pencil_data! — Method
synchronize_pencil_data!(field)Synchronize PencilArray data across MPI processes to ensure consistency.
GeoDynamo.synchronize_pencil_transforms! — Method
synchronize_pencil_transforms!(field::SHTnsSpecField{T}) where TEnsure all pending PencilFFTs operations are completed and data is consistent across processes.
GeoDynamo.test_halo_exchange — Method
test_halo_exchange(pencil::Pencil, ::Type{T}=Float64; halo_width::Int=1, verbose::Bool=true) where TTest halo exchange functionality by creating a test array with rank-based values. Returns true if halo exchange is working correctly.
Example
pencils = create_pencil_topology(shtns_config)
test_halo_exchange(pencils.θ, Float64; halo_width=1, verbose=true)GeoDynamo.transform_field_and_gradients_to_physical! — Method
transform_field_and_gradients_to_physical!(𝔽::AbstractScalarField{T}, ws::GradientWorkspace{T}) where TTransform scalar field and all gradient components to physical space in a single batched operation to minimize communication.
GeoDynamo.transpose_with_timer! — Function
transpose_with_timer!(dest, src, label=:default)Perform transpose with optional timing and statistics.
Arguments
dest::PencilArray: Destination arraysrc::PencilArray: Source arraylabel::Symbol: Label for timing statistics (default::default)
Notes
Uses PencilArrays.transpose! which creates a Transposition internally. Enable timing with ENABLE_TIMING[] = true.
GeoDynamo.truncate_spectral_modes! — Function
truncate_spectral_modes!(config::SHTnsKitConfig, alm::Matrix{ComplexF64},
lmax_new::Int, mmax_new::Int=lmax_new;
alm_out::Union{Matrix{ComplexF64},Nothing}=nothing)Truncate spectral coefficients to a lower resolution. Sets all modes with l > lmaxnew or m > mmaxnew to zero.
Arguments
config: SHTnsKit configurationalm: Input spectral coefficientslmax_new: New maximum degreemmax_new: New maximum order (default = lmax_new)alm_out: Optional output array
GeoDynamo.update_derived_parameters! — Method
update_derived_parameters!(params::GeoDynamoParameters)Update derived parameters based on primary parameters.
GeoDynamo.validate_magnetic_configuration — Method
validate_magnetic_configuration(ℬ::SHTnsMagneticFields{T}, config::SHTnsKitConfig) where TValidate magnetic field configuration consistency with SHTns setup
GeoDynamo.validate_mpi_consistency! — Method
validate_mpi_consistency!(field::SHTnsSpecField{T}) where TCheck that spectral field data is valid (no NaN/Inf) across all MPI processes. Returns the field after validation. Warns if any process has invalid data.
GeoDynamo.validate_parameters — Method
validate_parameters(params::GeoDynamoParameters; strict::Bool=false)Validate all simulation parameters for physical correctness and numerical stability.
Arguments
params::GeoDynamoParameters: Parameters to validatestrict::Bool=false: If true, throw errors on invalid params; if false, issue warnings
Returns
(is_valid::Bool, errors::Vector{String}, warnings::Vector{String})
GeoDynamo.validate_pencil_decomposition — Method
validate_pencil_decomposition(config::SHTnsKitConfig)Validate that pencil decomposition is optimal for the problem size and MPI configuration.
GeoDynamo.validate_radial_distribution — Method
validate_radial_distribution(pencils; warn_uneven::Bool=true, strict::Bool=true) -> BoolValidate that radial dimension has compatible distribution across all pencils.
MPI Synchronization Requirement
The SHTnsKit transforms use MPI.Allreduce inside per-radial-level loops. All processes must have the SAME number of local radial levels, otherwise processes will enter/exit the loop at different times causing MPI DEADLOCK.
Arguments
pencils: Named tuple of pencil configurationswarn_uneven: If true, emit warning for uneven distributionstrict: If true (default), throw an error instead of just warning
Returns
true if distribution is valid (all processes have same local radial count). false if there's a potential synchronization issue.
Default Behavior
Strict mode is enabled by default to prevent MPI deadlock in production runs. Set strict=false only for debugging purposes.
Example
# Recommended: use default strict mode
validate_radial_distribution(pencils)
# For debugging only: disable strict mode
validate_radial_distribution(pencils; strict=false)GeoDynamo.validate_velocity_configuration — Method
validate_velocity_configuration(𝒰::SHTnsVelocityFields{T}, config::SHTnsKitConfig) where TValidate velocity field configuration consistency with SHTns setup
GeoDynamo.verify_all_ranks_wrote — Method
verify_all_ranks_wrote(output_dir, hist_number; geometry="shell", expected_dims=nothing)Verify that the single parallel output file exists for a given history number and has correct global dimensions.
GeoDynamo.write_coordinate_data! — Method
write_coordinate_data!(ds, field_info, config)Write coordinate arrays. Only rank 0 writes coordinates (they are global/shared).
GeoDynamo.write_field_data! — Method
write_field_data!(ds, fields, config, field_info)Write field data using parallel offset writes. Each rank writes its local pencil slice at the correct global position.
GeoDynamo.write_fields! — Function
write_fields!(state::SimulationState, tracker, metadata, config, shtns_config, pencils)All-ranks entry point: synchronizes the output decision via MPI.Bcast, then extracts fields only if output is actually needed. Must be called by every rank on every timestep to avoid MPI deadlocks.
GeoDynamo.write_grid_file! — Method
write_grid_file!(config, field_info, shtns_config, metadata)Write a separate grid file containing coordinate and grid information. Written only once by rank 0 at the start of the simulation.
GeoDynamo.zero_scalar_work_arrays! — Method
zero_scalar_work_arrays!(𝔽::AbstractScalarField{T}) where TEfficiently zero all work arrays for a scalar field.
Boundary Conditions
The bcs submodule handles boundary condition loading, interpolation, and application.
At a Glance
GeoDynamo.bcs
├── load_boundary_conditions! # Load from files
├── read_netcdf_boundary_data # Read raw data
├── write_netcdf_boundary_data # Write data
└── validate_netcdf_boundary_file # Validate structureusing GeoDynamo
GeoDynamo.bcs.load_boundary_conditions!(
temperature = "thermal_bc.nc",
velocity = "velocity_bc.nc"
)GeoDynamo.bcs.AbstractBoundaryCondition — Type
AbstractBoundaryCondition{T}Abstract base type for all boundary conditions.
GeoDynamo.bcs.BoundaryCache — Type
BoundaryCache{T}Cache structure for storing processed boundary data.
GeoDynamo.bcs.BoundaryConditionSet — Type
BoundaryConditionSet{T}Complete set of boundary conditions for inner and outer boundaries.
GeoDynamo.bcs.BoundaryData — Type
BoundaryData{T}Common data structure for boundary condition data from any source.
GeoDynamo.bcs.BoundaryLocation — Type
BoundaryLocationEnumeration for boundary locations.
GeoDynamo.bcs.BoundaryType — Type
BoundaryTypeEnumeration for boundary condition types.
GeoDynamo.bcs.FieldType — Type
FieldTypeEnumeration for different physical field types.
GeoDynamo.bcs.ProgrammaticBoundarySet — Type
ProgrammaticBoundarySet{T}Wrapper around BoundaryConditionSet that also stores BC types for each boundary. Returned by create_programmatic_temperature_boundaries and create_programmatic_composition_boundaries.
GeoDynamo.bcs.SpectralBoundaryCoefficients — Type
SpectralBoundaryCoefficients{T}Stores spectral boundary condition coefficients for inner and outer boundaries. Row 1 = inner boundary, Row 2 = outer boundary (matching Fortran convention).
Fields
bc_real::Matrix{T}: Real part of spectral BCs [2, nlm]bc_imag::Matrix{T}: Imaginary part of spectral BCs [2, nlm]nlm::Int: Number of spectral modessource_file::String: Path to the source filesource_format::Symbol: Format used to load (:physical or :spectral)
GeoDynamo.bcs.Ylm — Type
Ylm(l::Int, m::Int)Spherical harmonic pattern specifier for programmatic boundary conditions.
Examples
# Create Y₂¹ pattern with amplitude 0.5
boundary = create_programmatic_boundary(Ylm(2, 1), config, 0.5)
# Create Y₄⁻² pattern
boundary = create_programmatic_boundary(Ylm(4, -2), config, 1.0)
# Time-dependent oscillating Y₃² pattern
boundary = create_time_dependent_programmatic_boundary(Ylm(3, 2), config, (0.0, 10.0), 100;
amplitude=0.3)GeoDynamo.bcs._get_cached_bc_shtns_config — Method
_get_cached_bc_shtns_config(lmax, mmax, nlat, nlon)Get or create a cached SHTnsKit configuration for boundary transforms. Reuses configurations to avoid repeated setup/teardown overhead. Thread-safe implementation using a lock for the check-then-set pattern.
GeoDynamo.bcs._load_physical_format — Method
Load physical-space boundary data from NetCDF, transform to spectral via SHTnsKit.
GeoDynamo.bcs._load_spectral_format — Method
Load pre-computed spectral boundary coefficients from NetCDF (Fortran-compatible format).
GeoDynamo.bcs._parse_boundary_spec — Method
_parse_boundary_spec(spec::Tuple, cfg) -> (values::Matrix, bc_type::BoundaryType)Parse a boundary specification tuple into physical-space values and BC type.
Supported spec formats:
(:uniform, value)or(:dirichlet, value): Dirichlet BC with uniform value(:neumann, value): Neumann BC with uniform flux value
GeoDynamo.bcs.add_noise_to_boundary — Function
add_noise_to_boundary(boundary_data::BoundaryData, noise_amplitude::Real,
noise_type::Symbol=:gaussian)Add noise to existing boundary data.
GeoDynamo.bcs.apply_boundary_conditions! — Method
apply_boundary_conditions!(𝔽, field_type::FieldType, solver_state)Apply boundary conditions during solver operations.
This function integrates boundary conditions with the timestepping and solving process.
GeoDynamo.bcs.apply_boundary_conditions_to_rhs! — Method
apply_boundary_conditions_to_rhs!(rhs, state, field_type::FieldType)Apply boundary conditions to right-hand side during timestepping.
This function modifies the RHS vector to enforce boundary conditions during implicit and explicit timestepping methods.
GeoDynamo.bcs.apply_composition_bc_to_rhs! — Method
apply_composition_bc_to_rhs!(rhs, comp_field)Apply composition boundary conditions to RHS vector.
GeoDynamo.bcs.apply_composition_boundaries! — Method
apply_composition_boundaries!(comp_field, pbs::ProgrammaticBoundarySet; time=0.0)Apply programmatic composition boundary conditions to a composition field. Same interface as apply_temperature_boundaries!.
GeoDynamo.bcs.apply_gaussian_smoothing! — Method
apply_gaussian_smoothing!(data::AbstractMatrix, theta::Vector, phi::Vector, radius::Real)Apply Gaussian smoothing kernel to 2D data array.
GeoDynamo.bcs.apply_magnetic_bc_to_rhs! — Method
apply_magnetic_bc_to_rhs!(rhs, magnetic_field)Apply magnetic field boundary conditions to RHS vector.
GeoDynamo.bcs.apply_temperature_bc_to_rhs! — Method
apply_temperature_bc_to_rhs!(rhs, temp_field)Apply temperature boundary conditions to RHS vector.
GeoDynamo.bcs.apply_temperature_boundaries! — Method
apply_temperature_boundaries!(temp_field, pbs::ProgrammaticBoundarySet; time=0.0)Apply programmatic temperature boundary conditions to a temperature field.
Transforms physical-space boundary data to spectral coefficients and stores them in the field's boundary_values matrix, along with setting BC types.
Arguments
temp_field: SHTnsTemperatureField to apply boundaries topbs: ProgrammaticBoundarySet containing boundary data and BC typestime: Current simulation time (for time-dependent boundaries)
GeoDynamo.bcs.apply_velocity_bc_to_rhs! — Method
apply_velocity_bc_to_rhs!(rhs, velocity_field)Apply velocity boundary conditions to RHS vector.
GeoDynamo.bcs.bilinear_interpolate — Method
bilinear_interpolate(data::Matrix{T}, theta_idx::Tuple{Int, Int}, phi_idx::Tuple{Int, Int},
theta_weights::Tuple{T, T}, phi_weights::Tuple{T, T}) where TPerform bilinear interpolation on a 2D data array. Handles periodic boundary conditions in phi direction.
GeoDynamo.bcs.cache_boundary_data! — Method
cache_boundary_data!(cache::BoundaryCache{T}, key::String, data::Array{T}) where TCache processed boundary data.
GeoDynamo.bcs.check_interpolation_bounds — Method
check_interpolation_bounds(boundary_data::BoundaryData, target_theta::Vector{T},
target_phi::Vector{T}) where TCheck if target grid is within the bounds of the source grid and warn if extrapolation is needed.
GeoDynamo.bcs.clear_bc_shtns_config_cache! — Method
clear_bc_shtns_config_cache!()Clear the cached SHTnsKit configurations for boundary transforms. Call this when grid parameters change or to free memory. Thread-safe implementation.
GeoDynamo.bcs.clear_boundary_cache! — Method
clear_boundary_cache!(cache::BoundaryCache)Clear all cached boundary data.
GeoDynamo.bcs.compute_boundary_condition_residual — Method
compute_boundary_condition_residual(field, field_type::FieldType)Compute residual to check how well boundary conditions are satisfied.
Returns a measure of how much the current field violates the boundary conditions. Useful for monitoring solution quality and debugging.
GeoDynamo.bcs.copy_boundary_conditions! — Method
copy_boundary_conditions!(dest_𝔽, src_𝔽, field_type::FieldType)Copy boundary conditions from one field to another. Both fields must have boundary condition fields already defined.
GeoDynamo.bcs.create_boundary_data — Method
create_boundary_data(values::Array{T}, field_type::String;
theta=nothing, phi=nothing, time=nothing,
units="", description="", file_path="programmatic") where TCreate a BoundaryData structure from raw data.
GeoDynamo.bcs.create_hybrid_composition_boundaries — Method
create_hybrid_composition_boundaries(file_spec::String, prog_spec::Tuple, cfg; swap_boundaries=false)Create composition boundaries with one from file and one programmatic.
GeoDynamo.bcs.create_hybrid_temperature_boundaries — Method
create_hybrid_temperature_boundaries(file_spec::String, prog_spec::Tuple, cfg; swap_boundaries=false)Create temperature boundaries with one from file and one programmatic. When swap_boundaries=false, file is inner and programmatic is outer. When swap_boundaries=true, file is outer and programmatic is inner.
GeoDynamo.bcs.create_interpolation_cache — Method
create_interpolation_cache(boundary_data::BoundaryData, target_theta::Vector{T},
target_phi::Vector{T}) where TCreate interpolation cache for efficient repeated interpolations.
GeoDynamo.bcs.create_programmatic_boundary — Function
create_programmatic_boundary(ylm::Ylm, config, amplitude::Real=1.0; kwargs...)Create a boundary pattern from a spherical harmonic Yₗᵐ using SHTnsKit synthesis. Values are produced on the Gauss-Legendre grid of the given config.
Examples
boundary = create_programmatic_boundary(Ylm(2, 1), config, 0.5)
boundary = create_programmatic_boundary(Ylm(4, -2), config, 1.0)GeoDynamo.bcs.create_programmatic_composition_boundaries — Method
create_programmatic_composition_boundaries(inner_spec::Tuple, outer_spec::Tuple, cfg)Create a ProgrammaticBoundarySet for composition from programmatic specifications. Same interface as create_programmatic_temperature_boundaries.
GeoDynamo.bcs.create_programmatic_temperature_boundaries — Method
create_programmatic_temperature_boundaries(inner_spec::Tuple, outer_spec::Tuple, cfg)Create a ProgrammaticBoundarySet for temperature from programmatic specifications.
Arguments
inner_spec: Tuple specifying inner boundary, e.g.(:uniform, 100.0)outer_spec: Tuple specifying outer boundary, e.g.(:uniform, 250.0)cfg: SHTnsKitConfig with grid parameters
Returns
A ProgrammaticBoundarySet{Float64} containing boundary data and BC types.
Examples
bset = create_programmatic_temperature_boundaries((:uniform, 1.0), (:uniform, 0.0), cfg)
bset = create_programmatic_temperature_boundaries((:dirichlet, 1.0), (:neumann, 0.0), cfg)GeoDynamo.bcs.create_time_dependent_programmatic_boundary — Method
create_time_dependent_programmatic_boundary(ylm::Ylm, config, time_span, ntime; kwargs...)Create a time-dependent boundary pattern from a spherical harmonic Yₗᵐ with cosine time modulation. Values are produced on the Gauss-Legendre grid.
Example
boundary = create_time_dependent_programmatic_boundary(Ylm(3, 2), config, (0.0, 10.0), 100;
amplitude=0.5, time_factor=2π)GeoDynamo.bcs.determine_field_type_from_name — Method
determine_field_type_from_name(field_name::String) -> FieldTypeDetermine field type from field name string.
GeoDynamo.bcs.enforce_boundary_conditions_in_solution! — Method
enforce_boundary_conditions_in_solution!(solution, state, field_type::FieldType)Enforce boundary conditions in the solution vector after timestepping.
This function ensures that the solution satisfies the boundary conditions after each timestep, which may be necessary for certain discretization schemes.
GeoDynamo.bcs.enforce_composition_bc_in_solution! — Method
enforce_composition_bc_in_solution!(solution, comp_field)Enforce composition boundary conditions in solution vector.
GeoDynamo.bcs.enforce_magnetic_bc_in_solution! — Method
enforce_magnetic_bc_in_solution!(solution, magnetic_field)Enforce magnetic field boundary conditions in solution vector.
GeoDynamo.bcs.enforce_temperature_bc_in_solution! — Method
enforce_temperature_bc_in_solution!(solution, temp_field)Enforce temperature boundary conditions in solution vector.
GeoDynamo.bcs.enforce_velocity_bc_in_solution! — Method
enforce_velocity_bc_in_solution!(solution, velocity_field)Enforce velocity boundary conditions in solution vector.
GeoDynamo.bcs.estimate_interpolation_error — Method
estimate_interpolation_error(boundary_data::BoundaryData, target_theta::Vector{T},
target_phi::Vector{T}) where TEstimate interpolation error based on grid resolution differences.
GeoDynamo.bcs.find_boundary_time_index — Method
find_boundary_time_index(boundary_set::BoundaryConditionSet, current_time::Float64)Find the appropriate time index for the current simulation time. Used by field-specific boundary condition modules.
GeoDynamo.bcs.find_grid_indices — Method
find_grid_indices(coords::Vector{T}, target::T; is_periodic::Bool=false) where TFind the two surrounding indices in a coordinate array for interpolation. Handles periodic coordinates (e.g., longitude) if is_periodic=true.
GeoDynamo.bcs.get_bc_vectors_from_field — Method
get_bc_vectors_from_field(field)Extract boundary condition vectors from a field's cache for use in implicit solves.
Returns
A named tuple (inner_real, outer_real, inner_imag, outer_imag) where each element is either a Vector{T} of length nlm or nothing if no file BCs are loaded.
GeoDynamo.bcs.get_boundary_condition_summary — Method
get_boundary_condition_summary(𝔽, field_type::FieldType)Get a summary of the current boundary condition state.
GeoDynamo.bcs.get_boundary_data — Method
get_boundary_data(field, field_type::FieldType)Get boundary data from field using unified interface with fallback support.
GeoDynamo.bcs.get_boundary_statistics — Method
get_boundary_statistics(boundary_data::BoundaryData)Get statistical information about boundary data.
GeoDynamo.bcs.get_cached_data — Method
get_cached_data(cache::BoundaryCache{T}, key::String) where TRetrieve cached boundary data.
GeoDynamo.bcs.get_comm — Method
get_comm()Get MPI communicator, initializing MPI if needed. Always returns a valid communicator (never nothing).
GeoDynamo.bcs.get_current_boundaries — Method
get_current_boundaries(field, field_type::FieldType)Get current boundary values for any field type.
GeoDynamo.bcs.get_current_simulation_time — Method
get_current_simulation_time(solver_state)Extract current simulation time from solver state.
GeoDynamo.bcs.get_default_boundary_type — Method
get_default_boundary_type(field_type::FieldType, location::BoundaryLocation) -> BoundaryTypeGet default boundary condition type for a field at a specific location.
GeoDynamo.bcs.get_default_units — Method
get_default_units(field_type::FieldType) -> StringGet default units for a field type.
GeoDynamo.bcs.get_field_from_state — Method
get_field_from_state(state, field_type::FieldType)Extract the appropriate field from simulation state.
GeoDynamo.bcs.get_interpolation_statistics — Method
get_interpolation_statistics(boundary_data::BoundaryData, interpolated_data::Array{T}) where TCompute statistics comparing original and interpolated data.
GeoDynamo.bcs.get_interpolation_weights — Method
get_interpolation_weights(coords::Vector{T}, target::T, indices::Tuple{Int, Int};
is_periodic::Bool=false) where TCalculate interpolation weights for linear interpolation. Handles periodic wrapping when is_periodic=true and indices wrap around (e.g., (n, 1)).
GeoDynamo.bcs.get_netcdf_file_info — Method
get_netcdf_file_info(filename::String)Get information about a NetCDF boundary condition file.
GeoDynamo.bcs.get_nprocs — Method
get_nprocs()Get number of MPI processes (with fallback).
GeoDynamo.bcs.get_rank — Method
get_rank()Get MPI rank (with fallback).
GeoDynamo.bcs.get_time_index — Method
get_time_index(field, field_type::FieldType)Get current time index from field using unified interface with fallback support.
GeoDynamo.bcs.initialize_boundary_conditions! — Method
initialize_boundary_conditions!(𝔽, field_type::FieldType)Initialize boundary condition support for a field structure.
IMPORTANT: The field structure must already have the following fields defined:
- boundaryconditionset (can be nothing)
- boundaryinterpolationcache (Dict{String, Any})
- boundarytimeindex (Ref{Int})
For scalar fields (TEMPERATURE, COMPOSITION):
- bctypeinner, bctypeouter (Vector{Int})
- boundary_values (Matrix)
For vector fields (VELOCITY, MAGNETIC):
- toroidal and poloidal components, each with bctypeinner, bctypeouter, boundary_values
Note: The field struct must be a mutable struct since this function modifies its fields.
GeoDynamo.bcs.interpolate_boundary_to_grid — Method
interpolate_boundary_to_grid(boundary_data::BoundaryData, target_theta::Vector{T},
target_phi::Vector{T}, time_index::Int=1) where TInterpolate boundary data to a target grid using bilinear interpolation.
GeoDynamo.bcs.interpolate_with_cache — Function
interpolate_with_cache(boundary_data::BoundaryData, cache::Dict, time_index::Int=1)Perform interpolation using pre-computed cache for efficiency.
GeoDynamo.bcs.load_composition_boundaries_from_files — Method
load_composition_boundaries_from_files(inner_file::String, outer_file::String, cfg)Load composition boundary conditions from two NetCDF files.
GeoDynamo.bcs.load_spectral_bc_from_file — Method
load_spectral_bc_from_file(filename::String, config; format::Symbol=:physical, T::Type=Float64)Load boundary conditions from a NetCDF file and return spectral coefficients.
Arguments
filename: Path to the NetCDF fileconfig: SHTnsKitConfig (or any object withlmax,mmax,nlmfields)format::physicalfor physical-space data,:spectralfor pre-computed coefficientsT: Numeric type for the coefficients (default Float64)
NetCDF File Formats
Physical format (:physical):
- Variables:
"inner"[nlat, nlon] and/or"outer"[nlat, nlon] - Or a single variable with 3rd dimension of size 2:
"temperature"nlat, nlon, 2
Spectral format (:spectral, Fortran-compatible):
- Variables:
"Cbc_Re"[2, nlm] and"Cbc_Im"[2, nlm] - Row 1 = inner boundary, Row 2 = outer boundary
Returns
SpectralBoundaryCoefficients{T}with spectral BC data
GeoDynamo.bcs.load_temperature_boundaries_from_files — Method
load_temperature_boundaries_from_files(inner_file::String, outer_file::String, cfg)Load temperature boundary conditions from two NetCDF files.
GeoDynamo.bcs.log_boundary_condition_status — Function
log_boundary_condition_status(state, rank::Int=0)Log the status of all boundary conditions in the simulation state.
GeoDynamo.bcs.print_boundary_data_info — Function
print_boundary_data_info(boundary_data::BoundaryData, prefix::String="")Print detailed information about boundary data.
GeoDynamo.bcs.print_boundary_info — Method
print_boundary_info(boundary_set::BoundaryConditionSet)Print comprehensive information about a boundary condition set.
GeoDynamo.bcs.print_boundary_summary — Method
print_boundary_summary(field, field_type::FieldType)Print a summary of loaded boundary conditions for any field type.
GeoDynamo.bcs.read_netcdf_boundary_data — Method
read_netcdf_boundary_data(filename::String; precision::Type{T}=Float64) where TRead boundary condition data from a NetCDF file.
Returns a BoundaryData structure containing all boundary information.
GeoDynamo.bcs.reset_boundary_conditions! — Method
reset_boundary_conditions!(𝔽, field_type::FieldType)Reset/clear boundary conditions for a field.
GeoDynamo.bcs.shtns_physical_to_spectral — Method
shtns_physical_to_spectral(physical_data::Matrix{T}, config; return_complex::Bool=false) where TTransform physical boundary data to spectral coefficients using SHTnsKit. This is a common utility function used by both thermal and composition modules.
Arguments
physical_data: 2D array of physical values on (nlat, nlon) gridconfig: SHTnsKit configuration with lmax, mmax, nlm fieldsreturn_complex: If true, returns complex coefficients; otherwise real part only
Returns
Vector of spectral coefficients of length nlm.
Performance (v1.1.15)
Uses cached SHTnsKit configurations to avoid repeated setup overhead.
GeoDynamo.bcs.shtns_spectral_to_physical — Method
shtns_spectral_to_physical(coeffs::Vector, config, nlat::Int, nlon::Int)Transform spectral coefficients to physical boundary data using SHTnsKit. Inverse of shtnsphysicalto_spectral.
Arguments
coeffs: Vector of spectral coefficients of length nlmconfig: SHTnsKit configuration with lmax, mmax fieldsnlat, nlon: Output grid dimensions
Returns
Matrix of physical values on (nlat, nlon) grid.
GeoDynamo.bcs.smooth_boundary_data — Method
smooth_boundary_data(boundary_data::BoundaryData, smoothing_radius::Real)Apply spatial smoothing to boundary data.
GeoDynamo.bcs.store_bc_in_field! — Method
store_bc_in_field!(field, bc_coeffs::SpectralBoundaryCoefficients)Store spectral boundary coefficients into a field's boundary_interpolation_cache. The field must have a boundary_interpolation_cache::Dict{String, Any} attribute.
After calling this, get_bc_vectors_from_field(field) will return the stored vectors.
GeoDynamo.bcs.update_boundary_conditions_for_timestep! — Method
update_boundary_conditions_for_timestep!(state, current_time::Float64)Update all boundary conditions for the current timestep.
This function should be called at the beginning of each timestep to ensure all fields have up-to-date boundary conditions.
GeoDynamo.bcs.update_time_dependent_boundaries! — Method
update_time_dependent_boundaries!(field, field_type::FieldType, current_time::Float64)Update time-dependent boundary conditions for any field type.
GeoDynamo.bcs.validate_boundary_compatibility — Method
validate_boundary_compatibility(inner::BoundaryData, outer::BoundaryData, field_name::String)Validate that inner and outer boundary data are compatible.
GeoDynamo.bcs.validate_boundary_files — Method
validate_boundary_files(field_type::FieldType, boundary_specs::Dict, config)Validate boundary condition files for any field type.
GeoDynamo.bcs.validate_field_boundary_compatibility — Method
validate_field_boundary_compatibility(𝔽, field_type::FieldType, boundary_set::BoundaryConditionSet)Validate that a field structure is compatible with boundary conditions.
GeoDynamo.bcs.validate_interpolation_grids — Method
validate_interpolation_grids(src_theta::Vector, src_phi::Vector,
tgt_theta::Vector, tgt_phi::Vector)Validate that source and target grids are compatible for interpolation.
GeoDynamo.bcs.validate_netcdf_boundary_file — Function
validate_netcdf_boundary_file(filename::String, required_vars::Vector{String}=[])Validate that a NetCDF boundary condition file has the required structure.
GeoDynamo.bcs.write_netcdf_boundary_data — Method
write_netcdf_boundary_data(filename::String, boundary_data::BoundaryData)Write boundary condition data to a NetCDF file.
Boundary Topography
The topography submodule provides linearized boundary topography coupling.
At a Glance
GeoDynamo.bcs.topography
├── enable_topography! # Turn on coupling
├── disable_topography! # Turn off coupling
├── is_topography_enabled # Check status
├── TopographyCouplingConfig # Configuration struct
├── TopographyField # Topography data
├── GauntTensorCache # Coupling coefficients
└── precompute_gaunt_tensors! # Compute tensorsGeoDynamo.bcs.topography.BoundaryDerivativeCache — Type
BoundaryDerivativeCache{T}Cache of boundary values and radial derivatives for a spectral field. All values are stored for m >= 0 (SHTnsKit triangular indexing) and are expanded to negative m using conjugate symmetry.
GeoDynamo.bcs.topography.GauntTensorCache — Type
GauntTensorCache(lmax, lmax_topo; nth=0, nph=0)
GauntTensorCache{T}Cache for pre-computed Gaunt tensor integrals used in topography mode coupling.
Gaunt integrals arise from triple products of spherical harmonics:
\[G_{\ell m, \ell' m', LM} = \int Y_\ell^{m*} Y_{\ell'}^{m'} Y_L^{M} d\Omega\]
This cache stores three types of Gaunt tensors:
- G: Basic Gaunt integrals for shift terms
- G_∇: Gradient Gaunt integrals G^{(∇)} for slope terms
- G_cross: Cross Gaunt integrals G^{(×)} for tangential coupling
Arguments
lmax::Int: Maximum spherical harmonic degree for field variableslmax_topo::Int: Maximum degree for topography expansionnth::Int=0: Number of θ quadrature points (auto if 0)nph::Int=0: Number of φ quadrature points (auto if 0)
Example
gaunt = GauntTensorCache(64, 16)
precompute_gaunt_tensors!(gaunt)See also: precompute_gaunt_tensors!, get_gaunt_tensor
GeoDynamo.bcs.topography.GauntTensorCache — Method
GauntTensorCache{T}(lmax::Int, lmax_topo::Int; nth::Int=0, nph::Int=0) where TCreate a Gaunt tensor cache with SHTnsKit configuration.
Arguments
lmax::Int: Maximum spherical harmonic degree for fieldslmax_topo::Int: Maximum degree for topographynth::Int: Number of theta points (default: 2*max(lmax,lmax_topo) + 2)nph::Int: Number of phi points (default: 2*nth)
GeoDynamo.bcs.topography.StefanState — Type
StefanState(; kwargs...)
StefanState{T}Stefan condition state for tracking ICB (inner core boundary) evolution.
The Stefan condition relates the rate of phase boundary motion to the heat flux discontinuity across the interface:
\[\rho L \frac{\partial h_i}{\partial t} = k_{oc} \frac{\partial T}{\partial n}\bigg|_{oc} - k_{ic} \frac{\partial T}{\partial n}\bigg|_{ic}\]
This structure tracks the ICB topography evolution including latent heat release and optional Clapeyron slope corrections.
Keyword Arguments
lmax::Int=32: Maximum spherical harmonic degreeri::Float64=0.35: Inner core radius (nondimensional)k_ic::Float64=1.0: Inner core thermal conductivityk_oc::Float64=1.0: Outer core thermal conductivityrho::Float64=1.0: Density at ICBL::Float64=1.0: Latent heat of fusionuse_clapeyron::Bool=false: Include Clapeyron slope correctionclapeyron_slope::Float64=0.0: Clapeyron slope dT_m/dP (K/Pa)
Example
state = StefanState(lmax=64, ri=0.35, k_ic=2.0, k_oc=1.0)See also: initialize_stefan_state!, update_icb_topography!
GeoDynamo.bcs.topography.StefanState — Method
StefanState{T}(; lmax=32, ri=0.35, kwargs...) where TCreate an uninitialized Stefan state with default parameters.
Arguments
lmax::Int=32: Maximum spherical harmonic degreeri::Float64: Inner core radiusk_ic::Float64=1.0: Inner core thermal conductivity (nondimensional)k_oc::Float64=1.0: Outer core thermal conductivity (nondimensional)rho::Float64=1.0: Density (nondimensional)L::Float64=1.0: Latent heat (nondimensional)use_clapeyron::Bool=false: Include Clapeyron correctionclapeyron_slope::Float64=0.0: Clapeyron slope dT_m/dP
GeoDynamo.bcs.topography.TopographyCouplingConfig — Type
TopographyCouplingConfigConfiguration structure for enabling/disabling topography coupling.
Fields
enabled::Bool: Master switch for all topography coupling (default: false)velocity_coupling::Bool: Enable velocity BC topography correctionsmagnetic_coupling::Bool: Enable magnetic BC topography correctionsthermal_coupling::Bool: Enable thermal BC topography correctionsstefan_enabled::Bool: Enable Stefan condition for ICB evolutioninclude_shift_terms::Bool: Include O(εh) shift terms (more accurate but slower)include_slope_terms::Bool: Include O(ε∇h) slope terms (required for coupling)epsilon::Float64: Topography amplitude parameter ε (default: 0.01)lmax_topo::Int: Maximum degree for topography expansion (default: same as simulation)
Example
config = TopographyCouplingConfig(
enabled = true,
velocity_coupling = true,
magnetic_coupling = true,
epsilon = 0.02
)See also: enable_topography!, get_topography_config
GeoDynamo.bcs.topography.TopographyData — Type
TopographyData
TopographyData{T}Complete topography data container for both ICB and CMB boundaries.
This structure holds the spectral topography fields for inner and outer boundaries, along with pre-computed Gaunt tensor caches for efficient mode coupling calculations.
Fields
icb::Union{TopographyField, Nothing}: Inner core boundary (ICB) topographycmb::Union{TopographyField, Nothing}: Core-mantle boundary (CMB) topographygaunt_cache::Union{GauntTensorCache, Nothing}: Pre-computed Gaunt tensorsepsilon::Float64: Topography amplitude parameter εis_time_dependent::Bool: Whether topography evolves (e.g., Stefan condition)
Example
topo_data = TopographyData{Float64}(icb_field, cmb_field, gaunt, 0.02, false)See also: TopographyField, create_topography_data, GauntTensorCache
GeoDynamo.bcs.topography.TopographyData — Method
TopographyData{T}() where TCreate empty TopographyData with no topography.
GeoDynamo.bcs.topography.TopographyField — Type
TopographyField(lmax, mmax, radius, location)
TopographyField{T}Spectral representation of boundary topography h(θ, φ) expanded in spherical harmonics.
The topography is represented as:
\[h(\theta, \phi) = \sum_{L=0}^{L_{max}} \sum_{M=-L}^{L} h_{LM} Y_L^M(\theta, \phi)\]
Arguments
lmax::Int: Maximum spherical harmonic degree Lmmax::Int: Maximum azimuthal order M (capped at lmax)radius::Float64: Reference boundary radiuslocation::BoundaryLocation:INNER_BOUNDARY(ICB) orOUTER_BOUNDARY(CMB)
Fields
radius: Reference radius of the boundarylmax,mmax: Maximum degree and ordernlm: Total number of spectral coefficientscoeffs_real,coeffs_imag: Real and imaginary parts of h_{LM}location: Boundary location enumrms_amplitude,max_amplitude: Topography statistics
Example
topo = TopographyField(32, 32, 0.35, INNER_BOUNDARY)See also: TopographyData, set_topography_coefficients!
GeoDynamo.bcs.topography.TopographyField — Method
TopographyField{T}(lmax::Int, mmax::Int, radius::T, location::BoundaryLocation) where TCreate an empty TopographyField with zero coefficients.
GeoDynamo.bcs.topography.__apply_∂r! — Method
__apply_∂r!(output, matrix, input)Local banded-matrix apply for derivative operators.
GeoDynamo.bcs.topography._compute_gradient_fallback — Method
_compute_gradient_fallback(l, m, cache)Fallback gradient computation using finite differences on the Y_l^m grid.
GeoDynamo.bcs.topography._gauss_legendre_point — Method
_gauss_legendre_point(n, i)Compute the i-th Gauss-Legendre quadrature point and weight for n points.
GeoDynamo.bcs.topography._get_gauss_legendre_from_shtns — Method
_get_gauss_legendre_from_shtns(sht_config, nlat)Extract Gauss-Legendre quadrature points and weights. SHTnsKit uses Gauss-Legendre points internally.
GeoDynamo.bcs.topography._wigner_3j — Method
_wigner_3j(l1, l2, l3, m1, m2, m3)Compute Wigner 3j symbol using Racah formula.
GeoDynamo.bcs.topography.apply_all_topography_corrections! — Method
apply_all_topography_corrections!(fields, topography, config)Apply all enabled topography corrections to the simulation fields.
This is the main entry point for applying topography coupling during the simulation timestep.
Arguments
fields: Named tuple or struct containing velocity, magnetic, temperature fieldstopography: TopographyData containing ICB and CMB topographyconfig: TopographyCouplingConfig (optional, uses global if not provided)
GeoDynamo.bcs.topography.apply_clapeyron_correction! — Method
apply_clapeyron_correction!(state::StefanState{T}, pressure_field) where TApply Clapeyron slope correction to the melting temperature at ICB.
The melting temperature varies with pressure: Tm(P) = Tm0 + (dT_m/dP) ΔP
This modifies the effective temperature boundary condition at the ICB.
GeoDynamo.bcs.topography.apply_composition_topography_correction! — Method
apply_composition_topography_correction!(composition_field, topography::TopographyData,
config::TopographyCouplingConfig)Apply topography corrections to compositional boundary conditions.
Composition follows the same mathematical structure as temperature, so we can reuse the thermal correction functions.
GeoDynamo.bcs.topography.apply_magnetic_correction_at_boundary! — Method
apply_magnetic_correction_at_boundary!(poloidal, toroidal, topo_field,
gaunt, ε, config, location, bc_type)Apply magnetic topography corrections at a specific boundary.
Arguments
bc_type: :insulatinginner, :insulatingouter, or :conducting_inner
GeoDynamo.bcs.topography.apply_magnetic_topography_correction! — Method
apply_magnetic_topography_correction!(magnetic_field, topography::TopographyData,
config::TopographyCouplingConfig)Apply topography corrections to magnetic boundary conditions.
This modifies the boundary values of the magnetic field's poloidal and toroidal components to account for topographic coupling.
Arguments
magnetic_field: SHTnsMagneticFields or similar structure with toroidal/poloidal fieldstopography: TopographyData containing ICB and/or CMB topographyconfig: TopographyCouplingConfig with coupling parameters
GeoDynamo.bcs.topography.apply_thermal_correction_at_boundary! — Method
apply_thermal_correction_at_boundary!(spectral, cache, boundary_values,
bc_inner, bc_outer, topo_field,
gaunt, ε, config, location, T_cond)Apply thermal topography corrections at a specific boundary.
GeoDynamo.bcs.topography.apply_thermal_topography_correction! — Method
apply_thermal_topography_correction!(temperature_field, topography::TopographyData,
config::TopographyCouplingConfig;
T_cond::Union{Function, Nothing}=nothing)Apply topography corrections to thermal boundary conditions.
Arguments
temperature_field: SHTnsTemperatureField or similar scalar field structuretopography: TopographyData containing ICB and/or CMB topographyconfig: TopographyCouplingConfig with coupling parametersT_cond: Optional conductive temperature profile function T_cond(r)
GeoDynamo.bcs.topography.apply_velocity_correction_at_boundary! — Method
apply_velocity_correction_at_boundary!(poloidal, toroidal, topo_field,
gaunt, ε, config, location)Apply velocity topography corrections at a specific boundary.
GeoDynamo.bcs.topography.apply_velocity_topography_correction! — Method
apply_velocity_topography_correction!(velocity_field, topography::TopographyData,
config::TopographyCouplingConfig)Apply topography corrections to velocity boundary conditions.
This modifies the boundary values of the velocity field's poloidal and toroidal components to account for topographic coupling.
Arguments
velocity_field: SHTnsVelocityFields or similar structure with toroidal/poloidal fieldstopography: TopographyData containing ICB and/or CMB topographyconfig: TopographyCouplingConfig with coupling parameters
GeoDynamo.bcs.topography.assemble_magnetic_boundary_operator — Method
assemble_magnetic_boundary_operator(l::Int, topo::TopographyField{T},
gaunt::GauntTensorCache{T},
config::TopographyCouplingConfig,
location::BoundaryLocation) where TAssemble the magnetic boundary condition operator matrix row for mode l.
Returns a sparse representation of coupling coefficients.
Arguments
l: Target spherical harmonic degreetopo: Topography field at boundarygaunt: Gaunt tensor cacheconfig: Coupling configurationlocation: INNERBOUNDARY (ICB) or OUTERBOUNDARY (CMB)
GeoDynamo.bcs.topography.assemble_thermal_boundary_operator — Method
assemble_thermal_boundary_operator(l::Int, topo::TopographyField{T},
gaunt::GauntTensorCache{T},
config::TopographyCouplingConfig,
bc_type::Symbol) where TAssemble the thermal boundary condition operator matrix row for mode l.
Arguments
l: Target spherical harmonic degreetopo: Topography field at boundarygaunt: Gaunt tensor cacheconfig: Coupling configurationbc_type: :dirichlet or :neumann
GeoDynamo.bcs.topography.assemble_velocity_boundary_operator — Method
assemble_velocity_boundary_operator(l::Int, topo::TopographyField{T},
gaunt::GauntTensorCache{T},
config::TopographyCouplingConfig,
bc_type::Symbol) where TAssemble the boundary condition operator matrix row for mode l.
Returns a sparse representation of coupling coefficients to other modes.
Arguments
l: Target spherical harmonic degreetopo: Topography field at boundarygaunt: Gaunt tensor cacheconfig: Coupling configurationbc_type: :impermeability, :noslip, or :stressfree
GeoDynamo.bcs.topography.compute_associated_legendre — Method
compute_associated_legendre(l::Int, m::Int, x::T) where TCompute the associated Legendre polynomial P_l^m(x). Uses the standard normalization (not Schmidt or fully normalized).
GeoDynamo.bcs.topography.compute_boundary_derivative_cache — Method
compute_boundary_derivative_cache(field, ∂r, ∂²r, domain) -> BoundaryDerivativeCacheCompute boundary values and radial derivatives for all modes using the full radial profile (MPI-safe). This is expensive but avoids per-mode Allreduce inside tight coupling loops.
GeoDynamo.bcs.topography.compute_boundary_heat_flux — Method
compute_boundary_heat_flux(temperature_field, topography::TopographyData,
config::TopographyCouplingConfig,
location::BoundaryLocation;
k::Float64=1.0) -> MatrixCompute the heat flux at a topographic boundary.
The normal heat flux on the true surface (to first order) is: qn = -k [∂r T - ε ∇H h · ∇H T + εh ∂_rr T]
Returns heat flux on the (θ, φ) grid.
GeoDynamo.bcs.topography.compute_boundary_heat_flux_spectral — Method
compute_boundary_heat_flux_spectral(temperature_field, r::T, side::Symbol) where TCompute spectral coefficients of heat flux at a boundary.
Arguments
temperature_field: Temperature fieldr: Boundary radiusside: :inner or :outer
Returns vector of spectral coefficients for ∂_r T at the boundary.
GeoDynamo.bcs.topography.compute_cmb_insulating_correction — Method
compute_cmb_insulating_correction(l, m, poloidal, toroidal, topo,
gaunt, ro, config) -> (P_corr, T_corr)Compute topography correction to CMB insulating boundary condition.
Flat-sphere conditions:
- ∂r P{b,ℓm} + (ℓ+1)/ro P{b,ℓm} = 0
- T_{b,ℓm} = 0
With topography, the poloidal condition becomes: [∂r P + (ℓ+1)/ro P]{ℓm} + ε Σ h^o{LM} (α^o ∂_r P + β^o T + γ^o P) = 0
and toroidal: T + εho ∂r T = 0
GeoDynamo.bcs.topography.compute_cross_gaunt_tensor — Method
compute_cross_gaunt_tensor(l1::Int, m1::Int, l2::Int, m2::Int, L::Int, M::Int,
cache::GauntTensorCache{T}) where TCompute the cross Gaunt integral: G^{(×)}{l1,m1,l2,m2,L,M} = ∫ Y{l1}^{m1*} r̂ · (∇H Y{l2}^{m2} × ∇H YL^M) dΩ
This integral couples toroidal and poloidal modes through topography. Uses SHTnsKit for gradient evaluation when available.
GeoDynamo.bcs.topography.compute_dirichlet_thermal_correction — Method
compute_dirichlet_thermal_correction(l, m, spectral, topo, gaunt, rb, config, dTcond_dr)Compute topography correction to Dirichlet thermal BC for mode (l, m).
From PDF equation 38: Θ{ℓm} + ε Σ h^b{LM} G{ℓm,ℓ'm',LM} ∂r Θ{ℓ'm'} = [Tb - Tcond(rb)]{ℓm} - ε Σ h^b{LM} G{ℓm,00,LM} ∂r T_cond
The correction to the RHS involves:
- Shift term: h · ∂_r Θ (couples modes)
- Conductive correction: h · ∂r Tcond (modifies boundary value)
GeoDynamo.bcs.topography.compute_gaunt_from_wigner3j — Method
compute_gaunt_from_wigner3j(l1::Int, m1::Int, l2::Int, m2::Int, L::Int, M::Int)Compute Gaunt coefficient using Wigner 3j symbols (analytic formula).
For the Gaunt integral with conjugate: G = ∫ Y{l1}^{m1*} Y{l2}^{m2} Y_L^M dΩ
Using Yl^{m*} = (-1)^m Yl^{-m}, the formula is: G = (-1)^{m1} * sqrt((2l1+1)(2l2+1)(2L+1)/(4π)) * (l1 l2 L; 0 0 0) * (l1 l2 L; -m1 m2 M)
This is faster than numerical integration for production use.
GeoDynamo.bcs.topography.compute_gaunt_tensor — Method
compute_gaunt_tensor(l1::Int, m1::Int, l2::Int, m2::Int, L::Int, M::Int,
cache::GauntTensorCache{T}) where TCompute the basic Gaunt integral using SHTnsKit for spherical harmonic evaluation: G{l1,m1,l2,m2,L,M} = ∫ Y{l1}^{m1*} Y{l2}^{m2} YL^M dΩ
Uses numerical quadrature on Gauss-Legendre × uniform φ grid.
GeoDynamo.bcs.topography.compute_gradient_gaunt_tensor — Method
compute_gradient_gaunt_tensor(l1::Int, m1::Int, l2::Int, m2::Int, L::Int, M::Int,
cache::GauntTensorCache{T}) where TCompute the gradient Gaunt integral using the analytic identity: G^{(∇)}{l1,m1,l2,m2,L,M} = (1/2)[ℓ2(ℓ2+1) + L(L+1) - ℓ1(ℓ1+1)] G{l1,m1,l2,m2,L,M}
This is more efficient and accurate than numerical gradient computation.
GeoDynamo.bcs.topography.compute_icb_insulating_correction — Method
compute_icb_insulating_correction(l, m, poloidal, toroidal, topo,
gaunt, ri, config) -> (P_corr, T_corr)Compute topography correction to ICB insulating boundary condition.
Flat-sphere conditions:
- ∂r P{b,ℓm} - ℓ/ri P{b,ℓm} = 0
- T_{b,ℓm} = 0
With topography, the poloidal condition becomes: [∂r P - ℓ/ri P]{ℓm} + ε Σ h^i{LM} (α^i ∂_r P + β^i T + γ^i P) = 0
GeoDynamo.bcs.topography.compute_impermeability_correction — Method
compute_impermeability_correction(l, m, poloidal, toroidal, topo,
gaunt, rb, config) -> ComplexCompute the topography correction to the impermeability condition for mode (l, m).
The flat-sphere condition is: uᵣ = ℓ(ℓ+1)/r² P_{ℓm} = 0
With topography: uᵣ - ε(∇H h)·uₜ + εh ∂r uᵣ = 0
In spectral space (schematic): ℓ(ℓ+1)/r² P{ℓm} + ε Σ{LM,ℓ'm'} h{LM} [ G · ∂r(ℓ'(ℓ'+1)/r² P{ℓ'm'}) # shift term - G^{(∇)} · ∂r P{ℓ'm'} # slope term (poloidal) - G^{(×)} · T{ℓ'm'} # slope term (toroidal) ] = 0
GeoDynamo.bcs.topography.compute_neumann_thermal_correction — Method
compute_neumann_thermal_correction(l, m, spectral, topo, gaunt, rb, config,
dTcond_dr, d2Tcond_dr2)Compute topography correction to Neumann thermal BC for mode (l, m).
From PDF equation 39: ∂r Θ{ℓm} - ε Σ h^b{LM} G^{(∇)}{ℓm,ℓ'm',LM} Θ{ℓ'm'} + ε Σ h^b{LM} G{ℓm,ℓ'm',LM} ∂rr Θ{ℓ'm'} = -q{b,ℓm}/k - ∂r Tcond δ{ℓ0}δ{m0} - ε Σ h^b{LM} G{ℓm,00,LM} ∂rr Tcond
The correction involves:
- Slope term: -∇H h · ∇H Θ (gradient coupling)
- Shift term: h · ∂_rr Θ (second derivative coupling)
- Conductive correction: h · ∂rr Tcond
GeoDynamo.bcs.topography.compute_normal_velocity_spectral — Method
compute_normal_velocity_spectral(velocity_field, r::T,
location::BoundaryLocation=OUTER_BOUNDARY) where TCompute spectral coefficients of normal (radial) velocity at a boundary.
uₙ = uᵣ = ℓ(ℓ+1)/r² P at the boundary
Returns vector of spectral coefficients for uᵣ.
GeoDynamo.bcs.topography.compute_noslip_correction — Method
compute_noslip_correction(l, m, poloidal, toroidal, topo,
gaunt, rb, config) -> (Complex, Complex)Compute topography correction to no-slip condition for mode (l, m).
The flat-sphere condition is: uₜ = 0
With topography: uₜ + εh ∂r uₜ = U{b,t}
Returns (poloidalcorrection, toroidalcorrection).
GeoDynamo.bcs.topography.compute_potential_matching_coefficients — Method
compute_potential_matching_coefficients(l::Int, topo::TopographyField{T},
gaunt::GauntTensorCache{T},
location::BoundaryLocation) where TCompute the coefficients for matching the core magnetic field to an external potential field across a topographic boundary.
For an insulating exterior, B = -∇Φ where:
- Φext = Σ a{ℓm} r^{-(ℓ+1)} Yℓ^m (exterior, r > ro)
- Φint = Σ b{ℓm} r^ℓ Yℓ^m (interior, r < ri)
Continuity of B_t at the true surface introduces topography coupling.
GeoDynamo.bcs.topography.compute_stefan_flux — Method
compute_stefan_flux(state::StefanState{T}) -> Vector{Complex{T}}Compute the Stefan flux contribution F_{ℓm} for topography evolution.
F{ℓm} = kic ∂n Θ^{ic}{ℓm} - k ∂n Θ{ℓm}
Returns spectral coefficients of the net heat flux imbalance.
GeoDynamo.bcs.topography.compute_stefan_flux_with_topography — Method
compute_stefan_flux_with_topography(state::StefanState{T}, temperature_ic,
temperature_oc, topo_data::TopographyData,
gaunt::GauntTensorCache{T},
config::TopographyCouplingConfig) where TCompute Stefan flux including topography corrections to the normal derivative.
The linearized normal derivative at r = ri is: ∂n ≈ ∂r - ε ∇H hi · ∇H + εhi ∂rr
This adds coupling between modes through Gaunt tensors.
GeoDynamo.bcs.topography.compute_stressfree_correction — Method
compute_stressfree_correction(l, m, poloidal, toroidal, topo,
gaunt, rb, config) -> ComplexCompute topography correction to stress-free condition for mode (l, m).
The flat-sphere condition is: ∂_r(uₜ/r) = 0
With topography: ∂r(uₜ/r) = (ε/rb)(∇H h) ∂r uᵣ
The RHS involves the slope of topography coupling with radial velocity gradient.
GeoDynamo.bcs.topography.create_random_topography — Method
create_random_topography(spectrum::Function, radius::Float64,
location::BoundaryLocation; lmax::Int=32,
seed::Int=0) -> TopographyFieldCreate random topography with prescribed power spectrum.
Arguments
spectrum: Function l -> power at degree l (e.g., l -> l^(-2) for red spectrum)radius: Boundary radiuslocation: INNERBOUNDARY or OUTERBOUNDARYlmax: Maximum degreeseed: Random seed (0 for no seed)
Example
# Create topography with l^(-2) spectrum
topo = create_random_topography(l -> 1.0/max(l,1)^2, 1.0, OUTER_BOUNDARY)GeoDynamo.bcs.topography.create_spherical_harmonic_topography — Method
create_spherical_harmonic_topography(l::Int, m::Int, amplitude::Float64,
radius::Float64, location::BoundaryLocation;
lmax::Int=32) -> TopographyFieldCreate single spherical harmonic topography h = amplitude * Y_l^m(θ, φ). For m >= 0, sets the real (cosine) part. For m < 0, sets the imaginary (sine) part via conjugate symmetry, since only |m| entries are stored.
GeoDynamo.bcs.topography.create_topography_data — Method
create_topography_data(; icb_coeffs=nothing, cmb_coeffs=nothing,
icb_radius=nothing, cmb_radius=nothing,
lmax=32, mmax=32, epsilon=0.01) -> TopographyDataCreate TopographyData from spectral coefficients.
Arguments
icb_coeffs: Complex vector of ICB topography coefficients h_{LM}cmb_coeffs: Complex vector of CMB topography coefficients h_{LM}icb_radius: Inner boundary radius (default: from parameters)cmb_radius: Outer boundary radius (default: from parameters)lmax, mmax: Maximum spherical harmonic degree/orderepsilon: Topography amplitude parameter
Example
# Create CMB topography with degree-2 pattern
cmb_h = zeros(ComplexF64, 6)
cmb_h[lm_to_index(2, 0, 32)] = 0.1 # h_{2,0}
topo = create_topography_data(cmb_coeffs=cmb_h, cmb_radius=1.0, lmax=32)GeoDynamo.bcs.topography.create_uniform_topography — Method
create_uniform_topography(amplitude::Float64, radius::Float64,
location::BoundaryLocation; lmax::Int=32) -> TopographyFieldCreate uniform (degree-0) topography h = amplitude everywhere.
GeoDynamo.bcs.topography.disable_topography! — Method
disable_topography!()Disable all topography coupling.
GeoDynamo.bcs.topography.enable_topography! — Method
enable_topography!(; kwargs...)Enable topography coupling with optional configuration.
Arguments
epsilon::Float64=0.01: Topography amplitude parametervelocity::Bool=true: Enable velocity couplingmagnetic::Bool=true: Enable magnetic couplingthermal::Bool=true: Enable thermal couplingstefan::Bool=false: Enable Stefan conditionslope_terms::Bool=true: Include slope termsshift_terms::Bool=true: Include shift termslmax_topo::Int=-1: Maximum topography degree (-1 for auto)
Example
enable_topography!(epsilon=0.05, stefan=true)GeoDynamo.bcs.topography.evaluate_spherical_harmonic_gradient_grid — Method
evaluate_spherical_harmonic_gradient_grid(l::Int, m::Int, cache::GauntTensorCache{T}) where TEvaluate ∇H Yl^m on the Gauss-Legendre × uniform φ grid using SHTnsKit.
Returns (∇θ, ∇φ) matrices of complex values.
GeoDynamo.bcs.topography.evaluate_spherical_harmonics_grid — Method
evaluate_spherical_harmonics_grid(l::Int, m::Int, cache::GauntTensorCache{T}) where TEvaluate Y_l^m on the Gauss-Legendre × uniform φ grid using SHTnsKit.
Returns a (nlat, nlon) matrix of complex values.
GeoDynamo.bcs.topography.evaluate_topography — Method
evaluate_topography(field::TopographyField{T}, config) where T -> Matrix{T}Evaluate topography in physical space using SHTnsKit synthesis.
Arguments
field: TopographyField containing spectral coefficientsconfig: SHTnsKit configuration for the transform
Returns h(θ, φ) as a nlat × nlon matrix on the Gauss-Legendre grid.
GeoDynamo.bcs.topography.evaluate_topography — Method
evaluate_topography(field::TopographyField{T}, theta::Vector{T},
phi::Vector{T}) where T -> Matrix{T}Evaluate topography in physical space on an arbitrary (θ, φ) grid. This uses direct summation and is slower than the SHTnsKit version.
Returns h(θi, φj) as a nlat × nlon matrix.
GeoDynamo.bcs.topography.evaluate_topography_fallback — Method
evaluate_topography_fallback(field::TopographyField{T}, config) where TFallback evaluation when SHTnsKit synthesis fails.
GeoDynamo.bcs.topography.gaunt_on_the_fly — Method
gaunt_on_the_fly(l1, m1, l2, m2, L, M; use_wigner=true)Compute a single Gaunt coefficient on-the-fly. Useful when only a few coefficients are needed.
GeoDynamo.bcs.topography.gauss_legendre_nodes — Method
gauss_legendre_nodes(n::Int) -> (nodes, weights)Compute Gauss-Legendre quadrature nodes and weights. Returns nodes in [-1, 1] and corresponding weights.
GeoDynamo.bcs.topography.get_coefficient — Method
get_coefficient(field::TopographyField{T}, l::Int, m::Int) where TGet the h_{l,m} coefficient from the topography field.
GeoDynamo.bcs.topography.get_cross_gaunt — Method
get_cross_gaunt(cache::GauntTensorCache{T}, l1, m1, l2, m2, L, M) where TGet the cross Gaunt tensor G^{(×)}_{l1,m1,l2,m2,L,M} from cache.
GeoDynamo.bcs.topography.get_gaunt_tensor — Method
get_gaunt_tensor(cache::GauntTensorCache{T}, l1, m1, l2, m2, L, M) where TGet the basic Gaunt tensor G_{l1,m1,l2,m2,L,M} from cache. Returns 0 if not found (implies zero due to selection rules).
GeoDynamo.bcs.topography.get_gradient_gaunt — Method
get_gradient_gaunt(cache::GauntTensorCache{T}, l1, m1, l2, m2, L, M) where TGet the gradient Gaunt tensor G^{(∇)}_{l1,m1,l2,m2,L,M} from cache.
GeoDynamo.bcs.topography.get_spectral_boundary_value — Function
get_spectral_boundary_value(field, l::Int, m::Int, location::BoundaryLocation=OUTER_BOUNDARY)Get the boundary value of spectral coefficient (l, m).
GeoDynamo.bcs.topography.get_spectral_coefficient — Function
get_spectral_coefficient(field, l::Int, m::Int)Get spectral coefficient (l, m) from a field.
GeoDynamo.bcs.topography.get_spectral_radial_derivative — Function
get_spectral_radial_derivative(field, l::Int, m::Int, r,
location::BoundaryLocation=OUTER_BOUNDARY;
∂r, domain)Compute the radial derivative of spectral coefficient (l, m) at a boundary. Requires access to the radial derivative matrix and domain.
GeoDynamo.bcs.topography.get_stefan_diagnostics — Method
get_stefan_diagnostics(state::StefanState{T}) where TGet diagnostic information about the Stefan condition state.
GeoDynamo.bcs.topography.get_topography_coefficients — Method
get_topography_coefficients(field::TopographyField{T}) -> Vector{Complex{T}}Get complex spectral coefficients from topography field.
GeoDynamo.bcs.topography.get_topography_config — Method
get_topography_config() -> TopographyCouplingConfigGet the current topography coupling configuration.
GeoDynamo.bcs.topography.gradient_gaunt_from_basic — Method
gradient_gaunt_from_basic(l1::Int, l2::Int, L::Int, G_basic::T) where TCompute gradient Gaunt using the identity: G^{(∇)} = (1/2)[ℓ2(ℓ2+1) + L(L+1) - ℓ1(ℓ1+1)] G
This avoids computing gradients explicitly.
GeoDynamo.bcs.topography.index_to_lm — Method
index_to_lm(idx::Int, lmax::Int) -> (l, m)Convert linear index back to (l, m).
GeoDynamo.bcs.topography.initialize_gaunt_cache! — Method
initialize_gaunt_cache!(topo::TopographyData{T}, lmax_field::Int;
precompute::Bool=true) where TInitialize and optionally precompute Gaunt tensor cache for topography coupling.
GeoDynamo.bcs.topography.initialize_stefan_state! — Method
initialize_stefan_state!(state::StefanState{T}, temperature_ic, temperature_oc,
velocity_field; gaunt_cache=nothing) where TInitialize the Stefan state from current field values.
Arguments
state: StefanState to initializetemperature_ic: Inner core temperature field (or spectral coefficients)temperature_oc: Outer core temperature fieldvelocity_field: Velocity field for computing uₙgaunt_cache: Optional pre-computed Gaunt tensors
GeoDynamo.bcs.topography.is_no_slip_boundary — Method
is_no_slip_boundary(field, location::BoundaryLocation) -> BoolCheck if the field uses Dirichlet tangential conditions at the boundary.
GeoDynamo.bcs.topography.is_stress_free_boundary — Method
is_stress_free_boundary(field, location::BoundaryLocation) -> BoolCheck if the field has stress-free boundary conditions at the given location.
GeoDynamo.bcs.topography.is_topography_enabled — Method
is_topography_enabled() -> BoolCheck if topography coupling is enabled.
GeoDynamo.bcs.topography.lm_to_index — Method
lm_to_index(l::Int, m::Int, lmax::Int) -> IntConvert (l, m) to linear index for spectral coefficient storage. Uses the convention: index = l(l+1)/2 + m + 1 for m >= 0
GeoDynamo.bcs.topography.lm_to_spectral_index — Method
lm_to_spectral_index(l::Int, m::Int, config) -> IntConvert (l, m) to spectral array index using SHTnsKit convention.
GeoDynamo.bcs.topography.load_topography_from_array — Method
load_topography_from_array(h_physical::Matrix{T}, radius::Float64,
location::BoundaryLocation, config;
lmax::Int=-1) where TLoad topography from a physical space array h(θ, φ) by transforming to spectral space.
Arguments
h_physical: 2D array of topography values on (θ, φ) gridradius: Boundary radiuslocation: INNERBOUNDARY or OUTERBOUNDARYconfig: SHTnsKit configuration for transformlmax: Maximum degree to retain (-1 for config.lmax)
GeoDynamo.bcs.topography.load_topography_from_file — Method
load_topography_from_file(filename::String, location::BoundaryLocation;
radius::Union{Float64, Nothing}=nothing) -> TopographyFieldLoad topography from a NetCDF file.
Expected NetCDF structure:
- Dimensions: l, m (or lm for 1D storage)
- Variables: hreal, himag (or h for complex)
- Attributes: lmax, radius (optional)
GeoDynamo.bcs.topography.precompute_gaunt_tensors! — Method
precompute_gaunt_tensors!(cache::GauntTensorCache{T};
verbose::Bool=true, use_wigner::Bool=true) where TPrecompute all non-zero Gaunt tensors up to lmax.
Arguments
verbose::Bool=true: Print progress informationuse_wigner::Bool=true: Use analytic Wigner 3j formula (faster and more accurate)
GeoDynamo.bcs.topography.print_stefan_summary — Method
print_stefan_summary(state::StefanState)Print a summary of the Stefan condition state.
GeoDynamo.bcs.topography.print_topography_summary — Method
print_topography_summary(topography::TopographyData)Print a summary of the current topography configuration.
GeoDynamo.bcs.topography.save_topography_to_file — Method
save_topography_to_file(field::TopographyField, filename::String)Save topography field to NetCDF file.
GeoDynamo.bcs.topography.set_topography_coefficients! — Method
set_topography_coefficients!(field::TopographyField{T}, coeffs::Vector) where TSet spectral coefficients for a topography field.
Accepts either:
- Complex vector: splits into real and imaginary parts
- Real vector: sets real parts only (imaginary = 0)
GeoDynamo.bcs.topography.set_topography_config! — Method
set_topography_config!(config::TopographyCouplingConfig)Set the topography coupling configuration.
GeoDynamo.bcs.topography.update_icb_topography! — Method
update_icb_topography!(state::StefanState{T}, dt::T, velocity_field,
temperature_ic, temperature_oc;
topo_data::Union{TopographyData, Nothing}=nothing,
gaunt::Union{GauntTensorCache{T}, Nothing}=nothing,
config::Union{TopographyCouplingConfig, Nothing}=nothing) where TUpdate the ICB topography based on the Stefan condition.
From Eq. 22/40: ε ∂t hi = uₙ + (kic ∂n Tic - k ∂n T) / (ρ L)
or equivalently with Stefan number: ε ∂t hi = uₙ + (1/St) (λ ∂n Θic - ∂_n Θ)
Arguments
state: StefanState to updatedt: Time stepvelocity_field: Current velocity fieldtemperature_ic: Inner core temperaturetemperature_oc: Outer core temperaturetopo_data: Optional TopographyData for coupled evolutiongaunt: Optional Gaunt cache for topography couplingconfig: Optional coupling configuration
GeoDynamo.bcs.topography.update_icb_topography_semiimplicit! — Method
update_icb_topography_semiimplicit!(state::StefanState{T}, dt::T, velocity_field,
temperature_ic, temperature_oc;
theta::T=0.5) where TUpdate ICB topography using a semi-implicit (θ-scheme) time integration.
h^{n+1} = h^n + dt [θ RHS^{n+1} + (1-θ) RHS^n]
where RHS = (1/ε) [uₙ + F/(ρL)]
Arguments
theta::T=0.5: Implicitness parameter (0.5 = Crank-Nicolson, 1.0 = backward Euler)
GeoDynamo.bcs.topography.update_topography_statistics! — Method
update_topography_statistics!(field::TopographyField{T}) where TUpdate RMS and max amplitude statistics for the topography field.
Initial Conditions
The InitialConditions module provides helpers for setting up simulation fields.
At a Glance
GeoDynamo.InitialConditions
├── Scalar Fields
│ ├── set_temperature_ic!
│ ├── set_composition_ic!
│ └── randomize_scalar_field!
│
├── Vector Fields
│ ├── set_velocity_initial_conditions!
│ └── randomize_vector_field!
│
├── Magnetic Field
│ └── randomize_magnetic_field!
│
└── File I/O
├── load_initial_conditions!
└── save_initial_conditionsstate = initialize_simulation(Float64)
set_temperature_ic!(state.temperature; profile = :conductive)
randomize_scalar_field!(state.temperature; amplitude = 1e-3)
randomize_magnetic_field!(state.magnetic; amplitude = 1e-5)GeoDynamo.InitialConditions — Module
InitialConditionsModule for loading and generating initial conditions for geodynamo simulations. Supports loading from NetCDF files, generating random fields, and setting prescribed analytical patterns.
GeoDynamo.InitialConditions.generate_random_composition! — Method
generate_random_composition!(comp_field, amplitude, modes_range)Generate random composition initial conditions with stratified base profile.
Uses PencilArray structure with datareal/dataimag arrays.
GeoDynamo.InitialConditions.generate_random_initial_conditions! — Method
generate_random_initial_conditions!(field, field_type::Symbol;
amplitude=1.0, modes_range=1:10,
seed=nothing)Generate random initial conditions for any field type.
Arguments
field: Field structure to initializefield_type: Type of field (:temperature, :magnetic, :velocity, :composition)amplitude: Overall amplitude of random perturbationsmodes_range: Range of spherical harmonic modes to exciteseed: Random seed for reproducibility (optional)
Examples
# Random temperature field
generate_random_initial_conditions!(temp_field, :temperature, amplitude=0.1)
# Random magnetic field with specific modes
generate_random_initial_conditions!(mag_field, :magnetic,
amplitude=0.01, modes_range=1:20, seed=42)GeoDynamo.InitialConditions.generate_random_magnetic! — Method
generate_random_magnetic!(mag_field, amplitude, modes_range)Generate random magnetic initial conditions with dipolar bias.
Uses PencilArray structure with datareal/dataimag arrays.
GeoDynamo.InitialConditions.generate_random_temperature! — Method
generate_random_temperature!(temp_field, amplitude, modes_range)Generate random temperature initial conditions with base conductive profile and random perturbations.
Uses PencilArray structure with datareal/dataimag arrays.
GeoDynamo.InitialConditions.generate_random_velocity! — Method
generate_random_velocity!(vel_field, amplitude, modes_range)Generate random velocity initial conditions.
Uses PencilArray structure with datareal/dataimag arrays.
GeoDynamo.InitialConditions.load_composition_initial_conditions! — Method
load_composition_initial_conditions!(comp_field, file_path::String)Load composition initial conditions from NetCDF file.
Note: NetCDF loading not yet implemented. Use set_analytical_composition! with :stratified pattern instead.
GeoDynamo.InitialConditions.load_initial_conditions! — Method
load_initial_conditions!(field, field_type::Symbol, file_path::String)Load initial conditions from NetCDF file for any field type.
Arguments
field: Field structure (temperature, magnetic, velocity, or composition type)field_type: Field type (:temperature, :magnetic, :velocity, :composition)file_path: Path to NetCDF file containing initial conditions
File Format
NetCDF files should contain:
- For scalar fields: spectral coefficients array
- For vector fields: toroidal and poloidal spectral coefficients
- Coordinate arrays: lm indices, radial grid
GeoDynamo.InitialConditions.load_magnetic_initial_conditions! — Method
load_magnetic_initial_conditions!(mag_field, file_path::String)Load magnetic initial conditions from NetCDF file.
Note: NetCDF loading not yet implemented. Use set_analytical_magnetic! with :dipole pattern instead.
GeoDynamo.InitialConditions.load_temperature_initial_conditions! — Method
load_temperature_initial_conditions!(temp_field, file_path::String)Load temperature initial conditions from NetCDF file.
Note: NetCDF loading not yet implemented. Use set_analytical_temperature! with :conductive pattern instead.
GeoDynamo.InitialConditions.load_velocity_initial_conditions! — Method
load_velocity_initial_conditions!(vel_field, file_path::String)Load velocity initial conditions from NetCDF file.
Note: NetCDF loading not yet implemented. Use set_analytical_velocity! with :convective pattern instead.
GeoDynamo.InitialConditions.randomize_magnetic_field! — Method
randomize_magnetic_field!(field; amplitude, lmax, domain=nothing)Populate magnetic toroidal/poloidal fields with random perturbations.
GeoDynamo.InitialConditions.randomize_scalar_field! — Method
randomize_scalar_field!(field; amplitude, lmax, domain=nothing)Populate a scalar spectral field (temperature/composition) with random perturbations up to degree lmax. If a radial domain is provided and includes r=0, ball regularity is enforced.
GeoDynamo.InitialConditions.randomize_vector_field! — Method
randomize_vector_field!(field; amplitude, lmax, domain=nothing)Populate velocity-like toroidal/poloidal fields with random perturbations up to degree lmax.
GeoDynamo.InitialConditions.save_initial_conditions — Method
save_initial_conditions(field, field_type::Symbol, file_path::String)Save current field state as initial conditions to NetCDF file.
This function is useful for saving generated or computed initial conditions for later use in simulations.
GeoDynamo.InitialConditions.set_analytical_composition! — Method
set_analytical_composition!(comp_field, pattern, amplitude; parameters...)Set analytical composition patterns.
Uses PencilArray structure with datareal/dataimag arrays.
GeoDynamo.InitialConditions.set_analytical_initial_conditions! — Method
set_analytical_initial_conditions!(field, field_type::Symbol, pattern::Symbol;
amplitude=1.0, parameters...)Set analytical initial conditions based on predefined patterns.
Patterns
:conductive- Conductive temperature profile:dipole- Dipolar magnetic field:convective- Small convective velocity pattern:stratified- Stratified composition profile
Examples
# Conductive temperature profile
set_analytical_initial_conditions!(temp_field, :temperature, :conductive)
# Earth-like dipolar magnetic field
set_analytical_initial_conditions!(mag_field, :magnetic, :dipole, amplitude=1.0)GeoDynamo.InitialConditions.set_analytical_magnetic! — Method
set_analytical_magnetic!(mag_field, pattern, amplitude; parameters...)Set analytical magnetic field patterns.
Uses PencilArray structure with datareal/dataimag arrays.
GeoDynamo.InitialConditions.set_analytical_temperature! — Method
set_analytical_temperature!(temp_field, pattern, amplitude; parameters...)Set analytical temperature patterns.
Uses PencilArray structure with datareal/dataimag arrays.
GeoDynamo.InitialConditions.set_analytical_velocity! — Method
set_analytical_velocity!(vel_field, pattern, amplitude; parameters...)Set analytical velocity patterns.
Uses PencilArray structure with datareal/dataimag arrays.
Spherical Shell Geometry
The GeoDynamoShell module provides shell-specific domain setup.
Overview
CMB (Core-Mantle Boundary)
╱ ╲
╱ Outer Core (Fluid) ╲
╱ ┌─────────────────────┐ ╲
│ │ │ │
│ │ ICB (Inner Core │ │
│ │ Boundary) │ │
│ │ │ │
╲ └─────────────────────┘ ╱
╲ ╱
╲__________________________╱Shell geometry simulates fluid dynamics between two concentric spherical boundaries—like Earth's outer core.
GeoDynamo.GeoDynamoShell.apply_shell_composition_boundaries! — Method
apply_shell_composition_boundaries!(comp_field, boundary_set; time=0)GeoDynamo.GeoDynamoShell.apply_shell_temperature_boundaries! — Method
apply_shell_temperature_boundaries!(temp_field, boundary_set; time=0)Wrapper around core boundary application for shell geometry.
GeoDynamo.GeoDynamoShell.create_shell_composition_field — Method
create_shell_composition_field(T, cfg::ShellConfig; nr=GeoDynamo.i_N)GeoDynamo.GeoDynamoShell.create_shell_hybrid_composition_boundaries — Method
create_shell_hybrid_composition_boundaries(inner_spec, outer_spec, cfg::ShellConfig; precision=Float64)Create composition boundaries for shell geometry. Dispatches to appropriate function based on spec types:
- Both Tuple: fully programmatic boundaries
- String + Tuple: hybrid (one from file, one programmatic)
- Both String: both from files
GeoDynamo.GeoDynamoShell.create_shell_hybrid_temperature_boundaries — Method
create_shell_hybrid_temperature_boundaries(inner_spec, outer_spec, cfg::ShellConfig; precision=Float64)Create temperature boundaries for shell geometry. Dispatches to appropriate function based on spec types:
- Both Tuple: fully programmatic boundaries
- String + Tuple: hybrid (one from file, one programmatic)
- Both String: both from files
GeoDynamo.GeoDynamoShell.create_shell_magnetic_fields — Method
create_shell_magnetic_fields(T, cfg::ShellConfig; nr_oc=GeoDynamo.i_N, nr_ic=GeoDynamo.i_Nic)GeoDynamo.GeoDynamoShell.create_shell_pencils — Method
create_shell_pencils(cfg::ShellConfig; optimize=true)Create a shell-oriented pencil decomposition using the core topology helper.
GeoDynamo.GeoDynamoShell.create_shell_physical_field — Method
create_shell_physical_field(T, cfg::ShellConfig, domain::GeoDynamo.RadialDomain, pencil)GeoDynamo.GeoDynamoShell.create_shell_radial_domain — Function
create_shell_radial_domain(nr=i_N) -> RadialDomainCreate a radial domain suitable for a spherical shell using the global parameter d_rratio for inner radius ratio. This is a thin wrapper over GeoDynamo.create_radial_domain.
GeoDynamo.GeoDynamoShell.create_shell_spectral_field — Method
create_shell_spectral_field(T, cfg::ShellConfig, domain::GeoDynamo.RadialDomain, pencil)GeoDynamo.GeoDynamoShell.create_shell_temperature_field — Method
create_shell_temperature_field(T, cfg::ShellConfig; nr=GeoDynamo.i_N)GeoDynamo.GeoDynamoShell.create_shell_vector_field — Method
create_shell_vector_field(T, cfg::ShellConfig, domain::GeoDynamo.RadialDomain, pencils)GeoDynamo.GeoDynamoShell.create_shell_velocity_fields — Method
create_shell_velocity_fields(T, cfg::ShellConfig; nr=GeoDynamo.i_N)Solid Ball Geometry
The GeoDynamoBall module provides ball-specific domain setup.
Overview
╱‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾╲
╱ ╲
│ Full Sphere │
│ │
│ (No inner core) │
│ │
╲ ╱
╲____________________╱Ball geometry is for full-sphere simulations without an inner boundary—like stellar cores or early planetary interiors.
GeoDynamo.GeoDynamoBall.apply_ball_composition_regularity! — Method
apply_ball_composition_regularity!(comp_field)GeoDynamo.GeoDynamoBall.apply_ball_temperature_regularity! — Method
apply_ball_temperature_regularity!(temp_field)Convenience to enforce scalar regularity on the temperature spectral field. Call after assembling or updating temp_field.spectral.
GeoDynamo.GeoDynamoBall.ball_physical_to_spectral! — Method
ball_physical_to_spectral!(phys::GeoDynamo.SHTnsPhysField,
spec::GeoDynamo.SHTnsSpecField)Wrapper for transforms in a solid sphere that enforces scalar regularity at r=0 after analysis. Use this for scalar fields (temperature, composition, etc.).
GeoDynamo.GeoDynamoBall.ball_vector_analysis! — Method
ball_vector_analysis!(vec::GeoDynamo.SHTnsVectorField,
tor::GeoDynamo.SHTnsSpecField,
pol::GeoDynamo.SHTnsSpecField)Wrapper for vector analysis in a solid sphere; enforces vector regularity at r=0 after transforming to spectral toroidal/poloidal.
GeoDynamo.GeoDynamoBall.create_ball_composition_field — Method
create_ball_composition_field(T, cfg::BallConfig; nr=GeoDynamo.i_N)GeoDynamo.GeoDynamoBall.create_ball_magnetic_fields — Method
create_ball_magnetic_fields(T, cfg::BallConfig; nr=GeoDynamo.i_N)Create magnetic fields for a solid sphere. Since a "core" split is not used in a ball, we pass the same domain for both oc and ic to reuse the core implementation.
GeoDynamo.GeoDynamoBall.create_ball_pencils — Method
create_ball_pencils(cfg::BallConfig; optimize=true)GeoDynamo.GeoDynamoBall.create_ball_physical_field — Method
create_ball_physical_field(T, cfg::BallConfig, domain::GeoDynamo.RadialDomain, pencil)GeoDynamo.GeoDynamoBall.create_ball_radial_domain — Function
create_ball_radial_domain(nr=i_N) -> RadialDomainCreate a radial domain for a solid sphere (inner radius = 0). Uses a cosine-stretched grid similar to the shell for compatibility, but sets the inner radius to zero and adjusts the coordinate columns to match expectations of downstream operators.
GeoDynamo.GeoDynamoBall.create_ball_spectral_field — Method
create_ball_spectral_field(T, cfg::BallConfig, domain::GeoDynamo.RadialDomain, pencil)GeoDynamo.GeoDynamoBall.create_ball_temperature_field — Method
create_ball_temperature_field(T, cfg::BallConfig; nr=GeoDynamo.i_N)GeoDynamo.GeoDynamoBall.create_ball_vector_field — Method
create_ball_vector_field(T, cfg::BallConfig, domain::GeoDynamo.RadialDomain, pencils)GeoDynamo.GeoDynamoBall.create_ball_velocity_fields — Method
create_ball_velocity_fields(T, cfg::BallConfig; nr=GeoDynamo.i_N)GeoDynamo.GeoDynamoBall.enforce_ball_scalar_regularity! — Method
enforce_ball_scalar_regularity!(spec::GeoDynamo.SHTnsSpecField)Enforce scalar regularity at r=0 for solid sphere: for l>0, the scalar amplitude must vanish at r=0. Sets inner radial plane to zero for all nonzero l modes (both real and imaginary parts).
GeoDynamo.GeoDynamoBall.enforce_ball_vector_regularity! — Method
enforce_ball_vector_regularity!(tor_spec::GeoDynamo.SHTnsSpecField,
pol_spec::GeoDynamo.SHTnsSpecField)Enforce vector-field regularity at r=0 for solid sphere. For smooth fields, both toroidal and poloidal potentials behave like r^{l+1}, so they vanish at r=0 for all l ≥ 1. Zeros the inner radial plane for l≥1.
External Dependencies
GeoDynamo.jl builds on these Julia packages:
| Package | Purpose | Documentation |
|---|---|---|
| SHTnsKit.jl | Spherical harmonic transforms | GitHub |
| PencilArrays.jl | Domain decomposition | Docs |
| MPI.jl | Message passing | Docs |
| NetCDF.jl | File I/O | Docs |
See Also
| Topic | Page |
|---|---|
| Parameter configuration | Configuration |
| Time integration | Time Integration |
| Output formats | Data Output |
| Transforms | Spherical Harmonics |
| Development | Developer Guide |