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 structure
Usage
using GeoDynamo

grid = SphericalShellGrid(nr = 64, lmax = 31)
model = GeodynamoModel(grid)
simulation = Simulation(model; Δt = 1e-5, stop_time = 0.02)
state = simulation.model.state

GeoDynamo.bcs.load_boundary_conditions!(state.temperature, GeoDynamo.TEMPERATURE, Dict(
    :inner => (:uniform, 1.0),
    :outer => (:dirichlet, 0.0),
))

Boundary Condition API

GeoDynamo.bcs.load_boundary_conditions!Function
load_boundary_conditions!(field, field_type::FieldType, boundary_specs::Dict)

Unified interface to load boundary conditions for any field type.

Arguments

  • field: Field structure to apply boundary conditions to
  • field_type: Type of field (TEMPERATURE, COMPOSITION, VELOCITY, MAGNETIC)
  • boundary_specs: Dictionary specifying boundary condition sources

Current Behavior

  • For TEMPERATURE and COMPOSITION, this high-level helper accepts programmatic tuple specs like (:uniform, value), (:dirichlet, value), and (:neumann, flux) and immediately embeds them into the field.
  • File-based scalar loading is validated but not applied here because the matrix-embedded BC workflow needs an explicit field-side setup path.
  • VELOCITY and MAGNETIC BCs remain matrix-embedded and are not configured through this helper.

Examples

# Temperature boundaries
load_boundary_conditions!(temp_field, TEMPERATURE, Dict(
    :inner => (:uniform, 1.0),
    :outer => (:dirichlet, 0.0),
))

# Composition boundaries
load_boundary_conditions!(comp_field, COMPOSITION, Dict(
    :inner => (:neumann, 0.0),
    :outer => (:dirichlet, 0.0),
))
source
GeoDynamo.bcs.update_time_dependent_boundaries!Function
update_time_dependent_boundaries!(field, field_type::FieldType, current_time::Float64)

Update time-dependent boundary conditions for any field type.

For scalar fields, this refreshes the active boundary time index and rebuilds the spectral boundary rows from the current physical-space boundary slice. Vector BCs remain matrix-embedded and are therefore rejected if a time-dependent boundary set is attached.

source
GeoDynamo.bcs.validate_boundary_filesFunction
validate_boundary_files(field_type::FieldType, boundary_specs::Dict, config)

Validate boundary condition specifications for any field type.

  • NetCDF file specs are checked with validate_netcdf_boundary_file.
  • Scalar tuple specs are validated via the programmatic boundary parser.
  • Velocity and magnetic BCs reject tuple specs here because their supported configuration path is still the matrix-embedded timestep system.
source
GeoDynamo.bcs.SpectralBoundaryCoefficientsType
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 modes
  • source_file::String: Path to the source file
  • source_format::Symbol: Format used to load (:physical or :spectral)
source
GeoDynamo.bcs.load_spectral_bc_from_fileFunction
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 file
  • config: SHTnsKitConfig (or any object with lmax, mmax, nlm fields)
  • format: :physical for physical-space data, :spectral for pre-computed coefficients
  • T: Numeric type for the coefficients (default Float64)

NetCDF File Formats

Physical format (:physical):

  • Variables: "inner" with shape (nlat, nlon) and/or "outer" with shape (nlat, nlon)
  • Or a single variable with 3rd dimension of size 2: "temperature" with shape (nlat, nlon, 2) (slice 1 = inner, slice 2 = outer)

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
source
GeoDynamo.bcs.store_bc_in_field!Function
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 attribute.

After calling this, get_bc_vectors_from_field(field) will return the stored vectors.

source
GeoDynamo.bcs.get_bc_vectors_from_fieldFunction
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.

source

Boundary Data And File API

GeoDynamo.bcs.create_boundary_dataFunction
create_boundary_data(values::Array{T}, field_type::String; 
                    theta=nothing, phi=nothing, time=nothing,
                    units="", description="", file_path="programmatic") where T

Create a BoundaryData structure from raw data.

source
GeoDynamo.bcs.find_boundary_time_indexFunction
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.

source
GeoDynamo.bcs.read_netcdf_boundary_dataFunction
read_netcdf_boundary_data(filename::String; precision::Type{T}=Float64) where T

Read boundary condition data from a NetCDF file.

Returns a BoundaryData structure containing all boundary information.

source

Boundary Application API

