10. NB. Fourier wavenumbers¶
Philipp Schlatter
pschlatt@mech.kth.se
SimEx/FLOW, KTH Engineering Mechanics, Royal Institute of Technology, Stockholm, Sweden
This notebook is a part of the KTH-Nek5000 lecture notes.
In this notebook, we discuss the typical representation of the wavenumbers for one-dimensional real-to-complex Fourier transforms, assuming even-numbered transforms (i.e. the number of grid points in physical space \(N\) is even) in a domain with length \(2\pi/\alpha\).
import numpy as np
from math import pi
10.1. Physical space¶
We generate a random signal \(u(x_i)=u_i\) and the indices \(i\) as an easy example with \(N=6\):
N=6
u=np.random.rand(N)
i=range(1,N+1)
print(u)
[0.4077557 0.59917605 0.19378549 0.60898424 0.68924684 0.2003087 ]
10.2. Spectral space¶
uhat=np.fft.fft(u)
k=np.concatenate(( range(0,int(N/2)),range(-int(N/2),0) ))
The Fourier transform is now defined as \(u(x) = \sum_k \hat{u}_k e^{\mathrm{i} \alpha k x}\). The complex Fourier coefficients \(\hat{u}(k)=\hat{u}_k\) have the following wavenumbers \(k\)
print(uhat)
[ 2.69925702+0.00000000e+00j -0.24300233+8.36528630e-02j
0.17548139-7.74511374e-01j -0.11768097-6.93889390e-18j
0.17548139+7.74511374e-01j -0.24300233-8.36528630e-02j]
print(k)
[ 0 1 2 -3 -2 -1]
The function fftshift
moves the zero mode to the middle
print(np.fft.fftshift(uhat))
[-0.11768097-6.93889390e-18j 0.17548139+7.74511374e-01j
-0.24300233-8.36528630e-02j 2.69925702+0.00000000e+00j
-0.24300233+8.36528630e-02j 0.17548139-7.74511374e-01j]
print(np.fft.fftshift(k))
[-3 -2 -1 0 1 2]
10.3. Discussion¶
Since we start with a real signal \(u(x_i)=u_i\), the data in Fourier space \(\hat{u}(k)=\hat{u}_k\) needs to fulfil \(\hat{u}_k = \hat{u}_{-k}^*\) with the complex conjugate \((\cdot)^*\). For the highest wavenumber \(k=-3\), it turns out that \(e^{\mathrm{i}kx}=\cos(kx)+\mathrm{i}\sin(kx)=\cos(kx)\) because \(\sin(kx)=0\) on all grid points. Thus the condition for \(k=-3\) is only that \(\hat{u}_{-3}\) is real, and the imaginary part needs to be zero. Otherwise an inverse transform would not be real. For a derivative \(i k \hat{u}_k\) of \(a\) to be real, also the real part of \(k=-3\) needs to be zero, \(i.e.\) the whole mode \(k=-3\) needs to be set to zero (oddball mode).
With normal FFT convection, this means (for \(N=6\), i.e. 6 real numbers in physical space):
Physical space: [N N N N N N]
\(\rightarrow\) 6 real degrees of freedom
Fourier space: [N 0 N N N N N 0 C C C C]
\(\rightarrow\) 6 real degrees of freedom
Here, N indicates a real number, and C a complex conjugate. However, as disussed the oddball mode needs to be set to zero, i.e.
Fourier space without oddball mode: [N 0 N N N N 0 0 C C C C]
\(\rightarrow\) 5 real degrees of freedom.
That essentially means that a signal that is represented in physical space with \(N=6\) real numbers will be represented with only 5 numbers in spectral space, with wavenumbers \(k=-2, -1, 0, 1, 2\), i.e. ranging from \(-K\) to \(K\) with \(K=N/2-1\).
A discussion of 2D transforms is given in e.g. the Simson user’s manual.