Python NumPy中exp(-x^2)的快速傅里叶变换

Python NumPy中exp(-x^2)的快速傅里叶变换,python,numpy,fft,Python,Numpy,Fft,我必须用数值计算高斯函数的二阶导数: 我已经阅读了关于这个话题的每一个问题,但是没有得出一个好的结果。我选择NumPy作为我的工具 我们教授的指导是: 使用步骤dx=1获取大小为N=128的x数组。所以,-64,-63,…,62,63。计算f(x) 在f(x)上执行FFT,并接收变换后的数组f\m 用f_m乘以,其中为虚单位,为导数和 执行逆FFT以接收导数 在某些FFT实现中,您可能必须按1/n进行缩放(但这是目前最小的问题) 下面是我的代码,尽可能简单 import numpy as np

我必须用数值计算高斯函数的二阶导数:
我已经阅读了关于这个话题的每一个问题,但是没有得出一个好的结果。我选择NumPy作为我的工具

我们教授的指导是:

  • 使用步骤
    dx=1
    获取大小为
    N=128
    x
    数组。所以,
    -64,-63,…,62,63
    。计算
    f(x)
  • f(x)
    上执行FFT,并接收变换后的数组
    f\m
  • 用f_m乘以,其中为虚单位,为导数和
  • 执行逆FFT以接收导数
  • 在某些FFT实现中,您可能必须按
    1/n
    进行缩放(但这是目前最小的问题)
  • 下面是我的代码,尽可能简单

    import numpy as np
    
    # Set some parameters
    n = 128
    dx = 1
    a = 0.001
    
    # Create x, calculate f(x) and its FFT
    x = np.arange(-n/2, n/2) * dx
    psi = np.exp(-a * x * x)
    f_m = np.fft.fft(psi)
    
    # k_m creation according to professor (point 3. in my instruction)
    k_m = np.arange(-n/2, n/2, dtype=float)
    k_m[:int(n / 2)] = (2 * np.pi * k_m[:int(n / 2)]) / (n * dx)
    k_m[int(n / 2):] = (2 * np.pi * (k_m[int(n / 2):] - n)) / (n * dx)
    
    # Multiply f_m by (j * k_m)^q. For q=2, this is -k_m^2
    f_m *= -k_m * k_m
    # Inverse FFT on the result to get the second derivative and scale by 1 / n
    f_m = np.fft.ifft(f_m) / n
    
    
    我不能得到的一件事是,结果仍然有虚部,所以有些东西是不对的。有人能帮忙吗

    编辑:Cris Luengo的答案有效。

    这部分错了:

    k_m = np.arange(-n/2, n/2, dtype=float)
    
    步骤3中的说明讨论了从0到n-1的
    m
    。代码应该如下所示:

    k_m=np.arange(0,n,dtype=float)
    一半=整数(n/2)+1;#注意这里的+1!
    k_m[:half]=(2*np.pi*k_m[:half])/(n*dx)
    k_m[half:=(2*np.pi*(k_m[half:-n))/(n*dx)
    
    FFT产生一个输出,其中第一个元素(索引0)是0频率,而不是频率
    -n/2

    如果您使用
    fftshift
    将0频率槽移到阵列的中间,您当前版本的
    k_m
    阵列可能是正确的,尽管我不能完全确定这一点(可能应该删除下半部分中的
    -n


    最后,这里不需要除以
    n

    f_m = np.fft.ifft(f_m) / n
    
    NumPy IFFT已经标准化

    在验证虚部几乎为零后,请记住绘制
    f_m.real
    (这些值应仅因数值舍入误差而与零不同)


    如果你把
    a
    放大一点,例如
    a=0.005
    ,那么你的输入高斯完全适合输入信号,并且你不会因为过滤被切断的信号而产生难看的边缘效果。

    你可以用一个更简单的
    k
    ,只要你在某个点执行正确的FT移位,发动机罩下的机具与您的讲师或@CrisLuengo明确书写的相同

    import numpy as np
    
    
    # Set some parameters
    n = 128
    dx = 1
    a = 0.001
    
    # Create x, calculate f(x) and its FFT
    x = np.arange(-n // 2, n // 2) * dx
    f_x = np.exp(-a * x ** 2)
    dd_f_x = 2 * a * np.exp(-a * x ** 2) * (2 * a * x ** 2 - 1)
    
    f_k = np.fft.fft(f_x)
    k = np.fft.ifftshift(np.arange(-n // 2, n // 2))
    k = (2 * np.pi * k / (n * dx))
    dd_f_k = -k ** 2 * f_k
    dd_f_x_ = np.fft.ifft(dd_f_k)
    
    其工作原理与预期一致:

    import matplotlib.pyplot as plt
    
    
    fig, ax = plt.subplots(1, 1, squeeze=True)
    ax.plot(x, dd_f_x_.real, label='∂²/∂x² f(x) with DFT')
    ax.plot(x, dd_f_x, label='∂²/∂x² f(x)')
    ax.legend()
    

    谢谢你的回答。更改为
    f_m=np.fft.fftshift(np.fft.fft(psi))
    k_m=np.arange(0,n,dtype=float)
    后仍然不起作用,尽管…@lkky7:是的,你应该做这两件事中的一件,而不是两件。谢谢你,这改变了一些事情,但仍然是一个坏结果。删除
    -n
    也不会改变这一点:(将结果添加到edit@lkky7当我用我的更改运行代码时,我确实看到了一个正确的二阶导数。请注意,您正在将其与图形中的一阶导数进行比较。您还将结果按比例缩小了一个因子
    n
    ,这是您不应该做的。如果将
    a
    的影响增大,结果确实会产生一个难看的边缘效果还需要注意的是,您需要忽略(几乎为零)虚部,并绘制
    f_m.real