GeoDynamo.bcs.initialize_boundary_conditions!Function
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 (BoundaryInterpolationCache)
  • 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.

source
GeoDynamo.bcs.apply_boundary_conditions!Function
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.

source
GeoDynamo.bcs.copy_boundary_conditions!Function
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.

source
GeoDynamo.bcs.apply_temperature_boundaries!Function
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 to
  • pbs: ProgrammaticBoundarySet containing boundary data and BC types
  • time: Current simulation time (for time-dependent boundaries)
source
GeoDynamo.bcs.apply_composition_boundaries!Function
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!.

source

Boundary Interpolation And Programmatic API

GeoDynamo.bcs.interpolate_boundary_to_gridFunction
interpolate_boundary_to_grid(boundary_data::BoundaryData, target_theta::Vector{T}, 
                            target_phi::Vector{T}, time_index::Int=1) where T

Interpolate boundary data to a target grid using bilinear interpolation.

source
GeoDynamo.bcs.create_interpolation_cacheFunction
create_interpolation_cache(boundary_data::BoundaryData, target_theta::Vector{T}, 
                          target_phi::Vector{T}) where T

Create interpolation cache for efficient repeated interpolations.

source
GeoDynamo.bcs.check_interpolation_boundsFunction
check_interpolation_bounds(boundary_data::BoundaryData, target_theta::Vector{T}, 
                          target_phi::Vector{T}) where T

Check if target grid is within the bounds of the source grid and warn if extrapolation is needed.

source
GeoDynamo.bcs.estimate_interpolation_errorFunction
estimate_interpolation_error(boundary_data::BoundaryData, target_theta::Vector{T}, 
                            target_phi::Vector{T}) where T

Estimate interpolation error based on grid resolution differences.

source
GeoDynamo.bcs.YlmType
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)
source
GeoDynamo.bcs.ProgrammaticBoundarySetType
ProgrammaticBoundarySet{T}

Wrapper around BoundaryConditionSet that also stores BC types for each boundary. Returned by create_programmatic_temperature_boundaries and create_programmatic_composition_boundaries.

source
GeoDynamo.bcs.create_programmatic_boundaryFunction
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)
source
GeoDynamo.bcs.create_time_dependent_programmatic_boundaryFunction
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π)
source
GeoDynamo.bcs.create_programmatic_temperature_boundariesFunction
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)
source
GeoDynamo.bcs.create_hybrid_temperature_boundariesFunction
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.

source
GeoDynamo.bcs.BoundaryInterpolationCacheType
BoundaryInterpolationCache{T}

Typed storage for spectral boundary condition coefficients owned by a field. The string-key accessors keep legacy boundary helper code working, while hot solver paths can read the concrete matrix fields directly.

source
GeoDynamo.bcs._get_cached_bc_shtns_configMethod
_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.

source
GeoDynamo.bcs._parse_boundary_specMethod
_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
source
GeoDynamo.bcs.bilinear_interpolateMethod
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 T

Perform bilinear interpolation on a 2D data array. Handles periodic boundary conditions in phi direction.

source
GeoDynamo.bcs.find_grid_indicesMethod
find_grid_indices(coords::Vector{T}, target::T; is_periodic::Bool=false) where T

Find the two surrounding indices in a coordinate array for interpolation. Handles periodic coordinates (e.g., longitude) if is_periodic=true.

source
GeoDynamo.bcs.get_commMethod
get_comm()

Get MPI communicator, initializing MPI if needed. Always returns a valid communicator (never nothing).

source
GeoDynamo.bcs.get_interpolation_weightsMethod
get_interpolation_weights(coords::Vector{T}, target::T, indices::Tuple{Int, Int};
                          is_periodic::Bool=false) where T

Calculate interpolation weights for linear interpolation. Handles periodic wrapping when is_periodic=true and indices wrap around (e.g., (n, 1)).

source
GeoDynamo.bcs.shtns_physical_to_spectralMethod
shtns_physical_to_spectral(physical_data::Matrix{T}, config; return_complex::Bool=false) where T

Transform 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) grid
  • config: SHTnsKit configuration with lmax, mmax, nlm fields
  • return_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.

source
GeoDynamo.bcs.shtns_spectral_to_physicalMethod
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 nlm
  • config: SHTnsKit configuration with lmax, mmax fields
  • nlat, nlon: Output grid dimensions

Returns

Matrix of physical values on (nlat, nlon) grid.

source