Skip to content

About

C++17 spherical harmonic transforms with a PySpharm-compatible API

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

pyspharm-cpp

CI Docs Codecov PyPI version Conda version License

pyspharm-cpp implements a PySpharm-compatible Python API for scalar and vector spherical harmonic transforms (SHTs), spectral regridding, Legendre functions, and interpolation. It uses ducc0's C++ transforms with nanobind and requires only NumPy at runtime.

For lower-level spherical harmonic transforms, consider using ducc0. For atmospheric science operations such as relative vorticity, divergence, streamfunction, velocity potential, spectral filtering, and regridding, consider using spharmgrid. Spharmgrid supports Xarray fields with a ducc0 CPU backend and separate JAX/S2FFT and PyTorch/torch-harmonics interfaces for GPU calculations.

Installation

Install from PyPI:

python -m pip install pyspharm-cpp

Or install from conda-forge with Conda or Mamba:

conda install -c conda-forge pyspharm-cpp
mamba install -c conda-forge pyspharm-cpp

Python 3.11 or newer is required. Source builds need a C++17 compiler; Git checkouts also need the ducc0 submodule. Source distributions include the required ducc0 files. The Python module imports as spharm_cpp; import spharm_cpp as spharm is convenient when adapting PySpharm code.

Example

import numpy as np
import spharm_cpp as spharm

nlon, nlat = 32, 16
sht = spharm.Spharmt(nlon, nlat, gridtype="gaussian")
lat, _ = spharm.gaussian_lats_wts(nlat)
lon = np.arange(nlon) * (360.0 / nlon)

field = np.cos(np.deg2rad(lat))[:, None] * np.cos(np.deg2rad(lon))[None, :]
coefficients = sht.grdtospec(field, ntrunc=1)
reconstructed = sht.spectogrd(coefficients)
np.testing.assert_allclose(reconstructed, field, atol=2e-12, rtol=2e-12)

Differences from PySpharm

  • Backend: ducc0 replaces the SPHEREPACK transforms.
  • Precision: float64/complex128 by default; float32/complex64 can be selected with dtype=np.float32.
  • Legendre functions: legfunc="computed" is the default. Stored Legendre functions (legfunc="stored") are not supported.
  • Batched interpolation: legendre and specintrp also accept one-dimensional coordinate arrays, using overloads of the original scalar functions.
  • Truncation: Clenshaw–Curtis analysis supports degrees through min(nlat-2, nlon//2); Gaussian analysis through min(nlat-1, nlon//2). Vector analysis excludes the even-longitude Nyquist order.
  • Other differences: zero truncation, optional float64 geodesic coordinates, index dtype, and mixed-precision regridding are documented in the PySpharm comparison.

See numerical conventions for coefficient ordering and normalization, and the quickstart and API reference for usage.

Performance

Measured SHT latencies on a Gaussian 1280 × 640 grid

Median timings in milliseconds on the Gaussian 1280 × 640 grid, which has the largest measured speedup among the five cases (69.42× for wind analysis). ducc0 and pyspharm-cpp use eight threads; pyspharm is serial. All timings use float32 and the same truncation.

Operation pyspharm f32 pyspharm-cpp f32 ducc0 f32 Speedup vs pyspharm
Scalar analysis 139.024 ms 2.103 ms 2.411 ms 66.11×
Scalar synthesis 32.081 ms 2.227 ms 2.304 ms 14.41×
Wind analysis 339.515 ms 4.890 ms 3.389 ms 69.42×
Wind synthesis 67.204 ms 5.432 ms 4.558 ms 12.37×

See benchmark results and reproduction instructions for all five grid cases.

License

GPL-2.0-or-later. ducc0 is included as an unmodified submodule; see third-party notices. ducc0 is used under its respective license.

About

C++17 spherical harmonic transforms with a PySpharm-compatible API

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages