Spherical sampling
FlowGeometries.SphericalSampling.AbstractEquiangularAlgorithm — Type
AbstractEquiangularAlgorithmWhich construction computes an equiangular node family's sine sums: Recurrence, always available, or Transform, which needs an FFT planner.
A type, as the mask policies are. The two agree to round-off, so naming one pins a result across machines that differ in whether an FFT backend is installed.
FlowGeometries.SphericalSampling.AbstractLatLonSampling — Type
AbstractLatLonSampling <: AbstractTensorProductSphericalSamplingGeophysical / model latitude–longitude grids. No exact band-limited SHT claim.
FlowGeometries.SphericalSampling.AbstractReducedGaussianSampling — Type
AbstractReducedGaussianSampling <: AbstractRingSamplingRing samplings on Gaussian latitudes. Default: OctahedralGaussianSampling.
FlowGeometries.SphericalSampling.AbstractRingSampling — Type
AbstractRingSampling <: AbstractSphericalSamplingIso-latitude rings whose longitude count varies by ring, so the layout is not a tensor product. A reduced Gaussian grid is the canonical case: latitudes are the Gaussian ones, but each ring carries only as many longitudes as its circumference warrants.
FlowGeometries.SphericalSampling.AbstractSpectralQuadratureSampling — Type
AbstractSpectralQuadratureSampling <: AbstractTensorProductSphericalSamplingSamplings with a known exact quadrature for band-limited spherical harmonics (up to a documented lmax ↔ grid-size relation).
FlowGeometries.SphericalSampling.AbstractSphericalSampling — Type
AbstractSphericalSamplingHow points are placed on the sphere. Orthogonal to FlowGeometries.Geometry.AbstractSphericalGeometry (the metric / radius) and to grid architecture (StructuredGrid vs unstructured).
FlowGeometries.SphericalSampling.AbstractTensorProductSphericalSampling — Type
AbstractTensorProductSphericalSampling <: AbstractSphericalSamplingIso-latitude × equispaced-longitude (or arbitrary lon/lat) layouts that fit a 2D StructuredGrid with axes (λ, φ).
FlowGeometries.SphericalSampling.ClenshawCurtisSampling — Type
ClenshawCurtisSampling <: AbstractClenshawCurtisSamplingOpen equiangular Clenshaw–Curtis grid: $θ_i = π(i−1/2)/N_θ$ (no poles), $N_λ = 2N_θ − 1$, $l_{\max} = N_θ − 1$.
This is not the same as Driscoll–Healy: different $N_θ(l_{\max})$, open vs polar-cap nodes, and a different quadrature.
FlowGeometries.SphericalSampling.CubedSphereSampling — Type
CubedSphereSampling <: AbstractCubedSphereSamplingInscribed-cube projection: six logically rectangular panels (gnomonic by default). Quasi-uniform alternative to global lat–lon (e.g. FV3).
FlowGeometries.SphericalSampling.DriscollHealyEqualSampling — Type
DriscollHealyEqualSampling <: AbstractDriscollHealySamplingDriscoll–Healy DH1 layout: $N_θ × N_θ$ with $N_θ = 2(l_{\max}+1)$, $Δθ = π/N_θ$, $Δλ = 2π/N_θ$.
FlowGeometries.SphericalSampling.DriscollHealySampling — Type
DriscollHealySampling <: AbstractDriscollHealySamplingDriscoll–Healy equiangular grid, rectangular (DH2) layout: $N_θ × 2N_θ$ with $N_θ = 2(l_{\max}+1)$, $Δθ = π/N_θ$, $Δλ = π/N_θ$. Includes the north pole band, excludes the south (weight at the north pole is zero).
See also DriscollHealyEqualSampling for the square DH1 $N_θ × N_θ$ layout.
FlowGeometries.SphericalSampling.FibonacciSampling — Type
FibonacciSampling(n)n points on the spherical Fibonacci (golden-spiral) lattice: z_k = (2k+1)/n - 1 with λ_k = 2πk/φ mod 2π, φ the golden ratio.
z advances in equal steps, so the points are spread one per equal-area band, and the golden angle in longitude — the most irrational rotation there is — keeps them from lining up into visible spokes at any n. Quasi-uniform with no polar clustering and no panel seams.
FlowGeometries.SphericalSampling.GaussLegendreSampling — Type
GaussLegendreSampling <: AbstractGaussLegendreSamplingGauss–Legendre (Gauss–Neumann) latitudes: $μ = \cosθ$ at the $N_θ$ roots of $P_{N_θ}$, with $N_λ = 2N_θ − 1$ equispaced longitudes. Exact for band-limit $l_{\max} = N_θ − 1$.
FlowGeometries.SphericalSampling.HEALPixSampling — Type
HEALPixSampling <: AbstractHEALPixSamplingHierarchical Equal Area isoLatitude Pixelisation (Górski et al.). Equal-area pixels on $4 N_{\mathrm{side}} − 1$ iso-latitude rings; not a tensor-product $N_λ × N_φ$ array ($n_λ$ varies by ring).
FlowGeometries.SphericalSampling.IcosahedralSampling — Type
IcosahedralSampling <: AbstractIcosahedralSamplingIcosahedral geodesic discretization (triangular faces; hexagonal dual is the Voronoi mesh). Quasi-uniform; unstructured connectivity.
FlowGeometries.SphericalSampling.LatLonSampling — Type
LatLonSampling <: AbstractLatLonSamplingArbitrary model lat–lon (regional or global, poles optional). No spectral exactness claim.
FlowGeometries.SphericalSampling.McEwenWiauxSampling — Type
McEwenWiauxSampling <: AbstractMcEwenWiauxSamplingMcEwen–Wiaux (2011) equiangular sampling: $θ_t = π(2t+1)/(2L−1)$ for $t = 0,…,L−1$, $λ_p = 2π p/(2L−1)$ for $p = 0,…,2L−2$, with $L = l_{\max}+1$. Requires asymptotically $∼ 2 L^2$ samples (about half of classical DH).
FlowGeometries.SphericalSampling.Nested — Type
Nested()Pixels numbered so that each is subdivided into four contiguous children — a quadtree per base face. The ordering that makes a neighbourhood contiguous. Requires nside to be a power of two.
FlowGeometries.SphericalSampling.OctahedralGaussianSampling — Type
OctahedralGaussianSampling(N)Octahedral reduced Gaussian grid with N latitude rings between pole and equator (2N rings in all).
Ring i counted from either pole carries 4i + 16 longitudes — 20 on the ring nearest the pole and four more on each successive ring — which totals 4N(N+9) points. Latitudes are the 2N Gaussian latitudes, so the latitude quadrature is the Gauss–Legendre one.
FlowGeometries.SphericalSampling.OpenNodes — Type
OpenNodes(), ClosedNodes()The two equiangular colatitude families: open θᵢ = π(i−½)/N (Clenshaw–Curtis) and closed θᵢ = π(i−1)/N (Driscoll–Healy). They are types, so the sum below dispatches on which one it has.
FlowGeometries.SphericalSampling.Recurrence — Type
Recurrence()The angle-addition recurrence: O(nlat·nterm), no dependency, defined for every element type.
FlowGeometries.SphericalSampling.ReducedGaussianSampling — Type
ReducedGaussianSampling(nlon_per_ring)Reduced Gaussian grid with an explicit longitude count per ring, north to south.
The classical reduced grids are published as tables — the count holds constant across blocks of latitudes and jumps between them — so the table is the input. Use OctahedralGaussianSampling for the octahedral rule, which is a formula.
FlowGeometries.SphericalSampling.Ring — Type
Ring()Pixels numbered along iso-latitude rings, north to south and east within a ring. The ordering that makes a ring contiguous, so a longitude transform per ring is possible.
FlowGeometries.SphericalSampling.ScatteredSphericalSampling — Type
ScatteredSphericalSampling <: AbstractScatteredSphericalSamplingArbitrary $(λ, φ)$ point set (NUFFT / NUFSHT paths).
FlowGeometries.SphericalSampling.Transform — Type
Transform()One length-nlat backward transform: O(nlat·log nlat). Implemented by the AbstractFFTs extension, and raises without one — a planner has to exist for this to mean anything.
FlowGeometries.SphericalSampling.YinYangSampling — Type
YinYangSampling <: AbstractYinYangSamplingOverset of two low-latitude lat–lon patches (Kageyama–Sato), avoiding polar singularities while keeping structured coordinates on each panel.
FlowGeometries.SphericalSampling._cubed_cell_angles — Method
_cubed_cell_angles(::Type{T}, n, i, j) -> (ξ, η)Panel-local gnomonic angles of cell (i, j)'s centre: ξ = -π/4 + (i - ½)·(π/2)/n.
FlowGeometries.SphericalSampling._cubed_cell_edges — Method
_cubed_cell_edges(::Type{T}, n, i, j) -> (X1, X2, Y1, Y2)Tangents of cell (i, j)'s panel-local boundary angles, -π/4 + (i-1)·Δ and -π/4 + i·Δ. These are the gnomonic-plane coordinates its area is the solid angle of.
FlowGeometries.SphericalSampling._cubed_cell_lonlat — Method
_cubed_cell_lonlat(::Type{T}, n, f, i, j) -> (λ, φ)Cell (f, i, j)'s centre in global (λ, φ): its panel-local angles through the gnomonic map and onto the sphere.
FlowGeometries.SphericalSampling._cubed_lin — Method
_cubed_lin(f, i, j, n) -> Int
_cubed_unlin(lin, n) -> (f, i, j)The cubed sphere's cell numbering and its inverse: panel by panel, i fastest within a panel. This is the order cubed_sphere_points! writes, so it is what every consumer of those points indexes by.
FlowGeometries.SphericalSampling._equiangular_algorithm — Method
_equiangular_algorithm(T) -> AbstractEquiangularAlgorithmThe default for element type T: Recurrence unless a loaded extension can plan a transform for it. The single place availability is consulted, so no method below branches on it.
FlowGeometries.SphericalSampling._equiangular_sums! — Method
The recurrence: sin((2k+1)θ) = 2cos(2θ)·sin((2k−1)θ) − sin((2k−3)θ), seeded with s₋₁ = −sin θ, s₀ = sin θ, so each term costs two multiplies and no transcendental.
FlowGeometries.SphericalSampling._equiangular_sums! — Method
_equiangular_sums!(s, family, nlat, nterm[, algorithm]) -> ss[i] = Σ_{k=0}^{nterm-1} sin((2k+1)·θᵢ)/(2k+1) for the given node family.
With no algorithm, _equiangular_algorithm chooses one for the element type.
FlowGeometries.SphericalSampling._equiangular_weights! — Method
_equiangular_weights!(w, family, nlat[, algorithm]) -> wLatitude quadrature weights for an equiangular node set, from the sine-series expansion of the sinθ Jacobian:
wᵢ = (4/N)·sinθᵢ·Σ_{k=0}^{⌊N/2⌋} sin((2k+1)θᵢ)/(2k+1)family is OpenNodes or ClosedNodes, so one construction serves both. Weights sum to ∫₀^π sinθ dθ = 2 — see latitude_weights for why every sampling here uses that normalization.
algorithm selects which construction computes the sums; omitted, the element type's default does.
FlowGeometries.SphericalSampling._gauss_legendre! — Method
_gauss_legendre!(T, μ, w, n)Core solve. Either output may be nothing, so a caller that wants only the nodes or only the weights needs no scratch vector for the other half.
FlowGeometries.SphericalSampling._gauss_legendre_newton! — Method
_gauss_legendre_newton!(T, TW, μ, w, n, m)Nodes and weights by Newton on Pₙ, evaluated by the Bonnet recurrence from a Tricomi start.
O(n) per root, so O(n²) overall — but it is exact arithmetic converging to eps(TW), which the asymptotic expansion's fixed Float64 coefficient set cannot do. That makes it the right method for wide element types at any n, and for small n, where the expansion is inaccurate and the quadratic cost is microseconds.
FlowGeometries.SphericalSampling._gauss_legendre_μ! — Method
_gauss_legendre_μ!(μ, w) -> NamedTuple{(:μ,:w)}Write n = length(μ)-point Gauss–Legendre nodes/weights on $μ ∈ (-1, 1)$ into the provided buffers, ascending in μ (length(μ) == length(w)).
Newton's method on $Pₙ$, evaluated by the Bonnet recurrence, from a Tricomi starting estimate accurate to $O(n⁻³)$ — so 2–4 iterations reach machine precision. Roots come in $±$ pairs, so only the upper half is solved.
Needs $O(1)$ scratch. Time is $O(n²)$: each of the $n/2$ roots costs an $O(n)$ recurrence. The Bogaert-style asymptotic expansions below are the $O(n)$ path.
FlowGeometries.SphericalSampling._healpix_nested_cloud! — Method
_healpix_nested_cloud!(λ, φ, nside) -> (; λ, φ)The whole HEALPix cloud in NESTED pixel order.
The ring quantities are tabulated once, 4·nside − 1 of them, so the acos and the latitude conversion run per ring here too. A nested pixel's ring and position along it come from its face coordinates (_hp_xyf2ringj), and the coordinates are then the ring walk's own expressions, so the two orderings hold the same numbers to the bit. Both writes are sequential.
FlowGeometries.SphericalSampling._hp_ang2xyf — Method
_hp_ang2xyf(nside, θ, ϕ) -> (ix, iy, face)Face-local coordinates of the pixel containing colatitude θ, longitude ϕ, by the HEALPix projection (Górski et al. 2005). Division and remainder, so it holds for any nside, including one that is not a power of two.
FlowGeometries.SphericalSampling._ico_decode — Method
_ico_decode(id, ν) -> (kind, a, b)Which entity owns vertex id: kind = 1 a corner (a the corner, b unused), 2 a macro-edge interior (a the edge, b its position from the edge's low corner), 3 a face interior (a the face, b its position in the face's own lattice walk).
FlowGeometries.SphericalSampling._ico_face_ij — Method
_ico_face_ij(k, ν) -> (i, j)The face-interior lattice node whose position in the walk for i in 1:(ν-1), j in 1:(ν-1-i) is k.
Row i of the walk holds ν-1-i nodes, so the nodes before it number S(i-1) = (i-1)(ν-1) - (i-1)i/2. Then m = i-1 is the largest value with S(m) < k, and j = k - S(m). S(m) < k rearranges to m² - m(2ν-3) + 2k > 0, so the smaller root of that quadratic brackets m; its floor is taken and then stepped in either direction, so the result does not depend on the square root's last bit.
FlowGeometries.SphericalSampling._ico_fold_incident_triangles — Method
_ico_fold_incident_triangles(f, acc, i, j, face, ν) -> accThread acc = f(acc, other1, other2) over the triangles of one face that contain lattice node (i, j), other1 and other2 being the other two vertices' ids.
A triangle belongs to exactly one face, so folding over each of a vertex's occurrences visits each incident triangle once. The two lattice orientations give up to three triangles each.
FlowGeometries.SphericalSampling._ico_lattice_id — Method
_ico_lattice_id(f, i, j, ν) -> Int_ico_node_id with the load-time constants supplied: the global id of face f's barycentric lattice node (i, j).
FlowGeometries.SphericalSampling._ico_node_id — Method
_ico_node_id(f, face, i, j, ν, edge_index, nint, face_base) -> IntGlobal vertex id of barycentric lattice node (i, j) (with i + j ≤ ν, weights ν-i-j, i, j on the face's corners A, B, C) of face f. A node on a corner or a macro-edge resolves to that shared entity's id, so the two faces meeting at an edge agree with no lookup table.
FlowGeometries.SphericalSampling._ico_occurrences — Method
_ico_occurrences(id, ν) -> (NTuple{5,NTuple{3,Int}}, n)Every (face, i, j) lattice position vertex id occupies, in the first n entries. A face interior has one, a macro-edge interior two, a corner five; the twelve corners are the geodesic sphere's twelve pentagons.
FlowGeometries.SphericalSampling._ico_vertex_dir — Method
_ico_vertex_dir(::Type{T}, id, ν) -> NTuple{3,T}Vertex id's unit direction, from the entity that owns it: a base corner, a normalized point along a macro-edge, or a normalized barycentric combination on a face. The same expressions icosahedral_vertices! writes, one vertex at a time.
FlowGeometries.SphericalSampling._icosahedron_base — Method
_icosahedron_base(T) -> NTuple{12,NTuple{3,T}}The 12 unit vertices of the base icosahedron, in the order _ICOSAHEDRON_FACES indexes them. A tuple, so it costs no allocation. Every raw vertex is a permutation of (0, ±1, ±φ) and so shares the norm √(1+φ²), formed once.
FlowGeometries.SphericalSampling._put_lonlat! — Method
_put_lonlat!(λ, φ, v, p, T)Normalize p and write vertex v's longitude and latitude. Top-level, so it captures nothing.
FlowGeometries.SphericalSampling._yin_yang_panel_coords — Method
_yin_yang_panel_coords(::Type{T}, nlon, nlat, i, j) -> (λ, φ)Cell (i, j)'s centre in the panel's own frame, where the panel is the separable lat–lon patch [-3π/4, 3π/4] × [-π/4, π/4]. For yin this frame is the global one.
FlowGeometries.SphericalSampling._yin_yang_rotate — Method
_yin_yang_rotate(λ, φ) -> (λ_global, φ_global)The Kageyama–Sato rotation carrying a panel-frame (λ, φ) onto yang's position on the sphere. Yang is yin rigidly rotated, so this is the whole difference between the two panels.
FlowGeometries.SphericalSampling.admits_exact_bandlimited_quadrature — Method
admits_exact_bandlimited_quadrature(sampling) -> BoolWhether this sampling's latitude_weights integrate the products that spectral analysis actually forms — two degree-lmax functions, hence degree 2·lmax — exactly at the sampling's own bandlimit.
That is a stronger statement than "the quadrature integrates a single P_l up to lmax", and the distinction decides the answer here. Measured exactness of the weights in this package:
| sampling | exact for a single P_l up to | bandlimit | needs 2·lmax | exact? |
|---|---|---|---|---|
| Gauss–Legendre | 2N−1 | N−1 | 2N−2 | yes |
| Driscoll–Healy | N−1 | N/2−1 | N−2 | yes |
| Clenshaw–Curtis | N−1 | N−1 | 2N−2 | no |
Clenshaw–Curtis's band limit describes what its grid can represent; its quadrature supports quadrature-based analysis only to lmax ≈ (N−1)/2. Use GaussLegendreSampling when analysis must be exact at the stated band limit.
FlowGeometries.SphericalSampling.ang2pix — Method
ang2pix(nside, θ, ϕ; scheme = Ring()) -> IntThe 0-based index of the pixel containing colatitude θ ∈ [0, π] and longitude ϕ.
θ is a colatitude, matching the HEALPix convention throughout this section; use colatitude to convert a geographic latitude.
FlowGeometries.SphericalSampling.axes_lengths — Method
axes_lengths(sampling, nlat; nlon=nothing) -> NamedTuple{(:nlon,:nlat)}Buffer lengths required by spherical_axes!: (; nlon, nlat).
FlowGeometries.SphericalSampling.bandlimit — Method
bandlimit(sampling, nlat) -> lmaxMaximum spherical-harmonic degree supported by nlat latitude samples under sampling.
FlowGeometries.SphericalSampling.colatitude — Method
Colatitude $θ ∈ [0, π]$ from geographic latitude $φ ∈ [-π/2, π/2]$.
FlowGeometries.SphericalSampling.cubed_sphere_points! — Method
cubed_sphere_points!(λ, φ, panel, n; backend=nothing) -> NamedTuple{(:λ,:φ,:panel)}Gnomonic cubed-sphere cell centres into caller-owned buffers of length 6n², plus each point's panel index. Pass panel = nothing when the panel id is not wanted, and it is not computed.
See cubed_sphere_points for the allocating form.
FlowGeometries.SphericalSampling.cubed_sphere_points — Method
cubed_sphere_points([T = Float64], n; backend=nothing) -> NamedTuple{(:λ,:φ,:panel)}Gnomonic cubed-sphere cell centres: 6n² distinct points, plus each point's panel index.
Allocating wrapper around cubed_sphere_points!. Use spherical_points(CubedSphereSampling(), n) when the panel id is not needed.
FlowGeometries.SphericalSampling.geographic_latitude — Method
Geographic latitude $φ$ from colatitude $θ$.
FlowGeometries.SphericalSampling.icosahedral_mesh — Function
icosahedral_mesh([T = Float64], frequency) -> (; λ, φ, edges, triangles, verts)Geodesic vertices at frequency ν as both lon/lat (λ, φ) and unit vectors (verts), plus the 10ν²+2 mesh's undirected edges (i,j) with i < j and its 20ν² triangles (i,j,k) (1-based). Vertex numbering is topological — corners, then macro-edge interiors, then face interiors — so it is deterministic and every vertex is generated exactly once.
FlowGeometries.SphericalSampling.icosahedral_vertices — Function
icosahedral_vertices([T = Float64], frequency=1) -> NamedTuple{(:λ,:φ)}The 10ν²+2 geodesic vertices as longitude/latitude, without building the mesh topology — several times faster than icosahedral_mesh at large ν, which also returns edges and triangles.
FlowGeometries.SphericalSampling.icosahedral_vertices! — Method
icosahedral_vertices!(λ, φ, frequency = 1) -> NamedTuple{(:λ,:φ)}Write the 10ν²+2 geodesic vertices' longitude/latitude into the caller's buffers, allocating nothing. The numbering is icosahedral_mesh's topological one — corners, then macro-edge interiors, then face interiors — so each vertex is emitted at its own index with no intermediate array and no lookup.
FlowGeometries.SphericalSampling.latitude_weights! — Function
latitude_weights!(w, sampling, nlat) -> wFill preallocated latitude quadrature weights (length(w) == nlat). The equiangular families also take algorithm — see latitude_weights.
FlowGeometries.SphericalSampling.latitude_weights! — Method
latitude_weights!(w, ::AbstractClenshawCurtisSampling, nlat)Weights for the open nodes θᵢ = π(i−½)/N, from the same sine-series rule as the closed equiangular families.
These integrate a single P_l exactly for l ≤ N−1, which is weaker than bandlimit(ClenshawCurtisSampling(), N) = N−1 suggests: spectral analysis integrates products of two degree-lmax functions, so a quadrature exact to l ≤ N−1 supports quadrature-based analysis only up to lmax ≈ (N−1)/2. The reported band limit describes what the grid represents; this quadrature integrates to half of it. Use GaussLegendreSampling (exact to 2N−1) where analysis must be exact at the stated band limit.
FlowGeometries.SphericalSampling.latitude_weights — Method
latitude_weights([T = Float64], sampling::AbstractReducedGaussianSampling) -> Vector{T}Gauss–Legendre weights for the grid's rings, north to south, normalized as everywhere else in this module so that Σw = 2. A full-sphere integral is then Σⱼ wⱼ (2π/nlonⱼ) Σᵢ f, the longitude factor varying by ring because the ring populations do.
FlowGeometries.SphericalSampling.latitude_weights — Method
latitude_weights([T = Float64], s, nlat) -> Vector{T}
latitude_weights!(w, s, nlat) -> wLatitude quadrature weights wⱼ for sampling s, normalized so that
Σⱼ wⱼ = ∫₀^π sinθ dθ = 2for every sampling that provides them. The weights therefore carry the sinθ Jacobian and nothing else; the longitude factor is the caller's, so a full-sphere integral is always
∫ f dΩ ≈ (2π/nlon) · Σⱼ wⱼ Σᵢ f(λᵢ, φⱼ)regardless of which sampling produced the weights. Not every sampling has them — LatLonSampling has no spectral quadrature at all, and McEwenWiauxSampling's is a different construction.
The equiangular families — Driscoll–Healy and Clenshaw–Curtis — additionally take algorithm::AbstractEquiangularAlgorithm, which pins the construction of their sine sums. The two constructions agree only to round-off, so naming one fixes the result across machines that differ in whether an FFT backend is installed. Gauss–Legendre's weights come from a root solve, so it takes no algorithm.
FlowGeometries.SphericalSampling.nlat_for_bandlimit — Method
nlat_for_bandlimit(sampling, lmax) -> nlatFlowGeometries.SphericalSampling.nlon_for_nlat — Method
nlon_for_nlat(sampling, nlat) -> nlonFlowGeometries.SphericalSampling.nlon_in_ring — Function
nlon_in_ring(sampling, ring) -> Int
nlon_in_ring(sampling, nlat, ring) -> IntLongitudes on a single iso-latitude ring, counted from the north pole, in O(1) and allocating nothing.
The per-ring form of nlon_per_ring, and the one a ring-by-ring loop wants: the table costs an allocation and an O(nrings) build per call, which a loop over rings pays again on every iteration if it asks for it there.
FlowGeometries.SphericalSampling.nlon_per_ring — Method
nlon_per_ring(sampling) -> Vector{Int}
nlon_per_ring(sampling, nlat; nlon=nothing) -> Vector{Int}Longitudes on each iso-latitude ring, north to south.
Defined for every sampling laid out in rings, so a caller walking a map ring by ring — a per-ring longitude transform, a zonal reduction, a row-wise sweep — writes one loop for all of them. A sampling that carries its own size (HEALPixSampling, the reduced Gaussians) answers from itself; a tensor-product one takes the nlat that fixes its shape, as npoints does.
FlowGeometries.SphericalSampling.npoints — Method
npoints(::AbstractScatteredSphericalSampling, λ, φ) -> IntThe number of points in a scattered set, i.e. length(λ).
FlowGeometries.SphericalSampling.npoints — Method
npoints(sampling, args...) -> IntNumber of geographic samples produced by spherical_points! / spherical_points.
FlowGeometries.SphericalSampling.nrings — Method
nrings(sampling) -> Int
nrings(sampling, nlat) -> IntNumber of iso-latitude rings, for any sampling laid out in them — the loop bound that goes with nlon_per_ring.
FlowGeometries.SphericalSampling.pix2ang — Method
pix2ang([T = Float64], nside, pix; scheme = Ring()) -> (θ, ϕ)Colatitude and longitude of pixel pix's centre (0-based index).
FlowGeometries.SphericalSampling.pix2vec — Method
pix2vec([T = Float64], nside, pix; scheme = Ring()) -> NTuple{3}Unit vector to pixel pix's centre.
FlowGeometries.SphericalSampling.ring2nest — Method
ring2nest(nside, pix) -> Int
nest2ring(nside, pix) -> IntConvert a 0-based pixel index between the two orderings. Both need nside to be a power of two, which is the condition for the nested quadtree to exist.
FlowGeometries.SphericalSampling.ring_info — Method
ring_info([T = Float64], nside, ring) -> NamedTupleWhat HEALPix ring ring ∈ 1:(4·nside-1) contains, counted from the north pole: startpix (the 0-based RING index of its first pixel, matching ang2pix), ringpix (how many pixels it holds), colatitude, latitude, and shifted — whether its pixel centres are offset half a pixel in ϕ.
Ring width grows 4, 8, … through the polar cap, is 4·nside across the equatorial belt, and shrinks again symmetrically, so this is how to walk a HEALPix map ring by ring without decoding every pixel.
FlowGeometries.SphericalSampling.ring_latitudes — Method
ring_latitudes([T = Float64], sampling) -> Vector{T}The Gaussian latitudes of a reduced Gaussian grid's rings, north to south.
FlowGeometries.SphericalSampling.ring_range — Function
ring_range(sampling, ring) -> UnitRange{Int}
ring_range(sampling, nlat, ring) -> UnitRange{Int}The 1-based slice of the flattened point vector holding one iso-latitude ring, north to south — the indices spherical_points writes that ring into.
O(1) for every sampling, so a ring-by-ring pass is a loop over slices carrying no running offset. The octahedral rule's offset is a closed form in the ring index; the tabulated reduced grid carries cumulative counts, built once with the sampling.
FlowGeometries.SphericalSampling.spherical_axes — Function
spherical_axes([T = Float64], sampling, nlat; nlon=…) -> NamedTuple{(:λ,:φ)}Allocating wrapper around spherical_axes!.
The element type leads, as it does for zeros and rand, so it takes part in dispatch and the returned eltype is known from the signature.
FlowGeometries.SphericalSampling.spherical_axes! — Function
spherical_axes!(λ, φ, sampling, nlat; nlon=…) -> NamedTuple{(:λ,:φ)}Fill preallocated longitude / geographic-latitude axes. Requires length(λ) == sz.nlon and length(φ) == sz.nlat for sz = axes_lengths(...).
FlowGeometries.SphericalSampling.spherical_points! — Function
spherical_points!(λ, φ, sampling, args...) -> NamedTuple{(:λ,:φ)}Fill preallocated point-coordinate buffers. See npoints for required lengths.
FlowGeometries.SphericalSampling.spherical_points! — Method
spherical_points!(λ_out, φ_out, ::AbstractScatteredSphericalSampling, λ, φ) -> NamedTupleCopy a scattered point set into caller-owned buffers.
The source arrays are required, a scattered sampling carrying no rule to generate points from.
FlowGeometries.SphericalSampling.spherical_points! — Method
spherical_points!(λ, φ, sampling::AbstractReducedGaussianSampling; scratch = nothing) -> NamedTupleRing-by-ring points of a reduced Gaussian grid, north to south, longitudes equispaced within each ring starting at zero. Buffer length is npoints.
The Gaussian latitudes need one value per ring, which cannot overlap the output here (see the note in the body), so scratch — any vector of at least nrings(sampling) elements — makes the fill allocation-free for a caller filling many grids.
FlowGeometries.SphericalSampling.spherical_points! — Method
spherical_points!(λ, φ, sampling::FibonacciSampling) -> NamedTupleThe n golden-spiral points, allocating nothing.
FlowGeometries.SphericalSampling.spherical_points — Method
spherical_points(::AbstractScatteredSphericalSampling, λ, φ) -> NamedTuple{(:λ,:φ)}A scattered sampling's points are the caller's arrays, so this hands them back. It exists so a scattered set can be driven through the same entry point as a generated one.
FlowGeometries.SphericalSampling.spherical_points — Method
spherical_points([T = Float64], sampling, args...) -> NamedTuple{(:λ,:φ)}Every point of the sampling, flattened, as longitude/latitude vectors. Allocating wrapper around spherical_points!; use npoints to size buffers for the in-place form.
For a tensor-product sampling this is the outer product of its axes, so prefer spherical_axes when the separable form will do.
FlowGeometries.SphericalSampling.spherical_quadrature! — Function
spherical_quadrature!(λ, φ, w, sampling, nlat; nlon=…) -> NamedTuple{(:λ,:φ,:w)}Fill preallocated axes and latitude weights together. Buffer lengths are as for spherical_axes!, with length(w) == sz.nlat.
This is the entry point to use whenever both are needed. Gauss–Legendre nodes and weights fall out of a single root solve, but spherical_axes! keeps only the nodes and latitude_weights! only the weights — so calling them in sequence pays the $O(n²)$ solve twice. Every other sampling has independent closed forms for the two, and gets the generic method.
FlowGeometries.SphericalSampling.spherical_quadrature — Method
spherical_quadrature([T = Float64], sampling, nlat; nlon=…) -> NamedTuple{(:λ,:φ,:w)}Allocating wrapper around spherical_quadrature!.
FlowGeometries.SphericalSampling.vec2pix — Method
vec2pix(nside, v; scheme = Ring()) -> IntThe 0-based index of the pixel containing direction v, which need not be normalized.
FlowGeometries.SphericalSampling.yin_yang_panels! — Method
yin_yang_panels!(λyin, φyin, λyang, φyang, nlon, nlat) -> (; yin, yang)The two Kageyama–Sato panels. yin is a pair of axes (nlon and nlat long): in its own frame the panel is a separable lat–lon patch. yang is that panel rotated onto the sphere, which is separable in neither global longitude nor latitude, so it is a pair of nlon × nlat fields, one (λ, φ) per cell.
The argument types carry that difference.
FlowGeometries.SphericalSampling.yin_yang_panels — Method
yin_yang_panels([T = Float64], nlon, nlat) -> (; yin, yang)Allocating wrapper around yin_yang_panels!.