三阶与四阶辛积分器的测试结果很奇怪


10

我的回答关于MSE问题关于汉密尔顿的2D物理模拟,我一直在使用高阶建议辛积分

然后,我认为演示不同时间步长对具有不同顺序的方法的全局精度的影响可能是一个好主意,为此我编写并运行了Python / Pylab脚本。为了比较,我选择了:

奇怪的是,无论我选择什么时间步长,Ruth的三阶方法在我的测试中似乎都比Ruth的四阶方法更精确,甚至高出一个数量级。

因此,我的问题是:我在这里做错了什么?详细信息如下。

这些方法在具有可分离哈密​​顿量的系统中展现出它们的优势,即可以写为

H(q,p)=T(p)+V(q)
,其中q包括所有位置坐标, p包括共轭矩a, T表示动力学能量和V势能。

在我们的设置中,我们可以通过对其施加的质量进行归一化。因此,力变成加速度,而力矩变成速度。

辛积分器带有特殊的(给定的,恒定的)系数,我将它们标记为a1,,anb1,,bn。与那些系数,一个步骤,用于从时间演进系统t 到时间t+δt的形式为

  • 对于i=1,,n

    1. 给定所有位置的向量q,计算所有加速度的向量gq
    2. 将所有速度的向量v改变bigδt
    3. 变化矢量q的所有位置的aivδt

现在的智慧在于系数。这些是

[a1a2b1b2]=[121201](leap2)[a1a2a3b1b2b3]=[2323172434124](ruth3)[a1a2a3a4b1b2b3b4]=1223[12123212321201231](ruth4)

y+y=0y(0)=1y(0)=0
(y(t),y(t))=(cost,sint)
(q,v)(y,y)

我已经整合有超过上述方法中的IVP 用的步长与整数之间选择某处和。考虑到jump2的速度,我将该方法的值增加了三倍。然后,我在相空间中绘制了所得曲线,并放大到 ,在理想情况下,曲线应该再次到达。t[0,2π]δt=2πNN10100Ñ 1 0 = 2 πN(1,0)t=2π

这是和图和缩放:N=12N=36

N = 12N = 12,放大

N = 36N = 36,放大

对于,leap2步长 发生比到达更接近家ruth4 与步长。对于,ruth4胜过jump2。但是,在到目前为止我测试过的所有设置中,ruth3的步长与ruth4相同,比其他两个都离家更近。N=122 π2π3N 2π2πNN=36

这是Python / Pylab脚本:

import numpy as np
import matplotlib.pyplot as plt

def symplectic_integrate_step(qvt0, accel, dt, coeffs):
    q,v,t = qvt0
    for ai,bi in coeffs.T:
        v += bi * accel(q,v,t) * dt
        q += ai * v * dt
        t += ai * dt
    return q,v,t

def symplectic_integrate(qvt0, accel, t, coeffs):
    q = np.empty_like(t)
    v = np.empty_like(t)
    qvt = qvt0
    q[0] = qvt[0]
    v[0] = qvt[1]
    for i in xrange(1, len(t)):
        qvt = symplectic_integrate_step(qvt, accel, t[i]-t[i-1], coeffs)
        q[i] = qvt[0]
        v[i] = qvt[1]
    return q,v

c = np.math.pow(2.0, 1.0/3.0)
ruth4 = np.array([[0.5, 0.5*(1.0-c), 0.5*(1.0-c), 0.5],
                  [0.0,         1.0,          -c, 1.0]]) / (2.0 - c)
ruth3 = np.array([[2.0/3.0, -2.0/3.0, 1.0], [7.0/24.0, 0.75, -1.0/24.0]])
leap2 = np.array([[0.5, 0.5], [0.0, 1.0]])

accel = lambda q,v,t: -q
qvt0 = (1.0, 0.0, 0.0)
tmax = 2.0 * np.math.pi
N = 36

fig, ax = plt.subplots(1, figsize=(6, 6))
ax.axis([-1.3, 1.3, -1.3, 1.3])
ax.set_aspect('equal')
ax.set_title(r"Phase plot $(y(t),y'(t))$")
ax.grid(True)
t = np.linspace(0.0, tmax, 3*N+1)
q,v = symplectic_integrate(qvt0, accel, t, leap2)
ax.plot(q, v, label='leap2 (%d steps)' % (3*N), color='black')
t = np.linspace(0.0, tmax, N+1)
q,v = symplectic_integrate(qvt0, accel, t, ruth3)
ax.plot(q, v, label='ruth3 (%d steps)' % N, color='red')
q,v = symplectic_integrate(qvt0, accel, t, ruth4)
ax.plot(q, v, label='ruth4 (%d steps)' % N, color='blue')
ax.legend(loc='center')
fig.show()

我已经检查了简单的错误:

  • 没有维基百科的错字。我已经检查的参考文献,特别是(123)。
  • 我的系数序列正确。如果与Wikipedia的顺序进行比较,请注意,操作员应用程序的排序从右到左有效。我的编号与Candy / Rozmus一致。如果仍然尝试其他订购,结果会变得更糟。

我的怀疑:

  • 错误的步长排序:也许Ruth的3阶方案在某种程度上具有较小的隐含常数,如果步长真的很小,那么4阶方法会赢吗?但是我什至尝试了,而三阶方法仍然更好。N=360
  • 错误的测试:我的测试有什么特别之处,可以让露丝的三阶方法表现得像高阶方法一样?

