fft

Command Docstrings

Command line

Command help
pgkyl fft --help
  Usage: pgkyl fft [OPTIONS]

    Calculate the Fourier Transform or the power-spectral density of input
    data. Only works on 1D data at present.

  Options:
    -p, --psd         Limits output to positive frequencies and returns the power
                      spectral density |FT|^2.
    -i, --iso         Bins power spectral density |FT|^2, making 1D power
                      spectra from multi-dimensional data.
    -u, --use TEXT    Specify a 'tag' to apply to (default all tags).
    -t, --tag TEXT    Optional tag for the resulting array
    -l, --label TEXT  Custom label for the result
    -h, --help        Show this message and exit.

Fourier analysis on one-dimensional data is available in pgkyl. This does not mean that the simulation has to be 1D, but for higher-D simulations one must first reduce the dimensionaly of the data before doing an FFT.

For example, we take a simple incompressible Euler 2D simulation of a velocity shear instability (Kelvin Helmholtz). Using the pgkyl command

pgkyl "incompEuler-KH-2x-p1_fluid_[0-9]*.bp" interp anim -a -x 'x' -y 'y' --clabel '$\psi(x,y)$'

we obtain the following velocity potential

This simulation was initialized with a slow variation in x and a small but more oscillatory perturbation in y:

\[\psi(x,y,t=0) = \alpha\sin(k_y y)+\cos(k_x x)\]

where \(\alpha=0.05\), \(k_x=2\pi/L_x\), \(k_y=16\pi/L_y\), and \(L_y=4L_x=40\). If we were to examine the Fourier transform of this initial condition at \(x=5\) with

pgkyl incompEuler-KH-2x-p1_fluid_0.bp interp sel --z0 5. fft ev 'f[0] abs' pl -x '$k_y$' -y '$\psi_{k_y}(x=5)$' --logy --xscale 6.283185

where we scaled the \(x\)-axis by \(2\pi\) because of SciPy’s fftfreq convention, we would obtain

../../_images/incompEuler-KH-2x-p1_fluid_z0eq5p0_fft_0.png

or most commonly one looks at the power spectrum of a signal, which we can obtain with the -p flag:

pgkyl incompEuler-KH-2x-p1_fluid_0.bp interp sel --z0 5. fft -p pl -x '$k_y$' -y '$|\psi_{k_y}(x=5)|^2$' --xscale 6.283185 --logy

This plot has the peak we would expect at \(k_y=16\pi/L_y=1.2566\), but it also has two other peaks we did not expect. This is because we are FFT-ing interpolated DG data which introduces modes if the transform is not done weakly (not covered here).

../../_images/incompEuler-KH-2x-p1_fluid_z0eq5p0_fftPower_0.png

We could also look at how this spectrum changes in time with the following command

pgkyl "incompEuler-KH-2x-p1_fluid_[0-9]*.bp" interp sel --z0 5. fft -p collect pl --group 1 --logy -x '$k_y/(2\pi)$' -y '$\left|\psi_{k_y}(x=5)\right|^2$' --clabel 'time'
../../_images/incompEuler-KH-2x-p1_fluid_z0eq5p0_fftPower.png

showing how the spectrum goes from being peaked at specific \(k_y\)’s to being a fully filled spectrum when turbulence sets in.

Script mode

Although it is possible to call postgkyl’s fft command from a script, we recommend that you instead use SciPy’s fft package directly (or alternatively NumPy’s fft package). Here’s an example of how to perform the same FFT described in the command line section above

import postgkyl as pg
from scipy.fft import fft, fftfreq
import matplotlib.pyplot as plt
import numpy as np

fileName = 'incompEuler-KH-2x-p1_fluid_0.bp'
polyOrder, basisType = 1, 'ms'

pgData   = pg.GData(fileName)
pgInterp = pg.GInterpModal(pgData, polyOrder, basisType)
pgInterp.interpolate(overwrite=True)
yInt, psi_z0eq5p0 = pg.data.select(pgData, z0=5.0)

y = 0.5*(yInt[1][:-1]+yInt[1][1:])

ky, psi_z0eq5p0_ky = 2.*np.pi*fftfreq(np.size(y)), fft(np.squeeze(psi_z0eq5p0))

plt.semilogy(ky, np.abs(psi_z0eq5p0_ky))
plt.show()

where we used the select command to pick the data at \(x=5\), transformed the \(y\) coordinates from nodal to cell-center coordinates, and squeezed the data to remove redundant dimensions.