API Reference

This page documents all exported types and functions from AtmosTransport.jl and its submodules.

Architectures

AtmosTransport.ArchitecturesModule
Architectures

CPU and GPU backend abstraction following the Oceananigans.jl pattern.

All architecture-dependent behavior (array allocation, kernel launch, device selection) dispatches on AbstractArchitecture subtypes so that a single codebase runs on both CPU and GPU without branching.

Interface contract

Any new architecture subtype must implement:

  • array_type(arch) → the array constructor (e.g. Array, CuArray)
  • device(arch) → the KernelAbstractions device

GPU-specific methods are defined in ext/AtmosTransportCUDAExt.jl (weak dependency).

source
AtmosTransport.Architectures.GPUType
struct GPU <: AtmosTransport.Architectures.AbstractArchitecture

Run on a GPU device. The concrete array type (e.g. CuArray) and device are provided by the CUDA extension (ext/AtmosTransportCUDAExt.jl).

source

Parameters

AtmosTransport.ParametersModule
Parameters

Type-stable parameter management from TOML configuration files.

Inspired by CliMA/ClimaParams.jl: parameters are read from TOML once, converted to the chosen float type FT, and stored in concrete structs. Downstream code receives these structs (not dictionaries), so all access is type-stable and zero-cost after construction.

Usage

params = load_parameters(Float64)                          # defaults only
params = load_parameters(Float32; override="experiment.toml")  # with overrides
params.planet.radius       # ::Float32, type-stable
params.numerics.cfl_limit  # ::Float32
source
AtmosTransport.Parameters.ModelParametersType
struct ModelParameters{FT, P<:AtmosTransport.Parameters.PlanetParameters{FT}, N<:AtmosTransport.Parameters.NumericsParameters{FT}, S<:AtmosTransport.Parameters.SimulationParameters{FT}}

Top-level container holding all parameter groups. Passed to grid constructors, advection kernels, etc.

  • planet: physical constants of the planet

  • numerics: numerical tuning knobs

  • simulation: run-time simulation settings

source
AtmosTransport.Parameters.PlanetParametersType
struct PlanetParameters{FT}

Physical constants of the planet (Earth by default).

  • radius: planetary radius [m]

  • gravity: gravitational acceleration [m/s²]

  • reference_surface_pressure: reference surface pressure [Pa]

  • kappa_vk: von Kármán constant [-]

  • cp_dry: specific heat of dry air [J/kg/K]

  • rho_ref: reference air density [kg/m³] (ISA sea level)

source
AtmosTransport.Parameters.load_parametersMethod
load_parameters(
    ::Type{FT<:AbstractFloat};
    override,
    defaults
) -> AtmosTransport.Parameters.ModelParameters{FT, _A, _B, _C} where {FT<:AbstractFloat, _A<:AtmosTransport.Parameters.PlanetParameters{FT}, _B<:AtmosTransport.Parameters.NumericsParameters{FT}, _C<:AtmosTransport.Parameters.SimulationParameters{FT}}

Read defaults TOML, merge with optional override TOML, and return a fully type-stable ModelParameters{FT}.

override can be a file path (String) or an already-parsed Dict.

source

Communications

AtmosTransport.CommunicationsModule
Communications

Communication abstraction layer inspired by ClimaComms.jl.

All inter-process communication (halo exchange, reductions) goes through AbstractComms so that single-process and MPI codes share the same physics.

Interface contract

Any new comms subtype must implement:

  • fill_halo!(field, grid, comms) — exchange halo data between neighbors
  • reduce_sum(x, comms) — global sum reduction
  • barrier(comms) — synchronization point
source

Grids

AtmosTransport.GridsModule
Grids

Grid types for atmospheric transport: latitude-longitude and cubed-sphere, with hybrid sigma-pressure vertical coordinates.

All physics code accesses grid properties through generic accessor functions (xnode, ynode, znode, cell_area, cell_volume, Δx, Δy, Δz) that dispatch on AbstractGrid, ensuring grid-agnostic kernels.

Concrete grid types

  • LatitudeLongitudeGrid — regular lat-lon (ERA5/TM5 native)
  • CubedSphereGrid — equidistant gnomonic cubed-sphere (GEOS/MERRA-2 native)

Vertical coordinates

  • HybridSigmaPressure — hybrid σ-p levels (ERA5 137L, MERRA-2 72L, TM5 25-60L)
source
AtmosTransport.Grids.GRID_COORD_STATUSConstant
GRID_COORD_STATUS

Tracks whether grid coordinates were loaded from GMAO files or use default gnomonic coordinates. Keyed by objectid(grid).

Set by _load_gmao_coordinates! in src/IO/configuration.jl. Checked by regrid_latlon_to_cs to warn about potential coordinate mismatches.

source
AtmosTransport.Grids.AbstractStructuredGridType
abstract type AbstractStructuredGrid{FT, Arch} <: AtmosTransport.Grids.AbstractGrid{FT, Arch}

Grids with a logically rectangular structure per region/panel. Both LatitudeLongitudeGrid and CubedSphereGrid are structured.

source
AtmosTransport.Grids.AbstractVerticalCoordinateType
abstract type AbstractVerticalCoordinate{FT}

Supertype for vertical coordinate systems. Parametric on float type FT.

Interface contract

Any subtype must implement:

  • n_levels(vc) — number of vertical levels
  • pressure_at_level(vc, k, p_surface) — pressure at level k given surface pressure
  • level_thickness(vc, k, p_surface) — thickness (in Pa) of level k
source
AtmosTransport.Grids.CubedSphereGridType
struct CubedSphereGrid{FT, Arch, VZ} <: AtmosTransport.Grids.AbstractStructuredGrid{FT, Arch}

Gnomonic equidistant cubed-sphere grid with 6 panels of Nc × Nc cells. Uses the same projection as NASA GEOS-FP/FV3 (Putman & Lin, 2007).

  • architecture: compute architecture (CPU or GPU)

  • Nc: cells per panel edge (e.g. 90 for C90)

  • Nz: number of vertical levels

  • Hp: panel-edge halo width

  • Hz: vertical halo width

  • λᶜ: cell-center longitudes per panel [degrees]

  • φᶜ: cell-center latitudes per panel [degrees]

  • λᶠ: cell-face longitudes per panel (Nc+1 × Nc+1) [degrees]

  • φᶠ: cell-face latitudes per panel (Nc+1 × Nc+1) [degrees]

  • Aᶜ: cell areas per panel [m²] — gnomonic default, overwritten by GMAO when available

  • Δxᶜ: local x metric terms (edge lengths) per panel [m]

  • Δyᶜ: local y metric terms (edge lengths) per panel [m]

  • radius: planet radius [m]

  • gravity: gravitational acceleration [m/s²]

  • reference_pressure: reference surface pressure [Pa]

  • connectivity: panel connectivity

  • vertical: vertical coordinate

source
AtmosTransport.Grids.CubedSphereGridMethod
CubedSphereGrid(
    arch;
    FT,
    Nc,
    vertical,
    halo,
    radius,
    gravity,
    reference_pressure
)

Construct a gnomonic equidistant cubed-sphere grid with Nc cells per panel edge and vertical coordinate.

Grid coordinates, cell areas, and metric terms are computed from the gnomonic (central) projection following the GEOS/FV3 convention. Cell areas are exact spherical areas via Girard's theorem.

Keyword arguments

  • FT: floating-point type (default Float64)
  • Nc: cells per panel edge (e.g. 48, 90, 180)
  • vertical: vertical coordinate (e.g. HybridSigmaPressure)
  • halo: (Hp, Hz) panel-edge and vertical halo widths (default (3, 1))
  • radius: planet radius in meters (default Earth)
  • gravity: gravitational acceleration (default 9.81 m/s²)
  • reference_pressure: reference surface pressure in Pa (default 101325)
source
AtmosTransport.Grids.FlatType
struct Flat <: AtmosTransport.Grids.AbstractTopology

Flat (degenerate) dimension — single grid point, used to reduce dimensionality.

source
AtmosTransport.Grids.HybridSigmaPressureType
struct HybridSigmaPressure{FT} <: AtmosTransport.Grids.AbstractVerticalCoordinate{FT}

Hybrid sigma-pressure coordinate: p(k) = A(k) + B(k) * p_surface.

Vectors A and B have length Nz + 1 (level interfaces / half-levels). Level centers are at the midpoint of adjacent interfaces.

  • A: pressure coefficient at each interface [Pa]

  • B: sigma coefficient at each interface [dimensionless]

source
AtmosTransport.Grids.LatitudeLongitudeGridType
struct LatitudeLongitudeGrid{FT, Arch, VZ, V, RG} <: AtmosTransport.Grids.AbstractStructuredGrid{FT, Arch}

Regular latitude-longitude grid with hybrid sigma-pressure vertical coordinate.

Planet constants (radius, gravity, reference pressure) are stored in the grid so that all accessor functions are self-contained and type-stable. Values come from config/defaults.toml via ModelParameters, or can be overridden in the constructor.

Accessor functions

  • xnode, ynode — horizontal coordinates (longitude, latitude)
  • znode — vertical coordinate (pressure at level/interface center)
  • cell_area, cell_volume — horizontal area and 3D cell volume
  • Δx, Δy, Δz — grid spacing in x, y, and vertical (pressure thickness)
  • architecture: compute architecture (CPU or GPU)

  • Nx: number of grid cells in x (longitude)

  • Ny: number of grid cells in y (latitude)

  • Nz: number of vertical levels

  • Hx: halo width in x

  • Hy: halo width in y

  • Hz: halo width in z

  • λᶜ: cell-center longitudes — device array (length Nx)

  • λᶠ: cell-face longitudes — device array (length Nx+1)

  • φᶜ: cell-center latitudes — device array (length Ny)

  • φᶠ: cell-face latitudes — device array (length Ny+1)

  • Δλ: uniform longitude spacing [degrees]

  • Δφ: uniform latitude spacing [degrees]

  • vertical: vertical coordinate (e.g. HybridSigmaPressure)

  • radius: planet radius [m]

  • gravity: gravitational acceleration [m/s²]

  • reference_pressure: reference surface pressure [Pa]

  • reduced_grid: reduced grid specification for polar CFL handling, or nothing

  • λᶜ_cpu: CPU-cached cell-center longitudes for host-side scalar access

  • λᶠ_cpu: CPU-cached cell-face longitudes for host-side scalar access

  • φᶜ_cpu: CPU-cached cell-center latitudes for host-side scalar access

  • φᶠ_cpu: CPU-cached cell-face latitudes for host-side scalar access

source
AtmosTransport.Grids.PanelConnectivityType
struct PanelConnectivity

Describes how the 6 panels of a cubed-sphere connect at their edges. Each panel has 4 neighbors (north, south, east, west), identified by panel index and orientation (rotation needed to align axes).

  • neighbors: per-panel neighbor info: (north, south, east, west) as (panel, orientation) tuples
source
AtmosTransport.Grids.ReducedGridSpecType
struct ReducedGridSpec

Per-latitude specification of zonal cell clustering for CFL stability.

  • Nx: number of uniform-grid zonal cells

  • cluster_sizes: length-Ny vector; how many fine cells form one reduced cell

  • reduced_counts: length-Ny vector; effective number of zonal cells (Nx / cluster_size)

source
AtmosTransport.Grids._fill_edge!Method

Copy Hp layers of interior data from source panel near edge q_e into the halo of destination panel outside edge e, applying the along-edge orientation mapping.

Dispatches to a GPU kernel for device arrays, or a CPU loop for host arrays.

source
AtmosTransport.Grids._gnomonic_xyzMethod
_gnomonic_xyz(ξ, η, panel)

Map local tangent-plane coordinates (ξ, η) to Cartesian (x, y, z) on the unit sphere via the gnomonic (central) projection for the given panel.

ξ = tan(α), η = tan(β) where α, β ∈ [-π/4, π/4] are the angular coordinates on the cube face.

source
AtmosTransport.Grids.allocate_cubed_sphere_fieldMethod
allocate_cubed_sphere_field(grid)
allocate_cubed_sphere_field(grid, Nz)

Allocate a cubed-sphere 3D field as NTuple{6, Array{FT, 3}} with extended dimensions (Nc + 2*Hp) × (Nc + 2*Hp) × Nz per panel, initialized to zero. Interior indices are [Hp+1:Hp+Nc, Hp+1:Hp+Nc, :].

source
AtmosTransport.Grids.cell_volumeMethod
cell_volume(
    i,
    j,
    k,
    g::AtmosTransport.Grids.LatitudeLongitudeGrid{FT};
    p_surface
) -> Any

Volume of cell (i, j, k) as pressure thickness × area / g. Under hydrostatic balance this gives mass per cell (kg).

source
AtmosTransport.Grids.compute_reduced_gridMethod
compute_reduced_grid(
    Nx::Int64,
    φᶜ::AbstractVector;
    max_cluster
) -> Union{Nothing, AtmosTransport.Grids.ReducedGridSpec}

Auto-compute per-latitude cluster sizes so that the effective zonal spacing Δx_eff ≈ R·Δλ (equatorial value) at every latitude.

Cluster sizes are constrained to be divisors of Nx so that cells divide evenly. max_cluster caps the maximum cluster size (defaults to Nx).

Returns nothing if no reduction is needed (all cluster sizes are 1).

source
AtmosTransport.Grids.copy_corners!Method
copy_corners!(data, grid, dir)

Fill corner ghost cells for a cubed-sphere 3D field. Must be called AFTER fill_panel_halos! (which fills edge halos that corner rotations read from).

dir selects the rotation:

  • dir=1: for X-direction PPM (rotates Y-edge data into corners)
  • dir=2: for Y-direction PPM (rotates X-edge data into corners)
source
AtmosTransport.Grids.default_panel_connectivityMethod
default_panel_connectivity()

Return the GEOS-FP native cubed-sphere panel connectivity.

Panel numbering follows the GEOS-FP file convention (nf=1..6), which differs from the textbook convention. Connectivity and orientations are verified against the corner coordinate data in the native C720 NetCDF files.

Edge-to-edge connections (Panel p edge → Panel q edge): P1 north→P3 west(rev) P1 south→P6 north(aln) P1 east→P2 west(aln) P1 west→P5 north(rev) P2 north→P3 south(aln) P2 south→P6 east(rev) P2 east→P4 south(rev) P2 west→P1 east(aln) P3 north→P5 west(rev) P3 south→P2 north(aln) P3 east→P4 west(aln) P3 west→P1 north(rev) P4 north→P5 south(aln) P4 south→P2 east(rev) P4 east→P6 south(rev) P4 west→P3 east(aln) P5 north→P1 west(rev) P5 south→P4 north(aln) P5 east→P6 west(aln) P5 west→P3 north(rev) P6 north→P1 south(aln) P6 south→P4 east(rev) P6 east→P2 south(rev) P6 west→P5 east(aln)

source
AtmosTransport.Grids.expand_row!Method
expand_row!(c, c_red_new, c_red_old, j, k, r, Nx)

Distribute the change (crednew - credold) uniformly back to the fine cells. Preserves sub-grid structure while conserving the volume-averaged concentration.

source
AtmosTransport.Grids.expand_row_mass!Method
expand_row_mass!(
    rm,
    m,
    rm_red_new,
    rm_red_old,
    m_red_new,
    m_red_old,
    j,
    k,
    r,
    Nx
)

Distribute mass changes from a reduced-grid advection step back to fine cells. Changes in rm and m are distributed proportionally to each fine cell's original mass fraction within the reduced cell, guaranteeing exact conservation of both tracer mass and air mass.

rmfine[i] += (rmrednew[ir] - rmredold[ir]) × (rmold[i] / rmredold[ir]) mfine[i] += (mrednew[ir] - mredold[ir]) × (mold[i] / mredold[ir])

source
AtmosTransport.Grids.fill_cgrid_halos!Method
fill_cgrid_halos!(cx_h, cy_h, cx_src, cy_src, grid)

Fill C-grid halos for face-centered Courant/flux arrays. CY gets i-halos from EAST/WEST neighbors; CX gets j-halos from NORTH/SOUTH neighbors. At cross-type edges, CX and CY are swapped (Nc+1 face values map 1:1 between directions).

cx_h[p] has shape (Nc+1, Nc+2Hp, Nz) with interior at [:, Hp+1:Hp+Nc, :]. cy_h[p] has shape (Nc+2Hp, Nc+1, Nz) with interior at [Hp+1:Hp+Nc, :, :]. cx_src[p] and cy_src[p] are the non-haloed source arrays.

source
AtmosTransport.Grids.fill_panel_halos!Method
fill_panel_halos!(data, grid)

Fill halo regions of a cubed-sphere 3D field by copying interior data from neighboring panels with the correct edge-to-edge mapping and orientation.

data is NTuple{6, Array{FT, 3}} with each panel (Nc + 2*Hp) × (Nc + 2*Hp) × Nz.

source
AtmosTransport.Grids.merge_upper_levelsMethod
merge_upper_levels(vc, merge_above_Pa; min_thickness_Pa=500, p_surface=101325)

Merge thin upper-atmosphere levels above merge_above_Pa into coarser layers with a minimum thickness of min_thickness_Pa. Levels below the threshold are kept unchanged.

Returns (merged_vc, merge_map) where:

  • merged_vc: new HybridSigmaPressure with fewer levels
  • merge_map: Vector{Int} of length n_levels(vc) mapping each native level index to its merged level index (for use in met data regridding)
source
AtmosTransport.Grids.reduce_am_row!Method
reduce_am_row!(am_red, am, j, k, r, Nx)

Pick mass flux am at reduced-grid cell boundaries. am has shape (Nx+1, Ny, Nz); am_red has length Nx_red + 1. The face between reduced cells i_red-1 and i_red corresponds to fine face (i_red - 1) * r + 1.

source
AtmosTransport.Grids.reduce_row!Method
reduce_row!(c_red, c, j, k, r, Nx)

Average r adjacent fine cells into one reduced cell for latitude j, level k. c_red must have length Nx ÷ r.

source
AtmosTransport.Grids.reduce_row_mass!Method
reduce_row_mass!(q_red, q, j, k, r, Nx)

Sum r adjacent fine cells of an extensive field (rm or m) into one reduced cell for latitude j, level k. q_red must have length Nx ÷ r.

source
AtmosTransport.Grids.reduce_velocity_row!Method
reduce_velocity_row!(u_red, u, j, k, r, Nx)

Pick face velocities at reduced-grid cell boundaries. u has shape (Nx+1, Ny, Nz); u_red has length Nx_red + 1. Face ired corresponds to fine face `(ired - 1) * r + 1`.

source
AtmosTransport.Grids.total_sizeFunction

Return the total array size including halo regions for memory allocation.

For LatitudeLongitudeGrid: (Nx + 2*Hx, Ny + 2*Hy, Nz + 2*Hz) — interior dimensions plus halo on both sides of each dimension.

source
AtmosTransport.Grids.xnodeFunction

Horizontal x-coordinate at index (i, j) and location loc (Center or Face). On lat-lon grids this is longitude; on cubed-sphere it is the local panel x-coordinate.

source
AtmosTransport.Grids.ynodeFunction

Horizontal y-coordinate at index (i, j) and location loc. On lat-lon grids this is latitude; on cubed-sphere it is the local panel y-coordinate.

source
AtmosTransport.Grids.znodeFunction

Vertical coordinate at level k and location loc. Returns pressure, sigma, or height depending on the vertical coordinate type.

source
AtmosTransport.Grids.znodeMethod
znode(
    k,
    g::AtmosTransport.Grids.LatitudeLongitudeGrid{FT},
    ::AtmosTransport.Grids.Center;
    p_surface
) -> Any

Pressure (Pa) at vertical level or interface k for reference surface pressure.

source
AtmosTransport.Grids.ΔxMethod

Horizontal x-spacing (m) at cell center (i, j). Uses cell-center latitude φᶜ (TM5 convention). At the poles the grid cell collapses in x; clamped to Δy to prevent CFL violation and division-by-zero. Physical fluxes near poles are small due to v·cos(φ) → 0.

source
AtmosTransport.Grids.ΔzFunction

Vertical grid spacing at level k. Units depend on vertical coordinate (Pa for pressure-based, m for height-based).

source
AtmosTransport.Grids.ΔzMethod
Δz(
    k,
    g::AtmosTransport.Grids.LatitudeLongitudeGrid{FT};
    p_surface
) -> Any

Pressure thickness (Pa) of vertical level k.

source

Fields

AtmosTransport.FieldsModule
Fields

Field types for storing tracer concentrations and meteorological data on grids.

Fields carry their grid, location (Center/Face per dimension), data (with halos), and boundary conditions. Architecture-aware: data lives on CPU or GPU arrays depending on the grid's architecture.

Key types

  • Field{LX, LY, LZ} — a 3D field at a specified staggered location
  • Center, Face — location tags for staggered grids

Key functions

  • set!(field, value) — initialize a field
  • interior(field) — view of interior data (no halos)
  • data(field) — full data including halos
source
AtmosTransport.Fields.AbstractFieldType
abstract type AbstractField{LX, LY, LZ, G}

Supertype for all field types. Parametric on:

  • LX, LY, LZ: location types (Center or Face) per dimension
  • G: grid type
source
AtmosTransport.Fields.FieldType
struct Field{LX, LY, LZ, G, D, B} <: AtmosTransport.Fields.AbstractField{LX, LY, LZ, G}

A 3D field on a grid at a specified staggered location.

Data is stored as an OffsetArray to include halo regions with negative/zero indices, so that stencil operations can index field[i-1, j, k] without bounds checking in the interior.

  • grid: the grid this field lives on

  • _data: underlying data array (OffsetArray including halos)

  • boundary_conditions: boundary conditions attached to this field

source
AtmosTransport.Fields.ValueBCType
struct ValueBC{T} <: AtmosTransport.Fields.AbstractBoundaryCondition

Prescribed value (Dirichlet) boundary condition.

  • value: the prescribed boundary value
source
AtmosTransport.Fields.TracerFieldsMethod
TracerFields(names, grid)

Create a NamedTuple of Fields at (Center, Center, Center) for each tracer name.

Example

tracers = TracerFields((:CO2, :CH4), grid)
tracers.CO2  # a Field{Center, Center, Center}
source
AtmosTransport.Fields.set!Method
set!(f, value)

Set field interior to value. value can be:

  • A scalar (fills uniformly)
  • A function f(x, y, z) evaluated at cell centers
  • An array matching the interior size
source

Advection

AtmosTransport.AdvectionModule
Advection

Advection schemes for tracer transport, each with a paired discrete adjoint.

Every advection scheme dispatches on both the scheme type AND the grid type, so that grid-specific stencils (e.g. cubed-sphere panel boundaries) are handled transparently.

Interface contract for new schemes

advect!(tracers, velocities, grid, scheme::YourScheme, Δt)
adjoint_advect!(adj_tracers, velocities, grid, scheme::YourScheme, Δt)

Optional (has defaults):

advection_cfl(grid, velocities, scheme::YourScheme)
source
AtmosTransport.Advection.AbstractAdvectionSchemeType
abstract type AbstractAdvectionScheme

Supertype for all advection schemes. Each subtype must implement both forward and adjoint methods.

Required methods

advect!(tracers, velocities, grid, scheme, Δt)
adjoint_advect!(adj_tracers, velocities, grid, scheme, Δt)

These may further dispatch on grid type for grid-specific boundary handling.

Directional variants

For operator splitting, directional methods are also needed:

advect_x!(tracers, velocities, grid, scheme, Δt)
advect_y!(tracers, velocities, grid, scheme, Δt)
advect_z!(tracers, velocities, grid, scheme, Δt)

and their adjoints:

adjoint_advect_x!(adj_tracers, velocities, grid, scheme, Δt)
adjoint_advect_y!(adj_tracers, velocities, grid, scheme, Δt)
adjoint_advect_z!(adj_tracers, velocities, grid, scheme, Δt)
source
AtmosTransport.Advection.CSPratherWorkspaceType
struct CSPratherWorkspace{FT, A3h<:AbstractArray{FT, 3}}

Workspace for Prather advection on cubed-sphere grids. Holds prognostic slopes (6 panels each, haloed) plus shared double-buffer arrays.

  • rxm: x-slope panels (haloed, persist across timesteps)

  • rym: y-slope panels (haloed, persist across timesteps)

  • rzm: z-slope panels (haloed, persist across timesteps)

  • rm_buf: double-buffer for rm (single panel, shared)

  • m_buf: double-buffer for m (single panel, shared)

  • rxm_buf: double-buffer for rxm

  • rym_buf: double-buffer for rym

  • rzm_buf: double-buffer for rzm

source
AtmosTransport.Advection.CubedSphereGeometryCacheType
struct CubedSphereGeometryCache{FT, A2<:AbstractArray{FT, 2}, A1<:AbstractArray{FT, 1}}

Device-side geometry cache for cubed-sphere mass-flux advection.

Unlike the lat-lon GridGeometryCache (which stores 1-D area/dy vectors), this stores per-panel 2-D cell area and metric arrays.

  • area: per-panel cell areas [m²], NTuple of Nc×Nc matrices

  • dx: per-panel Δx at cell centers [m], NTuple of Nc×Nc matrices

  • dy: per-panel Δy at cell centers [m], NTuple of Nc×Nc matrices

  • bt: vertical B-ratio for mass-flux closure, length Nz

  • gravity

  • Nc

  • Nz

  • Hp

