FFT泊松求解器的收敛速度


16

FFT毒物求解器的理论收敛速度是多少?

我正在求解泊松方程: 其中 在域具有周期边界条件。该电荷密度是净中性的。解决方案如下: 其中。在倒易空间 其中是倒易空间矢量。我对Hartree能源感兴趣: Ñ

2VH(x,y,z)=4πn(x,y,z)
[02]×[02]×[02]VħX=Ñ y
n(Xÿž=3πX-1个2+ÿ-1个2+ž-1个2-1个
[02]×[02]×[02]x=xyzVHG
VHX=ñÿ|X-ÿ|d3ÿ
X=Xÿž GEH=1
VHG=4πñGG2
G
ËH=1个2ñXñÿ|X-ÿ|d3Xd3ÿ=1个2VHXñXd3X
在倒数空间中(离散化后)为: 的被省略术语,这有效地使电荷密度净中性的(并且由于它是已经中立,那么一切都是一致的)。
ËH=2πG0|ñG|2G2
G=0

对于上面的测试问题,可以通过分析评估: 该能量应收敛多快?

ËH=12835π=1.16410 ...

这是一个使用NumPy进行计算的程序。

from numpy import empty, pi, meshgrid, linspace, sum
from numpy.fft import fftn, fftfreq
E_exact = 128/(35*pi)
print "Hartree Energy (exact):      %.15f" % E_exact
f = open("conv.txt", "w")
for N in range(3, 384, 10):
    print "N =", N
    L = 2.
    x1d = linspace(0, L, N)
    x, y, z = meshgrid(x1d, x1d, x1d)

    nr = 3 * ((x-1)**2 + (y-1)**2 + (z-1)**2 - 1) / pi
    ng = fftn(nr) / N**3

    G1d = N * fftfreq(N) * 2*pi/L
    kx, ky, kz = meshgrid(G1d, G1d, G1d)
    G2 = kx**2+ky**2+kz**2
    G2[0, 0, 0] = 1  # omit the G=0 term

    tmp = 2*pi*abs(ng)**2 / G2
    tmp[0, 0, 0] = 0  # omit the G=0 term
    E = sum(tmp) * L**3
    print "Hartree Energy (calculated): %.15f" % E
    f.write("%d %.15f\n" % (N, E))
f.close()

这是一个收敛图(只是绘制conv.txt上面脚本中的,是一个笔记本,如果您想自己玩这个的话,可以这样做):

FFT收敛图

如您所见,收敛是线性的,这令我感到惊讶,我认为FFT的收敛速度快得多。

更新

该解决方案在边界处具有风头(我之前没有意识到这一点)。为了使FFT快速收敛,解决方案必须使所有导数平滑。因此,我还尝试了以下右侧:

nr = 3*pi*sin(pi*x)*sin(pi*y)*sin(pi*z)/4

您可以将其放到上面的脚本中(更新的脚本)。确切的解决方案是,这应该是无限可微的。在这种情况下,确切的积分是。但是,FFT解算器仍然仅朝着该精确解线性收敛,可以通过运行上面的脚本并绘制会聚点(使用图更新的笔记本)进行检查。VH=πXπÿπžËH=3π8

有谁知道3D的任何基准测试,以便使我看到比线性更快的收敛速度?


Ondrej,您的平滑密度的傅立叶变换不是增量函数吗?我承认自己懒得运行它,但是它应该在第一次尝试时得到确切的答案。
马特·克奈普利

我觉得是这样的。但是,从笔记本图可以看出,它不会一次收敛。我不知道发生了什么。
昂德里杰·塞蒂克

Ondrej,您确定您的实现正确吗?我记得在研究生院尝试为家庭作业分配频谱求解器,并完全扰乱了常数。我注意到您正在通过查看计算出的能量与精确能量之间的绝对距离来测量误差。您对问题的实际解决方案的收敛是什么样的?这应该易于计算,甚至可以绘制问题的二维切片。
阿隆·艾玛迪亚

Aron ---我对照其他代码检查了我的实现,但是我检查了我的初始采样错误,因此两个代码中都有相同的错误。马特是对的,现在它在第一次尝试上趋于融合。请参阅下面的答案。
2013年

Answers:


10

首先让我回答所有问题:

FFT毒物求解器的理论收敛速度是多少?

只要解足够平滑,理论收敛就是指数的。

这种能量应收敛多快?

ËH

有谁知道3D的任何基准测试,以便使我看到比线性更快的收敛速度?

产生周期且无限可微(包括跨越周期边界)的解的任何右侧都应按指数收敛。


在上面的代码中,恰好有一个错误,导致收敛慢于指数。使用平滑密度代码(https://gist.github.com/certik/5549650/),以下修补程序修复了该错误:

@@ -6,7 +6,7 @@ f = open("conv.txt", "w")
 for N in range(3, 180, 10):
     print "N =", N
     L = 2.
-    x1d = linspace(0, L, N)
+    x1d = linspace(0, L, N+1)[:-1]
     x, y, z = meshgrid(x1d, x1d, x1d)

     nr = 3*pi*sin(pi*x)*sin(pi*y)*sin(pi*z)/4

问题是实际空间采样不能重复第一个点和最后一个点(由于周期性边界条件,该点的值相同)。换句话说,问题在于设置初始采样。

如上所述,修复后,密度会在一次迭代中收敛。所以我什至没有绘制收敛图。

但是,可以尝试更困难的密度,例如:

     nr = 3*pi*exp(sin(pi*x)*sin(pi*y)*sin(pi*z))/4

那么收敛是指数级的,如预期的那样。这是此密度的收敛图: 在此处输入图片说明 在此处输入图片说明


太棒了 抱歉,我没有更多帮助!
阿隆·艾玛迪亚
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.