在我的回答到关于MSE问题关于汉密尔顿的2D物理模拟,我一直在使用高阶建议辛积分。
然后,我认为演示不同时间步长对具有不同顺序的方法的全局精度的影响可能是一个好主意,为此我编写并运行了Python / Pylab脚本。为了比较,我选择了:
- (jump2) 我熟悉的Wikipedia的2阶示例,尽管我知道它的名称是jumpfrog,
- (ruth3)Ruth的三阶辛积分器,
- (ruth4)露丝的四阶辛格积分器。
奇怪的是,无论我选择什么时间步长,Ruth的三阶方法在我的测试中似乎都比Ruth的四阶方法更精确,甚至高出一个数量级。
因此,我的问题是:我在这里做错了什么?详细信息如下。
这些方法在具有可分离哈密顿量的系统中展现出它们的优势,即可以写为
在我们的设置中,我们可以通过对其施加的质量进行归一化。因此,力变成加速度,而力矩变成速度。
辛积分器带有特殊的(给定的,恒定的)系数,我将它们标记为和。与那些系数,一个步骤,用于从时间演进系统 到时间的形式为
对于:
- 给定所有位置的向量q,计算所有加速度的向量
- 将所有速度的向量改变
- 变化矢量的所有位置的
现在的智慧在于系数。这些是
我已经整合有超过上述方法中的IVP 用的步长与整数之间选择某处和。考虑到jump2的速度,我将该方法的值增加了三倍。然后,我在相空间中绘制了所得曲线,并放大到 ,在理想情况下,曲线应该再次到达。Ñ (1 ,0 )吨= 2 π
这是和图和缩放:
对于,leap2步长 发生比到达更接近家ruth4 与步长。对于,ruth4胜过jump2。但是,在到目前为止我测试过的所有设置中,ruth3的步长与ruth4相同,比其他两个都离家更近。2 π 2π
这是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()
我已经检查了简单的错误:
- 没有维基百科的错字。我已经检查的参考文献,特别是(1, 2, 3)。
- 我的系数序列正确。如果与Wikipedia的顺序进行比较,请注意,操作员应用程序的排序从右到左有效。我的编号与Candy / Rozmus一致。如果仍然尝试其他订购,结果会变得更糟。
我的怀疑:
- 错误的步长排序:也许Ruth的3阶方案在某种程度上具有较小的隐含常数,如果步长真的很小,那么4阶方法会赢吗?但是我什至尝试了,而三阶方法仍然更好。
- 错误的测试:我的测试有什么特别之处,可以让露丝的三阶方法表现得像高阶方法一样?