source
AtmosTransport.Advection.CubedSphereMassFluxWorkspaceType
struct CubedSphereMassFluxWorkspace{FT, A3<:AbstractArray{FT, 3}}

Pre-allocated buffers for cubed-sphere mass-flux advection. One set of haloed buffers is reused across all panels (sequential processing). CFL buffers are sized to the largest flux array per direction.

  • rm_buf: tracer mass buffer (haloed, Nc+2Hp × Nc+2Hp × Nz)

  • m_buf: air mass buffer (haloed, Nc+2Hp × Nc+2Hp × Nz)

  • cfl_x: CFL scratch for x-direction (Nc+1 × Nc × Nz)

  • cfl_y: CFL scratch for y-direction (Nc × Nc+1 × Nz)

  • cfl_z: CFL scratch for z-direction (Nc × Nc × Nz+1)

source
AtmosTransport.Advection.GCHPGridGeometryType
GCHPGridGeometry{FT, A2, A2x, A2y}

Precomputed grid metric terms on GPU for GCHP-faithful fvtp2d. Computed once from the gnomonic projection and uploaded to device.

Fields:

  • area_dev — cell area [m²], shape (Nc, Nc) per panel
  • dxa_dev — cell X-width [m], shape (Nc, Nc) per panel
  • dya_dev — cell Y-width [m], shape (Nc, Nc) per panel
  • dy_dev — Y-edge length at X-faces [m], shape (Nc+1, Nc) per panel
  • dx_dev — X-edge length at Y-faces [m], shape (Nc, Nc+1) per panel
source
AtmosTransport.Advection.GCHPGridGeometryMethod
GCHPGridGeometry(grid::CubedSphereGrid)

Compute GCHP grid geometry from the gnomonic projection and upload to device. Edge lengths (dy at X-faces, dx at Y-faces) are computed from face coordinates via great-circle distance.

NOTE: sin_sg is approximated as 1.0 (exact at panel center, ~5% error at corners). This can be refined later by computing exact great-circle angles.

source
AtmosTransport.Advection.GCHPTransportWorkspaceType
GCHPTransportWorkspace{FT, A3x, A3y}

Runtime workspace for GCHP-faithful transport. Holds area fluxes computed from Courant numbers and grid geometry.

The LinRoodWorkspace (shared buffers: qbuf, fxin, fxout, fyin, fyout, qout, dp_out) is passed separately.

source
AtmosTransport.Advection.GridGeometryCacheType
GridGeometryCache{FT, A1}

Device-side cache of grid geometry vectors that are constant for a given grid. Eliminates repeated host→device transfers of area_j, dy_j, dx_face, and bt that previously occurred on every call to compute_air_mass! / compute_mass_fluxes!.

Construct once with build_geometry_cache, then pass to the in-place compute_air_mass! and compute_mass_fluxes! overloads.

source
AtmosTransport.Advection.PPMAdvectionType
struct PPMAdvection{ORD} <: AtmosTransport.Advection.AbstractPPMScheme

Piecewise Parabolic Method advection scheme (Putman & Lin, 2007).

Parameters

  • ORD ∈ {4, 5, 6, 7}: Subgrid distribution method
    • ORD=4 (Putman & Lin Sec. 4): Optimized PPM (LR96 PPM + minmod)
    • ORD=5 (Putman & Lin Sec. 4): PPM with Huynh's 2nd constraint (quasi-monotonic)
    • ORD=6 (Putman & Lin Appendix B): Quasi-5th order, non-monotonic (better L∞ errors)
    • ORD=7 (Putman & Lin Appendix C): RECOMMENDED — ORD=5 + special edge treatment for gnomonic cubed-sphere face discontinuities

Interface

Like other advection schemes, this supports both forward and adjoint methods, with grid-specific implementations for LatitudeLongitudeGrid and CubedSphereGrid.

For the cubed-sphere mass-flux path (production code), dispatch on Val{ORD} inside kernels for compile-time specialization.

Example

# Create advection scheme with ORD=7 (recommended)
scheme = PPMAdvection{7}()

# Use in run loop (currently not yet integrated with main advect! interface)
# Cubed-sphere mass flux: strang_split_massflux_ppm!(rm, m, am, bm, cm, grid, Val(7), ws)
source
AtmosTransport.Advection.PratherAdvectionType
struct PratherAdvection <: AtmosTransport.Advection.AbstractAdvectionScheme

Prather (1986) second-order moments advection scheme. Carries prognostic slopes (rxm, rym, rzm) alongside tracer mass.

  • use_limiter: apply positivity limits on slopes (|rxm| ≤ rm)
source
AtmosTransport.Advection.PratherWorkspaceType
struct PratherWorkspace{FT, A3<:AbstractArray{FT, 3}}

Workspace holding prognostic slope fields for one tracer + double-buffer outputs.

  • rxm: x-slope of tracer mass

  • rym: y-slope of tracer mass

  • rzm: z-slope of tracer mass

  • rm_buf: double-buffer output for rm

  • m_buf: double-buffer output for air mass

  • rxm_buf: double-buffer output for rxm

  • rym_buf: double-buffer output for rym

  • rzm_buf: double-buffer output for rzm

source
AtmosTransport.Advection.SlopesAdvectionType
struct SlopesAdvection{L} <: AtmosTransport.Advection.AbstractAdvectionScheme

Russell-Lerner slopes advection scheme.

  • use_limiter: enable/disable flux limiter. When off: forward is linear, adjoint is exact (machine precision). When on: monotone but adjoint is approximate (continuous adjoint).
source
AtmosTransport.Advection.VerticalRemapWorkspaceType
VerticalRemapWorkspace{FT, A3, A1}

GPU workspace for conservative PPM vertical remapping.

  • pe_tgt: Target pressure edges from hybrid coords (6 panels, Nc x Nc x Nz+1)
  • dp_tgt: Target layer thickness (6 panels, Nc x Nc x Nz)
  • m_save: Saved air mass before horizontal transport (shared across tracers)
  • ak_dev: Hybrid A coefficients on GPU (Nz+1)
  • bk_dev: Hybrid B coefficients on GPU (Nz+1)
source
AtmosTransport.Advection._interpolate_dry_dp_kernel!Method

Interpolate dry dp from two moist DELP snapshots with temporally interpolated QV. GCHP uses SPHU0 for DryPLE0 and SPHU2 for DryPLE1 (each endpoint uses its own QV). dp = ((1-frac)×delp0 + frac×delp1) × (1 - ((1-frac)×qv0 + frac×qv1))

source
AtmosTransport.Advection._lock_surface_pe_kernel!Method

Lock target surface PE to source surface PE, absorbing the difference in the bottom layer. Prevents column mass change through the remap (GCHP: pe2(npz+1) = pe1(npz+1)). Must be called AFTER compute_target_pressure_from_delp_direct! AND compute_source_pe_from_evolved_mass!.

source
AtmosTransport.Advection._massflux_x_cs_kernel_ppm!Method
_massflux_x_cs_kernel_ppm!(rm_new, rm, m_new, m, am, Hp, Nc, ::Val{ORD})

X-direction mass-flux advection using Putman & Lin PPM (all ORD variants).

Uses PPM subgrid distribution (ORD=4,5,6,7) instead of Russell-Lerner slopes. Fluxes computed identically to Russell-Lerner path (TM5-style mass conserving).

source
AtmosTransport.Advection._pe_from_ps_hybrid_kernel!Method
_pe_from_ps_hybrid_kernel!(pe, dp, ps_dry_out, delp, qv, ak, bk, Hp, Nc, Nz)

Compute pressure edges using the pure GCHP algorithm:

  1. PS_total = ptop + sum(DELP) (total surface pressure from met DELP)
  2. DELPhybrid[k] = (ak[k+1]-ak[k]) + (bk[k+1]-bk[k]) × PStotal (exact hybrid formula)
  3. PSdry = ptop + sum(DELPhybrid[k] × (1 - QV[k])) (dry surface pressure)
  4. PE[k] = ak[k] + bk[k] × PS_dry (smooth hybrid PE)

All intermediate computation in Float64 for precision. This ensures PE is exactly on the hybrid grid with no per-level Float32 noise from DELP accumulation. Pure-pressure levels (bk=0) get PE=ak exactly.

Reference: GCHP GCHPctmEnv_GridCompMod.F90:calculate_ple with SPHU argument.

source
AtmosTransport.Advection._ppm_edge_valuesMethod
_ppm_edge_values(q_imm, q_im, q_i, q_ip, q_ipp, ::Val{ORD}) where ORD

Dispatch to the appropriate PPM subgrid distribution for the given ORD variant.

Returns (qL, qR) edge values for a parabolic flux calculation.

source
AtmosTransport.Advection._ppm_edge_values_ord4Method
_ppm_edge_values_ord4(q_imm, q_im, q_i, q_ip, q_ipp)

Compute PPM edge values (qL, qR) using ORD=4 (LR96 PPM + minmod).

Returns a tuple (qL, qR) of face values for a parabolic subgrid distribution. Uses a 5-point stencil with minmod slope limiter.

source
AtmosTransport.Advection._ppm_edge_values_ord5Method
_ppm_edge_values_ord5(q_imm, q_im, q_i, q_ip, q_ipp)

