Skip to content

FFT backends

The FFTW3/pocketfft/numpy backend chain and selection (env: PHOTONICS_FFT_BACKEND). Docstrings are the source of truth, rendered with mkdocstrings (numpydoc style).

photonics_helper._fftw

FFT backend for photonics_helper with automatic fallback chain.

Every FFT hotspot in :mod:photonics_helper.gnlse and :mod:photonics_helper.raman routes through this module. The best available backend is picked automatically so the package works everywhere:

  1. cupy (optional, opt-in) — GPU FFTs via :mod:cupy. Never selected automatically; enable with PHOTONICS_FFT_BACKEND=cupy. The solver stack is NumPy-native, so each call copies to the device, transforms, and copies back; the transfer is amortized only for very large grids. When cupy is missing (or no GPU is visible) the chain falls back to the CPU backends with a warning.
  2. FFTW3 (pyfftw) — fastest CPU backend; cached plans (one per grid size, reused across every split-step iteration) and optional multi-threading. Requires the optional pyfftw package (installable via the fftw extra).
  3. scipy.fft — pocketfft with multi-threading; ships with the package's core scipy dependency, so this is the default for installs without pyfftw.
  4. numpy.fft — always available; last-resort fallback.

All backends expose identical array conventions, so solver results are numerically equivalent (differences are ~1e-14 floating-point rounding).

Conventions

The functions mirror the shifted conventions used by :class:~photonics_helper.pulse.TemporalGrid (input centered at t=0, output centered at ω=0):

  • fft(A) == np.fft.fftshift(np.fft.fft(np.fft.ifftshift(A)))
  • ifft(A) == np.fft.fftshift(np.fft.ifft(np.fft.ifftshift(A)))

The dt / 1/dt scaling that appears at call sites (TemporalGrid.fft) is intentionally not applied here, keeping this a pure FFT layer.

Configuration

PHOTONICS_FFT_BACKEND — force a backend: cupy, fftw, scipy or numpy (default: auto). cupy is opt-in only and is never chosen by the automatic selection. If the forced backend is unavailable the next one in the chain is used and a warning is emitted.

PHOTONICS_FFTW_PLANNER — FFTW planner effort, default FFTW_ESTIMATE. Use FFTW_MEASURE (or FFTW_PATIENT) for long production runs where the one-time planning cost is amortized over thousands of transforms.

PHOTONICS_FFT_THREADS — threads per transform for FFTW3 and scipy, default 1. Multi-threading rarely pays off below ~2¹⁶ points; raise it for very large grids. (Measured on the 65536-point wright deck: threads=2 is optimal; threads=4 regresses — context-switch overhead on the fine-grained per-call lock/roll pattern.)

set_backend

set_backend(name: str | None = None) -> str

Select the active FFT backend and return its name.

Parameters:

Name Type Description Default
name str

One of "cupy", "fftw", "scipy", "numpy", or None for automatic selection (best available CPU backend; cupy is never auto-selected). An unavailable forced backend falls back to the next best with a warning.

None

Returns:

Type Description
str — the name of the backend now in use.

available

available() -> bool

True when an accelerated backend (cupy, FFTW3 or scipy) is active.

backend_name

backend_name() -> str

Human-readable name of the active backend.

fft

fft(A) -> np.ndarray

Shifted forward FFT — identical to np.fft.fftshift(np.fft.fft(np.fft.ifftshift(A))).

Parameters:

Name Type Description Default
A array_like — time-domain signal(s), index 0 at ``t=0`` (centered order).
required

Returns:

Type Description
Frequency-domain array(s), index 0 at ``ω=0`` (centered order), same
convention and scaling as ``np.fft.fft`` (unnormalized forward transform).

ifft

ifft(A_w) -> np.ndarray

Shifted inverse FFT — identical to np.fft.fftshift(np.fft.ifft(np.fft.ifftshift(A_w))).

Includes the 1/N normalization, matching np.fft.ifft.

Parameters:

Name Type Description Default
A_w array_like — frequency-domain signal(s), index 0 at ``ω=0``.
required

Returns:

Type Description
Time-domain array(s), index 0 at ``t=0``.

convolve_full

convolve_full(a, b) -> np.ndarray

Full linear convolution of two 1-D arrays along the last axis.

Drop-in replacement for scipy.signal.fftconvolve(a, b, mode='full') (same output ordering and length len(a) + len(b) - 1) implemented on the active backend.

Parameters:

Name Type Description Default
a array_like — 1-D signals to convolve.
required
b array_like — 1-D signals to convolve.
required

Returns:

Type Description
NDArray — full convolution, real dtype when both inputs are real.