可以给出误差的数值吗?从剧情中很难分辨出来。随着变化,误差如何缩放?它们是否按方法的顺序按比例缩放?通常,人们会在对数对数图上针对绘制误差以进行检查。 NNN
基里尔,2015年

@Kirill:正在努力。即将编辑。
ccorn

1
我怀疑的一件事是选择线性rhs:方法的截断错误通常取决于rhs的某些高阶导数,因此,如果rhs的所有高阶导数都消失了,您可能会观察到一些奇怪的收敛行为。可能值得尝试更不寻常的rhs。
基里尔

Answers:


9

按照Kirill的建议,我使用从几何上近似递增的值列表中的进行了测试,并且对于每个计算出的误差为 ,其中表示近似值通过数值积分获得。这是对数-对数图的结果:Ñ ε Ñ = Ž2 π - Ž0 2NNž

ϵ(N)=z~(2π)z~(0)2wherez~(t)=(y~(t),y~(t))
z~

在此处输入图片说明

所以ruth3确实具有相同的顺序作为ruth4对于测试用例,仅暗示常数的大小。141100

有趣。我将不得不进一步调查,也许尝试其他测试。

顺便说一下,这是错误脚本在Python脚本中的补充:

def int_error(qvt0, accel, qvt1, Ns, coeffs):
    e = np.empty((len(Ns),))
    for i,N in enumerate(Ns):
        t = np.linspace(qvt0[2], qvt1[2], N+1)
        q,v = symplectic_integrate(qvt0, accel, t, coeffs)
        e[i] = np.math.sqrt((q[-1]-qvt1[0])**2+(v[-1]-qvt1[1])**2)
    return e

qvt1 = (1.0, 0.0, tmax)
Ns = [12,16,20,24,32,40,48,64,80,96,128,160,192,
      256,320,384,512,640,768,1024,1280,1536,2048,2560,3072]

fig, ax = plt.subplots(1)
ax.set_xscale('log')
ax.set_xlabel(r"$N$")
ax.set_yscale('log')
ax.set_ylabel(r"$\|z(2\pi)-z(0)\|$")
ax.set_title(r"Error after 1 period vs #steps")
ax.grid(True)
e = int_error(qvt0, accel, qvt1, Ns, leap2)
ax.plot(Ns, e, label='leap2', color='black')
e = int_error(qvt0, accel, qvt1, Ns, ruth3)
ax.plot(Ns, e, label='ruth3', color='red')
e = int_error(qvt0, accel, qvt1, Ns, ruth4)
ax.plot(Ns, e, label='ruth4', color='blue')
ax.legend(loc='upper right')
fig.show()

与问题无关,但您能否将更改和更新放入问题本身,而不是作为单独的答案发布?这将保持答案应回答问题的惯例。
基里尔

1
@Kirill:这一个答案。ruth3在这里确实具有较高的顺序和较小的常数。由于您建议制作对数-对数错误图而被发现。因此,该问题已得到回答,即使回答了我自己,我也决不会改变问题的要点。
ccorn

就是说,我很乐意接受进一步的分析。(自动回答的问题会自动被接受,但是我想这可以改变。)
ccorn 2015年

2
我稍微看了一下,却找不到令人信服的解释。ruth3的这种四阶收敛与初始条件有很大关系:尝试设置并尝试在整个周期(半周期)内不积分。容易发生的一件事是,截断错误具有一些“零均值”组件,当您积分到整个周期时,它们会被抵消。我还尝试了来检查这是否与高导数很少有关,但是在我的测试中,似乎初始条件和周期性与此有关。V q = 1 / q + 对数q Vp00V(q)=1/q+logqV
基里尔2015年

2
这是超收敛的显示。像这样的简单测试问题在很多情况下都会出现此问题。使用线性方程式可以给出这种行为,并且泰勒级数的奇数项可以在出现这种情况时抵消很多。没有分析解决方案的非线性测试问题发生的可能性很小。
克里斯·拉卡卡斯

2

在整个间隔内绘制,的误差,并按预期阶数给出的步长的幂进行缩放,得出图q¨=qq(0)=1,q˙(0)=0

在此处输入图片说明

不出所料,增加子间隔数量的图形越来越接近极限曲线,该极限曲线是领先的误差系数。除了一个图以外,所有图中的收敛速度都非常快,几乎没有差异。这意味着,即使对于较大的步长,前导误差项也将主导所有其他项。

在三阶Ruth方法中,分量的前导系数似乎为零,可见极限曲线接近或等于水平轴。可见图清楚地显示了四阶误差项的优势。缩放四阶误差会得出与其他曲线相似的曲线。p

可以看到,在所有3种情况下,整个周期后,在,分量中前导阶的误差系数均为零。在组合两个分量的误差时,分量的行为占主导地位,从而错误地在对数图中给人以四阶方法的印象。qt=2πp

可以在附近找到分量中的最大系数。那里的对数图应反映正确的全局错误顺序。q3π/2


Ruth3p中三次误差项的消失是线性方程式简单性的产物,这表明了非线性示例,与相应的图q¨=sin(q)q(0)=1.3, q˙(0)=0

在此处输入图片说明

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.