Grids
FlowGeometries.Grids.AbstractAdjacency — Type
AbstractAdjacencyWhere a cell's neighbours come from: IndexStencilNeighbors, FormulaNeighbors or StoredMeshNeighbors. Read it with adjacency_source.
Distinct from AbstractCandidateSource: adjacency is the mesh's own neighbour relation, and a candidate source answers a question about distance, which no adjacency determines.
FlowGeometries.Grids.AbstractCandidateSource — Type
AbstractCandidateSourceHow a distance query enumerates the cells it must test: SeparableWindow or IndexedCandidates. Read it with candidate_source.
Membership is decided by the caller's exact distance ≤ r gate, so each need only return a superset of the ball, and the two enumerations agree on the result.
FlowGeometries.Grids.AbstractCellAddress — Type
AbstractCellAddressHow a cell of a grid is named: CartesianCells or FlatCells. Read it with cell_address.
FlowGeometries.Grids.AbstractCurvilinearGrid — Type
AbstractCurvilinearGrid{G,T} <: AbstractGrid{G,T}Curvilinear grids. Default: CurvilinearGrid.
FlowGeometries.Grids.AbstractEmbedding — Type
AbstractEmbeddingHow a grid's cell centres sit in the Euclidean space an index searches, and therefore what a physical radius means there. A type, as stencils are: the conversion is applied once per query, and being resolved at compile time it leaves no branch and no boxed radius in the hot path.
FlowGeometries.Grids.AbstractGrid — Type
AbstractGrid{G<:AbstractGeometry, T<:AbstractFloat}Supertype for all grid architectures.
FlowGeometries.Grids.AbstractStructuredGrid — Type
AbstractStructuredGrid{G, T} <: AbstractGrid{G,T}Rectilinear grids. Default: StructuredGrid.
FlowGeometries.Grids.AbstractTopology — Type
AbstractTopologyHow a coordinate direction closes: Periodic or Bounded.
Carried in the grid's type, so isperiodic is a compile-time answer and callers can dispatch on it. The cell measure depends on it: a wrapped boundary cell has a width that a bounded one lacks.
FlowGeometries.Grids.AbstractUnstructuredGrid — Type
AbstractUnstructuredGrid{G,T} <: AbstractGrid{G,T}Unstructured / node grids. Default: UnstructuredGrid.
FlowGeometries.Grids.AllActive — Type
AllActive(size)The mask of a grid where every cell participates, stored as its size alone. getindex is a constant the compiler can fold, and count is length without a scan.
FlowGeometries.Grids.ArcEmbedding — Type
ArcEmbedding(R)Points on the reference sphere of radius R, where the metric is the great-circle arc. A radius has to be converted to the chord it subtends.
FlowGeometries.Grids.AxisSummary — Type
AxisSummary{T}One direction's reductions: the values origin, bounds, extent, minimum_spacing and maximum_spacing report.
A stretched axis answers each of these by scanning, and a distance query reads them through Connectivity.MetricTopology, which is the default topology on every per-cell entry point. Holding them keeps that construction O(1) and keeps a query off the coordinates.
isbits, five numbers per direction, filled once by _axis_summary: one pass per axis, the O(∑ Nᵈ) the measure factors already cost. first is kept apart from lo because a descending axis starts at its largest value.
FlowGeometries.Grids.Bounded — Type
Bounded()A direction that ends: its first and last cells have one neighbour each.
FlowGeometries.Grids.CartesianCells — Type
CartesianCells()A cell is an NTuple{N,Int} into an N-dimensional array of cells, so a traversal walks CartesianIndices and converts to a linear index to report. Rectilinear, curvilinear and every panel layout.
FlowGeometries.Grids.CartesianEmbedding — Type
CartesianEmbedding()The coordinates themselves, replicated at the periodic images. A radius passes through unchanged.
FlowGeometries.Grids.CellListIndex — Type
CellListIndexA uniform-bin spatial index over the embedded cell centres: points are bucketed by which bin of side h they fall in, and a query visits the bins its ball can reach.
Three properties let it run on a device, where a tree cannot:
- it is arrays only — bin offsets, point ids and the bin each sits in — so
Adaptmoves it like any other field, and it holds no copy of the coordinates, which stay on the grid; - every point lands in exactly one bin, periodicity wrapping the bin coordinate and leaving the point where it is, so a query emits each cell once and needs no candidate buffer to deduplicate into.
fold_candidatesis therefore a fold, with no list to materialize; - bins are hashed into
O(n)buckets, so the memory is independent ofh. A dense lattice over a sphere binned at 100 km is(2R/h)³ ≈ 2×10⁶mostly empty cells, and grows ashshrinks.
Build it for the radius you intend to query at: h is that radius, so a query touches 3ᴰ bins. A much larger radius still works and costs (2⌈r/h⌉+1)ᴰ bins.
FlowGeometries.Grids.CellMesh — Type
CellMesh(cell_ptr, cell_nodes, node_ptr, node_cells)
CellMesh(cell_ptr, cell_nodes, nnodes)A node set's cells, and the nodes each one joins — both directions, each as CSR.
Node→node adjacency says which nodes are linked; it does not say which nodes bound a face. The cells do, and an area, a flux through an edge, or an interpolation inside a triangle is defined on them. A triangulation produces them, and the tessellation that computes a node set's Voronoi areas builds one, which is the mesh held here.
cell_nodes[cell_ptr[c] : cell_ptr[c+1]-1]are the nodes of cellc, in order around itnode_cells[node_ptr[i] : node_ptr[i+1]-1]are the cells incident on nodei
Both are O(n): a triangulation of n nodes has about 2n triangles and 6n entries either way. The second is the transpose of the first and the two-argument form builds it.
The cells are a triangulation or the caller's own. A k-nearest graph is neither planar nor symmetric once truncated, and its cells tile nothing, so it cannot serve here.
FlowGeometries.Grids.ChordEmbedding — Type
ChordEmbedding()The embedded distance already is the metric, or a lower bound on it: (λ, φ, r) on a sphere, where the metric is the 3-D chord, and geodetic coordinates on a spheroid, where the ECEF chord is at most the geodesic. A radius passes through unchanged; under-approximating means the query over-returns, and an index is allowed to over-return.
FlowGeometries.Grids.CubedSphereGrid — Type
CubedSphereGrid(geometry, n; mask = nothing)The gnomonic cubed sphere as a grid: six n × n panels of equiangular cells, 6n² in all.
It stores n, the geometry and the mask. A cell's coordinates are its panel-local angles through the gnomonic map, its neighbours are the panel-interior offsets and the exact seam fold, and its area is the closed-form solid angle of its gnomonic rectangle — so all three are arithmetic in (n, cell), and Base.summarysize is the same at every n.
Cells are numbered panel by panel with i fastest, matching SphericalSampling.cubed_sphere_points. panel_cell and cell_id convert between a cell id and its (panel, i, j).
Coordinates are (λ, φ): coords(grid, k) reads one cell, and materialize gives the whole cloud as dense vectors.
FlowGeometries.Grids.CurvilinearGrid — Type
CurvilinearGrid{T, G, N, TP, C, KC, MA, B}Curvilinear grid whose cell-center coordinates are N-dimensional arrays (e.g. an orthogonal curvilinear mesh). coordinates holds one N-D cell-center array per direction.
At N = 2 the cell measure is the exact quadrilateral area through the cell's four vertices. Those vertex arrays are what corners holds, one per direction and one larger in every direction. They are retained when the caller supplies them or asks for them with keep_corners = true, and are otherwise construction input to the area kernel alone — so corners is nothing on a grid built from centres, and has_corners reports which. In any dimension other than 2 the measure is the caller's to supply: the corner-area kernel is a 2-D algorithm with no N-D generalization here.
Type parameters
T: coordinate float type.G<:AbstractGeometry{T}is tied to it, so a mismatched-eltype geometry raises a type error.Ttherefore precedesG: Julia binds type parameters left to right, andG<:AbstractGeometry{T}requiresTalready bound.N: number of coordinate directions.C: tuple type of the center coordinate arrays.KC: tuple type of the cell-vertex arrays, orNothingwhere they were not retained.MA: array type of the derivedmeasurefield — independent ofC, since it is a computed field with no reason to match the coordinate arrays' storage type.B: array type of the activemask.
FlowGeometries.Grids.CurvilinearGrid — Method
CurvilinearGrid(geometry, coords..., mask; measure=nothing, corners=nothing, …)
CurvilinearGrid(geometry, coords..., measure, mask; corners=nothing, …)Build a curvilinear grid in any number of directions from one N-D cell-center coordinate array per direction. mask is the trailing array; a measure array before it is used verbatim (common when a dataset ships its own cell areas), and may equally be given as the measure keyword.
With no measure supplied, one is computed from the cell-vertex arrays — at N = 2 only, as the exact quadrilateral cell area. Spherical cells use the exact spherical-quadrilateral area, the spherical excess of the two triangles through the cell's four corner directions (see Geometry.spherical_excess); Cartesian cells the exact planar shoelace area. That kernel is a 2-D algorithm with no N-D generalization here, so in any other dimension the measure must be given.
Pass corners (a tuple of arrays, each one larger than the centers in every direction) for exact cell vertices, e.g. from the source mesh's own vertex grid; otherwise they are reconstructed from the centers per direction (see _centers_to_corners), which requires at least 2 cells across.
Corners supplied this way are kept on the grid, and reconstructed ones are input to the area kernel — pass keep_corners = true to keep those too, at one array per direction. Reconstruction happens only where something needs it, so a grid given its own measure derives none.
periodic is a Bool (applied to direction 1) or an NTuple{N,Bool}. When omitted, direction-1 periodicity is auto-detected the same way as StructuredGrid (full-circle spherical longitude), and every other direction is bounded.
FlowGeometries.Grids.FlatCells — Type
FlatCells()A cell is one integer into a flat list, so the index a traversal walks and the index it reports are the same number. Node sets, and the pixelizations whose cells are enumerated by a single id.
FlowGeometries.Grids.FormulaNeighbors — Type
FormulaNeighbors()Neighbours are closed-form arithmetic on the cell id, with no graph and no coordinates stored: a pixelization's face tables, a ring grid's in-ring and adjacent-ring maps, a panel seam.
A layout with this trait supplies formula_neighbors.
FlowGeometries.Grids.GridMeasure — Type
GridMeasure(grid)The cell measure of a layout whose measure is a formula, computed per entry and stored nowhere.
A genuine AbstractVector: indexing, broadcasting and collect behave as for the dense equivalent, and measure(grid, k) is what an entry is. sum goes through _total_measure, which a layout covering a known region answers in O(1).
FlowGeometries.Grids.HEALPixGrid — Type
HEALPixGrid(geometry, nside; scheme = SphericalSampling.Ring(), mask = nothing)The HEALPix pixelization as a grid: 12·nside² equal-area pixels on 4·nside − 1 iso-latitude rings.
It stores nside, the scheme, the geometry and the mask. A pixel's coordinates, its neighbours and its area are each closed-form in (nside, pixel), so those four fields are the whole grid: Base.summarysize is the same at nside = 1024 — 12.6 million pixels — as at nside = 1.
nlon varies by ring, so this is a layout of its own, and it answers the three traits a neighbourhood algorithm asks of one: cells are FlatCells (a pixel is one id), adjacency is FormulaNeighbors (the face tables of Górski et al.), and a distance query enumerates through IndexedCandidates.
Coordinates are (λ, φ): coords(grid, i) reads one pixel, and materialize gives the whole cloud as dense vectors.
FlowGeometries.Grids.IcosahedralGrid — Type
IcosahedralGrid(geometry, frequency; mask = nothing)The frequency-ν icosahedral geodesic as a grid: 10ν² + 2 vertices, twelve of them pentagonal and the rest hexagonal.
It stores ν, the geometry and the mask. Vertex ids are assigned by topology — the twelve corners, then each macro-edge's interior, then each face's — so a vertex's position, its neighbours and its dual-cell area are each arithmetic in (ν, id): reading the numbering backwards gives the lattice positions the vertex occupies, and everything follows from those.
A vertex sits on one face if a face owns it, two if a macro-edge does, and five if it is a corner. That count is its valence, so the twelve corners are the grid's twelve pentagons.
The measure is the spherical Voronoi dual, computed from the vertex's own incident triangles — each triangle split among its three vertices by the arcs from its circumcenter to its edge midpoints. It costs a fan of spherical excesses per cell, so use measure_array when sweeping every cell.
Coordinates are (λ, φ): coords(grid, id) reads one vertex, and materialize gives the whole cloud as dense vectors.
FlowGeometries.Grids.IndexStencilNeighbors — Type
IndexStencilNeighbors()Neighbours are offsets in the cell index space, wrapped or clipped per direction — the whole of what Connectivity.IndexTopology carries. Coordinates never enter.
FlowGeometries.Grids.IndexedCandidates — Type
IndexedCandidates()The grid has no separable axes to bound with, so candidates come from a spatial index over its cell centres.
FlowGeometries.Grids.Periodic — Type
Periodic()A direction that wraps: the last cell's neighbour is the first, one period away.
FlowGeometries.Grids.RingGrid — Type
RingGrid(geometry, sampling::AbstractReducedGaussianSampling; mask = nothing)
RingGrid(geometry, latitudes, nlon_per_ring, ring_area; mask = nothing)Iso-latitude rings whose longitude count varies by ring: the reduced Gaussian family, of which the octahedral grid is the operational case.
Storage is O(nrings) = O(√npoints) — one latitude, one longitude count, one offset and one cell area per ring. A point's longitude is (j−1)·2π/nlon[r], and its latitude and area are its ring's, so all three come from the ring's four numbers. At N = 1280 that is four vectors of 2560 entries, covering 6.6 million points.
Cells are numbered ring by ring from the north, matching SphericalSampling.ring_range and the order spherical_points writes.
Coordinates are (λ, φ): coords(grid, i) reads one point, and materialize gives the whole cloud as dense vectors.
FlowGeometries.Grids.RingwiseVector — Type
RingwiseVector(value, offset)The cell measure of a ring grid, held as its per-ring values.
Every cell of an iso-latitude ring has the same area, so npoints entries carry only nrings numbers — O(√npoints). A genuine AbstractVector: indexing, broadcasting and collect behave as for the dense equivalent.
sum is specialized to Σᵣ nlonᵣ·valueᵣ, O(nrings) against the dense O(npoints).
FlowGeometries.Grids.RotatedGrid — Type
RotatedGrid(base, rotation, map)A rectilinear grid whose cells are reported in a rotated frame: the mesh is base's, and a cell's position is map(rotation, λ, φ) evaluated where it is asked for.
rotate and unrotate build one. map is which direction the frame goes — Geometry.rotate for a mesh given in geographic coordinates and reported in the rotated frame, Geometry.unrotate for the reverse — and it is a singleton function type, so the choice resolves at compile time and the grid stays isbits apart from what base already holds.
Nothing is materialized. A rotation is an isometry of the sphere, so the cell measure carries over exactly and this shares base's array. The mesh, the mask, the index topology and the wrap lengths are base's too, all being properties of the cell lattice. What differs is where each cell sits, which costs two sincos pairs per coordinate access.
FlowGeometries.Grids.SeparableMeasure — Type
SeparableMeasure(factors)The cell measure of a rectilinear grid, held as its per-axis factors.
Every measure this package supports on such a grid is a product of one factor per axis (see _measure_factors), so the ∏ Nᵈ entries carry only ∑ Nᵈ numbers. It is a genuine AbstractArray: indexing, broadcasting and collect behave as for the dense equivalent.
sum is specialized to ∏ᵈ ∑ᵢ wᵈᵢ, O(∑ Nᵈ) against the dense O(∏ Nᵈ).
FlowGeometries.Grids.SeparableWindow — Type
SeparableWindow()The grid has separable axes, so a bounding index window per direction contains every cell within a given distance and is O(1) to compute — see Connectivity.metric_window. No index is needed and nothing is buffered.
FlowGeometries.Grids.SlabMeasure — Type
SlabMeasure(lead, slab, rest)The cell measure of a rectilinear grid with a single coupled pair of directions: measure[i, j, k, l…] == lead[i] · slab[j, k] · rest[1][l] · ….
A geodetic (λ, φ, h) volume element is (N(φ)+h)·cosφ·(M(φ)+h)·Δλ·Δφ·Δh. The height offsets both curvature radii, so no product of per-axis factors reproduces it and SeparableMeasure cannot hold it. Longitude enters none of that coupling, so only (φ, h) are stored together, giving Nφ·Nh + Nλ + … numbers against the dense ∏ Nᵈ.
sum and extrema are specialized on the same argument as the separable case: the whole is a product of independent groups, so its total is the product of their totals and its extremes are attained with every group at one of its own.
FlowGeometries.Grids.StaggeredGrid — Type
StaggeredGrid(geometry, axes...; mask = nothing, topology = nothing, period = nothing)
StaggeredGrid(center::StructuredGrid)One rectilinear mesh, readable at any staggered location: a family of grids.
A location is one FlowGeometries.Discretization.AbstractLocation per direction — Center() where the samples are the cell centres, Face() where they are the cell boundaries. On an Arakawa C arrangement the tracer sits at all-centres, the velocity component along direction d at Face() in d and Center() elsewhere, and the vorticity at Face() in the two directions it circulates about. grid_at returns the ordinary StructuredGrid at any of them, so every operator that already works on a rectilinear grid works at every location without knowing this type exists.
The face axes are built once, at construction. A face axis derived from a uniform primal axis is itself an Axes.UniformAxis — see FlowGeometries.Discretization.faces — so a uniform mesh stays uniform to every method that dispatches on spacing.
A periodic direction of N cells has N faces, its last face being its first; a bounded direction has N+1.
A mask is given over the centre cells, and a staggered point is active where every centre it is built from is. This is the finite-volume rule: a velocity face between an active and an inactive cell is a boundary, on the same footing as the least-squares gradient's unresolved direction and a stencil's masked cell.
FlowGeometries.Grids.StoredMeshNeighbors — Type
StoredMeshNeighbors()Neighbours are read from stored incidence, because the mesh is genuinely arbitrary and no formula describes it.
FlowGeometries.Grids.StructuredGrid — Type
StructuredGrid{T, G, N, S, TP, C, AT, BT}Rectilinear N-dimensional grid, for any N: one coordinate vector per direction (coordinates), an N-D cell measure (length in 1-D, area in 2-D, volume in 3-D, the N-D measure in general), an N-D active mask, per-direction topology, and the wrap period of each periodic direction.
Type parameters
T: coordinate float type.G<:AbstractGeometry{T}is tied to it, so a mismatched-eltype geometry raises a type error.Ttherefore precedesG: Julia binds type parameters left to right, andG<:AbstractGeometry{T}requiresTalready bound.CurvilinearGridandUnstructuredGridcarry the same convention.N: number of coordinate directions.S: theSphericalSamplingrecipe the axes came from, orNothingfor axes given directly. A zero-size singleton, so it costs nothing to carry and lets quadrature exactness, the matching latitude weights and a rebuild at another resolution dispatch on which node set this is — none of which the coordinates alone determine. Seesampling.TP: the per-directionAbstractTopology— singletons, so no storage, readable from the type.C: a heterogeneousNTuple{N,AbstractVector{T}}. Each axis independently keeps whatever concreteAbstractVector{T}type it was constructed with — anAxes.UniformAxis, a plainVector, a device array — so one axis can be uniform while another is stretched. AUniformAxis's type is a compile-time proof of constant spacing thatspacing_traitandspacingread without touching a coordinate, and a common vector type across the axes erases it.AT,BT: array types of the derivedmeasureand of the activemask.
FlowGeometries.Grids.StructuredGrid — Method
StructuredGrid(geometry, axes...; mask = nothing, topology = nothing, period = nothing)
StructuredGrid(geometry, axes..., mask; topology = nothing, period = nothing)Build a rectilinear grid in any number of dimensions from one coordinate vector per direction, pre-computing the separable cell measure from the geometry.
Each axis may independently be uniform or stretched, and keeps whichever it is in its own type — see isuniform. Axes are adapted to the geometry's float type T by _to_axis, which preserves uniformity and keeps a device-resident axis on its device.
For a SphericalGeometry the directions are (λ, φ, r, …): longitude, geographic latitude, and — in 3-D and above — the absolute radius from the origin. (A Geometry.SpheroidGeometry's third direction is a height above the surface instead.) Measures are the metric elements R·Δλ, R²cosφ·Δλ·Δφ and r²cosφ·Δλ·Δφ·Δr, with further directions entering as plain widths. A CartesianGeometry measure is the product of the per-direction widths.
Keywords
mask: anN-DBoolarray of active cells. Omit it (or passnothing) for an all-active grid, which stores only its size — seeAllActive. It may also be given positionally, after the axes.topology: per-direction closure. AcceptsPeriodic/Boundedinstances, a tuple of them, aBool, or a tuple ofBools; a single value or a short tuple applies to the leading directions and the rest areBounded. When omitted, direction 1 is auto-detected — on a spherical grid a longitude axis spanning the full circle isPeriodicand a regional span is not, in either storage order — and every other direction isBounded.period: the wrap length of each periodic direction. Omit it and the axis's own closure is used:2πfor spherical longitude, andextent + one spacingfor a Cartesian direction, which is exact for a uniform axis (n·|Δ|). A nonuniform periodic Cartesian direction has no closure to infer, its seam gap being undetermined by its samples, soperiodis required there.
FlowGeometries.Grids.UnstructuredGrid — Type
UnstructuredGrid(geometry, x, y, mask; k=6, radius=nothing, areas=nothing)Build an UnstructuredGrid whose adjacency comes from a k-d-tree nearest-neighbour search over the nodes: either the k nearest per node (default k = 6), or every neighbour within a physical radius. The two are mutually exclusive. Requires NearestNeighbors.
For SphericalGeometry the tree is built on the 3-D Cartesian embedding of the nodes, where nearest by chord distance and nearest by great-circle distance give the same ordering.
areas supplies per-node cell areas, as a dataset that ships its own does; nothing derives exact Voronoi-cell areas from a Delaunay or convex-hull tessellation (DelaunayTriangulation.jl for Cartesian, Quickhull.jl for spherical — see _voronoi_areas).
periodic/period declare a wrapping domain, and the neighbour search honours it: a node near one face finds the nodes across the opposite face. Spherical longitude wraps by default; a Cartesian box is opt-in and needs its period.
FlowGeometries.Grids.UnstructuredGrid — Type
UnstructuredGrid{T, G, V, VA, B, VI}Unstructured mesh (e.g. radial data, finite volume, or triangular mesh) where coords are 1D vectors.
Type parameters
T: coordinate float type.G<:AbstractGeometry{T}is tied to it, so a mismatched-eltype geometry raises a type error.Ttherefore precedesG: Julia binds type parameters left to right, andG<:AbstractGeometry{T}requiresTalready bound.CurvilinearGridfollows the same convention.C: tuple type of the per-direction node-coordinate vectors.VA: vector type of the derivedmeasurefield, independent ofC, a Voronoi tessellation having no reason to match the coordinate vectors' storage type.B: mask storage type.VN/VP: CSR neighbour-list and offset storage types, independent of each other. Their element type is a freeInteger, so a large mesh carriesInt32indices — half the memory and bandwidth ofInt64, and the width a GPU kernel wants — through this same type.
Neighbour adjacency is CSR: a flat neighbor_nbrs with neighbor_ptr offsets, node t owning neighbor_ptr[t]:neighbor_ptr[t+1]-1. The adjacency is immutable after construction, so the whole graph is two contiguous allocations and a traversal reads them in order.
FlowGeometries.Grids.UnstructuredGrid — Method
UnstructuredGrid(geometry, coords::Tuple, measure, mask[, neighbor_nbrs, neighbor_ptr]; periodic, period)
UnstructuredGrid(geometry, x, y, measure, mask[, neighbor_nbrs, neighbor_ptr]; periodic, period)Build a node grid in any number of directions from one coordinate vector per direction and CSR adjacency. Coordinates come as a tuple; the two-direction case may pass x, y positionally.
Omitting the CSR pair gives a grid with no adjacency — every node reports zero neighbours, which serves a scattered-point spectral method that never queries it. A real-space neighbourhood operation needs adjacency: build it (e.g. through the k-d-tree constructor below) and pass it in, or query by distance with Connectivity.neighbors_within, which reads coordinates.
periodic declares that the enclosing domain wraps in a direction, and period gives the wrap length there. A scattered point set carries no axis to infer this from, so both are explicit — except on a sphere, where longitude wraps at 2π by construction and is the default. See isperiodic and period.
FlowGeometries.Grids.YinYangGrid — Type
YinYangGrid(geometry, nlon, nlat; mask = nothing)The Kageyama–Sato Yin–Yang grid: two nlon × nlat lat–lon panels covering [-3π/4, 3π/4] × [-π/4, π/4] in their own frames, 2·nlon·nlat cells in all.
It stores nlon, nlat, the geometry and the mask. In its own frame each panel is a separable lat–lon patch, and yang is yin rigidly rotated, so a cell's coordinates are the panel formula composed with SphericalSampling._yin_yang_rotate. A cell's area depends on its latitude row alone.
Cells are numbered yin first with i fastest, then yang the same way, matching SphericalSampling.spherical_points(YinYangSampling(), nlon, nlat). panel_cell and cell_id convert between a cell id and its (panel, i, j).
The two panels overlap by construction, so the cell areas sum to 3√2πR² — 6.07% more than the sphere, at every resolution. That excess is the grid's real geometry, and integrating over both panels needs a partition-of-unity weight for the shared region, which is a modelling choice made on top of these areas. The panels are also not cross-linked: a cell's neighbours are its own panel's, which is the standard Yin–Yang discrete topology — the panels couple through interpolation.
FlowGeometries.Geometry.distance — Method
Geometry.distance(grid, I, J) -> T
Geometry.distance(grid::UnstructuredGrid, i, j) -> TDistance between the centres of two cells under the grid's own geometry and topology: the coordinates are resolved from the indices, reduced to the nearest image in every periodic direction, and handed to the point form of Geometry.distance.
Across a periodic seam this is the short way round: one spacing between the first and last cell of a periodic direction, where the point form on the raw coordinates gives the full extent. A bounded direction contributes its plain coordinate difference. See displacement for the offset it was taken from.
FlowGeometries.Grids._ambient_bound — Method
_ambient_bound(grid) -> TThe largest |x|, |y| or |z| any of this grid's cells can embed to.
FlowGeometries.Grids._axis_summary — Method
_axis_summary(x) -> AxisSummaryReduce axis x in a single pass. A uniform axis answers from first, step and length, reading no element.
FlowGeometries.Grids._build_kdtree_neighbors — Method
_build_kdtree_neighbors(geometry, coords::Tuple; k=6, radius=nothing) -> (nbrs, ptr)Extension hook: build CSR neighbor adjacency via a k-d tree. Overridden by a consumer NearestNeighbors extension (load using NearestNeighbors). radius, if given, switches to an all-neighbors-within-radius query (mutually exclusive with k); radius is in the grid's physical distance units — Geometry.distance, so meters for SphericalGeometry and the geometry's own units for CartesianGeometry.
FlowGeometries.Grids._cell_from_linear — Method
_cell_from_linear(grid, lin) -> cellThe cell a linear index names: the inverse of the linear index a traversal reports, and what turns a spatial index's answer back into a cell.
FlowGeometries.Grids._cell_indices — Method
_cell_indices(grid, cell) -> Tuple{Vararg{Int}}A cell as the index tuple every mask and coordinate accessor here takes: the tuple itself where cells are CartesianCells, and (i,) where they are FlatCells.
Both the trait and the cell's own type are dispatched on, because they answer different questions: the trait says how this layout names a cell, the cell's type how the caller named it. A pair that does not agree — an integer for a tuple-addressed grid — reaches the message below, at the entry point the caller wrote.
FlowGeometries.Grids._cell_measure — Method
_cell_measure(geometry, axes, periods)The grid's stored measure: a SeparableMeasure wherever the metric factors per axis, and a SlabMeasure where one pair of directions is coupled and the rest are not.
FlowGeometries.Grids._cell_named_by — Method
_cell_named_by(grid, I::Tuple) -> cellThe cell a caller named with the indices I: the tuple itself where cells are CartesianCells, and its single element where they are FlatCells. An entry point taking I::Vararg{Integer} hands the traversals this.
FlowGeometries.Grids._centers_to_corners — Method
_centers_to_corners(C) -> KReconstruct a cell-vertex array one larger in every direction from the N-D cell-center array C, by averaging the (up to 2^N) surrounding centers with a linearly-extrapolated one-cell ghost ring, so the true domain-boundary vertices land a half-cell outside the outermost centers. Used only when the caller does not supply explicit corner arrays; requires at least 2 centers across every direction.
Unlike the corner-area kernel this is dimension-generic: it is a multilinear midpoint, and the ghost ring is a per-direction linear extension of it.
FlowGeometries.Grids._curvilinear_periods — Method
_curvilinear_periods(geometry, centers, topology, period) -> NTuple{N,T}Wrap length per periodic direction, zero where bounded. Spherical longitude closes at 2π; a Cartesian direction's comes from that direction's own line of centres.
FlowGeometries.Grids._curvilinear_topology — Method
_curvilinear_topology(geometry, x, topo) -> NTuple{2,AbstractTopology}Per-direction closure. Absent a caller's choice, direction 1 is auto-detected from the first row of centres read as a longitude-like axis, as StructuredGrid does.
FlowGeometries.Grids._embedded_floor — Function
_embedded_floor(grid, embedding, h, ::Val{D}) -> NTuple{D,T}A lower bound on the embedded coordinate in each direction, less one bin, which is where the lattice starts. O(1): no cell is read.
Any bound serves: the lattice is unbounded along a direction that does not wrap, and bins are hashed, so a loose origin shifts every bin index equally. Taking it from the geometry indexes a layout without a pass over its cells.
FlowGeometries.Grids._embedding_for — Method
_embedding_for(geo, ncoords) -> AbstractEmbeddingThe space a geometry's ncoords-coordinate points sit in. embedding_of is this for a grid, which knows its own coordinate count; a caller holding loose coordinate vectors states it.
One definition, so an index built from a grid and one built from bare coordinates convert a radius through the same code.
FlowGeometries.Grids._ghost_points — Method
_ghost_points(pts, periodic, period) -> (all_pts, nghost)Replicate the D × N point matrix once per combination of periodic image offsets, originals in the first N columns. A wrapping domain is then searched by an ordinary Euclidean query over the images.
FlowGeometries.Grids._gnomonic_solid_angle — Method
_gnomonic_solid_angle(X1, X2, Y1, Y2) -> TThe solid angle subtended by the gnomonic rectangle [X1, X2] × [Y1, Y2] on the unit sphere, exactly.
atan(XY / √(1 + X² + Y²)) at a corner is the solid angle of the rectangle from the panel centre to that corner, so the four corners combine by inclusion–exclusion. Over a whole panel it gives 4π/6.
FlowGeometries.Grids._grid_points — Method
_grid_points(grid) -> (raw, D)Cell centres as a D × n matrix, in the grid's own coordinates.
FlowGeometries.Grids._ico_class — Method
_ico_class(k, ν) -> (b, c)Vertex k's symmetry class: the two smallest of its barycentric parts (i, j, ν−i−j), the largest being ν minus their sum.
All twenty faces are the same spherical triangle and the geodesic is built the same way on each, so a vertex's dual area depends only on its barycentric position within a face; the face being equilateral, only on that triple up to order. A vertex on a macro-edge or at a corner sits on several faces, and an isometry of the icosahedron carrying it to another vertex of its class carries those faces with it, so the areas agree there too.
The classes are the partitions of ν into three parts, O(ν²/12) of them against 10ν² + 2 vertices.
FlowGeometries.Grids._ico_dual_share — Method
_ico_dual_share(V, A, B) -> TVertex V's share of the spherical triangle (V, A, B): the quadrilateral (V, M_VA, O, M_VB) with O the circumcenter and M the edge midpoints, as two spherical excesses.
Those arcs are the triangle's perpendicular bisectors — O is equidistant from all three vertices and each midpoint from its two — so the share is exactly V's Voronoi cell restricted to that triangle, and the three shares tile the triangle.
FlowGeometries.Grids._ico_vertex_measure — Method
_ico_vertex_measure(grid, k, ν) -> TThe dual area of vertex k, from its own incident triangles: the fan of _ico_dual_shares over every face the vertex sits on.
FlowGeometries.Grids._linear_of — Method
_linear_of(grid, cell) -> IntThe linear index a cell reports as, and the inverse of _cell_from_linear.
FlowGeometries.Grids._max_gap — Method
_max_gap(x) -> maximum consecutive |gap|, or 0 if length(x) < 2Largest spacing anywhere on axis x, the counterpart of _min_gap. Together they bound how far an index window must reach to cover a given physical distance.
FlowGeometries.Grids._measure_factors — Method
_measure_factors(geometry, axes, periods) -> NTuple{N,AbstractVector}Per-axis factors whose outer product is the cell measure: measure[I...] == prod(w[d][I[d]]).
Every rectilinear cell measure this package supports is separable in exactly this way — Cartesian Δx·Δy·Δz, and spherical R²cosφ·Δλ·Δφ = (Δλ) · (R²cosφ·Δφ) or r²cosφ·Δλ·Δφ·Δr = (Δλ) · (cosφ·Δφ) · (r²·Δr). Building the measure as an outer product of these factors keeps the result in whatever array type the axes use, and exposes the separability to a caller that can exploit it.
A degenerate (length-1) angular axis drops its differential, so a zonal transect measures arc length R·cosφ·Δλ along its circle of latitude and a meridional one measures R·Δφ.
FlowGeometries.Grids._min_gap — Method
_min_gap(x) -> minimum consecutive |gap|, or Inf if length(x) < 2Smallest spacing found anywhere on axis x. It bounds the search radius for a genuinely nonuniform axis: a distance check still gates what is included, so the smallest gap anywhere can only widen the search window, and no in-range cell is missed.
FlowGeometries.Grids._min_image — Method
_min_image(p0, pt, prd) -> NTuplept brought to the image nearest p0, per component, for each direction with a nonzero wrap length.
For an angular coordinate the geometry's own distance is already 2π-periodic and this changes nothing (it also keeps Vincenty inside its |Δλ| ≤ π regime); on a periodic Cartesian coordinate it carries a pair across the seam. Per-component minimum image is the global minimum for a separable metric, which the Euclidean one is.
FlowGeometries.Grids._raw_coords — Method
_raw_coords(grid, I...) -> NTuplePositional coordinate values at indices I. Internal; prefer coords.
FlowGeometries.Grids._sep_extrema — Method
_sep_extrema(f, m) -> (lo, hi)Smallest and largest f(cell) over a SeparableMeasure, from the per-axis extremes.
A product's extremes are attained with every factor at one of its own endpoints, so all 2^N endpoint combinations are formed and the best taken. This holds for factors of either sign, where ∏ maximum alone holds only for non-negative ones, and it costs O(∑ Nᵈ + 2^N) against the dense O(∏ Nᵈ).
FlowGeometries.Grids._shift_set — Method
_shift_set(periodic, period)Offsets to replicate a point set by: (0,) in a non-wrapping direction, (0, -L, +L) in a wrapping one. Zero first, so the originals occupy the first block of the replicated set.
FlowGeometries.Grids._to_axis — Method
_to_axis(T, x) -> AbstractVector{T}Adapt axis input x to element type T, keeping whatever is known about its spacing and never collapsing a provably uniform axis into a plain Vector.
An axis already of element type T is kept exactly as it is, whatever type it is. A caller's own range subtype, a StepRangeLen whose TwicePrecision internals they want, a BigFloat-backed range — all pass through untouched. Nothing needs converting to get the uniform fast paths: those dispatch on Axes.spacing_trait, which is UniformSpacing() for every AbstractRange, so the caller's own range takes them.
Conversion happens only where the element type must change, and there an arbitrary range subtype cannot generically be rebuilt at a new eltype. That case becomes an Axes.UniformAxis{T}, which is also how a Float32 axis stops carrying Float64 internals. Call Axes.uniform_axis to convert at the call site.
Four methods, ordered so nothing is ambiguous (a StepRangeLen{T} is both an AbstractRange and an AbstractVector{T}, so the parameterized range form is needed to break that tie):
AbstractRange{T}/AbstractVector{T}: passthrough, zero cost, type preserved.AbstractRange(wrong eltype): rebuilt asUniformAxis{T}, still uniform and nowisbits.AbstractVector(wrong eltype): copied withsimilar, so a device-resident array stays in its own storage.
FlowGeometries.Grids._total_measure — Method
_total_measure(grid) -> Tsum(measure(grid)), from whatever the layout knows about the region its cells tile. The fallback adds the cells up; a layout tiling the whole sphere returns 4πR² without visiting one.
FlowGeometries.Grids._voronoi_areas — Method
_voronoi_areas(geometry, x, y) -> Vector{T}The areas alone, for a caller with no use for the cells — see _voronoi_tessellation.
FlowGeometries.Grids._voronoi_tessellation — Method
_voronoi_tessellation(geometry, x, y) -> (areas, mesh::CellMesh)Extension hook: exact per-node Voronoi-cell area from a Delaunay/convex-hull tessellation of the node coordinates, together with the triangulation it came from. Dispatched on the geometry type (each needs a different tessellation library): overridden for CartesianGeometry by a consumer DelaunayTriangulation extension (load using DelaunayTriangulation, planar Voronoi clipped to the point set's convex hull) and for SphericalGeometry by a consumer Quickhull extension (load using Quickhull, spherical Voronoi from the dual of the 3D convex hull of the unit-sphere embedding).
An Geometry.AbstractEllipsoidalGeometry has no such construction and says so: its cell areas are the caller's to supply.
FlowGeometries.Grids._wrap_lengths — Method
_wrap_lengths(grid, Val(N)) -> NTuple{N,T}Wrap length per direction, zero where the direction is bounded, so _min_image leaves those components alone.
FlowGeometries.Grids._wrap_sign — Method
_wrap_sign(x) -> ±1+1 for an ascending axis and -1 for a descending one: the sign that turns a period magnitude into the wrapped neighbour's offset in index order. Defined in Axes — it is a property of the axis alone, and the discretization layer needs the same answer.
FlowGeometries.Grids.adjacency_source — Function
adjacency_source(grid) -> AbstractAdjacencyWhere grid's neighbour relation comes from.
FlowGeometries.Grids.area — Method
area(grid, I...) -> Tmeasure under its 2-D name.
FlowGeometries.Grids.axis — Method
axis(grid::AbstractStructuredGrid, d::Integer) -> AbstractVectorDirection d's coordinate axis. Only rectilinear grids have axes; this is coordinates under the name that is exact for them.
FlowGeometries.Grids.axis_at — Method
axis_at(sg, d, loc) -> AbstractVectorDirection d's samples at location loc: the primal axis at Discretization.Center, its faces at Discretization.Face.
FlowGeometries.Grids.base_grid — Method
base_grid(grid::RotatedGrid) -> AbstractStructuredGridThe rectilinear mesh underneath. Its axes are the coordinates a derivative differences along; the rotation changes where cells are reported, leaving the lattice as it is.
FlowGeometries.Grids.bounds — Method
bounds(grid, d) -> (lo, hi)Smallest and largest coordinate along direction d, ordered lo ≤ hi regardless of whether the direction is stored ascending or descending. These are the extreme sample positions, i.e. cell centres.
O(1) on a rectilinear grid: an axis is monotone, as every search here bisects it, so its extremes are its endpoints. O(N) where the coordinates are per-cell fields, which carry no such order; a query that reads this repeatedly takes it from a MetricTopology, built once.
FlowGeometries.Grids.candidate_source — Function
candidate_source(grid) -> AbstractCandidateSourceHow a distance query on grid enumerates candidates.
FlowGeometries.Grids.cell_address — Function
cell_address(grid) -> AbstractCellAddressWhether grid's cells are named by an index tuple or by a single integer.
FlowGeometries.Grids.cell_at — Method
cell_at(grid, c)One element of cells as the cell spelling the grid's own entry points take: an index tuple where cells are addressed Cartesian-wise, a linear id where they are flat.
FlowGeometries.Grids.cell_id — Method
cell_id(grid, panel, i, j) -> IntThe cell id of (panel, i, j), the inverse of panel_cell.
FlowGeometries.Grids.cell_list — Method
cell_list(grid; ball, active_only = false) -> CellListIndexBuild a CellListIndex over grid's cell centres, binned at side ball — the radius you mean to query at. Needs no external package.
The default indexes every cell, which serves a query at either mask policy: an active_only = true query filters what it is handed.
active_only = true indexes the active region alone, sizing a mostly-masked grid — a basin, a catchment — by that region. Such an index answers queries at that same policy, and raises for one asking to see a masked cell. Ask for it where the policy is fixed, as a sweep does.
FlowGeometries.Grids.cell_mesh — Method
cell_mesh(grid) -> CellMesh | NothingThe grid's CellMesh, or nothing where it has none.
A node set built by tessellation keeps the cells that tessellation produced; one given its adjacency directly has only that adjacency, and no cells to speak of unless it is handed some.
FlowGeometries.Grids.cell_nodes — Method
cell_nodes(mesh, c) -> AbstractVector{<:Integer}The nodes of cell c, in order around it, as a view into the mesh's own storage.
FlowGeometries.Grids.cell_width — Method
cell_width(grid, d, i) -> TThe coordinate width of cell i along direction d: Discretization.cell_width on that direction's axis, with the grid's own wrap period. Non-negative whichever way the axis is stored.
A coordinate width, distinct from the cell measure: on a sphere measure is R²cosφ·Δλ·Δφ and this is the Δλ or Δφ in it. measure_factors folds the metric into each factor, so it does not expose these separately.
FlowGeometries.Grids.cell_widths — Method
cell_widths(grid, d) -> AbstractVectorcell_width along the whole of direction d, as Discretization.cell_widths on its axis with the grid's own wrap period. A uniform direction gets an Axes.ConstantVector, so nothing is materialized.
FlowGeometries.Grids.cells — Method
cells(grid)What a traversal of every cell iterates, and cell_at turns one of its elements into a cell. Together they are how a layout is walked without knowing how it names a cell — see cell_address.
FlowGeometries.Grids.center_grid — Method
center_grid(sg) -> StructuredGridThe primal grid sg was built from: every direction at Center(), which is where a tracer sits.
FlowGeometries.Grids.center_location — Method
center_location(sg) -> NTuple{N,Center}Every direction at Center().
FlowGeometries.Grids.coordinate_names — Method
coordinate_names(grid) -> NTuple{N,Symbol}The grid's coordinate names, from its geometry: (:x, :y[, :z]) or (:λ, :φ[, :r]).
FlowGeometries.Grids.coordinates — Method
coordinates(grid) -> NTuple{N,AbstractArray}
coordinates(grid, d::Integer) -> AbstractArrayThe grid's coordinate arrays, or just direction d's. Shape depends on the grid architecture: a StructuredGrid stores one 1-D axis vector per direction, a CurvilinearGrid one N-D array per direction, an UnstructuredGrid one value per node. Direction order matches Geometry.point_names — (x, y, z) for Cartesian, (λ, φ, r) for spherical.
See also axis (the rectilinear spelling), coords (a single point).
FlowGeometries.Grids.coords! — Method
coords!(out, grid, I...) -> outWrite positional coordinates into a preallocated AbstractVector (length(out) ≥ N).
FlowGeometries.Grids.coords — Method
coords(grid, I...) -> NamedTuplePoint at indices I, as a geometry-named NamedTuple:
- Cartesian:
(x=, y=)or(x=, y=, z=) - Spherical:
(λ=, φ=)or(λ=, φ=, r=)
See also coords!, coords(::Type, grid, I...).
FlowGeometries.Grids.coords — Method
coords(::Type{S}, grid, I...) -> SConstruct the point as type S — Tuple, NTuple{N,T}, NamedTuple, Vector{T}, or SVector{N,T}/MVector{N,T} when StaticArrays is loaded. See Geometry.build_point for how S is assembled.
FlowGeometries.Grids.corner_coords — Method
corner_coords(grid::CurvilinearGrid, I...) -> NamedTuple
corner_coords(S, grid::CurvilinearGrid, I...) -> SVertex I of the cell-vertex array, named by the geometry exactly as coords names cell centers.
FlowGeometries.Grids.corners — Method
corners(grid::CurvilinearGrid) -> NTuple{N,AbstractArray}
corners(grid::CurvilinearGrid, d::Integer) -> AbstractArrayThe cell-vertex coordinate arrays — one larger than coordinates in every direction, and in the same direction order.
Available on a grid that was given them or built with keep_corners = true; see has_corners.
FlowGeometries.Grids.displacement — Function
displacement(grid, I, J) -> NTuple{N,T}
displacement(grid::UnstructuredGrid, i, j) -> NTuple{N,T}The signed per-direction coordinate offset from cell I to cell J, reduced to the nearest image in every periodic direction — the offset Geometry.distance is taken from.
A coordinate quantity, so it lives here, while the distance extends Geometry.distance. Across a periodic seam the two cells' stored coordinates differ by nearly a full period, and this reports the short way round.
FlowGeometries.Grids.embed_point — Function
embed_point(grid, p) -> NTupleOne coordinate tuple through the same transform embedded_points applies to the cell centres, so a query seeded by a point searches the space the index was built in.
FlowGeometries.Grids.embedded_at — Method
embedded_at(grid, cell) -> NTuple{D,T}A cell's centre in the space an index searches, taken from the grid: O(1) arithmetic where the coordinates are a formula, a read where they are data.
FlowGeometries.Grids.embedded_points — Function
embedded_points(grid) -> (pts, nghost, embedding)The cell centres in the space an index searches, the number of periodic replications they carry, and the AbstractEmbedding saying what a radius means there.
One definition, so every index searches the same space as every other and as the k-d-tree construction path — the guarantee that an indexed query and a scan return the same cells rests on it.
FlowGeometries.Grids.embedded_radius — Method
embedded_radius(embedding, r) -> TA physical radius as a radius in the embedding.
FlowGeometries.Grids.embedding_of — Function
embedding_of(grid) -> AbstractEmbeddingThe Euclidean space this grid's cell centres sit in, and therefore what a physical radius means there.
Named separately from embedded_points because an index that streams the centres still has to know the space before it reads the first one.
FlowGeometries.Grids.extent — Method
extent(grid, d) -> Thi - lo from bounds: the span covered by direction d's samples. Zero for a singleton direction.
FlowGeometries.Grids.fold_candidates — Function
fold_candidates(f, acc, index, grid, I, r) -> accThread acc = f(acc, k) over every cell k the index reports near cell I, without building a list. A superset of the ball, each cell exactly once; the caller's exact distance gate decides membership.
A fold allocates nothing and needs no per-query buffer, so it runs inside a kernel. A tree walk needs one, having to deduplicate the periodic images it searches over.
FlowGeometries.Grids.fold_candidates_at — Method
fold_candidates_at(f, acc, index, q, r, scratch) -> accfold_candidates around an arbitrary point q, already in the index's embedding. A cell query is this one at the cell's own centre, so there is a single traversal.
scratch is a candidate buffer for an index that has to materialize one — a tree does, since it must deduplicate the periodic images it searches over. A cell list folds directly and ignores it.
FlowGeometries.Grids.formula_neighbors — Function
formula_neighbors(grid, cell) -> (ids::NTuple{K,Int}, n)A cell's neighbours as linear indices, in the first n entries of a fixed-width tuple, where K is max_neighbors(grid).
The tuple is a stack value, so a traversal over every cell of a layout whose adjacency is arithmetic allocates nothing and threads no scratch through. n varies where a layout has singular cells: a HEALPix pixel at a face corner has seven neighbours where the rest have eight.
The one method a FormulaNeighbors layout supplies.
FlowGeometries.Grids.frequency — Method
frequency(grid::IcosahedralGrid) -> IntThe subdivision frequency ν: the grid has 10ν² + 2 vertices and 20ν² triangles.
FlowGeometries.Grids.grid_at — Method
grid_at(sg, loc) -> StructuredGridThe grid of sg at location loc, one Discretization.Center/Discretization.Face per direction.
An ordinary StructuredGrid, so every rectilinear operator applies to it unchanged. It is built on request — there are 2^N locations and a mesh uses few of them — so a caller differencing repeatedly holds the result, the way a stencil plan is held.
FlowGeometries.Grids.has_cell_mesh — Method
has_cell_mesh(grid) -> BoolWhether cell_mesh has cells to give — what the operators that need a cell dispatch on.
FlowGeometries.Grids.has_corners — Method
has_corners(grid) -> BoolWhether grid retained its cell-vertex arrays, and so can answer corners and corner_coords.
FlowGeometries.Grids.has_spatial_index — Method
has_spatial_index(grid) -> BoolWhether the k-d tree behind spatial_index can be built for this grid — false until the NearestNeighbors extension is loaded. Answers "is the tree available?" without calling spatial_index speculatively and catching its error.
This is not a test for whether a grid can be indexed at all: cell_list needs no extension and is what the sweeps build.
FlowGeometries.Grids.has_symmetric_adjacency — Function
has_symmetric_adjacency(grid) -> BoolWhether the graph grid builds satisfies j ∈ N(i) ⟺ i ∈ N(j), answered from the layout.
A symmetric graph with sorted rows has the same arrays read as CSR and as CSC, so Connectivity.sparse_adjacency_matrix hands its buffers to the matrix without transposing. Connectivity.is_symmetric_adjacency answers the same question about a built graph, and pays a transpose to do it; this answers before one exists.
false by default, so a layout claims the shortcut only where its own formula gives it. Masking preserves it either way: an edge and its reverse are the same pair of cells, and both are dropped together. A layout whose neighbours are an index stencil answers through the stencil, which carries its own Stencils.is_symmetric.
FlowGeometries.Grids.incident_nodes — Method
incident_nodes(grid, idx::Integer) -> AbstractVector{<:Integer}The nodes stored as incident to node idx, as a zero-copy view into the CSR adjacency.
This is storage: it reports what the mesh holds, with no regard for the mask. neighbors is the query, and it honours active_only on every layout.
FlowGeometries.Grids.index_within! — Method
index_within!(buffer, index, grid, I, r) -> candidate cell indices
index_within(index, grid, I, r) -> candidate cell indicesExtension hook: the cells an index reports near I, as linear indices. It must return a superset of the cells within r; the caller applies the exact distance gate, so over-returning is safe and under-returning is not.
index_within! overwrites and returns buffer, so a sweep over many cells allocates nothing per query. index_within is the same query into a fresh vector.
FlowGeometries.Grids.isactive — Method
isactive(grid, I...) -> BoolWhether cell/node I participates (false = masked out).
FlowGeometries.Grids.isperiodic — Method
isperiodic(grid, d) -> BoolWhether coordinate direction d wraps. See topology for the type-level form and period for the wrap length.
FlowGeometries.Grids.isuniform — Method
isuniform(grid, d) -> Bool
isuniform(grid) -> BoolWhether coordinate direction d has constant spacing known from its type (all directions, for the no-d form). The answer comes from the type alone; no code path inspects coordinate values to decide it. See spacing_trait for the form a method can dispatch on.
A curvilinear or unstructured grid is never uniform: its coordinates are per-cell fields with no axes.
FlowGeometries.Grids.local_spacing — Method
local_spacing(grid, d, i) -> (h_m, h_p)The one-sided coordinate gaps around index i along direction d: Discretization.local_spacing on that direction's axis, with the wrap period taken from the grid, so a periodic seam is right without the caller supplying it.
Signed, so a descending axis reports negative gaps — see the axis-level form for why, and cell_width for the non-negative width built from them. Allocation-free, so this is the per-point form to call inside a loop assembling a finite-difference operator.
FlowGeometries.Grids.locate — Function
locate(grid, p) -> cell index
locate(grid, p; active_only=false, topology, scratch) -> cell indexThe cell of grid that p belongs to, as an NTuple of indices on a rectilinear or curvilinear grid and a node number on an UnstructuredGrid. p is a coordinate tuple in the grid's own coordinates.
On a StructuredGrid this is Discretization.locate per direction, so the answer is the cell whose faces bracket p — an O(1) lookup on a uniform axis and a bisection otherwise, with a periodic direction wrapped first. A direction p lies outside reports 0 for that direction.
Elsewhere there are no axes to bracket along and it is the nearest cell centre, which is exactly the containing cell for a node set, whose cells are the Voronoi regions of its nodes. On a curvilinear grid the two can differ where cells are strongly sheared, so the contract is nearest-centre. That form takes the keywords: topology carrying an index — cell_list — makes it a bin lookup, scratch is a Connectivity.ball_scratch buffer, and active_only restricts the answer to unmasked cells. It defaults to false here, where the ball queries default to true: which cell a point falls in is a question about the grid, answerable over the masked region.
FlowGeometries.Grids.location_at — Method
location_at(sg, d) -> NTuple{N,AbstractLocation}Where the velocity component along direction d sits: Face() in d, Center() in every other direction.
FlowGeometries.Grids.locations — Method
locations(sg) -> NTuple{N,NTuple{N,AbstractLocation}}All N velocity locations, one per direction — location_at for each, which together are the Arakawa C staggering itself.
FlowGeometries.Grids.mask — Method
mask(grid) -> AbstractArray{Bool}Which cells/nodes participate, as an array over the grid's own shape. Ask isactive for one cell; this is the whole array, and it is what fixes the grid's size.
FlowGeometries.Grids.materialize — Method
materialize(grid) -> NTuple{D,Vector}Every cell's coordinates, as one dense vector per direction.
How to ask a layout whose coordinates are a formula for them as data — for writing a file, or handing them to something that takes point clouds. It allocates D·n numbers, so it is an explicit call.
FlowGeometries.Grids.max_neighbors — Function
max_neighbors(grid) -> IntThe widest neighbour count any cell of grid can have, as a compile-time constant. It fixes the tuple width formula_neighbors returns.
FlowGeometries.Grids.maximum_spacing — Method
maximum_spacing(grid, d) -> TLargest gap between consecutive samples along direction d, the counterpart of minimum_spacing. A direction of fewer than two samples reports 0, the identity for max.
FlowGeometries.Grids.measure — Method
measure(grid, I...) -> TCell measure at index I: length in 1-D, area in 2-D, volume in 3-D, or the node's control-volume size on an unstructured grid. area is the 2-D spelling of the same quantity.
FlowGeometries.Grids.measure_array — Method
measure_array(grid) -> ArrayThe cell measure materialized densely. This is ∏ Nᵈ values — only ask for it when a dense array is genuinely required; measure already indexes and broadcasts.
FlowGeometries.Grids.measure_array — Method
measure_array(grid::IcosahedralGrid) -> VectorThe dual-cell areas of every vertex, the fan of spherical excesses evaluated once per symmetry class — see _ico_class. The two smallest barycentric parts key a (ν+1)² table.
FlowGeometries.Grids.measure_factors — Method
measure_factors(grid) -> NTuple{N,AbstractVector} or nothingThe grid's per-axis measure factors when it has them, else nothing. Callers that can exploit separability (a zonal mean weights by one factor only, a global integral is a product of sums) can avoid touching ∏ Nᵈ values at all.
FlowGeometries.Grids.minimum_spacing — Method
minimum_spacing(grid, d) -> TSmallest gap between consecutive samples along direction d, as a non-negative magnitude. O(1) when the direction is isuniform and O(N_d) otherwise. With maximum_spacing it bounds how far an index window must reach to cover a given physical distance, as a neighbourhood-by-distance query on a stretched axis needs. The two are also the exact test of whether a stretched axis happens to be equally spaced: its gaps are identical when they are equal.
A direction of fewer than two samples has no gap, and reports Inf — the identity for min.
FlowGeometries.Grids.ncells — Method
ncells(mesh) -> IntHow many cells the mesh has.
FlowGeometries.Grids.ncoordinates — Method
ncoordinates(grid) -> IntHow many coordinate directions a cell of grid has — 2 for (λ, φ), 3 for (x, y, z).
Separate from counting coordinates(grid) because a layout whose coordinates are a formula stores no arrays to count, and answers this from its parameters instead.
FlowGeometries.Grids.neighbor_nbrs — Method
neighbor_nbrs(grid::UnstructuredGrid) -> AbstractVector{<:Integer}
neighbor_ptr(grid::UnstructuredGrid) -> AbstractVector{<:Integer}The CSR adjacency arrays: the flat neighbour indices, and the per-node offsets into them.
FlowGeometries.Grids.neighbors — Function
neighbors(grid, I...; stencil = Stencils.Axial(1), active_only = true)The neighbours of cell I, as a lazy sequence of linear indices that allocates nothing.
Where they come from is the layout's adjacency_source: index-space offsets, which stencil selects among, or the mesh's own stored incidence, over which a stencil has no meaning.
active_only applies either way: a masked cell has no neighbours and is nobody's neighbour. See incident_nodes for the unfiltered storage behind a stored graph.
FlowGeometries.Grids.nlon_in_ring — Method
nlon_in_ring(grid::RingGrid, r::Integer) -> IntPoints in ring r, counted from the north.
FlowGeometries.Grids.node_cells — Method
node_cells(mesh, i) -> AbstractVector{<:Integer}The cells incident on node i, as a view into the mesh's own storage.
FlowGeometries.Grids.npanels — Method
npanels(grid) -> IntHow many panels the layout has — six for the cubed sphere, two for Yin–Yang.
FlowGeometries.Grids.npixels — Method
npixels(grid::HEALPixGrid) -> Int12·nside², the pixelization's own count — which is length(grid) whether or not a mask leaves some of them inactive.
FlowGeometries.Grids.nrings — Method
nrings(grid::RingGrid) -> IntHow many iso-latitude rings the grid has.
FlowGeometries.Grids.nside — Method
nside(grid::HEALPixGrid) -> IntThe resolution parameter: the grid has 12·nside² pixels on 4·nside − 1 rings.
FlowGeometries.Grids.origin — Method
origin(grid, d) -> TThe first coordinate along direction d.
FlowGeometries.Grids.panel_cell — Method
panel_cell(grid, k) -> (panel, i, j)Which panel cell k is on and where on it, the inverse of cell_id.
FlowGeometries.Grids.panel_shape — Method
panel_shape(grid::YinYangGrid) -> (nlon, nlat)The cell counts across one panel.
FlowGeometries.Grids.panel_size — Method
panel_size(grid) -> IntCells across one panel of a panel layout: n for the cubed sphere, whose panels are n × n.
FlowGeometries.Grids.period — Method
period(grid, d) -> TWrap length of coordinate direction d, meaningful only where isperiodic holds.
FlowGeometries.Grids.periodic_flags — Method
periodic_flags(grid) -> NTuple{N,Bool}topology as one Bool per direction. Const-folds, and unlike indexing the heterogeneous topology tuple it stays type-stable under a runtime direction.
FlowGeometries.Grids.rebuild — Method
rebuild(grid, fields::NamedTuple) -> gridgrid with the named fields replaced, its type parameters re-derived from what the new fields are.
The hook a storage change goes through — moving a grid's arrays to a device, rewrapping them — so one generic method serves every layout and no reconstruction elsewhere spells out a parameter list of its own.
fields need only name what changes; everything else is carried over.
FlowGeometries.Grids.reorder — Method
reorder(grid, perm) -> UnstructuredGridgrid with its nodes in the order perm gives — coordinates, measure and mask permuted, and the adjacency and any CellMesh renumbered to match, so every index the grid reports is an index into the new order.
Pair it with spatial_order, and permute your own fields by the same perm: f[perm] is that field on the reordered grid.
FlowGeometries.Grids.ring_of — Method
ring_of(grid::RingGrid, i::Integer) -> IntWhich ring cell i belongs to.
O(log nrings) by bisection of the cumulative counts. A closed form exists for the octahedral rule alone; a tabulated reduced grid's counts are arbitrary, so the search is what serves both.
FlowGeometries.Grids.ring_range — Method
ring_range(grid::RingGrid, r::Integer) -> UnitRange{Int}The cells of ring r, as a contiguous slice of the flattened numbering. O(1).
FlowGeometries.Grids.rotate — Method
rotate(grid::StructuredGrid, rot) -> RotatedGrid
unrotate(grid::StructuredGrid, rot) -> RotatedGridThe same mesh with its coordinates expressed in the other frame of Geometry.PoleRotation rot — unrotate being the usual direction, taking a rotated-pole grid's rectilinear (λ′, φ′) axes to the geographic coordinates of each cell.
A rotated lat–lon mesh is logically rectangular and geometrically warped, and only its own frame's axes are separable. The warping is a formula, so the result stores the mesh and the rotation and evaluates a cell's position where it is asked for; see RotatedGrid. Rotating a grid therefore costs one PoleRotation, against two centre arrays, two corner arrays and a dense measure to materialize it.
Two things carry over. The cell measure is exact under a rotation, an isometry of the sphere, so it is shared; recomputing it from rotated corners adds round-off. The index topology carries over too: the same mesh has the same neighbours, so a direction that wrapped still wraps, and longitude remains an angle mod 2π in either frame.
To difference along the mesh's own axes, ask base_grid for them: the frame changes where a cell is reported, leaving the lattice as it is.
FlowGeometries.Grids.rotation — Method
rotation(grid::RotatedGrid) -> PoleRotationThe frame the mesh is read in.
FlowGeometries.Grids.sampling — Method
sampling(grid) -> AbstractSphericalSampling | NothingThe node-set recipe grid's axes were built from, or nothing where they were given directly.
Coordinates do not determine it: Gauss–Legendre and an arbitrary lat–lon grid are the same numbers to within round-off, and only the recipe says which quadrature is exact on them. Keeping it means a grid can be asked for its matching weights, or rebuilt at another resolution, after construction.
FlowGeometries.Grids.scheme — Method
scheme(grid::HEALPixGrid) -> RingSchemeWhich pixel ordering the ids are in — Ring() or Nested().
FlowGeometries.Grids.size_tuple — Method
size_tuple(grid) -> NTuple{N,Int}size(grid), kept as a named function for call sites that read better spelled out.
FlowGeometries.Grids.spacing — Method
spacing(grid, d) -> TThe constant spacing of coordinate direction d, available without reading any coordinate. Signed, so a descending axis reports a negative spacing. Raises for a direction that is not isuniform — for a nonuniform one use minimum_spacing / maximum_spacing for its range of gaps, local_spacing for the gaps at one index, or cell_width / cell_widths for the width of a cell.
FlowGeometries.Grids.spacing_trait — Method
spacing_trait(grid, ::Val{d}) -> UniformSpacing() | NonuniformSpacing()Whether direction d's spacing is known from its type, as a value a method can dispatch on.
isuniform answers the same question as a Bool, which a method can only branch on. A kernel that selects the uniform form of an expression — a stencil row that is the same at every interior sample, an O(1) locate — selects it by dispatch, and that needs the direction in the type, hence the Val.
isuniform(grid, d::Integer) serves a direction chosen at run time.
FlowGeometries.Grids.spatial_index — Method
spatial_index(grid) -> opaque indexExtension hook: a range-queryable spatial index over the grid's cell centres, overridden by the NearestNeighbors extension. Paired with index_within!.
FlowGeometries.Grids.spatial_order — Method
spatial_order(grid) -> Vector{Int}A permutation of the grid's nodes along a Morton (Z-order) curve: perm[k] is the node that belongs in position k.
Scattered nodes usually arrive in whatever order they were generated, and a neighbour traversal then jumps across the whole array per edge. Along a space-filling curve, neighbours in space are neighbours in memory, so neighbor_nbrs[ptr[i]:ptr[i+1]-1] reads mostly-adjacent addresses.
The order is a property of the points: the same set, differently shuffled, sorts to the same sequence. So this repairs an incoherent input order and leaves a coherent one as it is.
The permutation is returned, and construction does not apply it. The node index is the caller's handle on their own data, and a renumbering here leaves every field they hold pointing at the wrong node. Apply it with reorder and permute those fields the same way.
FlowGeometries.Grids.topology — Method
topology(grid) -> NTuple{N,AbstractTopology}
topology(grid, d) -> AbstractTopologyThe grid's per-direction topology. Singletons, so this occupies no storage.
FlowGeometries.Grids.unrotate — Method
unrotate(grid::StructuredGrid, rot) -> RotatedGridrotate the other way: the mesh's axes are the rotated frame's, and each cell is reported at its geographic position. The usual direction for a rotated-pole grid.