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
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
。