【问题标题】:FFTW and fft with MatLabFFTW 和 fft 与 MatLab
【发布时间】:2013-10-10 08:42:52
【问题描述】:

我对离散 fft 有一个奇怪的问题。我知道高斯函数 exp(-x^2/2) 的傅里叶变换又是同一个高斯函数 exp(-k^2/2)。我尝试在 MatLab 和 FFTW 中使用一些简单的代码对其进行测试,但得到了奇怪的结果。

首先,结果的虚部不应该是零(在 MatLab 中)。

其次,实部的绝对值是高斯曲线,但没有绝对值的一半模态具有负系数。更准确地说,每一秒的模式都有一个系数,它应该是负数。

第三,得到的高斯曲线的峰值(在取实部的绝对值之后)不是一而是高得多。它的高度与 x 轴上的点数成正比。但是,比例因子不是 1,而是接近 1/20。

谁能解释我做错了什么?

这是我使用的 MatLab 代码:

    function [nooutput,M] = fourier_test

    Nx = 512;      % number of points in x direction

    Lx = 50;        % width of the window containing the Gauss curve

    x = linspace(-Lx/2,Lx/2,Nx);     % creating an equidistant grid on the x-axis

    input_1d = exp(-x.^2/2);                 % Gauss function as an input
    input_1d_hat = fft(input_1d);            % computing the discrete FFT
    input_1d_hat = fftshift(input_1d_hat);   % ordering the modes such that the peak is centred

    plot(real(input_1d_hat), '-')
    hold on
    plot(imag(input_1d_hat), 'r-')

【问题讨论】:

  • 您可能将连续 FT 与离散 FT 混为一谈。高斯的连续 FT 是高斯的,但我不确定 DFT (FFT) 是否如此。
  • 当然,离散性会使事情变得不精确,但离散 FT 是作为连续 FT 的近似值创建的。当点数和区间足够大时,也就是这里的情况,近似应该是好的。会有一些偏差,但绝对不应该那么大,那么系统。另外,当我增加 Nx 和 Lx 时,结果不会改变,这意味着达到了收敛。
  • 我认为在您的 DFT 情况下也可能存在隐式时移,这会转化为频域中的相位旋转 - 我希望幅度是正确的,相位是一条直线(模 2π,如果你不打开它,即锯齿)。

标签: matlab fft fftw


【解决方案1】:

答案基本上是 Paul R 在他的第二条评论中所建议的,您引入了一个相移(与频率线性相关),因为input_1d_hat 描述的高斯中心实际上位于k>0,其中k+1是input_1d_hat 的索引。相反,如果您将数据居中(例如 input_1d_hat(1) 对应于中心),您将在频域中获得相位校正的高斯:

    Nx = 512;      % number of points in x direction
    Lx = 50;        % width of the window containing the Gauss curve

    x = linspace(-Lx/2,Lx/2,Nx);     % creating an equidistant grid on the x-axis

    %%%%%%%%%%%%%%%%
    x=fftshift(x);   % <-- center
    %%%%%%%%%%%%%%%%

    input_1d = exp(-x.^2/2);                 % Gauss function as an input
    input_1d_hat = fft(input_1d);            % computing the discrete FFT
    input_1d_hat = fftshift(input_1d_hat);   % ordering the modes such that the peak is centered

    plot(real(input_1d_hat), '-')
    hold on
    plot(imag(input_1d_hat), 'r-')

根据 DFT 的定义,如果高斯没有居中,以至于最大值出现在 k=0,您将看到相位扭曲。关闭fftshift的效果是对数据集进行循环移位或左右交换,相当于将峰的中心移到k=0。

至于幅度缩放,这是在 Matlab 中实现的 DFT 定义的问题。来自 FFT 的文档:

For length N input vector x, the DFT is a length N vector X,
with elements
                 N
   X(k) =       sum  x(n)*exp(-j*2*pi*(k-1)*(n-1)/N), 1 <= k <= N.
                n=1
The inverse DFT (computed by IFFT) is given by
                 N
   x(n) = (1/N) sum  X(k)*exp( j*2*pi*(k-1)*(n-1)/N), 1 <= n <= N.
                k=1

请注意,在前向步骤中,总和未由 N 归一化。因此,如果您增加总和中的点数 Nx,同时保持高斯函数的宽度 Lx 不变你会按比例增加X(k)。

至于信号泄漏到虚频维度,这是由于 DFT 的离散形式,这会导致截断和其他影响,正如 Paul R 再次指出的那样。如果在保持 Nx 的同时减少 Lx恒定,您应该会看到虚维度中的信号量相对于相对于实际维度有所减少(比较光谱,同时保持实际维度中的峰值强度相等)。

您会发现类似问题的更多答案here 和here。

【讨论】:

  • 感谢您的提示。但是,我仍然不明白为什么要使用 fftshift 更改 x 数组。你能详细说明一下吗?我认为这是通过对输出执行 fftshift 来提供的。为什么我的版本中的高斯有效地以 x>0 为中心?
  • 您知道我遇到的其他两个问题的原因吗?我实施了您的解决方案。它修复了输出的两个部分的振荡,但虚部仍然不为零。此外,当我改变点数 Nx 时,它保持不变,而实部的峰值与 Nx 成比例变化。知道为什么会这样吗?
  • 知道如何在与 C++ 一起使用 FFTW 时解决该问题吗?在那里我得到了同样令人讨厌的振荡。您能否提供有关该问题的数学参考资料?我在解释 fft 例程的页面上没有看到关于此的评论。
  • @Fortran_user 关于您的第一个问题,当我的意思是中心时,我的意思是在峰值的中心将“时间”域变量的值设置为零。对于 FFT,input_1d(1) 是“零时刻”的幅度值。
  • @Fortran_user 另一个影响可以解释为 DFT 的离散性质。
猜你喜欢
  • 2013-02-24
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多