Compute PPM edge values (qL, qR) using ORD=5 (Huynh's second constraint).

Provides better accuracy than minmod while maintaining quasi-monotonicity. Reference: Huynh (1996), "Schemes and constraints for advection"

source
AtmosTransport.Advection._ppm_edge_values_ord6Method
_ppm_edge_values_ord6(q_imm, q_im, q_i, q_ip, q_ipp)

Compute PPM edge values (qL, qR) using ORD=6 (quasi-5th order, non-monotonic).

Provides better pointwise error metrics (L∞) at the cost of allowing occasional negative values (~1% in test cases).

source
AtmosTransport.Advection._ppm_face_edge_value_ord7_discontinuousMethod
_ppm_face_edge_value_ord7_discontinuous(
    q_left_0, q_left_1,
    q_right_0, q_right_1,
    orient::Int
)

Compute edge value at a gnomonic CS face discontinuity using Appendix C of Putman & Lin.

For ORD=7, when computing edge values at a CS face boundary, we average two one-sided second-order extrapolations to handle the coordinate discontinuity.

Returns the shared edge value used by both panels.

Arguments

  • q_left_0, q_left_1: interior values (0 and 1 cells from face) on left panel
  • q_right_0, q_right_1: interior values (0 and 1 cells from face) on right panel
source
AtmosTransport.Advection._ppm_face_valueMethod

Compute upwind PPM face value given mass flux, donor mass, and PPM edges.

Uses the full parabolic integral (FV3 xppm/yppm formula): Positive flow: face = c + (1-α)(br - α·b0) Negative flow: face = c + (1+α)(bl + α·b0) where bl = qL - c, br = qR - c, b0 = bl + br (curvature).

source
AtmosTransport.Advection._ppm_reconstruct_kernel!Method
_ppm_reconstruct_kernel!(q_al, q_ar, q_a6, rm_src, m_src, area, g_val, Hp, Nc, Nz)

Compute PPM parabolic coefficients (AL, AR, A6) for each column. One thread per (i,j) column, sequential k-loop. Follows fvmapz.F90 `ppmprofile` with iv=0 (positive definite), kord=7.

PPM parabola: f(s) = AL + s[(AR-AL) + A6(1-s)], s ∈ [0,1] where A6 = 3(2AA - (AL+AR)).

Phase ordering matches FV3 exactly: A: Monotonic slopes dc[k] → q_a6 scratch B: Interior edges AL[k] for k=3..Nz-1 C: Top boundary edges (area-preserving cubic) D: Bottom boundary edges (area-preserving cubic) E: AR[k] = AL[k+1] F: A6 + lmt=0 for top 2 layers G: Huynh 2nd constraint + lmt=2 for interior (dc/h2 recomputed on-the-fly) H: A6 + lmt=0 for bottom 2 layers

source
AtmosTransport.Advection._vertical_remap_column_kernel!Method
_vertical_remap_column_kernel!(rm, rm_src, m_src, q_al, q_ar, q_a6,
                                pe_tgt, dp_tgt, area, g, Hp, Nc, Nz)

Conservative PPM vertical remap for one panel of the cubed sphere. For each column (i,j):

  1. Compute source pressure edges from current air mass
  2. Read pre-computed PPM coefficients (AL, AR, A6)
  3. Integrate PPM polynomial over target layer intervals
  4. Write remapped rm = qremap * dptgt * area / g

Uses the general PPM integral: q_avg = AL + 0.5(pl+pr)(AR-AL+A6) - (A6/3)(pl²+plpr+pr²) where pl, pr are normalized coordinates within the source layer.

source
AtmosTransport.Advection._vertical_remap_hybrid_pe_kernel!Method

Conservative PPM vertical remap using pre-computed source pressure edges. Same algorithm as _vertical_remap_column_kernel!, but reads source PE from pe_src (hybrid coords) instead of computing from m_src × g / area. This ensures source and target PE are both on the smooth hybrid grid, eliminating noisy per-level displacement at the pure-pressure/hybrid boundary. q = rm/m still uses actual mass (correct mixing ratio).

source
AtmosTransport.Advection.adjoint_advect_x!Method
adjoint_advect_x!(adj_tracers, velocities, grid, scheme, Δt)

Adjoint of advect_x! for the Russell-Lerner slopes scheme.

When use_limiter = false: exact discrete adjoint (matrix transpose, machine precision). When use_limiter = true: continuous adjoint — reuses forward code with negated wind following TM5/NICAM-TM (Niwa et al., 2017).

source
AtmosTransport.Advection.adjoint_advect_y!Method
adjoint_advect_y!(adj_tracers, velocities, grid, scheme, Δt)

Discrete adjoint of advecty!. Overwrites adjtracers with A' * adj_tracers. Uses the spherical form matching the forward kernel (sin/cos weighting).

source
AtmosTransport.Advection.advect_x!Method
advect_x!(tracers, velocities, grid, scheme, Δt)

Russell-Lerner slopes advection in x (panel-local) on CubedSphereGrid. Fills panel halos, then advects each panel independently.

source
AtmosTransport.Advection.advect_x!Method
advect_x!(tracers, velocities, grid, scheme, Δt)

Russell-Lerner slopes advection in x (longitude). Periodic boundaries. When the grid has a reduced grid specification, high-latitude rows are advected on a coarser zonal grid (TM5-style) to avoid polar CFL violations.

source
AtmosTransport.Advection.advect_x_cs_panel!Method
advect_x_cs_panel!(
    rm,
    m,
    am,
    rm_buf,
    m_buf,
    Hp,
    Nc,
    use_limiter
)

X-direction mass-flux advection for a single cubed-sphere panel. rm, m, rm_buf, m_buf are haloed (Nc+2Hp × Nc+2Hp × Nz). am is interior-only (Nc+1 × Nc × Nz).

source
AtmosTransport.Advection.advect_x_mass_corrected!Method
advect_x_mass_corrected!(
    tracers,
    velocities,
    grid,
    scheme,
    Δt,
    Δp
)

Advect tracers in x with TM5-style mass correction.

  1. Save Δp before advection.
  2. Run concentration-based advect_x!.
  3. Update Δp via 1D mass-flux divergence.
  4. Rescale: c *= Δp_old / Δp_new.

Δp is modified in place to reflect the post-advection air mass.

source
AtmosTransport.Advection.advect_x_massflux!Method
advect_x_massflux!(
    rm_tracers,
    m,
    am,
    grid,
    use_limiter,
    rm_buf,
    m_buf,
    cluster_sizes
)

TM5-faithful x-advection using mass fluxes. Runs on CPU or GPU via KA kernels. Uses pre-allocated rm_buf and m_buf to avoid GPU allocations.

source
AtmosTransport.Advection.advect_x_massflux_reduced!Method
advect_x_massflux_reduced!(
    rm_tracers,
    m,
    am,
    grid,
    use_limiter
)

TM5-style reduced-grid x-advection for mass-flux form on CPU. For each latitude row with cluster size r > 1, reduces rm, m, and am to the coarser row, advects with the 1D slopes scheme, then expands back.

Rows with cluster size 1 use the standard kernel. All tracers see the original m for slope computation (m is updated once at the end, matching the non-reduced path).

source
AtmosTransport.Advection.advect_x_subcycled!Method
advect_x_subcycled!(
    tracers,
    vel,
    grid,
    scheme,
    dt;
    n_sub,
    cfl_limit
) -> Any

Subcycled x-advection. If n_sub is provided, uses that many sub-steps; otherwise automatically determines from CFL.

source
AtmosTransport.Advection.advect_y_massflux!Method
advect_y_massflux!(
    rm_tracers,
    m,
    bm,
    grid,
    use_limiter,
    rm_buf,
    m_buf
)

TM5-faithful y-advection using mass fluxes. Runs on CPU or GPU via KA kernels. Uses pre-allocated rm_buf and m_buf to avoid GPU allocations.

source
AtmosTransport.Advection.advect_z!Method
advect_z!(tracers, velocities, grid, scheme, Δt)

Russell-Lerner slopes advection in z (vertical) on CubedSphereGrid. No panel halo exchange needed — vertical is independent.

source
AtmosTransport.Advection.advect_z!Method
advect_z!(tracers, velocities, grid, scheme, Δt)

Russell-Lerner slopes advection in z (vertical). Bounded boundaries with zero flux at model top (k=1) and surface (k=Nz+1).

Sign convention: w > 0 means downward — flow from level k-1 toward level k (increasing k index, toward the surface). This matches the ERA5/ECMWF omega convention where omega > 0 is downward (increasing pressure).

source
AtmosTransport.Advection.advect_z!Method
advect_z!(tracers, velocities, grid, _, Δt)

First-order upwind advection in z (vertical). Zero-flux boundaries at model top (k=1) and surface (k=Nz+1).

Sign convention: w > 0 means downward — flow from level k-1 toward level k (increasing k index, toward the surface). This matches the ERA5/ECMWF omega convention where omega > 0 is downward (increasing pressure).

source
AtmosTransport.Advection.advect_z_cs_panel_column!Method
advect_z_cs_panel_column!(
    rm,
    m,
    rm_src,
    m_src,
    cm,
    Hp,
    Nc,
    Nz,
    use_limiter
)

Column-sequential Z-direction mass-flux advection for a single cubed-sphere panel. Reads slopes and fluxes from rm_src/m_src (original values) and writes updates to rm/m, ensuring exact flux telescoping and mass conservation. Gamma is clamped to [-1,1] to prevent negative-mass instabilities at high vertical CFL.

source
AtmosTransport.Advection.advect_z_massflux!Method
advect_z_massflux!(
    rm_tracers,
    m,
    cm,
    use_limiter,
    rm_buf,
    m_buf
)

TM5-faithful z-advection using mass fluxes. Runs on CPU or GPU via KA kernels. Uses pre-allocated rm_buf and m_buf to avoid GPU allocations.

source
AtmosTransport.Advection.allocate_cs_massflux_workspaceMethod
allocate_cs_massflux_workspace(ref_panel, Nc)

Allocate workspace buffers for cubed-sphere mass-flux advection. ref_panel is a haloed panel array whose size and device type are matched. Nc is the number of interior cells per panel edge (required so CFL scratch arrays are sized exactly to the flux dimensions — oversized arrays caused maximum() to read uninitialized GPU memory, producing garbage CFL values).

source
AtmosTransport.Advection.allocate_massflux_workspaceMethod
allocate_massflux_workspace(
    m,
    am,
    bm,
    cm;
    cluster_sizes_cpu
)

Allocate a workspace that matches the sizes of m, am, bm, cm. cluster_sizes_cpu is an Int32 vector of per-latitude cluster sizes (1 = uniform, >1 = reduced). Pass nothing for no reduced grid. Call once before the time loop; pass to strang_split_massflux!.

source
AtmosTransport.Advection.apply_divergence_damping_cs!Method
apply_divergence_damping_cs!(rm_panels, m_panels, grid, ws, damp_coeff)

Apply conservative del-2 divergence damping to tracer panels on cubed-sphere grid. Mass-conserving flux-form Laplacian diffusion on mixing ratio (c = rm/m). Typical damp_coeff values: 0.02–0.05 for mild smoothing of panel-boundary noise.

source
AtmosTransport.Advection.apply_mass_fixer!Method
apply_mass_fixer!(rm, m_ref, m_evolved, Nc, Nz, Hp)

Correct tracer mass rm to preserve mixing ratio q = rm/m when air mass is reset from m_evolved (post-advection) back to m_ref (DELP-derived).

Sets rm[i,j,k] = (rm[i,j,k] / m_evolved[i,j,k]) * m_ref[i,j,k] for interior cells.

source
AtmosTransport.Advection.calc_scaling_factorMethod
calc_scaling_factor(rm_panels, m_save_panels, ws_vr, gc, grid) → Float64

Compute the GCHP-style global scaling factor for post-remap mass correction.

Returns Σ(rm × g / area) / Σ(dp_tgt × q_remap) where q_remap = rm / m_save. This is equivalent to mass_on_source / mass_on_target, correcting for the mismatch between met DELP and hybrid PE target pressure structure.

Applied after vertical_remap_cs! when using hybrid PE target computation.

source
AtmosTransport.Advection.compute_air_mass_panel!Method
compute_air_mass_panel!(m, delp, qv, area, g, Nc, Nz, Hp)

Compute DRY air mass for a single cubed-sphere panel: m = delp × (1 - qv) × area / g. m, delp, and qv are haloed arrays (Nc+2Hp × Nc+2Hp × Nz). area is an interior-only array (Nc × Nc).

source
AtmosTransport.Advection.compute_air_mass_panel!Method
compute_air_mass_panel!(m, delp, area, g, Nc, Nz, Hp)

Compute air mass for a single cubed-sphere panel from pressure thickness. m and delp are haloed arrays (Nc+2Hp × Nc+2Hp × Nz). area is an interior-only array (Nc × Nc).

source
AtmosTransport.Advection.compute_area_fluxes!Method
compute_area_fluxes!(ws_gchp, cx_panels, cy_panels, geom, grid)

Compute area fluxes (xfx, yfx) from Courant numbers and grid geometry. Called once per window after CX/CY are uploaded to GPU.

GCHP reference: fv_tracer2d.F90:162-182.

source
AtmosTransport.Advection.compute_cm_mass_weighted_panel!Method
compute_cm_mass_weighted_panel!(cm, am, bm, m, Nc, Nz, Hp)

Compute vertical mass flux cm using mass-weighted residual correction, matching the LL preprocessor's approach. The column residual (pit = total horizontal convergence) is distributed proportionally to cumulative air mass, not to B-ratio (bt). This reduces mass-fixer corrections on CS grids.

  • cm: (Nc, Nc, Nz+1) — vertical flux at level interfaces
  • am: (Nc+1, Nc, Nz) — X-face mass flux (already scaled to kg/half-sub-step)
  • bm: (Nc, Nc+1, Nz) — Y-face mass flux (already scaled)
  • m: (Nc+2Hp, Nc+2Hp, Nz) — air mass (haloed), used for mass weighting
source
AtmosTransport.Advection.compute_cm_panel!Method
compute_cm_panel!(cm, am, bm, bt, Nc, Nz)

Compute vertical mass flux cm from horizontal convergence of am (X mass flux) and bm (Y mass flux) for a single panel, ensuring column mass conservation.

  • cm: (Nc, Nc, Nz+1) — vertical flux at level interfaces
  • am: (Nc+1, Nc, Nz) — X-face mass flux
  • bm: (Nc, Nc+1, Nz) — Y-face mass flux
  • bt: (Nz,) — B-ratio for sigma correction
source
AtmosTransport.Advection.compute_cm_pressure_fixer_panel!Method
compute_cm_pressure_fixer_panel!(
    cm,
    am,
    bm,
    bt,
    delp_curr,
    delp_next,
    area,
    g,
    n_sub,
    Nc,
    Nz,
    Hp;
    qv
)

Compute vertical mass flux cm using pressure-fixer formulation: incorporates the pressure tendency (DELPnext - DELPcurrent) so that air mass evolves toward the next window's target across sub-steps. Falls back to standard bt-only closure when delp_next === nothing.

source
AtmosTransport.Advection.compute_dm_per_sub_panel!Method
compute_dm_per_sub_panel!(
    dm,
    delp_curr,
    delp_next,
    area,
    g,
    n_sub,
    Nc,
    Nz,
    Hp;
    qv
)

Compute the air-mass increment per sub-step for the pressure-fixer mref evolution: `dm[i,j,k] = (DELPnext - DELPcurr) * area / (g * nsub)`.

source
AtmosTransport.Advection.compute_dry_ple!Method
compute_dry_ple!(ws_vr, ps_panels, sphu_panels, gc, grid)

Compute dry pressure level edges from PS and SPHU using GCHP's calculate_ple algorithm. Writes to ws_vr.pe_tgt and ws_vr.dp_tgt (or pesrc/pssrc depending on which workspace fields are passed).

PS is 2D (Nc+2Hp, Nc+2Hp) in hPa from CTMI1. SPHU is 3D (Nc+2Hp, Nc+2Hp, Nz) in kg/kg from CTMI1.

source
AtmosTransport.Advection.compute_mass_fluxesMethod
compute_mass_fluxes(u, v, grid, Δp, half_dt)

Compute mass fluxes am, bm, cm from staggered velocities, pressure thickness, and half-timestep. Uses KernelAbstractions kernels.

Returns (; am, bm, cm).

source
AtmosTransport.Advection.compute_target_pe_from_evolved_ps!Method
compute_target_pe_from_evolved_ps!(ws_vr, gc, grid)

Compute target PE from hybrid formula using EVOLVED surface pressure. Matches GCHP's remap target (fv_tracer2d.F90:999-1005): pe2(:,1) = ptop pe2(:,npz+1) = pe1(:,npz+1) ← same surface PE as source! pe2(:,k) = ak(k) + bk(k) * pe1(:,npz+1)

Must be called AFTER compute_source_pe_from_evolved_mass! (reads ws_vr.ps_src). Writes to ws_vr.pe_tgt, ws_vr.dp_tgt, ws_vr.ps_tgt.

source
AtmosTransport.Advection.compute_target_pe_from_hybrid_coords!Method
compute_target_pe_from_hybrid_coords!(ws_vr, ng_delp, qv_panels, gc, grid)

Build target PE using GCHP's approach: PE[k] = ak[k] + bk[k] * PS_dry.

Computes PS_dry = sum(delp * (1 - qv)) for each column, then reconstructs target pressure edge values directly from the hybrid coordinate definition. This is physically exact: pure-pressure levels get PE = ak (zero noise), hybrid levels vary smoothly with PS_dry via the bk coefficient.

Unlike the cumsum approach followed by fix_target_bottom_pe!, this avoids per-level QV fluctuations contaminating the target PE and eliminates all ad-hoc scaling. Reference: GCHP DryPLE computation in fvdycore.

source
AtmosTransport.Advection.compute_target_pe_from_ps_hybrid!Method
compute_target_pe_from_ps_hybrid!(ws_vr, delp_panels, qv_panels, gc, grid)

Compute TARGET pressure edges using the pure GCHP hybrid approach. Writes to ws_vr.pe_tgt, ws_vr.dp_tgt, and ws_vr.ps_tgt. Uses next-window DELP and current-window QV (<0.1% approximation).

source
AtmosTransport.Advection.compute_target_pressure_from_delp_direct!Method
compute_target_pressure_from_delp_direct!(ws_vr, ng_delp, gc, grid)

Build target PE as cumulative sum of next-window DELP, NOT via hybrid ak+bk*ps. This avoids artificial redistribution when dry-air correction makes the actual layer thicknesses differ from the hybrid formula.

petgt[1] = ptop; petgt[k+1] = petgt[k] + delp[k]; dptgt[k] = delp[k].

source
AtmosTransport.Advection.compute_target_pressure_from_dry_delp_direct!Method
compute_target_pressure_from_dry_delp_direct!(ws_vr, ng_delp, qv_panels, gc, grid)

Build target PE as cumulative sum of DRY next-window DELP: delp × (1 - qv). Uses current-window QV as approximation (QV changes <0.1% between hourly windows). Ensures target PE is on the same dry basis as source PE (from dry air mass).

source
AtmosTransport.Advection.fillz_panels!Method
fillz_panels!(rm_panels, dp_tgt_panels, grid)

Port of FV3's fillz (fv_fill.F90:34-139). Fixes negative mixing ratios after vertical remap by borrowing mass from neighboring levels, then applying a non-local column scaling if needed. Operates on CPU (called once after remap).

rm_panels are haloed (Nc+2Hp, Nc+2Hp, Nz) tracer mass arrays. dp_tgt_panels are unhaloed (Nc, Nc, Nz) target pressure thickness. The algorithm works on q = rm/dp (mixing ratio proxy) with dp weights:

  1. Top layer: if q < 0, borrow from level below
  2. Interior: if q < 0, borrow from above then below (limited)
  3. Bottom layer: if q < 0, borrow from above (limited)
  4. Non-local: if still negative, scale all positive values to conserve column mass

Conserves total tracer mass (Σ rm) per column exactly.

source
AtmosTransport.Advection.fillz_q!Method
fillz_q!(q_panels, m_panels, grid)

Post-advection positivity fixer for q-space transport. Fixes negative mixing ratios by borrowing mass from neighboring levels, then non-local column rescaling if needed. Port of GCHP's fillz (fv_fill.F90:51-156).

source
AtmosTransport.Advection.fix_target_bottom_pe!Method
fix_target_bottom_pe!(ws_vr, m_src_panels, gc, grid)

Fix target PE to match source column pressure while preserving pure-pressure levels. Pure-pressure levels (bk[k]==0 && bk[k+1]==0) get dptgt set from msrc directly (identity remap — no vertical transport where DELP is invariant). Only hybrid levels (bk > 0) are scaled to absorb the PS difference from horizontal mass divergence. This eliminates a ~0.23 ppm/window noise floor that the old uniform-scaling approach applied to all levels.

source
AtmosTransport.Advection.fv_tp_2d_cs!Method
fv_tp_2d_cs!(rm_panels, m_panels, am_panels, bm_panels,
              grid, ::Val{ORD}, ws, ws_lr; damp_coeff=0.0)

Lin-Rood horizontal advection for cubed-sphere grids. Averages X-first and Y-first PPM orderings (FV3 fvtp2d algorithm).

source
AtmosTransport.Advection.fv_tp_2d_cs_q!Method
fv_tp_2d_cs_q!(q_panels, dp_panels, m_panels, am_panels, bm_panels,
                 grid, ::Val{ORD}, ws, ws_lr; damp_coeff=0.0)

Q-space Lin-Rood horizontal advection. Evolves q (mixing ratio) and dp (pressure thickness in kg, same units as m) in-place. m_panels is read-only (used for CFL fraction in PPM face values).

source
AtmosTransport.Advection.fv_tp_2d_gchp!Method
fv_tp_2d_gchp!(q_panels, m_panels, am_panels, bm_panels,
                 cx_panels, cy_panels, xfx_panels, yfx_panels,
                 area_panels, grid, ::Val{ORD}, ws, ws_lr)

GCHP-faithful Lin-Rood horizontal advection. Key differences from fv_tp_2d_cs_q!:

  • PPM uses Courant number (cx/cy) for upwind integration
  • Pre-advection uses precomputed area fluxes (xfx/yfx) with exact sin_sg
  • Final flux averaging uses mass flux (am/bm) — identical to existing

Arguments:

  • q_panels — mixing ratio panels (haloed, modified in-place)
  • m_panels — air mass panels (haloed, modified in-place)
  • am/bm — mass flux panels (staggered, read-only)
  • cx/cy — Courant number panels (staggered, read-only)
  • xfx/yfx — precomputed area flux panels (staggered, read-only)
  • area_panels — cell areas per panel (Nc×Nc, read-only)
  • grid — CubedSphereGrid
  • ws — shared CubedSphereMassFluxWorkspace (rmbuf, mbuf)
  • ws_lr — LinRoodWorkspace (qbuf, fxin/out, fyin/out, qout, dp_out)
source
AtmosTransport.Advection.fv_tp_2d_gchp_fluxes!Method
fv_tp_2d_gchp_fluxes!(q_panels, cx_panels, cy_panels,
                        xfx_panels, yfx_panels, area_panels,
                        grid, ::Val{ORD}, ws_lr)

Compute Lin-Rood averaged face values using Courant-PPM. Does NOT update q or dp — only computes fluxes.

Output stored in ws_lr:

  • fx_in[p] — inner X face values (from original q)
  • fx_out[p] — outer X face values (from Y-pre-advected q_i)
  • fy_in[p] — inner Y face values (from original q)
  • fy_out — outer Y face values (from X-pre-advected q_j), reused per panel
source
AtmosTransport.Advection.gchp_calc_scaling_factorMethod
gchp_calc_scaling_factor(rm_panels, dp_tgt, delp_next, gc, grid) → Float64

GCHP's calcScalingFactor (fv_tracer2d.F90:1142-1186). Computes the ratio of tracer mass on the hybrid remap grid to tracer mass on the met target grid:

scaling = Σ(q_remap × dp_hybrid × area) / Σ(q_remap × delp_next × area)

where qremap = rm / mhybrid, mhybrid = dptgt × area / g (air mass on the hybrid target grid after remap), and delp_next is the actual met DELP.

Since Σ(q × dp × area) = Σ(rm / (dptgt×area/g) × dp × area) and for the numerator dp = dptgt, this simplifies to Σ(rm × g) = g × Σ(rm). The denominator is Σ(rm / (dptgt×area/g) × delpnext × area).

source
AtmosTransport.Advection.gchp_tracer_2d!Method
gchp_tracer_2d!(q_tracers, dp_panels, mfx, mfy, cx, cy,
                  xfx, yfx, area, rarea, grid, ::Val{ORD},
                  ws_lr, dp2_work)

Port of GCHP's tracer_2d (fv_tracer2d.F90:336-578). Horizontal advection with per-level subcycling, called ONCE per met window.

All tracers in q_tracers are advected simultaneously, sharing the same dp evolution (as in GCHP). dp_panels is modified in-place to contain the post-advection pressure thickness (dpA).

source
AtmosTransport.Advection.max_cfl_zMethod
max_cfl_z(velocities, grid, dt)

Maximum CFL number for z-advection. Uses per-column surface pressure from velocities.p_surface when available, falling back to reference pressure.

source
AtmosTransport.Advection.minmod_ppmMethod
minmod_ppm(a, b, c)

Minmod limiter for PPM: returns the value with smallest magnitude if all have the same sign, otherwise zero. Used in ORD=4 and ORD=5.

minmod(a, b, c) = {
    min(a, b, c)   if all > 0
    max(a, b, c)   if all < 0
    0              otherwise
}
source
AtmosTransport.Advection.recompute_cm_ll!Method

Recompute vertical mass flux cm from (dry-corrected) am and bm via the continuity-equation column sweep. Uses _cm_column_kernel! (defined in massfluxadvection.jl, same Advection module scope).

source
AtmosTransport.Advection.strang_split_gchp_ppm!Method
strang_split_gchp_ppm!(q_panels, m_panels, am_panels, bm_panels,
                         cm_panels, cx_panels, cy_panels,
                         geom, ws_gchp, grid, ::Val{ORD}, ws, ws_lr)

Full 3D advection with GCHP-faithful horizontal: Horizontal(GCHP) → Z → Z → Horizontal(GCHP)

source
AtmosTransport.Advection.strang_split_massflux!Method
strang_split_massflux!(
    rm_panels,
    m_panels,
    am_panels,
    bm_panels,
    cm_panels,
    grid,
    use_limiter,
    ws;
    cfl_limit
)

Perform a full Strang-split mass-flux advection step (X-Y-Z-Z-Y-X) on a CubedSphereGrid with CFL-adaptive subcycling per direction.

Each directional sweep computes the maximum per-face CFL across all 6 panels. When CFL exceeds cfl_limit, the sweep is subcycled: fluxes are divided by the subcycle count and the advection kernel is applied that many times.

Arguments:

  • rm_panels: NTuple{6, Array} of tracer mass (haloed)
  • m_panels: NTuple{6, Array} of air mass (haloed)
  • am_panels: NTuple{6, Array} of X mass flux (interior, Nc+1 × Nc × Nz)
  • bm_panels: NTuple{6, Array} of Y mass flux (interior, Nc × Nc+1 × Nz)
  • cm_panels: NTuple{6, Array} of Z mass flux (interior, Nc × Nc × Nz+1)
  • grid: CubedSphereGrid
  • use_limiter: enable minmod slope limiter
  • ws: CubedSphereMassFluxWorkspace
  • cfl_limit: maximum allowed CFL per sweep (default 0.95)
source
AtmosTransport.Advection.strang_split_massflux!Method
strang_split_massflux!(
    tracers,
    m,
    am,
    bm,
    cm,
    grid,
    use_limiter,
    ws;
    cfl_limit
)

Perform a full Strang-split advection step (X-Y-Z-Z-Y-X) using TM5-style mass-flux advection. Runs on CPU or GPU — same code path via KA kernels.

Converts concentration tracers to tracer mass, performs the split, then converts back. m is updated in-place to track air mass.

When ws::MassFluxWorkspace is provided, all temporary GPU arrays are pre-allocated, reducing per-step allocations from ~90 to zero.

source
AtmosTransport.Advection.strang_split_massflux_ppm!Method
strang_split_massflux_ppm!(rm_panels, m_panels, am_panels, bm_panels, cm_panels,
                           grid, ::Val{ORD}, ws; cfl_limit=0.95, damp_coeff=0.0)

Strang-split mass-flux advection using Putman & Lin PPM (all ORD variants).

Sequence: [optional damping] → X → Y → Z → Z → Y → X where Z uses the standard column-sequential kernel (PPM not needed vertically).

Keyword arguments

  • cfl_limit=0.95: maximum CFL before subcycling
  • damp_coeff=0.0: del-2 divergence damping coefficient (0 = off, typical: 0.02–0.05)

Dispatch on Val{ORD} ensures compile-time kernel specialization.

source
AtmosTransport.Advection.strang_split_prather!Method
strang_split_prather!(tracers, m, am, bm, cm, grid, pw_dict, use_limiter)

Full Strang-split advection using Prather (1986) prognostic slopes. pw_dict is a NamedTuple of PratherWorkspace keyed by tracer name. Tracers store mixing ratios (q = c); converted to rm = m*c for advection.

source
AtmosTransport.Advection.strang_split_prather_cs!Method
strang_split_prather_cs!(rm_panels, m_panels, am, bm, cm, grid, pw_cs, use_limiter;
                          cfl_limit=0.95, cfl_ws=nothing)

Cubed-sphere Prather advection with Strang splitting and prognostic slopes. pw_cs is a CSPratherWorkspace for the tracer being advected. cfl_ws is a CFL scratch array from CubedSphereMassFluxWorkspace.

source
AtmosTransport.Advection.subcycling_countsMethod
subcycling_counts(
    velocities,
    grid::AtmosTransport.Grids.LatitudeLongitudeGrid,
    dt;
    cfl_limit
) -> NamedTuple{(:nx, :ny, :nz, :cfl_x, :cfl_y, :cfl_z), <:NTuple{6, Any}}

Compute the number of sub-steps needed for each advection direction. Returns (nx, ny, nz) where each is ≥ 1.

source
AtmosTransport.Advection.update_pressure_x!Method
update_pressure_x!(Δp, u, grid, Δt)

Update pressure thickness Δp in the x-direction using first-order upwind mass-flux divergence. Periodic boundary conditions in longitude.

Modifies Δp in place.

source
AtmosTransport.Advection.update_pressure_y!Method
update_pressure_y!(Δp, v, grid, Δt)

Update pressure thickness Δp in the y-direction using first-order upwind mass-flux divergence. Zero-flux (wall) boundary at poles.

Modifies Δp in place.

source
AtmosTransport.Advection.update_pressure_z!Method
update_pressure_z!(Δp, w, Δt)

Update pressure thickness Δp in the z-direction using the continuity equation. w is omega at z-interfaces (Nx, Ny, Nz+1) with w > 0 = downward.

Zero flux at the model top (k=1) and surface (k=Nz+1).

Modifies Δp in place.

source
AtmosTransport.Advection.vertical_remap_cs!Method
vertical_remap_cs!(rm_panels, m_src_panels, ws_vr, ws, gc, grid;
                   flat=false, hybrid_pe=false)

Apply conservative vertical remapping for all 6 CS panels. Remaps tracer rm from source pressure to target pressure.

When hybrid_pe=true, uses pre-computed ws_vr.pe_src (from hybrid coords) for source pressure edges instead of deriving them from m_src. This ensures source and target PE are both on the smooth hybrid grid, eliminating noisy displacement at the pure-pressure/hybrid transition.

m_src_panels is the SAVED post-horizontal air mass — shared across all tracers and NOT modified by this function. The remap only modifies rm_panels.

source

Convection

AtmosTransport.ConvectionModule
Convection

Convective transport parameterizations with paired discrete adjoints.

Interface contract

convect!(tracers, met, grid, conv::AbstractConvection, Δt)
adjoint_convect!(adj_tracers, met, grid, conv::AbstractConvection, Δt)
source
AtmosTransport.Convection.AbstractConvectionType
abstract type AbstractConvection

Supertype for convective transport parameterizations.

Available concrete types:

Adding a new scheme

  1. Define struct MyScheme <: AbstractConvection end
  2. Implement convect! methods for CubedSphereGrid and LatitudeLongitudeGrid
  3. Add _needs_convection(::MyScheme) = true in run_implementations.jl
  4. If the scheme needs DTRAIN: add _needs_dtrain(::MyScheme) = true
  5. Add a type = "myscheme" branch in _build_convection (configuration.jl)
source
AtmosTransport.Convection.AbstractTracerSolubilityType
abstract type AbstractTracerSolubility

Supertype for tracer solubility traits used in convective wet scavenging.

Subtypes determine how much tracer mass is removed from the convective updraft by precipitation at each level.

source
AtmosTransport.Convection.InertTracerType
struct InertTracer <: AtmosTransport.Convection.AbstractTracerSolubility

Inert tracer — no wet scavenging. All updraft tracer mass is conserved during convective transport. Appropriate for CO₂, SF₆, ²²²Rn, CH₄.

source
AtmosTransport.Convection.RASConvectionType
struct RASConvection <: AtmosTransport.Convection.AbstractConvection

Relaxed Arakawa-Schubert (RAS) convection scheme (Moorthi & Suarez 1992), as implemented in GEOS-Chem (convection_mod.F90).

Uses both CMFMC (updraft mass flux at interfaces) and DTRAIN (detraining mass flux at layer centers) from GEOS met data. Entrainment is diagnosed from the mass balance: ENTRN = max(0, CMFMC + DTRAIN - CMFMC_below).

If DTRAIN data is unavailable at runtime, falls back to Tiedtke-style CMFMC-only transport with a warning.

See ras_convection.jl for the full algorithm and references.

source
AtmosTransport.Convection.SolubleTracerType
struct SolubleTracer <: AtmosTransport.Convection.AbstractTracerSolubility

Soluble tracer — subject to wet scavenging via Henry's law dissolution and retention in cloud condensate. Not yet implemented; will require precipitation flux fields (PFICU, PFLCU, DQRCU) from met data.

  • henry_constant: Henry's law constant [mol/L/atm]

  • retention_efficiency: fraction of dissolved tracer retained in updraft after rain-out (0–1)

source
AtmosTransport.Convection.TM5MatrixConvectionType
struct TM5MatrixConvection <: AtmosTransport.Convection.AbstractConvection

TM5-faithful matrix convection scheme (Heimann & Keeling, Tiedtke 1989).

Builds a full Nz×Nz transfer matrix per column from 4 met fields (updraft/downdraft entrainment and detrainment), then applies via implicit LU solve. This is the exact algorithm used in TM5 (tm5_conv.F90).

Key differences from TiedtkeConvection:

  • Uses 4 met fields (entu, detu, entd, detd) instead of 1 (CMFMC)
  • Builds Nz×Nz transfer matrix (non-local transport)
  • Implicit solve (unconditionally stable, no CFL limit)
  • Exact mass conservation to machine precision

Fields

  • lmax_conv::Int: maximum level for convection (0 = use full Nz)

See tm5_matrix_convection.jl for the matrix builder algorithm.

source
AtmosTransport.Convection.TiedtkeConvectionType
struct TiedtkeConvection <: AtmosTransport.Convection.AbstractConvection

Tiedtke (1989) mass-flux convection scheme, as used in TM5. Mass fluxes come from met data (fixed), so the operator is linear in tracers and the adjoint is the transpose of the mass-flux redistribution matrix.

The forward operator uses prescribed convective mass fluxes from met data (met.conv_mass_flux) to redistribute tracers vertically via upwind mass-flux transport. See tiedtke_convection.jl for implementation.

source
AtmosTransport.Convection._conv_cloud_dimMethod
_conv_cloud_dim(detu, entd, lmx)

Compute cloud top (li) and level of free sinking (ld) from detrainment/entrainment. Uses TM5 bottom-to-top convention (k=1=surface).

Returns (li, ld).

source
AtmosTransport.Convection._convect_column_kernel!Method

Grid-agnostic KA kernel for Tiedtke mass-flux convective transport.

For each (i,j) column, processes in three phases:

  1. (if :rm) Pre-convert: convert rm → q in-place (q = rm/m for all k).

  2. Flux divergence in q-space with mass-divergence correction: dq = Δt × g/Δp × [Fbelow - Fabove - qk × (CMFMCbelow - CMFMCabove)] where F[k] = CMFMC[k] × qupwind, selected by sign of CMFMC.

    The mass-divergence correction subtracts the air-mass-dilution term that a coupled model would handle via air mass update. This ensures exactly zero tendency for spatially uniform mixing ratio fields — critical for offline transport where air mass is held fixed during convection. Applied in both :rm and :mixing_ratio modes.

  3. (if :rm) Post-convert: convert q → rm (rm = q × m for all k). No per-column mass fix is applied; the global mass fixer in the run loop handles the small Σ rm drift from the correction breaking flux telescoping.

Mass conservation: Both modes: column Σ Δp×q / Σ rm NOT exactly preserved (mass-divergence correction breaks flux telescoping), but drift is small (~ppm level) and corrected by the global mass fixer. This avoids the systematic level-dependent bias that per-column mass fixes create.

Zero-flux boundary conditions at top (k=1) and surface (k=Nz+1).

source
AtmosTransport.Convection._max_conv_cfl_csMethod
_max_conv_cfl_cs(cmfmc_panels, delp_panels, dt, grav, Hp, Nc, Nz)

Estimate the maximum convective CFL across all 6 cubed-sphere panels. CFL at interface k = |cmfmc[k]| × dt × g / Δp, checked against the layer on both sides of the interface.

source
AtmosTransport.Convection._ras_column_kernel!Method

KA kernel for RAS convective transport with explicit entrainment/detrainment.

For each (i,j) column:

  • Pass 1 (k = Nz → 1): Compute updraft concentration q_cloud at each level by entraining environment air and mixing with the updraft from below.
  • Pass 2 (k = 1 → Nz): Apply tendency from updraft flux divergence and detrainment to the environment mixing ratio.

Arguments:

  • arr: tracer data (rm for CS, mixing ratio for LL), modified in-place
  • m: air mass per cell [kg] (used only in :rm mode)
  • cmfmc: convective mass flux at interfaces [kg/m²/s], size (..., Nz+1)
  • dtrain: detraining mass flux at layer centers [kg/m²/s], size (..., Nz)
  • delp: pressure thickness [Pa], size (..., Nz)
  • q_cloud_ws: workspace for updraft concentration, same shape as arr
  • i_off, j_off: index offsets for halo (Hp for CS, 0 for LL)
  • Nz: number of vertical levels
  • dt: timestep [s]
  • grav: gravitational acceleration [m/s²]
source
AtmosTransport.Convection._ras_subcyclingMethod
_ras_subcycling(cmfmc_panels, dtrain_panels, delp_panels, dt, grav, Hp, Nc, Nz)

Compute RAS subcycling parameters, caching result until invalidate_ras_cfl_cache!(). CPU-side scalar loop avoids GPU temporary allocations.

source
AtmosTransport.Convection.adjoint_convect!Method
adjoint_convect!(adj_tracers, met, grid, conv, Δt)

Discrete adjoint of convect! for the Tiedtke mass-flux scheme.

Since the forward operator is linear in tracer concentration (mass fluxes are fixed from met data), the adjoint is the exact matrix transpose. This gives machine-precision dot-product identity: ⟨L^T λ, δq⟩ = ⟨λ, L δq⟩.

The forward update for level k is: qnew[k] = q[k] + Δt·g/Δp[k] · (flux[k+1] - flux[k]) where flux[k] = M[k]·qupwind.

The adjoint scatters λnew[k] to λold via the transposed coefficients.

source
AtmosTransport.Convection.adjoint_convect!Method
adjoint_convect!(adj_tracers, tm5conv_data, delp, conv::TM5MatrixConvection,
                 grid::LatitudeLongitudeGrid, dt, planet; kwargs...)

Adjoint of TM5 matrix convection for lat-lon grids.

Builds the same conv1 matrix as the forward, then solves the transposed system: conv1^T * λold = λnew

This is equivalent to LAPACK dGeTrs with trans='T'.

source
AtmosTransport.Convection.convect!Method
convect!(
    rm_panels,
    m_panels,
    cmfmc_panels,
    delp_panels,
    conv,
    grid,
    dt,
    planet;
    dtrain_panels,
    workspace
)

Apply RAS convective transport to cubed-sphere panel arrays.

Uses CMFMC (updraft mass flux at interfaces) and DTRAIN (detraining mass flux at layer centers) to redistribute tracers vertically via the Relaxed Arakawa-Schubert scheme.

Each panel's tracer mass (rm) is processed in two passes:

  1. Bottom-to-top: compute updraft concentration by entraining environment air
  2. Top-to-bottom: apply tendency from updraft flux divergence and detrainment

If dtrain_panels is nothing, falls back to Tiedtke-style CMFMC-only transport with a one-time warning.

Adaptive subcycling keeps the convective CFL below 0.9 per substep.

Arguments

  • rm_panels: NTuple{6} of tracer mass arrays, modified in-place
  • m_panels: NTuple{6} of air mass arrays [kg]
  • cmfmc_panels: NTuple{6} of convective mass flux at interfaces [kg/m²/s]
  • delp_panels: NTuple{6} of pressure thickness [Pa]
  • conv::RASConvection: convection scheme selector
  • grid::CubedSphereGrid: grid specification
  • dt: timestep [s]
  • planet: planet parameters (gravity)

Keyword Arguments

  • dtrain_panels: NTuple{6} of detraining mass flux [kg/m²/s], or nothing
  • workspace: NTuple{6} of pre-allocated workspace arrays for q_cloud
source
AtmosTransport.Convection.convect!Method
convect!(rm_panels, m_panels, cmfmc_panels, delp_panels,
         conv, grid, dt, planet)

Apply Tiedtke mass-flux convection to cubed-sphere panel arrays.

Each panel's tracer mass (rm) is converted to mixing ratio, convected via upwind mass-flux transport, then converted back.

Adaptive subcycling keeps the convective CFL below 0.9 per substep, guaranteeing positivity without the need for a clamp.

source
AtmosTransport.Convection.convect!Method
convect!(
    tracers,
    cmfmc,
    delp,
    conv,
    grid,
    dt,
    planet;
    dtrain_panels,
    workspace
)

Apply RAS convective transport to lat-lon tracers (mixing ratios, GPU).

cmfmc is (Nx, Ny, Nz+1) updraft convective mass flux [kg/m²/s]. delp is (Nx, Ny, Nz) pressure thickness per layer [Pa]. dtrain keyword: (Nx, Ny, Nz) detraining mass flux [kg/m²/s], or nothing.

If dtrain is nothing, falls back to Tiedtke-style CMFMC-only transport. Adaptive subcycling keeps the convective CFL below 0.9 per substep.

source
AtmosTransport.Convection.convect!Method
convect!(tracers, cmfmc, delp, conv, grid, dt, planet)

Apply Tiedtke mass-flux convection to lat-lon tracers (mixing ratios, GPU).

cmfmc is (Nx, Ny, Nz+1) net convective mass flux [kg/m²/s]. delp is (Nx, Ny, Nz) pressure thickness per layer [Pa].

Adaptive subcycling keeps the convective CFL below 0.9 per substep.

source
AtmosTransport.Convection.convect!Method
convect!(tracers, met, grid, conv, Δt)

Apply Tiedtke mass-flux convection to all tracers in-place (lat-lon).

met should be a NamedTuple (or similar) with field conv_mass_flux: a 3D array of size (Nx, Ny, Nz+1) containing the net convective mass flux [kg/m²/s] at each interface level, positive upward.

If met is nothing or lacks conv_mass_flux, this is a no-op.

source
AtmosTransport.Convection.convect!Method
convect!(tracers, tm5conv_data, delp, conv::TM5MatrixConvection,
         grid::LatitudeLongitudeGrid, dt, planet; kwargs...)

Apply TM5 matrix convection to lat-lon tracers.

tm5conv_data is a NamedTuple with fields entu, detu, entd, detd, each of size (Nx, Ny, Nz) in our top-to-bottom convention. delp is (Nx, Ny, Nz) pressure thickness per layer [Pa].

For each (i,j) column:

  1. Reverse levels to TM5 bottom-to-top convention
  2. Compute cloud dimensions (li, ld)
  3. Build the Nz×Nz transfer matrix
  4. Solve conv1 * rm_new = rm_old via LU decomposition
  5. Reverse back and update tracers
source
AtmosTransport.Convection.tm5_conv_matrix!Method
tm5_conv_matrix!(conv1, m, entu, detu, entd, detd, lmx, li, ld, dt)

Build the TM5 convection transfer matrix for a single column.

All input arrays use TM5's bottom-to-top convention (k=1=surface).

Arguments

  • conv1::Matrix{FT}: output matrix (lmx × lmx), overwritten
  • m::Vector{FT}: air mass per level [kg/m²]
  • entu, detu: updraft entrainment/detrainment [kg/m²/s]
  • entd, detd: downdraft entrainment/detrainment [kg/m²/s]
  • lmx::Int: number of levels
  • li::Int: cloud top level (updraft stops here), 0 if no updraft
  • ld::Int: level of free sinking (downdraft starts here), 0 if no downdraft
  • dt::FT: timestep [s]

Returns

  • lmc::Int: highest active convection level (0 = no convection)
source
AtmosTransport.Convection.tracer_solubilityMethod
tracer_solubility(_)

Return the solubility trait for a given tracer species. Defaults to InertTracer (no scavenging) for all species. Override this method for soluble species when wet deposition is implemented.

Example

tracer_solubility(:sf6)        # → InertTracer()
tracer_solubility(:hno3)       # → SolubleTracer(2.1e5, 0.62) (future)
source
AtmosTransport.Convection.wet_scavenge_fractionMethod
wet_scavenge_fraction(_, args)

Compute the fraction of updraft tracer mass removed by wet scavenging at a given level. Returns 0.0 for inert tracers (no removal).

For soluble tracers (not yet implemented), this would depend on temperature, precipitation flux, and Henry's law constant.

source
AtmosTransport.Convection.wet_scavenge_fractionMethod
wet_scavenge_fraction(_, T, precip_flux, Δp)

Wet scavenging fraction for soluble tracers. Not yet implemented — raises an error. Will require precipitation flux fields from GEOS met data (PFICU, PFLCU from A3mstE collection).

source

Diffusion

AtmosTransport.DiffusionModule
Diffusion

Vertical diffusion parameterizations with paired discrete adjoints.

Vertical diffusion in atmospheric transport is typically an implicit solve (tridiagonal system). The adjoint is the transpose of the tridiagonal matrix, solved with a transposed Thomas algorithm.

Interface contract

diffuse!(tracers, met, grid, diff::AbstractDiffusion, Δt)
adjoint_diffuse!(adj_tracers, met, grid, diff::AbstractDiffusion, Δt)
source
AtmosTransport.Diffusion.AbstractDiffusionType
abstract type AbstractDiffusion

Supertype for vertical diffusion parameterizations.

Interface contract

Subtypes must implement:

diffuse!(tracers, met, grid, diff::YourDiffusion, Δt)
adjoint_diffuse!(adj_tracers, met, grid, diff::YourDiffusion, Δt)

For GPU support, implement KernelAbstractions kernels that dispatch on get_backend(array). See BoundaryLayerDiffusion for a minimal example and NonLocalPBLDiffusion for a full-featured implementation with counter-gradient transport.

Available implementations

  • NoDiffusion — no-op pass-through
  • BoundaryLayerDiffusion — static exponential Kz profile
  • PBLDiffusion — met-data-driven Kz from PBLH, u*, HFLUX (TM5/Beljaars & Viterbo 1998)
  • NonLocalPBLDiffusion — local + counter-gradient (Holtslag & Boville 1993 / GEOS-Chem VDIFF)
source
AtmosTransport.Diffusion.BoundaryLayerDiffusionType
struct BoundaryLayerDiffusion{FT} <: AtmosTransport.Diffusion.AbstractDiffusion

Boundary-layer vertical diffusion parameterization. Parametric exponential Kz profile (largest near surface, decaying upward).

Forward: implicit tridiagonal solve (Thomas algorithm). Adjoint: transposed tridiagonal solve (transposed Thomas algorithm).

  • Kz_max: maximum diffusivity [Pa²/s in pressure coords]

  • H_scale: e-folding scale height in levels from surface

source
AtmosTransport.Diffusion.NonLocalPBLDiffusionType
struct NonLocalPBLDiffusion{FT} <: AtmosTransport.Diffusion.AbstractDiffusion

Non-local PBL diffusion with counter-gradient transport following Holtslag & Boville (1993) / GEOS-Chem VDIFF.

Extends PBLDiffusion with a counter-gradient term γc that represents non-local transport by organized thermals in convective boundary layers. The tridiagonal matrix (LHS) is identical to local K-diffusion; only the RHS gets an additive source term from γc.

  • β_h: Businger-Dyer heat parameter (TM5 default: 15.0)

  • Kz_bg: background Kz above PBL [m²/s]

  • Kz_min: minimum Kz in PBL [m²/s]

  • Kz_max: maximum allowed Kz [m²/s]

  • fak: counter-gradient tuning constant (GEOS-Chem/Holtslag-Boville: 8.5)

  • sffrac: surface layer fraction of PBL (default: 0.1)

source
AtmosTransport.Diffusion.PBLDiffusionType
struct PBLDiffusion{FT} <: AtmosTransport.Diffusion.AbstractDiffusion

Met-data-driven PBL diffusion following TM5's revised LTG scheme (Beljaars & Viterbo 1998). Computes Kz profiles from PBLH, u*, and sensible heat flux using Monin-Obukhov similarity theory.

Unlike BoundaryLayerDiffusion (static exponential Kz), this scheme produces spatially and temporally varying Kz that depends on stability.

  • β_h: Businger-Dyer heat parameter (TM5 default: 15.0)

  • Kz_bg: background Kz above PBL [m²/s] (TM5 default: 0.1)

  • Kz_min: minimum Kz in PBL [m²/s]

  • Kz_max: maximum allowed Kz [m²/s] (safety clamp)

source
AtmosTransport.Diffusion._diffuse_cs_panel_kernel!Method

GPU kernel for cubed-sphere boundary-layer diffusion. Operates on haloed panel arrays where rm = air_mass × mixing_ratio.

For each (i,j) column:

  1. Convert rm → mixing ratio (c = rm/m)
  2. Apply implicit Thomas solve to c
  3. Convert back rm = c_new × m
source
AtmosTransport.Diffusion._nonlocal_pbl_diffuse_kernel!Method

Grid-agnostic KA kernel for non-local PBL diffusion (Holtslag-Boville).

Identical to _pbl_diffuse_kernel! except:

  • Computes counter-gradient γ_c in unstable boundary layers
  • Adds non-local source S_nl to the Thomas RHS at each BL level
  • Accepts sfc_flux (2D) for explicit surface tracer flux

The sfc_flux array provides per-column surface tracer flux [ppm·m/s]. If a column's sfc_flux == 0, the flux is diagnosed from the tracer gradient.

source
AtmosTransport.Diffusion._pbl_diffuse_kernel!Method

Grid-agnostic KA kernel for met-driven PBL diffusion.

For each (i,j) column:

  1. (if :rm) Convert tracer mass → mixing ratio
  2. Compute interface heights from DELP (hydrostatic approximation)
  3. Compute Obukhov length from surface fields
  4. Thomas solve: build tridiagonal + forward eliminate + back-substitute
  5. (if :rm) Convert mixing ratio back to tracer mass

w_scratch stores Thomas w-factors (avoids per-thread allocation on GPU).

source
AtmosTransport.Diffusion._pbl_kzMethod

Compute Kz [m²/s] at a given height using PBL-similarity (revised LTG). Pure function, no side effects — suitable for calling inside GPU kernels.

Physics constants are passed explicitly (no module-level globals).

Pr_inv (≥ 1) is the inverse Prandtl number applied to the unstable BL. It amplifies Kh relative to Km: in convective conditions Kh = Km × Pr_inv. Pass one(FT) for no correction (stable or neutral).

Above the PBL, Kz is linearly tapered from hpbl to 1.2·hpbl (smoothed entrainment zone), avoiding the unrealistic sharp cutoff that can produce artificial tracer gradients at the inversion.

source
AtmosTransport.Diffusion.build_diffusion_coefficientsMethod

Pre-compute the (a, b, c) tridiagonal coefficient vectors for the implicit diffusion solve (I - Δt·D) c_new = c_old. Because the Kz profile and Δz depend only on level index (at reference surface pressure), the coefficients are the same for every (i,j) column and can be computed once.

Works with any grid type that defines grid_size(grid).Nz and Δz(k, grid).

source
AtmosTransport.Diffusion.build_thomas_factorsMethod

Pre-factor the tridiagonal matrix into values needed for Thomas back-sub. For each level k, store w[k] (the modified super-diagonal ratio) and a normalization factor inv_denom[k] = 1 / (b[k] - a[k]*w[k-1]). The kernel then only does: g[1] = d[1] * invdenom[1] g[k] = (d[k] - a[k]*g[k-1]) * invdenom[k] for k=2..Nz x[Nz] = g[Nz] x[k] = g[k] - w[k]*x[k+1] for k=Nz-1..1

source
AtmosTransport.Diffusion.default_Kz_interfaceMethod
default_Kz_interface(k, Nz, Kz_max, H_scale, _)

Exponential Kz profile at interface between level k and k+1. Largest near surface (k close to Nz), decaying upward with e-folding depth H_scale levels.

  • k: interface index (between levels k and k+1)
  • Nz: total number of vertical levels
  • Kz_max: maximum diffusivity [Pa²/s]
  • H_scale: e-folding depth in levels from surface
source
AtmosTransport.Diffusion.diffuse_cs_panels!Method
diffuse_cs_panels!(rm_panels, m_panels, dw, Nc, Nz, Hp)

Apply boundary-layer vertical diffusion to cubed-sphere tracer panels. rm_panels is NTuple{6} of haloed 3D arrays (airmass × mixingratio). m_panels is NTuple{6} of haloed 3D arrays (air mass in kg).

source
AtmosTransport.Diffusion.diffuse_nonlocal_pbl!Method
diffuse_nonlocal_pbl!(rm_panels, m_panels, delp_panels,
                      pblh_panels, ustar_panels, hflux_panels, t2m_panels,
                      sfc_flux_panels, w_scratch_panels,
                      diff, grid, dt, planet)

Apply non-local PBL diffusion (Holtslag-Boville) to cubed-sphere panel arrays.

sfc_flux_panels is a 6-tuple of 2D arrays with per-column surface tracer flux [ppm·m/s]. Pass zeros to use gradient-diagnosed flux.

source
AtmosTransport.Diffusion.diffuse_nonlocal_pbl!Method
diffuse_nonlocal_pbl!(tracers, delp, pblh, ustar, hflux, t2m,
                      sfc_flux, w_scratch, diff, grid, dt, planet)

Apply non-local PBL diffusion to lat-lon tracers (mixing ratios).

sfc_flux is a 2D array with per-column surface tracer flux [ppm·m/s], or nothing to diagnose from gradient.

source
AtmosTransport.Diffusion.diffuse_pbl!Method
diffuse_pbl!(rm_panels, m_panels, delp_panels,
             pblh_panels, ustar_panels, hflux_panels, t2m_panels,
             w_scratch_panels, diff, grid, dt, planet)

Apply met-driven PBL diffusion to cubed-sphere panel arrays.

Each panel's tracer mass (rm) is converted to mixing ratio, diffused with column-varying Kz, then converted back.

source
AtmosTransport.Diffusion.diffuse_pbl!Method
diffuse_pbl!(tracers, delp, pblh, ustar, hflux, t2m,
             w_scratch, diff, grid, dt, planet)

Apply met-driven PBL diffusion to lat-lon tracers (mixing ratios).

Surface fields (pblh, ustar, hflux, t2m) and pressure thickness (delp) come from the met driver. The w_scratch array must have the same shape as the tracer arrays.

source
AtmosTransport.Diffusion.thomas_solve!Method
thomas_solve!(a, b, c, d, x, w, g, N)

Solve tridiagonal system A*x = d in-place using Thomas algorithm. a = sub-diagonal, b = main diagonal, c = super-diagonal. a[1] and c[N] are not used (boundary).

source

Chemistry

AtmosTransport.ChemistryModule
Chemistry

Atmospheric chemistry and loss-rate framework.

Provides a hierarchy of chemistry types for applying species-specific transformations (decay, photolysis, deposition, reactions) to tracer fields.

Type hierarchy

AbstractChemistry
├── NoChemistry               — inert tracers (no-op)
├── AbstractFirstOrderLoss    — first-order loss processes
│   └── RadioactiveDecay      — uniform constant decay (e.g. ²²²Rn)
└── CompositeChemistry        — combine multiple schemes for multi-tracer runs

The framework is designed for extension: future implementations can add spatially varying loss rates k(x,y,z), time-varying rates k(t), or full chemical mechanisms by subtyping AbstractChemistry.

Interface contract

apply_chemistry!(tracers, grid, chem::AbstractChemistry, Δt)
adjoint_chemistry!(adj_tracers, grid, chem::AbstractChemistry, Δt)
source
AtmosTransport.Chemistry.AbstractFirstOrderLossType
abstract type AbstractFirstOrderLoss <: AtmosTransport.Chemistry.AbstractChemistry

Supertype for first-order loss processes of the form:

dc/dt = -k * c

where k is the loss rate (s⁻¹). Subtypes differ in how k is specified:

  • RadioactiveDecay: uniform constant k = ln(2)/t_half
  • Future: SpatiallyVaryingLoss{FT} with k(x,y,z) field
  • Future: TimeVaryingLoss{FT} with k(x,y,z,t) callback
source
AtmosTransport.Chemistry.CompositeChemistryType
struct CompositeChemistry{S} <: AtmosTransport.Chemistry.AbstractChemistry

Applies multiple chemistry schemes sequentially. Use this when different tracers have different chemistry (e.g. ²²²Rn decays while CO₂ is inert).

  • schemes: vector of chemistry schemes to apply in order

Example

chem = CompositeChemistry([
    RadioactiveDecay(; species=:rn222, half_life=330_350.4, FT=Float32),
    # future: PhotolysisLoss(; species=:o3, ...)
])
source
AtmosTransport.Chemistry.RadioactiveDecayType
struct RadioactiveDecay{FT} <: AtmosTransport.Chemistry.AbstractFirstOrderLoss

First-order radioactive decay with a constant, spatially uniform rate.

The tracer is multiplied by exp(-λ Δt) each time step, where λ = ln(2) / t_half. This is exact for constant λ and any Δt.

Works on both CPU Array and GPU CuArray via broadcasting.

Common isotopes

  • ²²²Rn: half_life = 330_350.4 s (3.8235 days)
  • ⁸⁵Kr: half_life = 3.394e8 s (10.76 years)
  • ¹⁴C: half_life = 1.808e11 s (5730 years)
  • species: target tracer name (e.g. :rn222)

  • half_life: radioactive half-life [s]

  • lambda: decay constant λ = ln(2)/half_life [s⁻¹]

source
AtmosTransport.Chemistry.RadioactiveDecayMethod
RadioactiveDecay(; species, half_life, FT=Float64)

Construct a radioactive decay scheme. Precomputes λ = ln(2)/half_life.

Example

rn_decay = RadioactiveDecay(; species=:rn222, half_life=330_350.4, FT=Float32)
source
AtmosTransport.Chemistry.adjoint_chemistry!Method
adjoint_chemistry!(adj_tracers, grid, chem::RadioactiveDecay, Δt)

Adjoint of radioactive decay. Since c_new = c_old * f where f = exp(-λΔt), the adjoint is adj_c_old += f * adj_c_new, which for in-place update is adj_c .*= f — identical to the forward operation (self-adjoint).

source
AtmosTransport.Chemistry.apply_chemistry!Method
apply_chemistry!(tracers, grid, chem::RadioactiveDecay, Δt)

Apply radioactive decay: c .*= exp(-λ Δt) for the target species. Handles both regular arrays and NTuple{6} of panel arrays (cubed-sphere).

source

Time Steppers

AtmosTransport.TimeSteppersModule
TimeSteppers

Time integration for the atmospheric transport model.

The primary scheme is symmetric Strang operator splitting (TM5-style): advectx, advecty, advectz, convect, diffuse, sources, advectz, advecty, advectx.

The adjoint time step reverses the temporal order of operators and calls the adjoint of each operator.

Interface contract

time_step!(model, Δt)
adjoint_time_step!(model, Δt)
source
AtmosTransport.TimeSteppers.ClockType
mutable struct Clock{FT}

Tracks simulation time and iteration count.

  • time: current simulation time [seconds]

  • iteration: current iteration number

  • Δt: current time step [seconds]

source
AtmosTransport.TimeSteppers.OperatorSplittingTimeStepperType
struct OperatorSplittingTimeStepper{FT, A, C, D, Ch} <: AtmosTransport.TimeSteppers.AbstractTimeStepper

TM5-style symmetric Strang splitting.

  • advection: advection scheme

  • convection: convection parameterization

  • diffusion: vertical diffusion parameterization

  • chemistry: chemistry scheme (NoChemistry for inert tracers)

  • Δt_outer: outer time step [seconds] (e.g. 10800 for 3 hours)

source
AtmosTransport.TimeSteppers._extract_velocitiesMethod
_extract_velocities(met)

Extract the velocity NamedTuple (; u, v, w) from a met data object. Works with any object that has .u, .v, .w properties (NamedTuple, struct, or the result of prepare_met_for_physics).

source
AtmosTransport.TimeSteppers.time_step!Method
time_step!(model, Δt, Δp)

Perform one forward time step with TM5-style mass correction (pressure fixer).

Δp is a 3D pressure-thickness array (Nx, Ny, Nz) that is updated in place during each directional advection step. After each 1D advection, the tracer concentration is rescaled by Δp_old / Δp_new to account for the air mass change due to the 1D divergence created by operator splitting.

Initialize Δp from surface pressure at the start of each met-data interval.

source
AtmosTransport.TimeSteppers.time_step!Method
time_step!(model, Δt)

Perform one forward time step using symmetric Strang operator splitting. model must have fields: tracers, met_data, grid, timestepper, clock.

model.met_data should be a NamedTuple (or struct) with at least:

  • u, v, w — staggered velocity arrays for advection
  • optionally conv_mass_flux for convection
  • optionally diffusivity for diffusion

Use prepare_met_for_physics(met_source, grid) to create this from a MetDataSource object.

source
AtmosTransport.TimeSteppers.time_step_massflux!Method
time_step_massflux!(
    model,
    Δt,
    m,
    am,
    bm,
    cm;
    use_limiter,
    cfl_limit
)

TM5-faithful mass-flux time step. Uses pre-computed mass fluxes am, bm, cm and an air mass array m that tracks continuously through the Strang split (X-Y-Z-Z-Y-X) — no reset between directional steps.

use_limiter enables the minmod + positivity slope limiter.

source

Adjoint

AtmosTransport.AdjointModule
Adjoint

Infrastructure for the hand-coded discrete adjoint:

  • Revolve-style checkpointing for memory-bounded adjoint runs
  • 4DVar cost function structure
  • Gradient test utility (adjoint vs finite-difference verification)
source
AtmosTransport.Adjoint.AbstractObservationOperatorType
abstract type AbstractObservationOperator

Supertype for observation operators that map model state to observation space.

Interface contract

observe(op, model_state, time, location) → simulated observation
adjoint_observe!(adj_state, op, innovation, time, location) → accumulate adjoint forcing
source
AtmosTransport.Adjoint.CostFunction4DVarType
struct CostFunction4DVar{FT, B, R, H} <: AtmosTransport.Adjoint.AbstractCostFunction

Standard 4DVar cost function.

  • x_background: prior estimate of control variables

  • B_inv: inverse background error covariance (operator or matrix)

  • R_inv: inverse observation error covariance

  • obs_operator: observation operator (AbstractObservationOperator)

  • observations: vector of (time, location, value) tuples

source
AtmosTransport.Adjoint.RevolveCheckpointerType
struct RevolveCheckpointer{S} <: AtmosTransport.Adjoint.AbstractCheckpointer

Optimal checkpointing using the Revolve algorithm (Griewank & Walther, 2000).

  • n_snapshots: number of checkpoint storage slots

  • storage: storage backend (:memory or :disk)

source
AtmosTransport.Adjoint.StoreAllCheckpointerType
struct StoreAllCheckpointer <: AtmosTransport.Adjoint.AbstractCheckpointer

Simple checkpointer that stores the full tracer state at every time step. Use when memory is not a concern. O(n_steps) memory, no recomputation.

source
AtmosTransport.Adjoint.gradient_testMethod
gradient_test(
    model,
    cost_function,
    control,
    perturbation;
    epsilons
)

Generic gradient test interface. Currently delegates to the keyword-based version using a simple quadratic cost function.

For full 4DVar gradient tests with observation operators, use the keyword version directly with a custom setup.

source
AtmosTransport.Adjoint.gradient_testMethod
gradient_test(
;
    grid,
    timestepper,
    met_data,
    n_steps,
    Δt,
    epsilons,
    verbose
)

Run a gradient test for the full operator-splitting time stepper.

Sets up random initial conditions, runs the forward model n_steps times to compute a cost function J = 0.5 * ||c_final||², then runs the adjoint backward to compute ∇J. Compares the adjoint directional derivative against finite differences for a series of perturbation sizes ε.

Returns a vector of (ε, ratio) pairs. For a correct discrete adjoint, ratio → 1.0 as ε → 0.

Example

# Set up grid and time stepper with no limiter for exact gradients
grid = LatitudeLongitudeGrid(CPU(); size=(8, 4, 5), ...)
ts = OperatorSplittingTimeStepper(
    advection  = SlopesAdvection(use_limiter=false),
    convection = TiedtkeConvection(),
    diffusion  = BoundaryLayerDiffusion(Kz_max=50.0),
    Δt_outer   = 900.0)

# Constant met data (staggered velocities)
met = (; u = fill(5.0, 9, 4, 5),
         v = zeros(8, 5, 5),
         w = zeros(8, 4, 6),
         conv_mass_flux = zeros(8, 4, 6))

results = gradient_test(; grid, timestepper=ts, met_data=met, n_steps=3)
# All ratios should be ≈ 1.0
source
AtmosTransport.Adjoint.run_adjoint!Method
run_adjoint!(
    model,
    met_data,
    checkpointer::AtmosTransport.Adjoint.RevolveCheckpointer,
    n_steps,
    Δt;
    cost_gradient_fn
)

Execute a full forward-then-backward adjoint run with simplified multi-level checkpointing.

Stores n_snapshots checkpoints at evenly spaced steps. During the backward sweep, replays forward from the nearest checkpoint when state is needed.

source
AtmosTransport.Adjoint.run_adjoint!Method
run_adjoint!(
    model,
    met_data,
    checkpointer::AtmosTransport.Adjoint.StoreAllCheckpointer,
    n_steps,
    Δt;
    cost_gradient_fn
)

Execute a full forward-then-backward adjoint run with store-all checkpointing.

Returns the gradient of the cost function w.r.t. the initial tracer state (i.e. model.adj_tracers after the backward pass).

Algorithm (store-all)

  1. Store initial tracer state
  2. Forward loop: for step 1..nsteps: save checkpoint, timestep!
  3. Compute adjoint forcing: adjinit = costgradient_fn(model.tracers)
  4. Copy adjinit into model.adjtracers
  5. Backward loop: for step nsteps..1: restore from checkpoint, adjointtime_step!
  6. Return model.adj_tracers (gradient w.r.t. initial tracers)
source

Callbacks

AtmosTransport.CallbacksModule
Callbacks

Callback and forcing system for user-defined extensions without modifying core code.

Callbacks are checked and executed at defined points in the time-stepping loop. Forcing functions provide additional source terms.

Types

  • DiscreteCallback — fired when condition(model, t) returns true
  • Forcing — a function applied as a source term each time step
source
AtmosTransport.Callbacks.DiscreteCallbackType
struct DiscreteCallback{C, A} <: AtmosTransport.Callbacks.AbstractCallback

Callback that fires when condition(model, t) returns true.

  • condition: (model, t) → Bool

  • affect!: (model) → nothing (mutates model state)

source
AtmosTransport.Callbacks.ForcingType
struct Forcing{F}

User-defined source/forcing term applied every time step.

  • func: (x, y, z, t, params...) → value to be added to tracer tendency
source

I/O

AtmosTransport.IOModule
IO

Input/output for meteorological data, diagnostics, and configuration.

Met data sources (TOML-configured)

All met data sources are configured via TOML files in config/met_sources/:

  • geosfp.toml — NASA GEOS-FP (OPeNDAP, no auth, near real-time)
  • merra2.toml — NASA MERRA-2 (OPeNDAP, Earthdata auth, 1980–present)
  • era5.toml — ECMWF ERA5 (CDS API, ECMWF auth, 1940–present)

Canonical variable names are defined in config/canonical_variables.toml. Adding a new met data source requires only a new TOML file — no Julia code changes for OPeNDAP or local-file sources.

Convenience constructors

met = GEOSFPMetData(; FT=Float64)   # loads geosfp.toml
met = MERRAMetData(; FT=Float64)    # loads merra2.toml
met = ERA5MetData(; FT=Float64)     # loads era5.toml

# Or point to any TOML:
met = MetDataSource(Float64, "path/to/my_source.toml")

Output writers

  • NetCDFOutputWriter — schedule-based NetCDF output
  • Extensible via AbstractOutputWriter

Configuration

  • TOML-based run configuration (configuration.jl)
source
AtmosTransport.IO.GEOS_CS_PRODUCTSConstant

Registry of GEOS cubed-sphere products available from the WashU archive.

Two layout styles:

  • :hourly — one file per hour, organized in Y<year>/M<mm>/D<dd>/ subdirs (GEOS-FP)
  • :daily — one file per day with 24 timesteps, organized in YYYY/MM/ subdirs (GEOS-IT)
source
AtmosTransport.IO._PATH_CACHEConstant

Look up a flat binary surface data file in surface_data_bin_dir by date. Returns empty string if the file doesn't exist or dir is not set. Results are cached to avoid repeated stat syscalls.

source
AtmosTransport.IO.AbstractBinaryReaderType
abstract type AbstractBinaryReader

Supertype for mmap-based binary met-data readers.

Interface

load_window!(cpu_bufs..., reader, window_index)
Base.close(reader)
window_count(reader) → Int
source
AtmosTransport.IO.AbstractMassFluxMetDriverType
abstract type AbstractMassFluxMetDriver{FT} <: AtmosTransport.IO.AbstractMetDriver{FT}

Met driver that reads pre-computed mass fluxes (am, bm, cm, m). Examples: PreprocessedLatLonMetDriver, GEOSFPCubedSphereMetDriver.

source
AtmosTransport.IO.AbstractMetDataType
abstract type AbstractMetData{FT}

Supertype for meteorological data readers. Parametric on float type.

Canonical variable names

All met data types must provide these fields (via get_field):

  • :u_wind — zonal wind [m/s]
  • :v_wind — meridional wind [m/s]
  • :w_wind — vertical wind (pressure velocity) [Pa/s]
  • :temperature — temperature [K]
  • :specific_humidity — specific humidity [kg/kg]
  • :surface_pressure — surface pressure [Pa]
  • :diffusivity — vertical diffusivity Kz [m²/s] (optional)
  • :conv_mass_flux_up — convective updraft mass flux [kg/m²/s] (optional)
  • :conv_mass_flux_down — convective downdraft mass flux [kg/m²/s] (optional)
source
AtmosTransport.IO.AbstractMetDriverType
abstract type AbstractMetDriver{FT}

Supertype for all meteorological data drivers.

Interface contract

Concrete subtypes must implement:

total_windows(driver)           → Int
window_dt(driver)               → FT   (seconds per met window)
steps_per_window(driver)        → Int   (advection sub-steps per window)
load_met_window!(buf, driver, grid, win_index)  → nothing

Optional: metinterval(driver) → FT (time between met updates, seconds) startdate(driver) → Date (simulation start date for output timestamps) daterange(driver) → (startdate, end_date)

source
AtmosTransport.IO.AbstractOutputGridType
abstract type AbstractOutputGrid

Supertype for output grid specifications. Used when the output grid differs from the model grid (e.g. cubed-sphere → lat-lon regridding).

source
AtmosTransport.IO.AbstractRawMetDriverType
abstract type AbstractRawMetDriver{FT} <: AtmosTransport.IO.AbstractMetDriver{FT}

Met driver that reads raw wind fields and computes mass fluxes on the fly. Examples: ERA5MetDriver, GEOSFPWindMetDriver.

source
AtmosTransport.IO.BinaryOutputWriterType
struct BinaryOutputWriter{S<:AtmosTransport.IO.AbstractOutputSchedule, OG} <: AtmosTransport.IO.AbstractOutputWriter

Write diagnostic fields to a flat binary file for fast sequential I/O.

File layout: [8192-byte JSON header | timestep₁ | timestep₂ | ...]

Each timestep: Float64 time_seconds | Float32 field₁ | Float32 field₂ | ...

The file handle stays open for the duration of the simulation (or until the next daily rollover when split=:daily).

Call finalize_output! at the end of a run to update the header with the actual number of timesteps and optionally convert to NetCDF.

  • filepath: output file path (.bin) or stem for daily splitting

  • fields: name → field, function, or AbstractDiagnostic

  • schedule: output schedule

  • output_grid: optional output grid for regridding (nothing = native grid)

  • _write_count: number of writes so far (for current file when split=:daily)

  • _regrid_cache: lazily-built RegridMapping for GPU CS→lat-lon regridding

  • _io: persistent file handle (nothing until first write)

  • _header: metadata dict written as JSON header

  • auto_convert: if true, convert to NetCDF after finalize

  • start_date: simulation start date for CF-convention time units

  • split: file splitting mode: :none or :daily

  • _current_date: current date of open file (for daily splitting)

  • _current_path: path of currently open file (may differ from filepath for daily split)

  • _file_write_count: writes to current file (reset on daily rollover, used for per-file Nt)

source
AtmosTransport.IO.CSBinaryReaderType
struct CSBinaryReader{FT} <: AtmosTransport.IO.AbstractBinaryReader

Mmap-based reader for cubed-sphere preprocessed binary files. File layout: [8192-byte JSON header | window₁ data | window₂ data | …]

Each window contains (in order): delp panels × 6, am panels × 6, bm panels × 6.

  • data: mmap'd flat vector over entire data region (always Float32 on disk)

  • io: underlying IOStream

  • Nc: cells per panel edge

  • Nz: number of vertical levels

  • Hp: halo width

  • Nt: number of met windows

  • n_delp_panel: elements per panel for delp (haloed)

  • n_am_panel: elements per panel for am (staggered x)

  • n_bm_panel: elements per panel for bm (staggered y)

  • elems_per_window: total elements per window

  • has_courant: v2+: includes CX/CY Courant numbers (same staggering as am/bm)

  • has_area_flux: v3: includes precomputed XFX/YFX area fluxes (same staggering as am/bm)

  • has_qv: v4: includes QV at start/end of each window (Nc×Nc×Nz per panel, no halo)

  • has_ps: v4: includes PS at start/end of each window (Nc×Nc per panel)

  • n_qv_panel: elements per panel for QV (Nc×Nc×Nz, no halo)

  • n_ps_panel: elements per panel for PS (Nc×Nc)

source
AtmosTransport.IO.CollectionInfoType
struct CollectionInfo

Metadata for a dataset collection within a met data source.

  • key: lookup key (e.g. asmNvinst)

  • dataset: OPeNDAP dataset name or ESDT name

  • collection_name: file-level collection name (for MERRA-2 file naming)

  • frequency: temporal frequency (e.g. inst3, tavg3, tavg1)

  • vertical: vertical grid type (Nv, Ne, Nx, pressure)

  • levels: number of vertical levels

  • description: human-readable description

source
AtmosTransport.IO.CubedSphereMetBufferType
struct CubedSphereMetBuffer{FT, A3<:AbstractArray{FT, 3}} <: AtmosTransport.IO.AbstractMetBuffer{FT}

GPU-resident met-field buffers for cubed-sphere grids.

  • delp: haloed pressure thickness panels (Nc+2Hp, Nc+2Hp, Nz) × 6

  • am: x mass flux panels (Nc+1, Nc, Nz) × 6

  • bm: y mass flux panels (Nc, Nc+1, Nz) × 6

  • cm: z mass flux panels (Nc, Nc, Nz+1) × 6

  • cx: x Courant number panels (Nc+1, Nc, Nz) × 6 — for GCHP-faithful transport

  • cy: y Courant number panels (Nc, Nc+1, Nz) × 6 — for GCHP-faithful transport

  • xfx: x area flux panels (Nc+1, Nc, Nz) × 6 — precomputed with exact sin_sg

  • yfx: y area flux panels (Nc, Nc+1, Nz) × 6 — precomputed with exact sin_sg

source
AtmosTransport.IO.ERA5MetDriverType
struct ERA5MetDriver{FT} <: AtmosTransport.IO.AbstractRawMetDriver{FT}

Met driver that reads raw ERA5 model-level winds and computes mass fluxes on the fly. Suitable for lat-lon grids.

Wind fields are read from NetCDF, interpolated to staggered (face) positions, and mass fluxes are computed from pressure thickness + staggered winds.

  • files: ordered list of ERA5 NetCDF file paths (daily files)

  • A_coeff: hybrid A coefficients for the level range (Nz+1 values)

  • B_coeff: hybrid B coefficients for the level range (Nz+1 values)

  • met_interval: time between met updates [s]

  • dt: advection sub-step size [s]

  • steps_per_win: number of advection sub-steps per met window

  • nt_per_file: number of timesteps per file

  • n_windows: total number of met windows

  • lons: longitude vector (from first file)

  • lats: latitude vector (from first file, S→N)

  • level_top: topmost model level index

  • level_bot: bottommost model level index

  • _start_date: simulation start date (auto-detected from first file)

source
AtmosTransport.IO.ERA5MetDriverMethod
ERA5MetDriver(; FT, files, A_coeff, B_coeff, met_interval=21600, dt=900,
                level_top=50, level_bot=137)

Construct an ERA5 met driver from a list of NetCDF file paths and hybrid coefficients. Grid metadata (lons, lats, Nt) is read from the first file.

source
AtmosTransport.IO.GEOSFPCubedSphereMetDriverType
struct GEOSFPCubedSphereMetDriver{FT} <: AtmosTransport.IO.AbstractMassFluxMetDriver{FT}

Met driver for GEOS-FP cubed-sphere mass fluxes.

  • files: ordered list of data file paths (.bin or .nc4)

  • mode: ingestion mode: :binary or :netcdf

  • windows_per_file: windows per file (for binary multi-file mode)

  • n_windows: total number of met windows

  • Nc: cells per panel edge

  • Nz: number of vertical levels

  • Hp: halo width

  • met_interval: time between met updates [s]

  • dt: advection sub-step size [s]

  • steps_per_win: number of advection sub-steps per met window

  • coord_file: NetCDF file for reading panel coordinates (used by binary mode for regridding)

  • merge_map: merge map for vertical level merging (native level → merged level index), or nothing

  • mass_flux_dt: accumulation time for mass fluxes [s] (dynamics timestep; defaults to met_interval)

  • _start_date: simulation start date (for output timestamps)

  • surface_data_dir: directory with regridded CS surface fields (A1, A3mstE NetCDF); empty = use CTM co-location

  • surface_data_bin_dir: directory with flat binary CS surface fields (A1, A3mstE .bin); empty = use NetCDF fallback

  • surface_data_ll_dir: directory with raw 0.25° lat-lon surface fields for on-the-fly regrid to CS

  • _bilinear_weights: precomputed bilinear weights (i0, j0, wx, wy) for LL→CS regrid; nothing if disabled

  • verbose: print field statistics (wind speed, DELP ordering, NaN) on first window and every 24th

source
AtmosTransport.IO.GEOSFPCubedSphereMetDriverMethod
GEOSFPCubedSphereMetDriver(; FT, preprocessed_dir="", netcdf_files=[],
                              start_date, end_date, dt=900, met_interval=3600, Hp=3)

Construct a GEOS-FP cubed-sphere met driver.

If preprocessed_dir is given and contains .bin files, uses binary mode. Otherwise falls back to NetCDF files (either from netcdf_files or discovered in a data directory).

source
AtmosTransport.IO.GeosFPCubedSphereTimestepType
struct GeosFPCubedSphereTimestep{FT}

Container for one timestep of GEOS-FP cubed-sphere mass-flux data.

Mass fluxes are stored in C-grid convention: MFXC(i,j) is the flux through the east face of cell (i,j). Unlike a staggered grid, both arrays are (Nc, Nc, Nz) per panel.

The raw values from the file are "pressure-weighted accumulated" (Pa m²). Use convert_massflux_to_kgs! to convert to kg/s.

  • mfxc: X-direction mass flux per panel, NTuple{6, Array{FT,3}}, each (Nc, Nc, Nz)

  • mfyc: Y-direction mass flux per panel, NTuple{6, Array{FT,3}}, each (Nc, Nc, Nz)

  • delp: Pressure thickness per panel, NTuple{6, Array{FT,3}}, each (Nc, Nc, Nz)

  • ps: Surface pressure per panel, NTuple{6, Array{FT,2}}, each (Nc, Nc)

  • time: Timestamp

  • Nc: Cells per panel edge

  • Nz: Number of vertical levels

  • dt_met: Accumulation interval in seconds (for unit conversion)

source
AtmosTransport.IO.LatLonCPUBufferType
struct LatLonCPUBuffer{FT} <: AtmosTransport.IO.AbstractCPUStagingBuffer{FT}

CPU-side staging buffer for lat-lon met data (H→D transfer source).

  • m

  • am

  • bm

  • cm

  • ps

source
AtmosTransport.IO.LatLonMetBufferType
struct LatLonMetBuffer{FT, A3<:AbstractArray{FT, 3}, A2<:AbstractArray{FT, 2}} <: AtmosTransport.IO.AbstractMetBuffer{FT}

GPU-resident met-field buffers for lat-lon grids.

  • m_ref: reference air mass (Nx, Ny, Nz) — preserved across sub-steps

  • m_dev: working air mass (Nx, Ny, Nz) — modified during advection

  • am: x mass flux (Nx+1, Ny, Nz)

  • bm: y mass flux (Nx, Ny+1, Nz)

  • cm: z mass flux (Nx, Ny, Nz+1)

  • ps: surface pressure (Nx, Ny)

  • Δp: pressure thickness (Nx, Ny, Nz)

  • u: staggered u-wind (Nx+1, Ny, Nz)

  • v: staggered v-wind (Nx, Ny+1, Nz)

  • ws: pre-allocated advection workspace

source
AtmosTransport.IO.LatLonOutputGridType
struct LatLonOutputGrid{FT} <: AtmosTransport.IO.AbstractOutputGrid

Lat-lon output grid for regridding cubed-sphere data before writing. Supports regional subsetting via bounding box (default: global).

  • Nlon: number of longitude points

  • Nlat: number of latitude points

  • lon0: western boundary [degrees]

  • lon1: eastern boundary [degrees]

  • lat0: southern boundary [degrees]

  • lat1: northern boundary [degrees]

source
AtmosTransport.IO.MassFluxBinaryReaderType
struct MassFluxBinaryReader{FT} <: AtmosTransport.IO.AbstractBinaryReader

Mmap-based reader for lat-lon pre-computed mass-flux binary files. File layout: [4096-byte JSON header | window₁ data | window₂ data | …]

Each window contains (in order): m, am, bm, cm, ps — as flat Float32/Float64.

  • data: mmap'd flat vector over entire data region

  • io: underlying IOStream (must stay open while mmap is live)

  • Nx

  • Ny

  • Nz

  • Nt

  • n_m

  • n_am

  • n_bm

  • n_cm

  • n_ps

  • elems_per_window

  • lons

  • lats

  • dt_seconds

  • half_dt_seconds

  • steps_per_met

  • level_top

  • level_bot

source
AtmosTransport.IO.MetDataSourceType
struct MetDataSource{FT} <: AtmosTransport.IO.AbstractMetData{FT}

Config-driven meteorological data reader. Reads its variable mappings, collection definitions, and access URLs from a TOML configuration file.

  • config: parsed TOML configuration

  • buffers: cached field data (canonical name → array)

  • current_time: time of the currently loaded data

  • local_path: local data directory (overrides OPeNDAP if non-empty)

Construction

# From a specific TOML file:
met = MetDataSource(Float64, "config/met_sources/geosfp.toml")

# Using built-in configs:
met = MetDataSource(Float64, "geosfp")

# Convenience aliases:
met = GEOSFPMetData(Float64)
met = MERRAMetData(Float64)
met = ERA5MetData(Float64)
source
AtmosTransport.IO.MetSourceConfigType
struct MetSourceConfig

Complete configuration for a meteorological data source, parsed from TOML.

  • name: human-readable name (e.g. GEOS-FP)

  • description: source description

  • institution: providing institution

  • grid_info: grid type, resolution, dimensions

  • vertical: hybrid sigma-pressure vertical coordinate

  • access: protocol, base URL, auth settings

  • collections: collection key → info

  • variables: canonical name → mapping

  • toml_path: path to the source TOML file (for error messages)

source
AtmosTransport.IO.NetCDFOutputWriterType
struct NetCDFOutputWriter{S<:AtmosTransport.IO.AbstractOutputSchedule, OG} <: AtmosTransport.IO.AbstractOutputWriter

Write selected fields to NetCDF files on a schedule.

Fields can be:

  • AbstractField — extracted via interior()
  • Function — called with (model) argument
  • AbstractArray — written directly
  • AbstractDiagnostic — auto-computed from model state (column mean, surface slice, etc.)

For cubed-sphere grids, set output_grid to a LatLonOutputGrid to regrid panel data to lat-lon before writing.

  • filename: output file path

  • fields: name → field, function, or AbstractDiagnostic

  • schedule: output schedule

  • output_grid: optional output grid for regridding (nothing = native grid)

  • _write_count: number of writes so far

  • _regrid_cache: lazily-built RegridMapping for GPU CS→lat-lon regridding (nothing until first write)

  • deflate_level: NetCDF deflate compression level (0 = off, 1–9 = increasing compression)

  • digits: decimal places for rounding before write (nothing = no rounding)

  • start_date: simulation start date for CF-convention time units

  • _flux_accumulators: lazily-built flux accumulator state for ColumnFluxDiagnostic (nothing until first use)

source
AtmosTransport.IO.PreprocessedLatLonMetDriverType
struct PreprocessedLatLonMetDriver{FT} <: AtmosTransport.IO.AbstractMassFluxMetDriver{FT}

Met driver for pre-computed lat-lon mass fluxes (binary or NetCDF).

  • files: ordered list of mass-flux file paths (.bin or .nc)

  • windows_per_file: windows per file (indexed by file position)

  • n_windows: total number of met windows across all files

  • dt: advection sub-step size [s]

  • steps_per_win: number of advection sub-steps per met window

  • lons: longitude vector

  • lats: latitude vector

  • Nx

  • Ny

  • Nz

  • level_top: topmost model level index

  • level_bot: bottommost model level index

  • merge_map: merge map for vertical level merging (native level → merged level index), or nothing

  • _start_date: simulation start date (auto-detected from file time variable)

source
AtmosTransport.IO.PreprocessedLatLonMetDriverMethod
PreprocessedLatLonMetDriver(; FT, files, dt=nothing, merge_map=nothing)

Construct a preprocessed lat-lon met driver from file list. Grid metadata and dt are read from the first file's header. If dt is provided, it overrides the file's embedded value. If merge_map is provided, levels are merged on load (see merge_upper_levels).

source
AtmosTransport.IO.TemporalInterpolatorType
mutable struct TemporalInterpolator{M<:AtmosTransport.IO.AbstractMetData}

Manages two adjacent met data snapshots and interpolates between them.

  • met: the met data reader

  • t_prev: time of the earlier snapshot

  • t_next: time of the later snapshot

source
AtmosTransport.IO.TimeIntervalScheduleType
struct TimeIntervalSchedule <: AtmosTransport.IO.AbstractOutputSchedule

Output every interval seconds of simulation time.

  • interval: output interval in seconds of simulation time
source
AtmosTransport.IO.VarMappingType
struct VarMapping

Mapping from a canonical variable name to its native representation in a specific met data source.

  • canonical_name: canonical name (e.g. :u_wind)

  • native_name: name in the met file (e.g. U, u)

  • collection: key into the collections dict (e.g. asmNvinst)

  • unit_conversion: multiplicative factor: canonical = native × factor

  • cds_name: CDS API variable name (ERA5 only; empty otherwise)

source
AtmosTransport.IO.VerticalConfigType
struct VerticalConfig

Vertical coordinate configuration parsed from the [vertical] section of a met source TOML. All met sources use hybrid sigma-pressure coordinates; this struct records the source-specific details (level count, coefficient file).

  • coordinate_type: always HybridSigmaPressure for now

  • coefficients_file: path to the TOML file with A/B coefficients

  • n_levels: number of model levels

  • n_interfaces: number of level interfaces (n_levels + 1)

  • surface_pressure_var: canonical variable for surface pressure

  • log_surface_pressure_var: optional: ln(ps) variable (ERA5 model levels)

source
AtmosTransport.IO.ERA5MetDataMethod
ERA5MetData(
;
    FT,
    local_path,
    config_path
) -> AtmosTransport.IO.MetDataSource{Float64}

Create an ERA5 met data reader from the built-in TOML config.

source
AtmosTransport.IO.GEOSFPMetDataMethod
GEOSFPMetData(
;
    FT,
    local_path,
    config_path
) -> AtmosTransport.IO.MetDataSource{Float64}

Create a GEOS-FP met data reader from the built-in TOML config. Optionally override with a custom config path.

source
AtmosTransport.IO.MERRAMetDataMethod
MERRAMetData(
;
    FT,
    local_path,
    config_path
) -> AtmosTransport.IO.MetDataSource{Float64}

Create a MERRA-2 met data reader from the built-in TOML config.

source
AtmosTransport.IO._a3dyn_path_from_ctmMethod

Derive the A3dyn file path from a CTM_A1 file path by replacing the collection name in the filename. Returns empty string if the file doesn't exist.

A3dyn contains 3-hourly dynamics diagnostics including DTRAIN (detraining mass flux), OMEGA, RH, U, V at layer centers. Used by the RAS convection scheme.

source
AtmosTransport.IO._accumulate_flux_diagnostics!Method
_accumulate_flux_diagnostics!(writer, model; air_mass, tracers, met_fields)

Accumulate column tracer flux diagnostics for all ColumnFluxDiagnostic fields in the writer. Called every met window. Requires met_fields to contain:

  • :mass_flux_x — NTuple{6} GPU panels (Nc+1, Nc, Nz), scaled by mf_scale
  • :mass_flux_y — NTuple{6} GPU panels (Nc, Nc+1, Nz), scaled by mf_scale
  • :mf_scale — scale factor (half_dt) applied to mass fluxes
  • :dt_window — window duration in seconds
source
AtmosTransport.IO._bilinear_bracketMethod

Find the lower bracket index and fractional weight for bilinear interpolation. Returns (ilo, w) where val ≈ arr[ilo] × (1-w) + arr[i_lo+1] × w. Clamps to boundaries.

source
AtmosTransport.IO._build_advectionMethod

Build advection scheme from [advection] TOML section.

[advection]
scheme = "slopes"       # or "ppm" (default "slopes")
ppm_order = 7           # ORD ∈ {4, 5, 6, 7}, only if scheme="ppm"
linrood = false         # Lin-Rood cross-term splitting (CS grids, ppm only)
vertical_remap = false  # remap path for CS PPM
remap_pressure_fix = true  # scale target dp column to source mass (remap path)
source
AtmosTransport.IO._build_diffusionMethod

Build diffusion scheme from [diffusion] TOML section.

[diffusion]
type = "boundary_layer"    # or "none" (default)
Kz_max = 100.0             # Pa²/s  maximum diffusivity
H_scale = 8.0              # e-folding depth in levels from surface
source
AtmosTransport.IO._compute_cs_coordinatesMethod

Compute standard gnomonic cubed-sphere coordinates for Nc cells per edge.

Returns (lons, lats, corner_lons, corner_lats) where:

  • lons, lats: (Nc, Nc, 6) cell-center coordinates [degrees, 0–360]
  • corner_lons, corner_lats: (Nc+1, Nc+1, 6) cell-vertex coordinates [degrees]
source
AtmosTransport.IO._copy_mmap_to_haloed_3d!Method
_copy_mmap_to_haloed_3d!(dst, src_vec, src_off, Nc, Hp, Nz)

Copy a (Nc, Nc, Nz) contiguous mmap region directly into the interior of a (Nc+2Hp, Nc+2Hp, Nz) haloed panel using row-wise copyto! (Nc elements per call). No fill! needed — halos are filled by fillpanelhalos! on GPU.

source
AtmosTransport.IO._correct_cm_residual!Method

Distribute the continuity residual in cm so that cm[:,;,1]=0 (TOA) and cm[:,:,Nz+1]=0 (surface). The correction at each interface is proportional to the cumulative mass fraction above it:

cm_corrected[k] = cm_raw[k] - residual × Σm[1:k-1] / Σm[1:Nz]

This preserves the divergence between adjacent interfaces to first order while removing the accumulated numerical error from spectral wind closure.

source
AtmosTransport.IO._create_netcdf_fileMethod

Create NetCDF file for cubed-sphere grid output.

If output_grid is a LatLonOutputGrid, dimensions are (lon, lat, time). Otherwise native CS output uses GEOSCHEM-compatible dimensions: (Xdim, Ydim, nf, time) for 2D fields, (Xdim, Ydim, nf, lev, time) for 3D. Includes lons(Xdim, Ydim, nf) and lats(Xdim, Ydim, nf) coordinate arrays.

source
AtmosTransport.IO._create_netcdf_fileMethod
_create_netcdf_file(writer, model, grid)

Create a new NetCDF file with dimensions (lon, lat, lev, time) and coordinate variables. Defines all output variables. Does not write any time slices.

source
AtmosTransport.IO._ctm_i1_path_from_ctmMethod

Derive the CTMI1 (hourly QV+PS) file path from a CTMA1 file path. CTM_I1 is the GCHP-standard hourly instantaneous thermodynamic collection. Returns empty string if the file doesn't exist.

source
AtmosTransport.IO._extract_accumulated_fluxMethod
_extract_accumulated_flux(writer, name, model; regrid_cache, output_grid)

Extract accumulated column tracer flux for output. Returns a CPU array (regridded to lat-lon if output_grid is a LatLonOutputGrid).

source
AtmosTransport.IO._extract_field_dataMethod
_extract_field_data(
    field_or_func,
    model;
    air_mass,
    tracers,
    regrid_cache,
    output_grid,
    met_fields
)

Extract array data from a field entry for NetCDF writing. Ensures result is a CPU array.

source
AtmosTransport.IO._field_attribsMethod
_field_attribs(field_entry) → Dict{String,String}

Return a Dict of NetCDF attributes (units, long_name) for a diagnostic or field entry. Used by both direct NetCDF writers and the binary→NC converter.

source
AtmosTransport.IO._find_coord_fileMethod
_find_coord_file(config::Dict) → Union{String, Nothing}

Find a GEOS cubed-sphere coordinate reference file from the configuration. Checks [met_data].coord_file first, then falls back to the first .nc file in [met_data].netcdf_dir.

source
AtmosTransport.IO._geosfp_filenameMethod
_geosfp_filename(date::Date, hour::Int, product::String)

Build the remote filename for a GEOS cubed-sphere file. For :hourly products (GEOS-FP): one file per hour, e.g. GEOS.fp.asm.tavg_1hr_ctm_c0720_v72.20240601_0030.V01.nc4 For :daily products (GEOS-IT): one file per day (24 timesteps), e.g. GEOSIT.20230601.CTM_A1.C180.nc

source
AtmosTransport.IO._get_cs_file_coordsMethod
_get_cs_file_coords(model)

Load cubed-sphere cell-center coordinates from the GEOS-FP file if available. Returns (lons, lats) as (Nc×Nc×6) arrays, or (nothing, nothing) if no coordinate file is available.

source
AtmosTransport.IO._load_dtrain_from_bin!Method

Load DTRAIN from flat binary A3dyn file into pre-allocated panels.

Uses JSON-header binary format (same as A3mstE). Binary layout: [8192-byte JSON header] [timestep 1: DTRAIN p1..p6] [timestep 2] ... Each panel is Nc×Nc×Nz Float32 at layer centers. Vertical ordering is auto-detected from header (bottom-to-top for GEOS-IT, top-to-bottom for GEOS-FP).

source
AtmosTransport.IO._load_gmao_coordinates!Method
_load_gmao_coordinates!(grid::CubedSphereGrid, filepath::String)

Overwrite the gnomonic-computed cell-center coordinates in grid with the authoritative GMAO coordinates from a GEOS-FP/GEOS-IT NetCDF file or gridspec file. When corner coordinates are available, also overwrites cell areas — this eliminates up to 44% per-cell area errors that cause spurious oscillations in the pressure-fixer cm computation.

source
AtmosTransport.IO._load_qv_from_bin!Method

Load QV (specific humidity) from flat binary I3 file into pre-allocated panels.

Binary layout: [8192-byte JSON header] [timestep 1: QV p1..p6] [timestep 2] ... Each panel is Nc×Nc×Nz Float32 at layer centers. Vertical ordering is auto-detected from header (bottom-to-top for GEOS-IT, top-to-bottom for GEOS-FP).

source
AtmosTransport.IO._load_v4_qv_ps!Method
_load_v4_qv_ps!(qv_cpu, ps_panels, qv_next_cpu, ps_next_panels,
                 reader, local_win, Nc, Hp)

Load QV and PS at window boundaries from a v4 mass flux binary. Reads directly from mmap into haloed CPU panels — no intermediate temp buffers, no fill!, no element-by-element loops. Row-wise copyto! (Nc=180 elements per call).

Returns true if loaded, false if unavailable.

source
AtmosTransport.IO._merge_levels_latlon!Method

Merge native-level mass fluxes into coarser merged levels using merge_map.

For m/am/bm: sum native levels within each merged group. For cm: pick native cm at merged interface boundaries (consistent with continuity).

source
AtmosTransport.IO._parse_initial_conditionsMethod
_parse_initial_conditions(ic_cfg::Dict) → PendingInitialConditions

Parse IC config into entries (file + variablemap + timeindex). Also stores uniform IC entries (uniform_value) for deferred application.

source
AtmosTransport.IO._precompute_bilinear_weightsMethod
_precompute_bilinear_weights(cs_lons, cs_lats, src_lons, src_lats, Nc)

Precompute bilinear interpolation weights for mapping a regular lat-lon grid to cubed-sphere panel cell centers.

cs_lons/cs_lats are (Xdim, Ydim, nf) arrays from read_geosfp_cs_grid_info. src_lons/src_lats are 1D vectors of the regular grid coordinates.

Returns (i0, j0, wx, wy) — each an NTuple{6} of (Nc, Nc) arrays. For each CS cell (ii, jj, panel), the interpolated value is:

(1-wx)*(1-wy)*src[i0,j0] + wx*(1-wy)*src[i0+1,j0] +
(1-wx)*wy*src[i0,j0+1] + wx*wy*src[i0+1,j0+1]
source
AtmosTransport.IO._read_cmfmc_llMethod

Read CMFMC from a raw 0.25° A3mstE file and bilinearly interpolate to CS panels. Returns NTuple{6} of haloed 3D arrays (Nc+2Hp, Nc+2Hp, Nz_edge).

GEOS-FP 0.25° is already top-to-bottom (k=1=TOA), matching model convention.

source
AtmosTransport.IO._read_surface_fields_llMethod

Read surface fields from a raw 0.25° A1 file and bilinearly interpolate to CS panels. Returns a NamedTuple (pblh, ustar, hflux, t2m) where each is an NTuple{6} of haloed 2D arrays (Nc+2Hp, Nc+2Hp).

source
AtmosTransport.IO._regrid_panels_to_latlonMethod
_regrid_panels_to_latlon(panels, model, grid, output_grid, regrid_cache)

Regrid NTuple{6} of 2D panel data to a lat-lon array using GEOS-FP file coordinates (NOT gnomonic grid coordinates). Builds the RegridMapping lazily via regrid_cache (shared across all diagnostics).

Returns a CPU Array{FT,2} of size (Nlon, Nlat).

source
AtmosTransport.IO._surface_data_pathMethod
_surface_data_path(driver, file_idx, collection) → String

Look up a regridded surface data file in surface_data_dir by date. The date is derived from the file index (one file per day, day = fileidx offset from startdate). Returns empty string if the file doesn't exist.

source
AtmosTransport.IO._surface_ll_pathMethod
_surface_ll_path(driver, file_idx, collection) → String

Look up a raw 0.25° lat-lon surface data file in surface_data_ll_dir by date. Returns empty string if the file doesn't exist or LL dir is not set.

source
AtmosTransport.IO.build_model_from_configMethod
build_model_from_config(path::String) → TransportModel
build_model_from_config(config::Dict) → TransportModel

Build a fully configured TransportModel from a TOML file or parsed Dict.

Example TOML

[architecture]
use_gpu = true
float_type = "Float32"

[grid]
type = "cubed_sphere"       # or "latlon"
Nc = 720                    # for cubed_sphere
met_source = "geosfp"       # or "era5"

[met_data]
driver = "geosfp_cs"        # or "era5", "preprocessed_latlon"
preprocessed_dir = "~/data/geosfp_cs/preprocessed"
start_date = "2024-06-01"
end_date = "2024-06-05"
dt = 900
met_interval = 3600

[tracers.co2]
emission = "edgar"
edgar_version = "v8.0"
year = 2022

[output]
filename = "output.nc"
interval = 3600
output_grid = "latlon"
Nlon = 720
Nlat = 361

[buffering]
strategy = "single"          # or "double"
source
AtmosTransport.IO.build_vertical_coordinateMethod
build_vertical_coordinate(
    config::AtmosTransport.IO.MetSourceConfig;
    FT,
    level_range
) -> AtmosTransport.Grids.HybridSigmaPressure

Construct a HybridSigmaPressure from a met source configuration. Optionally pass level_range (e.g., 50:137) to select a subset of levels.

This is the universal entry point for building the vertical coordinate regardless of met source — the same code works for ERA5 (137 levels), GEOS-FP (72 levels), or MERRA-2 (72 levels).

Example

config = default_met_config("geosfp")
vc = build_vertical_coordinate(config)   # 72-level HybridSigmaPressure
source
AtmosTransport.IO.cgrid_to_staggered_panelsMethod
cgrid_to_staggered_panels(mfxc_panels, mfyc_panels)

Convert C-grid mass fluxes (where MFXC(i,j) = flux through east face of cell (i,j), MFYC(i,j) = flux through north face of cell (i,j)) to staggered arrays compatible with the advection kernels:

  • am: (Nc+1, Nc, Nz) — flux through X-faces (am(i,j) = flux into cell i from left)
  • bm: (Nc, Nc+1, Nz) — flux through Y-faces (bm(i,j) = flux into cell j from below)

Panel boundary fluxes (am[1,:,:] and bm[:,1,:]) are extracted from the adjacent panel's shared edge, using the correct flux variable (MFXC for east/west edges, MFYC for north/south edges) and applying the along-edge orientation flip.

The connectivity matches the GEOS-FP native cubed-sphere file convention (nf=1..6), verified from corner coordinate data.

West boundary connectivity: am[1, j, k] reads from neighbor's outgoing flux. Panels 2, 4, 6: neighbor's east edge (highX) → read MFXCq, aligned Panels 1, 3, 5: neighbor's north edge (highY) → read MFYCq, reversed

South boundary connectivity: bm[i, 1, k] reads from neighbor's outgoing flux. Panels 1, 3, 5: neighbor's north edge (highY) → read MFYCq, aligned Panels 2, 4, 6: neighbor's east edge (highX) → read MFXCq, reversed

source
AtmosTransport.IO.compute_continuity_omegaMethod
compute_continuity_omega(u, v, grid; p_surface)

Compute continuity-consistent vertical velocity (omega, Pa/s) from staggered horizontal winds on a LatitudeLongitudeGrid. This follows the TM5 approach (Bregman et al. 2003): integrate the horizontal mass flux divergence downward from the model top, then apply a correction so that omega vanishes at both the top and bottom boundaries.

The result satisfies the discrete continuity equation column-by-column, which eliminates the spurious convergence/divergence extremes that arise when using raw ERA5 omega with a fixed reference-pressure grid spacing.

Arguments

  • u: zonal wind on x-faces, size (Nx+1, Ny, Nz) [m/s]
  • v: meridional wind on y-faces, size (Nx, Ny+1, Nz) [m/s]
  • grid: the LatitudeLongitudeGrid providing geometry and vertical coordinate

Keyword arguments

  • p_surface: per-column surface pressure (Nx, Ny) array. When nothing (default) the grid's reference pressure is used uniformly.

Returns

  • ω: vertical velocity at z-interfaces, size (Nx, Ny, Nz+1) [Pa/s]. Sign convention: ω > 0 = downward (toward higher pressure / increasing k). Boundary values ω[:,:,1] = 0 (model top) and ω[:,:,Nz+1] = 0 (surface) are guaranteed by construction.
source
AtmosTransport.IO.convert_binary_to_netcdfMethod
convert_binary_to_netcdf(bin_path; nc_path=nothing, deflate_level=0) → nc_path

Read a binary output file and convert it to CF-compliant NetCDF. Streams timesteps one at a time for memory efficiency.

Supports both lat-lon and native cubed-sphere grids.

Can be called standalone from the Julia REPL:

using AtmosTransport
convert_binary_to_netcdf("output.bin"; deflate_level=4)
source
AtmosTransport.IO.default_met_configMethod
default_met_config(source)

Load a built-in met source config by short name.

Examples

config = default_met_config("geosfp")
config = default_met_config("merra2")
config = default_met_config("era5")
source
AtmosTransport.IO.ensure_local_cacheMethod
ensure_local_cache(src_path) → String

Optionally copy a binary file to local fast storage before mmap reading. By default, returns src_path unchanged (assumes data is already on fast disk). Set LOCAL_CACHE_DIR to a path to enable caching (e.g. for NFS → local NVMe).

source
AtmosTransport.IO.finalize_ic_vertical_interp!Method
finalize_ic_vertical_interp!(tracers, m_panels, delp_panels, grid)

After the first met window loads DELP and air mass is computed, perform pressure-based vertical interpolation of deferred IC data and convert from mixing ratio (mol/mol) to tracer mass (rm = q × m).

delp_panels should be NTuple{6} of GPU arrays with DELP [Pa]. m_panels should be NTuple{6} of GPU arrays with air mass [kg].

source
AtmosTransport.IO.finalize_ic_vertical_interp!Method
finalize_ic_vertical_interp!(tracers, m_3d, grid::LatitudeLongitudeGrid)

Lat-lon version: performs pressure-based vertical interpolation for deferred file-based ICs, and applies uniform ICs. LatLon tracers store mixing ratios (q), so the result is the interpolated mixing ratio directly (no mass conversion).

Target pressure levels are derived from air mass: dp = m × g / area. Source pressure levels from hybrid sigma: p = ap + bp × Psurf. Interpolation is linear in log-pressure.

source
AtmosTransport.IO.finalize_output!Method
finalize_output!(writer)

Finalize an output writer at the end of a simulation. No-op for most writers. For BinaryOutputWriter, updates the header with final Nt and optionally converts to NetCDF.

source
AtmosTransport.IO.finalize_output!Method
finalize_output!(writer)

Close the binary output file and update the header with the actual number of timesteps written. If auto_convert=true, converts to NetCDF.

source
AtmosTransport.IO.find_era5_filesMethod
find_era5_files(datadirs) → Vector{String}

Find ERA5 model-level NetCDF files across multiple data directories. Matches files starting with era5_ml_ and ending with .nc, excluding _tmp files.

source
AtmosTransport.IO.find_geosfp_cs_filesMethod
find_geosfp_cs_files(datadir, start_date, end_date; product="geosfp_c720") → Vector{String}

Find raw GEOS cubed-sphere NetCDF files in datadir.

For :hourly products (GEOS-FP): expects datadir/YYYYMMDD/*.nc4 (24 files/day). For :daily products (GEOS-IT): expects datadir/YYYYMMDD/GEOSIT.*.nc (1 file/day).

source
AtmosTransport.IO.find_massflux_shardsMethod
find_massflux_shards(dir, ft_tag) → Vector{String}

Discover monthly mass-flux shard files in dir. Prefers .bin over .nc for each month. Returns sorted list of file paths.

ft_tag is "float32" or "float64".

source
AtmosTransport.IO.find_preprocessed_cs_filesMethod
find_preprocessed_cs_files(dir, start_date, end_date, ft_tag) → Vector{String}

Find preprocessed cubed-sphere binary files in dir for the given date range. Expected filename pattern: geosfp_cs_YYYYMMDD_<ft_tag>.bin.

source
AtmosTransport.IO.geosfp_cs_local_pathMethod
geosfp_cs_local_path(date::Date; hour::Int=-1,
                     base_dir=joinpath(homedir(), "data", "geosfp_cs"),
                     product="geosfp_c720")

Build the local file path for a downloaded GEOS cubed-sphere file.

source
AtmosTransport.IO.geosfp_cs_tavg_urlMethod
geosfp_cs_tavg_url(date::Date, hour::Int; product="geosfp_c720")

Build URL for a GEOS cubed-sphere file from the Washington University archive.

product selects the data source — see GEOS_CS_PRODUCTS for available keys (e.g. "geosfp_c720", "geosit_c180"). For hourly products, hour selects which hourly file. For daily products, hour is ignored (the URL points to a whole-day file).

source
AtmosTransport.IO.get_era5_grid_infoMethod
get_era5_grid_info(filepath, FT)

Read ERA5 grid metadata: lons, lats (flipped S→N), level indices, and time count. Returns (lons, lats, levs, Nx, Ny, Nz, Nt).

source
AtmosTransport.IO.initialize_output!Method
initialize_output!(writer, model)

Create the NetCDF file with proper dimensions from model.grid, define all variables from writer.fields, and write coordinate variables (lon, lat, lev).

source
AtmosTransport.IO.load_all_window!Method
load_all_window!(cpu_buf, cmfmc_cpu, dtrain_cpu, sfc_cpu, troph_cpu,
                  driver, grid, win; needs_cmfmc, needs_dtrain, needs_sfc,
                  needs_qv, qv_cpu, ps_panels, qv_next_cpu, ps_next_panels)

Load all met data for a single window: mass fluxes + CMFMC + surface fields + DTRAIN + QV. Designed to be called from the async background thread in the double-buffer run loop so that all disk reads overlap with GPU compute.

Returns a NamedTuple (cmfmc, dtrain, sfc, qv) with the status of each load (false, true, or :cached).

source
AtmosTransport.IO.load_canonical_configMethod
load_canonical_config(toml_path)

Parse the canonical variables TOML file. Returns a dict mapping canonical variable names to their properties (units, dimensions, required, etc.).

source
AtmosTransport.IO.load_cmfmc_window!Method
load_cmfmc_window!(cmfmc, driver::PreprocessedLatLonMetDriver, grid, win) → Bool

Read convective mass flux for window win into cmfmc (Nx, Ny, Nz+1). Returns true if data was loaded, false if the file doesn't contain conv_mass_flux (or is binary format).

source
AtmosTransport.IO.load_configurationMethod
load_configuration(path)

Load a TOML configuration file and return a Dict.

Standard sections:

  • [architecture] — CPU/GPU, float type
  • [grid] — grid type, resolution, vertical levels
  • [met_data] — met driver type and paths
  • [tracers] — tracer definitions + emission sources
  • [output] — output fields, schedule, filename
  • [buffering] — single or double buffer
source
AtmosTransport.IO.load_cs_cx_cy_window!Method
load_cs_cx_cy_window!(cx_cpu, cy_cpu, reader::CSBinaryReader, win)

Load CX/CY Courant numbers from a v2 binary file. Returns false if the file doesn't contain Courant numbers (v1 format).

source
AtmosTransport.IO.load_cs_qv_ps_window!Method
load_cs_qv_ps_window!(qv_start, qv_end, ps_start, ps_end, reader, win)

Load embedded QV and PS at window boundaries from a v4 binary file. QV panels are (Nc, Nc, Nz) without halos; PS panels are (Nc, Nc). Returns false if the file doesn't contain QV/PS (v1-v3 format).

source
AtmosTransport.IO.load_cs_window!Method
load_cs_window!(delp_cpu, am_cpu, bm_cpu, reader::CSBinaryReader, win)

Copy cubed-sphere met fields for window win from the mmap'd binary into pre-allocated CPU panel tuples (NTuple{6}).

source
AtmosTransport.IO.load_cs_xfx_yfx_window!Method
load_cs_xfx_yfx_window!(xfx_cpu, yfx_cpu, reader::CSBinaryReader, win)

Load precomputed area fluxes from a v3 binary file. Returns false if the file doesn't contain area fluxes (v1/v2 format).

source
AtmosTransport.IO.load_cx_cy_window!Method
load_cx_cy_window!(cpu_buf::CubedSphereCPUBuffer, driver, grid, win)

Load CX/CY (accumulated Courant numbers) from NetCDF for GCHP-faithful transport. Only loads if cpubuf.cx is not nothing (i.e., usegchp=true in buffer allocation).

CX and CY have the same staggering as MFXC/MFYC — they're read from the same CTM collection (tavg1hrctm) as mass fluxes.

For binary mode, CX/CY must be included in the preprocessed binary (future work).

source
AtmosTransport.IO.load_edgar_cs_binaryMethod
load_edgar_cs_binary(bin_path, FT) → NTuple{6, Matrix{FT}}

Read a preprocessed EDGAR emission file on cubed-sphere panels. File layout: [4096-byte JSON header | panel₁ data | … | panel₆ data]

source
AtmosTransport.IO.load_initial_conditions!Method
load_initial_conditions!(tracers, filepath, grid::CubedSphereGrid; ...)

Load initial conditions for cubed-sphere grids. The source file is expected to be on a lat-lon grid; the loader regrids to each CS panel via nearest-neighbor interpolation.

tracers should be a NamedTuple where each value is an NTuple{6} of 3D haloed panel arrays.

source
AtmosTransport.IO.load_initial_conditions!Method
load_initial_conditions!(tracers, filepath, grid;
                          variable_map=Dict{Symbol,String}(),
                          time_index=1)

Load 3D initial condition fields from filepath into tracers.

Arguments:

  • tracers: NamedTuple of 3D arrays (e.g., (co2=Array{FT,3}, sf6=Array{FT,3}, ...))
  • filepath: path to NetCDF file containing initial fields
  • grid: model grid (LatitudeLongitudeGrid or CubedSphereGrid)
  • variable_map: maps tracer symbol → NetCDF variable name. For example: Dict(:co2 => "CO2", :sf6 => "SF6"). Tracers not in the map are skipped (left at their current values).
  • time_index: time step to read from multi-time files (default: 1)

For lat-lon grids, the loader performs bilinear interpolation from the source grid to the model grid when dimensions differ, or direct copy when they match.

Tracers not listed in variable_map are left unchanged (e.g., fossil_co2 and rn222 start from zero in CATRINE).

source
AtmosTransport.IO.load_met_configMethod
load_met_config(toml_path)

Parse a met source TOML file into a MetSourceConfig.

Example

config = load_met_config("config/met_sources/geosfp.toml")
config.name            # "GEOS-FP"
config.variables[:u_wind].native_name  # "u"
config.collections["asm_Nv_inst"].dataset  # "inst3_3d_asm_Nv"
source
AtmosTransport.IO.load_met_window!Method
load_met_window!(cpu_buf::LatLonCPUBuffer, driver::ERA5MetDriver, grid, win)

Read ERA5 winds for window win, stagger them, and build pressure thickness into cpu_buf. Returns the surface pressure array.

For ERA5, the CPU buffer is filled with:

  • cpu_buf.am ← staggered u-wind (Nx+1, Ny, Nz)
  • cpu_buf.bm ← staggered v-wind (Nx, Ny+1, Nz)
  • cpu_buf.m ← pressure thickness (Nx, Ny, Nz)
  • cpu_buf.ps ← surface pressure (Nx, Ny)

Note: For ERA5, the CPU buffer fields am/bm temporarily hold staggered winds (not mass fluxes). The GPU-side compute step converts them to true mass fluxes via compute_mass_fluxes!.

source
AtmosTransport.IO.load_met_window!Method
load_met_window!(cpu_buf::LatLonCPUBuffer, driver::PreprocessedLatLonMetDriver, grid, win)

Read pre-computed mass fluxes for window win into cpu_buf. Opens the appropriate file, reads the window, and closes.

source
AtmosTransport.IO.load_ps_from_ctm_i1!Method
load_ps_from_ctm_i1!(ps_panels, driver, grid, win) → true|false

Load surface pressure from CTMI1 (hourly instantaneous) into 2D panels. PS is in hPa from CTMI1. Returns false if CTM_I1 not available.

source
AtmosTransport.IO.load_qv_and_ps_pair!Method
load_qv_and_ps_pair!(qv_curr, qv_next, ps_curr, ps_next, driver, grid, win) → Bool

Load before/after QV+PS from CTM_I1 for GCHP-style DryPLE computation.

  • qvcurr, pscurr ← CTM_I1 at time=win (SPHU1, PS1)
  • qvnext, psnext ← CTM_I1 at time=win+1 (SPHU2, PS2)

For the last window of a day, reads PS2/SPHU2 from next day's CTMI1 t=1. Returns false if CTMI1 is not available.

source
AtmosTransport.IO.load_qv_window!Method
load_qv_window!(qv, driver::PreprocessedLatLonMetDriver, grid, win) → Bool

Read specific humidity (QV) for window win into qv (Nx, Ny, Nz). Returns true if data was loaded, false if the file doesn't contain a QV variable (or is binary format).

source
AtmosTransport.IO.load_qv_window!Method
load_qv_window!(qv_panels, driver, grid, win)

Load specific humidity (QV) into pre-allocated panels.

Tries CTMI1 (hourly instantaneous, GCHP-standard) first, then falls back to I3 (3-hourly instantaneous). CTMI1 provides QV at the same cadence as mass fluxes — this is what GCHP 14.7+ uses for SPHU1/SPHU2 imports.

Returns true if QV was loaded, :cached if unchanged, false if unavailable.

source
AtmosTransport.IO.load_surface_fields_window!Method
load_surface_fields_window!(sfc_panels, driver::GEOSFPCubedSphereMetDriver, grid, win;
                             troph_panels=nothing, ps_panels=nothing)

Load surface fields (PBLH, USTAR, HFLUX, T2M) from A1 files into pre-allocated panels.

A1 data is hourly (24 timesteps/day), same as CTM_A1, so the time index maps directly.

sfc_panels is a NamedTuple (pblh, ustar, hflux, t2m) where each is an NTuple{6} of 2D arrays (Nc+2Hp, Nc+2Hp).

If troph_panels is provided, also loads TROPPT (tropopause pressure, Pa). If ps_panels is provided, also loads PS (surface pressure, Pa) from v2+ binaries.

Returns true if surface fields were loaded, false if A1 data is not available.

source
AtmosTransport.IO.load_surface_fields_window!Method
load_surface_fields_window!(sfc, driver::PreprocessedLatLonMetDriver, grid, win) → Bool

Read PBL surface fields for window win into sfc NamedTuple with pblh, ustar, hflux, t2m arrays (each Nx × Ny). Returns true if all four fields were loaded, false if any are missing (or binary format).

source
AtmosTransport.IO.load_tm5conv_window!Method
load_tm5conv_window!(tm5conv, driver::PreprocessedLatLonMetDriver, grid, win) → Bool

Read TM5 convection fields (entu, detu, entd, detd) for window win. tm5conv is a NamedTuple with fields entu, detu, entd, detd, each of size (Nx, Ny, Nz). Returns true if all four fields were loaded, false if any are missing (or binary format).

source
AtmosTransport.IO.load_vertical_coefficientsMethod
load_vertical_coefficients(
    config::AtmosTransport.IO.MetSourceConfig;
    FT
) -> Tuple{Any, Any}

Load hybrid sigma-pressure A/B coefficients from the file referenced in the met source configuration. Works for any met source (ERA5, GEOS-FP, MERRA-2) because every source's TOML has a [vertical] section pointing to its coefficient file.

The returned vectors have length n_interfaces (= n_levels + 1).

Example

config = default_met_config("era5")
A, B = load_vertical_coefficients(config)   # 138-element vectors
source
AtmosTransport.IO.load_window!Method
load_window!(m, am, bm, cm, ps, reader::MassFluxBinaryReader, win)

Copy met fields for window win from the mmap'd binary into pre-allocated CPU arrays. Zero-copy from the mmap region via copyto!.

source
AtmosTransport.IO.prepare_met_for_physicsMethod
prepare_met_for_physics(
    met,
    grid;
    use_continuity_omega,
    p_surface
)

Convert the cell-center met data fields into the staggered arrays required by the physics operators. Returns a NamedTuple with:

  • u, v, w — staggered velocity components for advection
  • conv_mass_flux — net convective mass flux at interfaces (if available)
  • diffusivity — vertical diffusivity (if available)

This function is the bridge between the I/O system (canonical variables at cell centers) and the physics operators (staggered grids).

Keyword arguments

  • use_continuity_omega: if true (default for LatitudeLongitudeGrid), compute w from horizontal wind divergence via the continuity equation rather than staggering raw omega. This eliminates extreme values caused by inconsistent wind divergence and is the TM5 approach.
  • p_surface: optional per-column surface pressure (Nx, Ny) array.
source
AtmosTransport.IO.read_geosfp_cs_cmfmcMethod
read_geosfp_cs_cmfmc(filepath; FT, time_index, Hp)

Read convective mass flux (CMFMC) from a GEOS-IT A3mstE file.

CMFMC is at edge levels: (Nc, Nc, 6, Nz+1) where Nz+1 = 73 for 72 vertical layers. The returned NTuple{6} arrays are haloed to (Nc+2Hp, Nc+2Hp, Nz+1) with zero padding in halos.

GEOS-IT stores levels bottom-to-top (k=1 = surface). This function auto-detects and flips to TOA-first (k=1 = TOA) for consistency with the main met data reader.

Arguments

  • filepath: path to a GEOSIT.YYYYMMDD.A3mstE.C*.nc file
  • FT: float type (default Float32)
  • time_index: which 3-hourly timestep to read (1–8 for daily file)
  • Hp: halo padding width

Returns

  • cmfmc_haloed: NTuple{6, Array{FT,3}} of shape (Nc+2Hp, Nc+2Hp, Nz+1)
source
AtmosTransport.IO.read_geosfp_cs_dtrainMethod
read_geosfp_cs_dtrain(filepath; FT, time_index, Hp)

Read DTRAIN (detraining mass flux) from a GEOS-IT/FP A3dyn file.

DTRAIN is the convective detrainment rate [kg/m²/s] at layer centers, used by the RAS convection scheme alongside CMFMC. The detrainment flux represents cloud air being mixed back into the environment at each level's neutral buoyancy height.

The data is stored at layer centers (Nz levels, not Nz+1 edges like CMFMC). GEOS-IT files are bottom-to-top; this function flips to TOA-first convention.

Arguments

  • filepath: path to a GEOSIT.YYYYMMDD.A3dyn.C*.nc file
  • FT: float type (default Float32)
  • time_index: which 3-hourly timestep (1–8 for daily file)
  • Hp: halo padding width

Returns

  • dtrain_haloed: NTuple{6, Array{FT,3}} of shape (Nc+2Hp, Nc+2Hp, Nz)
source
AtmosTransport.IO.read_geosfp_cs_grid_infoMethod
read_geosfp_cs_grid_info(filepath::String)

Read the cubed-sphere grid coordinates (center lons/lats and corner lons/lats) from a GEOS cubed-sphere file. Returns (lons, lats, corner_lons, corner_lats).

GEOS-FP C720 files have all four; GEOS-IT C180 files only have center coordinates, so corner_lons and corner_lats may be nothing.

source
AtmosTransport.IO.read_geosfp_cs_surface_fieldsMethod
read_geosfp_cs_surface_fields(filepath; FT, time_index, Hp)

Read 2D surface fields (PBLH, USTAR, HFLUX, T2M, and optionally TROPPT) from a GEOS-IT A1 file.

Returns a NamedTuple (pblh, ustar, hflux, t2m[, troph]) where each is an NTuple{6} of haloed 2D arrays (Nc+2Hp, Nc+2Hp).

TROPPT is the tropopause pressure (Pa) based on the thermal lapse-rate definition. It is included when present in the file.

Arguments

  • filepath: path to a GEOSIT.YYYYMMDD.A1.C*.nc file
  • FT: float type (default Float32)
  • time_index: which hourly timestep to read (1–24 for daily file)
  • Hp: halo padding width
source
AtmosTransport.IO.read_geosfp_cs_timestepMethod
read_geosfp_cs_timestep(
    filepath;
    FT,
    time_index,
    dt_met,
    convert_to_kgs
)

Read one timestep of GEOS-FP cubed-sphere data from a local NetCDF file.

The file should be from the tavg_1hr_ctm_c0720_v72 collection. All variables (MFXC, MFYC, DELP, PS) are read from the same file.

Raw mass fluxes are in Pa⋅m² (pressure-weighted accumulated). Set convert_to_kgs=true to automatically convert to kg/s.

Arguments

  • filepath: Path to the NetCDF4 file
  • FT: Float type (default Float32, matching file storage)
  • time_index: Time index within the file (default 1)
  • dt_met: Accumulation interval in seconds (default 3600.0 for 1-hour)
  • convert_to_kgs: If true, convert mass fluxes from Pa⋅m² to kg/s
source
AtmosTransport.IO.read_met!Method
read_met!(
    met::AtmosTransport.IO.MetDataSource{FT},
    time_seconds::Real;
    variables
)

Read meteorological data for the given time into internal buffers.

Dispatches on the access protocol:

  • "opendap" → reads directly from OPeNDAP URL
  • "local" → reads from local NetCDF files (in met.local_path)
source
AtmosTransport.IO.stagger_winds!Method
stagger_winds!(u_stag, v_stag, u_cc, v_cc, Nx, Ny, Nz)

Interpolate cell-centered wind fields to staggered (face) positions. ustag has shape (Nx+1, Ny, Nz), vstag has shape (Nx, Ny+1, Nz).

source
AtmosTransport.IO.to_haloed_panelsMethod
to_haloed_panels(ts; Hp)

Convert a GeosFPCubedSphereTimestep to haloed panel arrays suitable for the cubed-sphere mass-flux advection kernels.

Returns (delp_haloed, mfxc, mfyc) where:

  • delp_haloed: NTuple{6, Array{FT,3}} with halo padding (Nc+2Hp × Nc+2Hp × Nz)
  • mfxc, mfyc: unchanged interior-only flux arrays
source
AtmosTransport.IO.upload!Method
upload!(gpu_buf::CubedSphereMetBuffer, cpu_buf::CubedSphereCPUBuffer)

Copy CPU staging buffer contents to GPU cubed-sphere met buffer.

source
AtmosTransport.IO.validate_met_configMethod
validate_met_config(
    config::AtmosTransport.IO.MetSourceConfig;
    canonical_path
) -> Bool

Validate a met source config against the canonical variables definition. Warns about missing required variables and unknown canonical names.

source
AtmosTransport.IO.write_output!Method
write_output!(
    writer,
    model,
    time;
    air_mass,
    tracers,
    met_fields
)

Write output if the schedule condition is met. Opens or creates the NetCDF file, appends a new time slice for each field, and increments _write_count.

source

Regridding

AtmosTransport.RegriddingModule
Regridding

Interpolation between met data grids and model grids.

When the met data grid differs from the model grid (e.g. ERA5 lat-lon 0.25° to model CubedSphereGrid C90), a regridder maps fields between them.

Regridder types

  • ConservativeRegridder — mass-preserving remapping (for tracers, mass fluxes)
  • BilinearRegridder — smooth interpolation (for winds, temperature)
  • IdentityRegridder — no-op when grids match

Interface contract

regrid!(target_field, source_data, regridder)
source
AtmosTransport.Regridding.BilinearRegridderType
struct BilinearRegridder{FT} <: AtmosTransport.Regridding.AbstractRegridder

Bilinear interpolation using precomputed sparse weights. Fast but not mass-conserving; suitable for smooth fields (wind, temperature).

  • weights: precomputed interpolation weights
source

Diagnostics

AtmosTransport.DiagnosticsModule
Diagnostics

Computed diagnostic fields for output and monitoring.

Provides GPU-compatible (KernelAbstractions) diagnostic computations that dispatch on grid type via multiple dispatch:

column_mean!(c_col, c, m)                                       # lat-lon
column_mean!(c_col_panels, rm_panels, m_panels, Nc, Nz, Hp)    # cubed-sphere

surface_slice!(c_sfc, c)                                        # lat-lon
surface_slice!(c_sfc_panels, c_panels, Nc, Nz, Hp)             # cubed-sphere

regrid_cs_to_latlon(panels, grid; Nlon, Nlat)                   # CS → lat-lon

Abstract diagnostic types

Diagnostic types can be stored in output writer field dicts for automatic computation during output:

ColumnMeanDiagnostic(:co2)
SurfaceSliceDiagnostic(:co2)
RegridDiagnostic(:co2; Nlon=720, Nlat=361)
source
AtmosTransport.Diagnostics.ColumnFluxDiagnosticType
struct ColumnFluxDiagnostic <: AtmosTransport.Diagnostics.AbstractDiagnostic

Time-integrated vertically-integrated column tracer flux (kg/m).

Computes FE = ∫₀ᵀ (1/g) ∫₀ᵖˢ u×qc dp dt (eastward) or FN = ∫₀ᵀ (1/g) ∫₀ᵖˢ v×qc dp dt (northward)

where T is the output interval (e.g. 3 hours). Requires an accumulator in the output writer that is updated every met window and reset on output.

  • species: tracer species symbol (e.g. :co2, :sf6)

  • direction: flux direction: :east for zonal (u×qc) or :north for meridional (v×qc)

source
AtmosTransport.Diagnostics.ColumnMassDiagnosticType
struct ColumnMassDiagnostic <: AtmosTransport.Diagnostics.AbstractDiagnostic

Column-integrated tracer mass (kg/m²). Computes mc = Σk(ck × mk) / A for lat-lon, or mc = Σk(rm_k) / A for cubed-sphere, where A is cell area. Required by CATRINE protocol: mc = (1/g) ∫₀ᵖˢ qc dp.

  • species: tracer symbol (e.g. :co2)
source
AtmosTransport.Diagnostics.EmissionFluxDiagnosticType
struct EmissionFluxDiagnostic <: AtmosTransport.Diagnostics.AbstractDiagnostic

Surface emission flux for a tracer species [kg/m²/s]. Extracts the current emission flux from the model's source vector. For time-varying emissions, returns the active snapshot.

  • species: tracer species symbol (e.g. :fossil_co2, :sf6)
source
AtmosTransport.Diagnostics.Full3DDiagnosticType
struct Full3DDiagnostic <: AtmosTransport.Diagnostics.AbstractDiagnostic

Full 3D tracer field diagnostic. Outputs the complete (lon, lat, lev) tracer array. Required by CATRINE protocol for all 4 tracers every 3 hours.

  • species: tracer symbol (e.g. :co2)
source
AtmosTransport.Diagnostics.MetField2DDiagnosticType
struct MetField2DDiagnostic <: AtmosTransport.Diagnostics.AbstractDiagnostic

2D met field diagnostic (surface pressure, PBL height, tropopause height, etc.). The field is retrieved from model.met_data or computed on-the-fly.

  • field_name: met field identifier (e.g. :surfacepressure, :pblheight, :tropopause_height)
source
AtmosTransport.Diagnostics.RegridDiagnosticType
struct RegridDiagnostic <: AtmosTransport.Diagnostics.AbstractDiagnostic

Cubed-sphere to lat-lon regridded diagnostic.

  • species: tracer symbol

  • Nlon: output longitude count

  • Nlat: output latitude count

source
AtmosTransport.Diagnostics.RegridMappingType
struct RegridMapping{AT_I, AT_F, FT}

Precomputed mapping from cubed-sphere panels to a regular lat-lon output grid. Built once via build_regrid_mapping; reused each write call to avoid redundant coordinate computation.

  • ii_panels: per-panel longitude bin indices (1-based, Nc×Nc; 0 = outside region)

  • jj_panels: per-panel latitude bin indices (1-based, Nc×Nc; 0 = outside region)

  • norm_inv: normalization weights (1/count, Nlon×Nlat)

  • scratch: working accumulator buffer (Nlon×Nlat)

  • gap_mask: boolean mask: true where count == 0 (gap cells needing fill)

  • Nlon: output longitude count

  • Nlat: output latitude count

  • lon0: western boundary [degrees]

  • lon1: eastern boundary [degrees]

  • lat0: southern boundary [degrees]

  • lat1: northern boundary [degrees]

  • n_gaps: number of gap cells

source
AtmosTransport.Diagnostics.SigmaLevelDiagnosticType
struct SigmaLevelDiagnostic <: AtmosTransport.Diagnostics.AbstractDiagnostic

Tracer mixing ratio at a target sigma level (pressure fraction of surface pressure). For sigma=0.8, extracts at the level where p ≈ 0.8 × p_surface (~800 hPa).

  • species: tracer symbol (e.g. :co2)

  • sigma: target sigma level (0..1, where 1 = surface)

source
AtmosTransport.Diagnostics.build_regrid_mappingMethod
build_regrid_mapping(
    grid,
    AT,
    Nlon,
    Nlat;
    lon0,
    lon1,
    lat0,
    lat1,
    file_lons,
    file_lats
)

Build a RegridMapping for the given cubed-sphere grid to a Nlon × Nlat lat-lon output grid.

Index arrays and normalization weights are computed on CPU (using CPU grid coordinates) then uploaded to the target device via AT (e.g. CuArray for GPU, Array for CPU).

source
AtmosTransport.Diagnostics.column_mass!Method
column_mass!(cm_col_panels, rm_panels, Nc, Nz, Hp)

Compute total tracer mass per column for cubed-sphere panels. rm_panels are NTuple{6} of haloed 3D arrays (tracer mass per cell). Result is in kg per column. Divide by cell area for kg/m².

source
AtmosTransport.Diagnostics.column_mass!Method
column_mass!(cm_col, c, m)

Compute total tracer mass per column: cmcol[i,j] = Σk(c[i,j,k] × m[i,j,k]). Result is in kg (tracer mass per grid cell column). Divide by cell area for kg/m².

source
AtmosTransport.Diagnostics.column_mean!Method
column_mean!(c_col_panels, rm_panels, m_panels, Nc, Nz, Hp)

Compute mass-weighted column mean for cubed-sphere panels. rm_panels and m_panels are NTuple{6} of haloed 3D arrays. c_col_panels is NTuple{6} of (Nc × Nc) 2D arrays.

source
AtmosTransport.Diagnostics.column_mean!Method
column_mean!(c_col, c, m)

Compute mass-weighted column mean of 3D tracer field c weighted by air mass m. Result stored in 2D array c_col.

Works on both CPU and GPU via KernelAbstractions.

source
AtmosTransport.Diagnostics.column_tracer_flux!Method
column_tracer_flux!(flux_panels, mf_panels, rm_panels, m_panels, Nc, Nz, Hp, direction)

Compute vertically-integrated column tracer flux for cubed-sphere panels.

mf_panels are mass flux panels: pass am for direction = :east, bm for direction = :north. rm_panels is tracer mass (kg), m_panels is air mass (kg). flux_panels is NTuple{6} of (Nc × Nc) output arrays, filled with Σk mf[facek] × (rm[k]/m[k]) in kg/s.

Note: the mass fluxes may already be scaled (e.g. by half_dt). The caller is responsible for unscaling when accumulating.

source
AtmosTransport.Diagnostics.regrid_cs_to_latlon!Method
regrid_cs_to_latlon!(mapping, c_col_panels)

Regrid cubed-sphere column-mean panels (6 × Nc × Nc, no halo) to a lat-lon grid using a precomputed RegridMapping.

Operates on the device where mapping and c_col_panels reside (GPU or CPU). Returns mapping.scratch (device array, Nlon × Nlat) — caller must Array() it for CPU/NetCDF use.

source
AtmosTransport.Diagnostics.regrid_cs_to_latlonMethod
regrid_cs_to_latlon(panels_cpu, grid; Nlon=720, Nlat=361)

Regrid cubed-sphere panel data (6 × Nc × Nc) to a regular lat-lon grid via nearest-neighbor binning. Returns (data_ll, lons, lats).

panels_cpu must be an NTuple{6, Matrix{FT}} of CPU arrays. grid must be a CubedSphereGrid (used to look up panel center coordinates).

source
AtmosTransport.Diagnostics.sigma_level_slice!Method
sigma_level_slice!(c_out_panels, rm_panels, m_panels, Nc, Nz, Hp, sigma)

Extract tracer mixing ratio at the sigma level for cubed-sphere panels. rm_panels is tracer mass, m_panels is air mass (both NTuple{6} of haloed 3D arrays). c_out_panels is NTuple{6} of (Nc × Nc) 2D arrays.

source

Sources

AtmosTransport.SourcesModule
Sources

Surface flux injection for atmospheric tracers.

Supports gridded flux inventories (EDGAR, CT-NRT, GFAS, Jena CarboScope) with conservative regridding from native resolution to the model grid.

Multi-component fluxes are handled via CombinedFlux (combines multiple sources) and TimeVaryingSurfaceFlux (time-dependent fields like 3-hourly biosphere).

Interface

apply_surface_flux!(tracers, source, grid, dt)
source
AtmosTransport.Sources.AbstractInventorySourceType
abstract type AbstractInventorySource <: AtmosTransport.Sources.AbstractSurfaceFlux

Supertype for named emission inventories. Each subtype carries metadata about the inventory (version, default file paths, species, sector info).

Use load_inventory(source, grid; kwargs...) to load and regrid.

source
AtmosTransport.Sources.CATRINESourceType
struct CATRINESource <: AtmosTransport.Sources.AbstractInventorySource

CATRINE intercomparison inventory (placeholder for future datasets). See: https://www.catrine-project.eu/

  • dataset

  • version

  • filepath

source
AtmosTransport.Sources.CombinedFluxType
struct CombinedFlux{S<:Tuple} <: AtmosTransport.Sources.AbstractSurfaceFlux

Multiple flux sources applied together (e.g. anthropogenic + biosphere + ocean CO₂).

  • components: tuple of AbstractSurfaceFlux components

  • label: human-readable label

source
AtmosTransport.Sources.ConservativeCSMapType
ConservativeCSMap{FT}

Source-indexed conservative mapping from a regular lat-lon grid to cubed-sphere panels. For each source cell at linear index k = (j-1)*Nlon + i, the CSR entries at offsets[k] : offsets[k+1]-1 list the CS cell(s) that the source cell contributes mass to.

Regridding uses mass accumulation: each source cell's mass is scattered to its target CS cell(s), then divided by exact CS cell area to get density. Sub-cell sampling ensures both fine→coarse and coarse→fine work correctly.

source
AtmosTransport.Sources.EdgarSourceType
struct EdgarSource <: AtmosTransport.Sources.AbstractInventorySource

EDGAR (Emissions Database for Global Atmospheric Research) inventory. Anthropogenic fossil + industrial CO2 emissions.

  • version: EDGAR version string (e.g. "v8.0")

  • filepath: path to EDGAR NetCDF file (optional — can be passed to load_inventory)

  • species: species symbol (e.g. :co2, :ch4)

source
AtmosTransport.Sources.SurfaceFluxType
struct SurfaceFlux{G, FT, D} <: AtmosTransport.Sources.AbstractSurfaceFlux

Constant-in-time surface mass flux field.

Type parameters:

  • G: Layout tag (LatLonLayout or CubedSphereLayout)
  • FT: Float type
  • D: Data container — Matrix{FT} for lat-lon, NTuple{6, Matrix{FT}} for cubed-sphere
  • flux: surface flux [kg/m²/s]

  • species: tracer name (e.g. :co2)

  • label: human-readable label

  • molar_mass: molar mass of emitted species [kg/mol]

source
AtmosTransport.Sources.TimeVaryingSurfaceFluxType
mutable struct TimeVaryingSurfaceFlux{G, FT, S} <: AtmosTransport.Sources.AbstractSurfaceFlux

Time-varying surface mass flux with periodic snapshot updates.

Type parameters:

  • G: Layout tag (LatLonLayout or CubedSphereLayout)
  • FT: Float type
  • S: Stack container — Array{FT,3} for lat-lon, Vector{NTuple{6, Matrix{FT}}} for cubed-sphere
  • flux_data: flux snapshots [kg/m²/s]

  • time_hours: time axis: elapsed hours from simulation start for each snapshot

  • species: tracer name

  • label: human-readable label

  • molar_mass: molar mass of emitted species [kg/mol]

  • current_idx: currently active time index

  • cyclic: if true, wrap sim_hours modulo the time span (for climatological data)

source
AtmosTransport.Sources._apply_gmao_orientation!Method

Apply GMAO face orientation: transpose faces 1,2,4,5; flip faces 4,5,3,6.

Matches gcpy csgrid_gmao: Python 0-indexed tiles [0,1,3,4] → Julia [1,2,4,5]. Operations on each 2D face arr[:,:,tile]:

  1. Transpose faces 1,2,4,5
  2. Flip dim 2 (columns) for faces 4,5 — Python np.flip(a, 1)
  3. Flip dim 1 (rows) for faces 4,5,3,6 — Python np.flip(a, 0)
  4. Swap faces 3 ↔ 6 (north/south pole)

Each step uses a temporary copy to avoid read-after-write issues.

source
AtmosTransport.Sources._find_gridfed_flux_varMethod
_find_gridfed_flux_var(ds) → (dataset_or_group, varname) or nothing

Find the GridFED emission variable, checking both flat variables and the CO2 group structure used in GridFEDv2024.1+ (group "CO2", variable "TOTAL").

source
AtmosTransport.Sources._load_gridfed_monthlyMethod

Load GridFED monthly flux fields in kg/m²/s at native resolution.

Returns (monthly_fluxes, lon_src, lat_src, time_hours) where time_hours is calendar-aware relative to start_date, and months before start_date are filtered out.

source
AtmosTransport.Sources._load_rn222_file!Method

Load one Rn222 NetCDF file, convert units, regrid, append to vectors.

Zhang Rn222 is climatological (12 monthly steps). Each month index ti is mapped to the calendar month relative to start_date: monthdt = DateTime(startyear, ti, 1) (wrapping into next year for ti > startmonth) Months before `startdate` are skipped.

source
AtmosTransport.Sources._noaa_sf6_scale_factorMethod
_noaa_sf6_scale_factor(noaa_file, base_year, target_year) → Float64

Compute a scaling factor from the NOAA SF6 global growth rate file to adjust base_year emissions for target_year.

The NOAA file (sf6_gr_gl.txt) contains columns: year, annualincrease (ppt/yr), uncertainty. The scale factor is: growthrate[targetyear] / growthrate[baseyear]. If targetyear == base_year, returns 1.0.

source
AtmosTransport.Sources.apply_emissions_window!Method
apply_emissions_window!(c, flux_dev, area_j_dev, ps_dev, A_coeff, B_coeff,
                         Nz, g, dt_window; molar_mass=M_CO2)

GPU-accelerated surface emission injection for lat-lon grids. Uses pressure-dependent air mass at the surface layer.

This is the GPU-optimized path; for CPU-only use, see apply_surface_flux!(tracers, source::SurfaceFlux{LatLonLayout}, grid, dt).

source
AtmosTransport.Sources.apply_emissions_window_pbl!Method
apply_emissions_window_pbl!(c, flux_dev, delp_dev, pblh_dev,
                             g, dt_window; molar_mass=M_CO2)

GPU-accelerated PBL-distributed surface emission injection for lat-lon grids. Distributes surface flux across boundary layer levels proportionally to air mass. Falls back to bottom-cell injection if PBL height is zero or missing.

source
AtmosTransport.Sources.apply_surface_flux!Method
apply_surface_flux!(rm_panels, source::SurfaceFlux{CubedSphereLayout}, area_panels, dt, Nc, Hp)

Inject cubed-sphere surface fluxes into haloed tracer panels. rm_panels is NTuple{6} of haloed 3D arrays (mixing-ratio × air-mass). area_panels is NTuple{6} of (Nc × Nc) cell area arrays.

Works on both CPU and GPU via KernelAbstractions dispatch.

source
AtmosTransport.Sources.apply_surface_flux!Method
apply_surface_flux!(tracers, source, grid, dt)

Inject surface flux into the lowest atmospheric layer on a lat-lon grid. Converts mass flux [kg/m²/s] to mixing ratio change [mol/mol] using cell air mass.

Δc = flux * dt * area * (M_air/M_tracer) / m_air_kg

where mairkg = Δp * area / g (hydrostatic air mass of surface layer).

source
AtmosTransport.Sources.apply_surface_flux_pbl!Method
apply_surface_flux_pbl!(rm_panels, flux_panels, area_panels, delp_panels, pblh_panels,
                         dt, mol_ratio, Nc, Hp)

Distribute surface flux across PBL levels proportionally to air mass (DELP). Falls back to bottom-cell injection if PBL height is zero or missing.

source
AtmosTransport.Sources.build_conservative_cs_mapMethod
build_conservative_cs_map(lons, lats, grid; cs_areas=nothing) → ConservativeCSMap

Build a conservative regridding map from a regular lat-lon grid to cubed-sphere using sub-cell sampling.

For each source cell, N_sub × N_sub sample points are placed uniformly within its bounds. Each sample finds the nearest CS cell center. The fraction of samples mapping to each CS cell becomes the weight.

This handles both fine→coarse (most samples → same CS cell, weight ≈ 1.0) and coarse→fine (samples spread across multiple CS cells).

If cs_areas is provided (e.g., from Met_AREAM2 or corner-based computation), these exact areas are stored in the map for density conversion. Otherwise, grid.Aᶜ (gnomonic areas) is used as fallback.

source
AtmosTransport.Sources.compute_areas_from_cornersMethod
compute_areas_from_corners(corner_lons, corner_lats, R, Nc) → NTuple{6, Matrix{Float64}}

Compute cell areas from GMAO corner coordinates using spherical quadrilateral formula (l'Huilier's theorem). Returns areas in m² that match GEOS-Chem's Met_AREAM2 to <0.04%.

corner_lons and corner_lats are (Nc+1, Nc+1, 6) arrays of cell corners in degrees.

source
AtmosTransport.Sources.conservative_regrid_llMethod
conservative_regrid_ll(flux_native, lon_src, lat_src, grid) → Matrix{FT}

Conservative (mass-preserving) regridding from a lat-lon source grid to a LatitudeLongitudeGrid model grid. Computes exact spherical overlap fractions between source and target cells using the sin(φ) latitude formula.

Suitable for any resolution ratio (fine→coarse and coarse→fine).

source
AtmosTransport.Sources.generate_cs_gridspecMethod
generate_cs_gridspec(Nc; R=6.371e6) → (corner_lons, corner_lats, lons, lats, areas)

Generate cubed-sphere grid specification for resolution CNc.

Returns NTuple of 6 arrays per quantity:

  • corner_lons[p], corner_lats[p]: (Nc+1, Nc+1) cell corner coordinates [degrees]
  • lons[p], lats[p]: (Nc, Nc) cell center coordinates [degrees]
  • areas[p]: (Nc, Nc) cell areas [m²]

Uses the GMAO gnomonic projection and face orientation, matching GEOS-Chem/GCHP conventions. Validated against GEOS-Chem Met_AREAM2 to <0.003% per cell for C180.

source
AtmosTransport.Sources.latlon_cell_areasMethod
latlon_cell_areas(lons, lats, R) → Vector{FT}

Compute cell areas for a regular lat-lon grid. Returns a vector of length Nlat since areas depend only on latitude for regular grids. Uses the exact spherical formula: A = R² × Δλ × |sin(φn) - sin(φs)|

source
AtmosTransport.Sources.load_cams_co2Method
load_cams_co2(filepath, target_grid; year, species=:co2)

Load CAMS CO2 surface fluxes from CATRINE THREDDS NetCDF and regrid to target_grid.

The CAMS product provides total CO2 flux (biosphere + ocean + fire + fossil combined) at ~0.1°, in kg CO2/m²/s. Files may contain multiple monthly time steps.

Returns a TimeVaryingSurfaceFlux for multi-step files, or a SurfaceFlux for single-step files.

source
AtmosTransport.Sources.load_carbontracker_fluxesMethod
load_carbontracker_fluxes(
    datadir::String,
    target_grid::AtmosTransport.Grids.LatitudeLongitudeGrid{FT};
    year,
    include_fossil
) -> Union{AtmosTransport.Sources.CombinedFlux{S} where S<:Tuple{AtmosTransport.Sources.TimeVaryingSurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(Array{_A, 3} where _A)}, AtmosTransport.Sources.TimeVaryingSurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(Array{_A, 3} where _A)}, AtmosTransport.Sources.TimeVaryingSurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(Array{_A, 3} where _A)}}, AtmosTransport.Sources.CombinedFlux{S} where S<:NTuple{4, AtmosTransport.Sources.TimeVaryingSurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(Array{_A, 3} where _A)}}}

Load CarbonTracker CT-NRT flux components from NetCDF files in datadir. Files are expected to be named CT-NRT.v*_flux1x1_YYYY-MM-DD.nc (daily, containing 8 × 3-hourly time steps).

Returns a CombinedFlux containing TimeVaryingSurfaceFlux for biosphere, ocean, and fire components, plus a static SurfaceFlux for fossil fuels (or nothing if include_fossil=false since EDGAR may already cover this).

Arguments:

  • datadir: directory containing CT-NRT flux NetCDF files
  • target_grid: model grid for regridding (if CT-NRT is already at 1x1 matching the model, regridding is a fast identity operation)
  • year: year to load (e.g., 2024)
  • include_fossil: whether to include CT-NRT fossil fuel component (default: false, since EDGAR is typically used separately)
source
AtmosTransport.Sources.load_cs_emission_binaryMethod
load_cs_emission_binary(bin_path, FT) → (panels_vec, time_hours, header)

Read a preprocessed cubed-sphere emission binary file. Header size is auto-detected from the header_bytes field (default 4096). Returns a vector of NTuple{6, Matrix{FT}} snapshots and time axis.

source
AtmosTransport.Sources.load_edgar_co2Method
load_edgar_co2(
    filepath::String,
    target_grid::AtmosTransport.Grids.LatitudeLongitudeGrid{FT};
    year,
    species
) -> Union{AtmosTransport.Sources.SurfaceFlux{AtmosTransport.Sources.CubedSphereLayout, _A, NTuple{6, _A1}} where {_A, _A1}, AtmosTransport.Sources.SurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(AbstractMatrix)}}

Read EDGAR v8.0 CO2 total emissions from filepath and conservatively regrid to target_grid.

EDGAR v8.0 provides annual total emissions in Tonnes on a 0.1°×0.1° grid. This function:

  1. Reads the native emission field
  2. Converts from Tonnes/year to kg/m²/s
  3. Conservative area-weighted regridding to the model grid

Returns a SurfaceFlux{FT}.

source
AtmosTransport.Sources.load_edgar_cs_binaryMethod
load_edgar_cs_binary(bin_path, FT) → NTuple{6, Matrix{FT}}

Read a preprocessed EDGAR emission file on cubed-sphere panels. File layout: [4096-byte JSON header | panel₁ data | … | panel₆ data]

source
AtmosTransport.Sources.load_edgar_sf6Method

Load EDGAR SF6 and regrid to cubed-sphere panels.

If a preprocessed binary file exists (same directory, named edgar_sf6_cs_c{Nc}_float32.bin), loads from binary directly. Otherwise regrids from the EDGAR NetCDF.

source
AtmosTransport.Sources.load_edgar_sf6Method
load_edgar_sf6(filepath, target_grid; year, noaa_growth_file="", scale_year=year)

Load EDGAR v8.0 annual SF6 total emissions and conservatively regrid to target_grid.

EDGAR SF6 has the same 0.1° format as EDGAR CO2 (Tonnes/year on grid). If noaa_growth_file is provided, the emission field is scaled so that the global total matches the NOAA-observed atmospheric SF6 growth rate for scale_year.

The CATRINE protocol specifies using 2022 EDGAR data for both 2022 and 2023, scaled to the NOAA SF6 growth rate each year.

Returns a SurfaceFlux{FT} with species=:sf6.

source
AtmosTransport.Sources.load_gfas_fire_fluxMethod
load_gfas_fire_flux(
    datadir::String,
    target_grid::AtmosTransport.Grids.LatitudeLongitudeGrid{FT};
    year
) -> Union{AtmosTransport.Sources.SurfaceFlux, AtmosTransport.Sources.TimeVaryingSurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(Array{_A, 3} where _A)}}

Load CAMS GFAS fire CO2 emissions from NetCDF file(s) in datadir and conservatively regrid to target_grid.

GFAS files are daily, 0.1° resolution, with variable cofire or co2fire in units of kg/m²/s (positive = emission).

If datadir contains multiple daily files, they are concatenated into a TimeVaryingSurfaceFlux. A single file produces a SurfaceFlux.

Arguments:

  • datadir: directory containing GFAS NetCDF files (one per day or month)
  • target_grid: model grid for conservative regridding
  • year: year to load (filters files by name)
source
AtmosTransport.Sources.load_gridfed_fossil_co2Method
load_gridfed_fossil_co2(filepath, grid::CubedSphereGrid; year, species)

Load GridFED fossil CO₂ and regrid to cubed-sphere panels.

If a preprocessed binary file exists (same directory, named gridfed_fossil_co2_cs_c{Nc}_float32.bin), loads from binary directly (~instant). Otherwise loads monthly flux fields at native 0.1° resolution, regrids each month to CS panels via conservative area-weighted regridding with global mass renormalization (~80s for C180).

Returns a TimeVaryingSurfaceFlux with monthly snapshots.

source
AtmosTransport.Sources.load_gridfed_fossil_co2Method
load_gridfed_fossil_co2(filepath, target_grid::LatitudeLongitudeGrid; year, species)

Load GridFED fossil fuel CO₂ emissions and conservatively regrid to target_grid.

filepath may be a single NetCDF file or a directory containing per-year NetCDF files (e.g. from GridFEDv2024.0 yearly ZIPs). For directories, all .nc files are loaded and concatenated into a TimeVaryingSurfaceFlux with monthly time steps.

GridFED data is at 0.1° resolution. Conservative regridding preserves global mass (CATRINE D7.1 protocol requirement).

Returns a TimeVaryingSurfaceFlux (multi-month) or SurfaceFlux (single step).

source
AtmosTransport.Sources.load_inventoryFunction
load_inventory(source, grid; kwargs...) → AbstractSurfaceFlux

Load an emission inventory and regrid to grid. Dispatches on both the inventory type and the grid type:

load_inventory(::EdgarSource, ::LatitudeLongitudeGrid; year, file)  → SurfaceFlux
load_inventory(::EdgarSource, ::CubedSphereGrid; year, file)        → SurfaceFlux
source
AtmosTransport.Sources.load_inventoryMethod
load_inventory(src::CATRINESource, grid; kwargs...)

Load CATRINE emission data. Dispatches on src.dataset:

  • "cams_co2"load_cams_co2
  • "gridfed_fossil_co2"load_gridfed_fossil_co2
  • "edgar_sf6"load_edgar_sf6
  • "zhang_rn222"load_zhang_rn222
source
AtmosTransport.Sources.load_jena_ocean_fluxMethod
load_jena_ocean_flux(
    filepath::String,
    target_grid::AtmosTransport.Grids.LatitudeLongitudeGrid{FT};
    year
) -> Union{AtmosTransport.Sources.SurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(Matrix)}, AtmosTransport.Sources.TimeVaryingSurfaceFlux{AtmosTransport.Sources.LatLonLayout, _A, A} where {_A, A<:(Array{_A, 3} where _A)}}

Load Jena CarboScope ocean CO2 flux from filepath and regrid to target_grid.

Converts from PgC/yr/cell to kg(CO2)/m²/s: fluxkgCO2m2s = (fluxPgCyrcell × 1e12 × (44.01/12.011)) / (dxyp × 365.25 × 86400)

Returns a TimeVaryingSurfaceFlux if the file contains multiple time steps, or a SurfaceFlux for a single-time-step file.

source
AtmosTransport.Sources.load_lmdz_co2Method
load_lmdz_co2(dirpath, target_grid; start_date, end_date, species=:co2,
              flux_var="flux_apos")

Load LMDZ/CAMS posterior CO2 surface fluxes from a directory of monthly NetCDF files and regrid to target_grid.

Files have naming pattern: zcamslcams55YYYYMMFT24r2rasfc3hco2flux.nc

Each file contains 3-hourly flux fields (time × lat × lon) in kgC/m²/s. These are converted to kgCO2/m²/s (×3.664) for the emission pipeline.

Returns a TimeVaryingSurfaceFlux for lat-lon grids.

source
AtmosTransport.Sources.load_zhang_rn222Method
load_zhang_rn222(dirpath, target_grid; species=:rn222)

Load Zhang et al. (2021) 222Rn surface emissions from monthly NetCDF files in dirpath and regrid to target_grid.

Expected file naming: *Rn*<MM>.nc or *rn222*<MM>.nc or a single file containing all 12 months.

Units in Zhang et al.: atoms/cm²/s Conversion to kg/m²/s: flux × (MRn222 / NA) × 1e4

Returns a TimeVaryingSurfaceFlux for monthly data.

source
AtmosTransport.Sources.log_flux_integralMethod
log_flux_integral(sf::SurfaceFlux, grid)

Compute and log the global integral of a SurfaceFlux in useful units. For CS grids: sum(flux × Aᶜ) over all 6 panels. For lat-lon grids: sum(flux × cell_areas).

source
AtmosTransport.Sources.nearest_neighbor_regridMethod
nearest_neighbor_regrid(flux_src, lon_src, lat_src, grid) → Matrix{FT}

Nearest-neighbor regridding from source lat-lon to model lat-lon grid. Handles any longitude/latitude convention automatically.

Not mass-conserving — use _conservative_regrid for high-resolution sources where mass conservation matters.

source
AtmosTransport.Sources.normalize_lons_latsMethod
normalize_lons_lats(lons, lats, flux, FT) → (lons_out, lats_out, flux_out)

Ensure south-to-north latitude ordering and [0, 360] longitude convention. Handles any input convention automatically.

source
AtmosTransport.Sources.regrid_edgar_to_csMethod
regrid_edgar_to_cs(edgar_flux, edgar_lons, edgar_lats, grid; file_lons=nothing, file_lats=nothing)

Regrid a lat-lon emission field (Tonnes/yr per cell) to cubed-sphere panels. Converts to kg/m²/s, then applies conservative area-weighted regridding via regrid_latlon_to_cs.

When file_lons and file_lats are provided (legacy), they are ignored — the unified regridder uses grid.λᶜ/φᶜ (which contain GMAO coordinates when loaded).

Returns NTuple{6, Matrix{FT}} of panel flux fields.

source
AtmosTransport.Sources.regrid_latlon_to_csMethod
regrid_latlon_to_cs(flux_kgm2s, lons, lats, grid; cs_map=nothing) → NTuple{6, Matrix}

Conservative regridding from lat-lon to cubed-sphere via mass accumulation.

Algorithm:

  1. For each source cell, compute mass = flux × area
  2. Scatter mass to target CS cell(s) using sub-cell sampling weights
  3. Divide accumulated mass by exact CS cell area → flux density

Mass conservation is exact by construction (weights sum to 1.0 per source cell).

source
AtmosTransport.Sources.update_time_index!Method

Update the active flux snapshot index based on simulation time (hours).

For cyclic=true sources (e.g. climatological monthly data), wraps sim_hours modulo the time span so the snapshots repeat every cycle.

source

Models

AtmosTransport.ModelsModule
Models

Top-level model type that assembles grid, fields, physics operators, met data, I/O, and time stepping into a single runnable object.

Supports both the legacy run!(model, met_source, t_start, t_end) path and the new driver-based run!(model) path with dispatch on (grid type, buffering strategy).

source
AtmosTransport.Models.DoubleBufferType
struct DoubleBuffer <: AtmosTransport.Models.AbstractBufferingStrategy

Double-buffer (ping-pong) strategy. Two sets of met buffers alternate so that CPU I/O for window N+1 overlaps with GPU compute on window N.

source
AtmosTransport.Models.IOSchedulerType
IOScheduler{B, GM, CM}

Abstracts met-data I/O scheduling for the unified run loop.

  • B <: AbstractBufferingStrategy — SingleBuffer or DoubleBuffer
  • GM — GPU met buffer type (LatLonMetBuffer or CubedSphereMetBuffer)
  • CM — CPU staging buffer type (LatLonCPUBuffer or CubedSphereCPUBuffer)

For SingleBuffer: only gpu_a/cpu_a are used; gpu_b/cpu_b are identical refs. For DoubleBuffer: two separate buffer pairs alternate via current toggle.

source
AtmosTransport.Models.SingleBufferType
struct SingleBuffer <: AtmosTransport.Models.AbstractBufferingStrategy

Sequential single-buffer strategy. Each met window is loaded, transferred to GPU, and then advection runs. No overlap between I/O and compute.

source
AtmosTransport.Models.TransportModelType
struct TransportModel{Arch, G, Tr, ATr, M, TS, Src, OW, CB, Buf, Adv, Chem, Diff, Conv} <: AtmosTransport.Models.AbstractModel{Arch}

The main atmospheric transport model.

  • architecture: CPU or GPU

  • grid: the computational grid

  • tracers: NamedTuple of tracer Fields (or raw arrays for direct GPU runs)

  • adj_tracers: NamedTuple of adjoint tracer Fields (nothing if not doing adjoint)

  • met_data: meteorological data (AbstractMetData or AbstractMetDriver)

  • clock: simulation clock

  • timestepper: time-stepping strategy

  • sources: vector of emission sources

  • output_writers: vector of output writers

  • callbacks: vector of callbacks

  • buffering: buffering strategy (SingleBuffer or DoubleBuffer)

  • advection_scheme: advection scheme (SlopesAdvection or PPMAdvection{ORD}, default SlopesAdvection)

  • chemistry: chemistry scheme (NoChemistry, RadioactiveDecay, CompositeChemistry, ...)

  • diffusion: vertical diffusion scheme (nothing or BoundaryLayerDiffusion or PBLDiffusion)

  • convection: convection scheme (nothing or TiedtkeConvection)

  • metadata: run metadata: config, user, hostname, timestamps

source
AtmosTransport.Models.TransportModelMethod
TransportModel(
;
    grid,
    tracers,
    met_data,
    advection,
    convection,
    diffusion,
    chemistry,
    Δt,
    sources,
    output_writers,
    callbacks,
    buffering,
    adjoint,
    adj_tracers,
    metadata
)

Construct a TransportModel with the new driver-based API.

This constructor supports both the legacy physics-operator style and the new met-driver + sources + buffering style.

source
AtmosTransport.Models.TransportPolicyType
struct TransportPolicy

Central transport configuration resolved once per simulation run.

All transport-related options (vertical method, pressure basis, mass balance) are collected here so that the run loop and physics phases can dispatch on policy fields rather than querying scattered metadata flags.

Construction

Use resolve_transport_policy(config) to build from TOML config, or construct directly for programmatic use:

TransportPolicy(vertical_operator=:pressure_remap, pressure_basis=:dry)

Fields

  • vertical_operator: Vertical transport method: :continuity_cm (Strang Z-advection) or :pressure_remap (FV3-style PPM remap)

  • pressure_basis: Air mass basis for advection: :dry (MFXC/MFYC are dry) or :moist

  • mass_balance_mode: Mass balance correction: :none, :column, or :global_fixer

  • pe_method: PE computation for vertical remap: :direct_cumsum (default) or :hybrid (GCHP-style ak+bk×PS + calcScalingFactor)

source
AtmosTransport.Models._run_loop!Method
_run_loop!(model, grid, buffering)

Unified run loop for all (grid type, buffering strategy) combinations. Uses multiple dispatch on grid for physics phases, and IOScheduler{B} for buffering. No if/else on types in the main loop body.

source
AtmosTransport.Models.advection_phase!Method
advection_phase!(tracers, sched, air, phys, model, grid, ws, n_sub, dt_sub, step)

Advection + convection sub-stepping. LL: NamedTuple dispatch (all tracers together). CS: per-tracer advection with mass fixer + m_ref advance along pressure trajectory.

source
AtmosTransport.Models.allocate_air_massMethod
allocate_air_mass(grid, arch) → NamedTuple

Allocate air mass arrays. Returns NamedTuple with m (working) and mref (reference). For CS, also includes dmper_sub for pressure fixer.

source
AtmosTransport.Models.allocate_tracersMethod
allocate_tracers(model, grid) → tracers NamedTuple

For LL grids, returns model.tracers as-is (already GPU arrays). For CS grids, allocates 6-panel NTuple per tracer and applies pending ICs.

source
AtmosTransport.Models.apply_global_mass_fixer!Method
apply_global_mass_fixer!(cs_tracers, grid, target_mass) → String

Scale rm globally so total tracer mass matches target_mass for each tracer. Returns a compact string describing the correction magnitude (in ppm).

source
AtmosTransport.Models.compute_mass_totals_subsetMethod
compute_mass_totals_subset(cs_tracers, grid, subset) → Dict{Symbol, Float64}

Like compute_mass_totals but only for tracers in subset with nonzero values. Avoids GPU→CPU copies for tracers that don't need mass fixing.

source
AtmosTransport.Models.load_and_upload_physics!Method
load_and_upload_physics!(phys, sched, driver, grid, w; arch)

Load physics fields and upload to GPU. For LL, loads each field from driver (IOScheduler only loads met data). For CS, physics was already loaded by IOScheduler's begin_load! — just upload to GPU based on sched.io_result.

source
AtmosTransport.Models.mass_showvalueMethod
mass_showvalue(mass_totals, expected_mass) → String

Format mass closure diagnostics: Δ = (modeled - expected) / expected. expected_mass = initial + cumulative emissions, so Δ shows only transport bias.

source
AtmosTransport.Models.mass_total_f64Method
mass_total_f64(rm_panels, Nc, Hp, Nz) → Float64

Sum total tracer mass across all 6 panels in Float64 precision. Used for per-stage mass balance diagnostics.

source
AtmosTransport.Models.resolve_transport_policyMethod
resolve_transport_policy(metadata::Dict) → TransportPolicy

Resolve transport policy from model metadata (parsed from TOML config). Maps legacy boolean flags to policy fields for backward compatibility.

source
AtmosTransport.Models.run!Method
run!(
    model::AtmosTransport.Models.TransportModel,
    met_source::AtmosTransport.IO.MetDataSource,
    t_start,
    t_end;
    Δt,
    met_update_interval,
    callback,
    verbose
) -> AtmosTransport.Models.TransportModel

Run the forward model from t_start to t_end using the legacy MetDataSource-based API.

At each met_update_interval, reads and prepares new met data from met_source. Between met updates, steps the model forward with Δt.

source
AtmosTransport.Models.run!Method
run!(model::TransportModel)

Run the forward model using the met driver, sources, and buffering strategy stored in the model. Dispatches on (model.grid, model.buffering).

source
AtmosTransport.Models.update_met_data!Method
update_met_data!(model, met_source, time)

Read meteorological data for time from met_source and prepare the staggered velocity fields for the physics operators. Updates model.met_data.

Returns the prepared met fields NamedTuple.

source