Skip to content

Regridding API

These are the offline conservative-regridding construction, persistence, and application helpers. See Regridding for the physical contract.

AtmosTransport.Regridding Module
julia
Regridding (src)

Offline conservative regridding between mesh types, built on ConservativeRegridding.jl.

Designed for the preprocessing stage: build a sparse weights matrix once per (source_mesh, target_mesh) pair, cache it to disk, and reuse at every subsequent run. The runtime transport core never calls into this module — TransportBinaryReader consumes binaries that are already on the target grid.

Workflow

julia
using AtmosTransport: LatLonMesh, CubedSphereMesh
using AtmosTransport.Regridding

src = LatLonMesh(Nx=1440, Ny=721)
dst = CubedSphereMesh(Nc=90)

# Build weights (expensive — minutes for C90, cached to disk)
r = build_regridder(src, dst; cache_dir="/tmp/atmos_regrid_cache")

# Apply to a 2D field
src_field = zeros(src.Nx * src.Ny)
dst_field = zeros(6 * dst.Nc * dst.Nc)
apply_regridder!(dst_field, r, src_field)

# Persist / export
save_regridder("weights.jld2", r)
save_esmf_weights("weights_esmf.nc", r)

Supported mesh types

Source/DestinationTree strategySpatial acceleration
LatLonMeshCellBasedGrid from (Nx+1)×(Ny+1) face corners → TopDownQuadtreeCursorO(log(Nx·Ny))
CubedSphereMesh6 per-panel convention-aware grids from CS corners → CubedSphereToplevelTreeO(log Nc²) per panel
ReducedGaussianMeshSectorized per-ring CellBasedGrid trees → MultiTreeWrapperO(nrings · log nlon)

All three produce SphericalCap extents at every tree level, which is required by CR.jl's spherical dual-DFS intersection search.

Known limitations

  • CubedSphereMesh uses analytical coordinates from src/Grids/CubedSphereMesh.jl. GEOSNativePanelConvention includes the GEOS-FP/GEOS-IT panel order, native orientation, and global -10° longitude offset used by GEOS grid files. Left-handed GEOS panels are wound correctly for tree traversal while preserving file-order indices.

  • ReducedGaussianMesh clamps polar face latitudes by 0.001° to avoid degenerate polygons at the poles. Also, its cell polygons use great-circle edges to approximate curved latitude boundaries. This approximation is visible on unusually coarse synthetic rings and converges as ring resolution increases.

Architecture reference

See docs/CONSERVATIVE_REGRIDDING.md for a full write-up of the algorithm, conventions, and verification results.

source
AtmosTransport.Regridding.IdentityRegrid Type
julia
IdentityRegrid{M}

Passthrough sentinel returned by build_regridder when source and target meshes are structurally equivalent (per meshes_equivalent). Carries the shared mesh so callers can introspect it like any Regridder.

source
AtmosTransport.Regridding.apply_regridder! Method
julia
apply_regridder!(dst, regridder, src) -> dst

Apply a regridder to field data. Thin wrapper over ConservativeRegridding.regrid! that handles n-dimensional arrays whose first dimension is the flattened horizontal index with any number of trailing dimensions (levels, time windows, tracers, etc).

dst and src may be:

  • plain Vectors of length n_dst / n_src, or

  • multi-dimensional arrays with a leading horizontal axis of length n_dst / n_src and matching trailing shape.

For the multi-dim case the horizontal regridding is applied column-by-column using CR.jl's temporary work arrays — no extra allocations per column.

source
AtmosTransport.Regridding.build_regridder Method
julia
build_regridder(src_mesh, dst_mesh; normalize=false, cache_dir=nothing, kwargs...) -> Regridder

Construct a ConservativeRegridding.Regridder that maps source-mesh fields to destination-mesh fields by true spherical polygon intersection.

If cache_dir is supplied, the regridder is cached on disk using a SHA-1 fingerprint of the (src_mesh, dst_mesh) pair. Subsequent calls with identical meshes load the cached weights instead of recomputing them. Custom construction kwargs cannot be combined with cache_dir, because arbitrary operators do not have a stable, portable cache fingerprint.

normalize=false matches the convention used by xESMF: the sparse intersections matrix contains raw area values (m²), and the per-cell normalization by dst_areas happens inside regrid!. Pass normalize=true to scale intersections, src_areas, and dst_areas by max(intersections) — useful for display but not for weight-level comparisons.

Any extra kwargs are forwarded to ConservativeRegridding.Regridder.

source
AtmosTransport.Regridding.cubed_sphere_face_corners Method
julia
cubed_sphere_face_corners(mesh::CubedSphereMesh)
    -> NTuple{6, Matrix{UnitSphericalPoint{Float64}}}

Return a 6-tuple of (Nc+1) × (Nc+1) corner-point matrices, one per panel, with corners on the unit sphere. Panel ordering follows mesh.convention; for each user-visible panel p, corner (i, j) matches panel_cell_corner_lonlat(mesh, p).

Used by Trees.treeify(::Spherical, ::CubedSphereMesh) to assemble a CubedSphereToplevelTree. Cached externally (the regridder cache includes the mesh hash) so this is only called once per (Nc, convention).

source
AtmosTransport.Regridding.load_regridder Method
julia
load_regridder(path) -> Regridder

Inverse of save_regridder. Rebuilds the temporary work arrays from the area vectors.

source
AtmosTransport.Regridding.meshes_equivalent Method
julia
meshes_equivalent(src, dst) -> Bool

True when the two meshes describe the same horizontal grid up to floating-point equality of the geometry-defining fields. Used by build_regridder to skip building a conservative regridder when the source and target are the same grid.

source
AtmosTransport.Regridding.save_esmf_weights Method
julia
save_esmf_weights(path, regridder;
                  src_shape=nothing, dst_shape=nothing,
                  src_grid_name="source", dst_grid_name="destination") -> path

Export the regridder weights to an ESMF offline-weights NetCDF file.

Format (ESMF convention):

variableshapemeaning
S(n_s,)weight value S[k] = intersections[row[k], col[k]] / dst_areas[row[k]]
row(n_s,)destination cell index (1-indexed)
col(n_s,)source cell index (1-indexed)
frac_a(n_a,)fraction of source cell covered by the destination grid
frac_b(n_b,)fraction of destination cell covered by the source grid
area_a(n_a,)source cell areas (mesh units, typically m²)
area_b(n_b,)destination cell areas

This format is what xESMF / ESMF_RegridWeightGen / GCHP's tile-file loader all consume, which lets the CR.jl output be diffed against xESMF fixtures at weight level and handed off to ESMF-based tooling.

Optional src_shape / dst_shape tuples (e.g. (Nx, Ny), (Nc, Nc, 6)) are stored as global attributes for provenance.

source
AtmosTransport.Regridding.save_regridder Method
julia
save_regridder(path, regridder) -> path

Write the regridder's intersection matrix and area vectors to path as a JLD2 file. Temporary work arrays are not serialized (they're rebuilt on load).

source