Regridding API
These are the offline conservative-regridding construction, persistence, and application helpers. See Regridding for the physical contract.
AtmosTransport.Regridding Module
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
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/Destination | Tree strategy | Spatial acceleration |
|---|---|---|
LatLonMesh | CellBasedGrid from (Nx+1)×(Ny+1) face corners → TopDownQuadtreeCursor | O(log(Nx·Ny)) |
CubedSphereMesh | 6 per-panel convention-aware grids from CS corners → CubedSphereToplevelTree | O(log Nc²) per panel |
ReducedGaussianMesh | Sectorized per-ring CellBasedGrid trees → MultiTreeWrapper | O(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
CubedSphereMeshuses analytical coordinates fromsrc/Grids/CubedSphereMesh.jl.GEOSNativePanelConventionincludes 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.ReducedGaussianMeshclamps 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.
AtmosTransport.Regridding.IdentityRegrid Type
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.
AtmosTransport.Regridding.apply_regridder! Method
apply_regridder!(dst, regridder, src) -> dstApply 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 lengthn_dst/n_src, ormulti-dimensional arrays with a leading horizontal axis of length
n_dst/n_srcand 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.
sourceAtmosTransport.Regridding.build_regridder Method
build_regridder(src_mesh, dst_mesh; normalize=false, cache_dir=nothing, kwargs...) -> RegridderConstruct 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.
AtmosTransport.Regridding.cubed_sphere_face_corners Method
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).
AtmosTransport.Regridding.load_regridder Method
load_regridder(path) -> RegridderInverse of save_regridder. Rebuilds the temporary work arrays from the area vectors.
AtmosTransport.Regridding.meshes_equivalent Method
meshes_equivalent(src, dst) -> BoolTrue 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.
AtmosTransport.Regridding.save_esmf_weights Method
save_esmf_weights(path, regridder;
src_shape=nothing, dst_shape=nothing,
src_grid_name="source", dst_grid_name="destination") -> pathExport the regridder weights to an ESMF offline-weights NetCDF file.
Format (ESMF convention):
| variable | shape | meaning |
|---|---|---|
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.
AtmosTransport.Regridding.save_regridder Method
save_regridder(path, regridder) -> pathWrite 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).