FFT convention#

Use the same Fourier signs, normalisation and array order when preparing fields, applying dispersion and comparing results. This page states the continuous and discrete conventions; the first tutorial shows them in a retrieval.

The continuous transform#

croak uses the physics convention: the \(1/2\pi\) lives on the inverse transform and the forward kernel is \(e^{+i\omega t}\).

\[\tilde E(\omega) = \int E(t)\, e^{+i\omega t}\,\mathrm{d}t, \qquad E(t) = \frac{1}{2\pi}\int \tilde E(\omega)\, e^{-i\omega t}\,\mathrm{d}\omega.\]

This differs from the engineering convention (opposite sign) and the symmetric convention (\(1/\sqrt{2\pi}\) on both); mixing them is a classic source of a flipped or mis-scaled spectrum.

The discrete transform#

On a uniform grid the integrals become Riemann sums, so Grid.fft and Grid.ifft carry the grid spacings:

\[\tilde E \approx \Delta t \sum E\, e^{+i\omega t}, \qquad E \approx \frac{\Delta\omega}{2\pi} \sum \tilde E\, e^{-i\omega t}.\]

These operate on centred arrays (zero frequency in the middle): each is an ifftshift → transform → fftshift sandwich with the appropriate scale. Because the scale factors are physical, g.fft followed by g.ifft is the identity and the transform approximates the continuous integral (Parseval’s energy relation holds with the \(1/2\pi\)).

Raw transforms#

The forward model runs in raw DFT-bin order for speed, using unnormalised, unshifted transforms. These are exposed as croak.grid.raw_fft() (scipy.fft.fft) and croak.grid.raw_ifft() (scipy.fft.ifft, with the \(1/N\)). Their adjoints — needed for the Wirtinger gradient — are:

  • adjoint of raw_fft is \(N \times\) raw_ifft;

  • adjoint of raw_ifft is \(\tfrac1N \times\) raw_fft.

These appear directly in ForwardModel.adjoint_single.

Practical implications#

  • Pass centred arrays to Grid.fft/Grid.ifft and to every public function; croak shifts to DFT-bin order internally where needed.

  • A delay \(\tau\) is a spectral phase ramp \(e^{+i\omega\tau}\) in the raw domain (see Grid.tshift), matching the forward kernel sign above.

  • The NumPy model uses scipy.fft; the JAX backend uses the corresponding JAX transforms with matching signs and normalisation.

See also#