辛积分法
辛积分法(symplectic integrator)是一类保持哈密顿系统辛结构的数值时间积分方法。它关注位置与动量之间的几何关系,而不只是某一步的数值误差。在长期振动和轨道计算中,保持这种结构常能避免某些持续的人为膨胀或收缩;但辛方法通常并不逐步精确保留原始能量,也不保证任意大步长都稳定。
振子的数值轨迹
考虑无量纲简谐振子,位置为 ,动量为 : 沿精确轨迹,。初态 的解为 ,相图是一条圆。
显式 Euler 同时使用旧位置与旧动量: 把两式平方相加,交叉项相消,得到 无论步长多小,只要 ,每一步都会增加能量;在固定步长下长期重复会向外螺旋。这里能明确指出问题,不能仅说图画得“不够圆”。
一种只改变更新顺序的方法是先更新动量,再用新动量更新位置: 它叫辛 Euler 法的一种形式。其精度仍为一阶,却具有不同的长期结构。对 ,首步为 ,真实能量 ;能量没有精确守恒,后面也不是每步都下降。
辛结构的定义
对 个位置与动量,按 排列坐标,令 一个可微的一步映射 称为辛映射,如果其导数矩阵 满足 这一条件保留的双线性量是 :对两条微小方向先作映射再计算,结果与先计算相同。辛性因此描述整个微分映射,并不只是某条已画出的轨迹。
精确哈密顿流本身是辛的。设其导数矩阵为 ,沿轨迹的线性化矩阵为 。Hessian 对称且 ,所以 。由乘积法则, 初时刻 ,因而等式始终等于 。这里假设 有足够连续二阶导数并且相应流存在。辛积分法以离散映射保留的正是这个结构。定义及其与能量的关系见 Hairer、Lubich 与 Wanner 的几何积分论文。[1]
剪切的组合与面积
对本例,辛 Euler 的矩阵为 其行列式为 。二维中直接相乘可验证 ,所以此处保面积恰好等价于辛性。先做一次动量剪切,再做一次位置剪切,也分别可验证为辛映射,组合仍为辛映射。
高维中仅保总体积则不足够。例如按 排列的矩阵 行列式为一,却把 面积乘以二、把 面积乘以一半,不满足 。因此不能用一个行列式检查替代一般辛性检查。
对于可分离 Hamiltonian ,同样的先动量、后位置更新为 这两个剪切在相应光滑条件下都是辛的。更对称的半步—整步—半步组合给出斯托默—韦尔莱法等二阶方法。一般非可分离 Hamiltonian 不能未经推导就把上述显式两式照搬过去。
一个真正精确保留的二次量
对谐振子,定义依赖步长的修正量 为把抵消过程写清,暂记旧值为 ,新值为 。由 , 再代入 ,右端成为 。因此 因此 逐步精确保留,而原始 通常上下振荡。两者的差来自交叉项,并没有把“能量”换个名字就证明原能量相等。
由 ,当 时有 所以修正量正定并控制真实能量,轨迹始终有界。首态 时 ,例如 给出 这是可以验证的全步数界,而不是只画若干步得到的经验结论。
步长限制仍不可丢。 的迹为 ,特征方程为 。当 时,两个根在单位圆上; 时有一个根的模大于一。 也出现非平凡 Jordan 情形,通常导致增长。这个方法对所有步长都是辛的,但并非对所有步长都稳定。
可运行的振子积分
代码只实现本文的无量纲谐振子与先动量、后位置的辛 Euler 法。输入为有限初态、正步长和非负整数步数,返回包含初态的状态二元组列表,不修改输入。每步常数次运算,总时间 ,保存全轨迹占 ,滚动推进只需常数额外空间。代码不替用户判断步长稳定性。
import math
def symplectic_oscillator(q0, p0, h, steps):
if not isinstance(steps, int) or steps < 0:
raise ValueError("steps must be a nonnegative integer")
q, p, h = map(float, (q0, p0, h))
if not all(math.isfinite(v) for v in (q, p, h)) or h <= 0:
raise ValueError("finite state and positive h required")
states = [(q, p)]
for _ in range(steps):
p = p - h * q
q = q + h * p
if not math.isfinite(q) or not math.isfinite(p):
raise OverflowError("intermediate or result outside floating-point range")
states.append((q, p))
return states
h = 0.2
states = symplectic_oscillator(1, 0, h, 1000)
q, p = states[1]
print(round(q, 6), round(p, 6)) # 0.96 -0.2
invariant_error = max(abs((q*q + p*p - h*q*p)/2 - 0.5) for q, p in states)
print(invariant_error) # near roundoff, not exactly zero in floating point变式取 ,首步应为 ,原能量为 ,修正量仍为 。如果先更新位置再把同一行代码中的新位置用于动量,那是另一种辛 Euler 次序,交叉项符号也会改变,不能把两种代码与同一个修正量混用。
长期结论的边界
对一般非线性 Hamiltonian,往往只能在光滑性、小步长、远离奇性等条件下,用修正方程解释长时间较小的能量误差;不能把谐振子精确修正量的计算直接推广成所有 Hamiltonian 都存在同一个精确保留函数。轨道的相位仍会积累误差,非辛方法也可能在短时间或给定容限内更准确。几何数值方法的价值在于与目标问题相匹配的结构保持,而非一种不分场景的精度保证。[1]
参考资料
- ↑ 1.0 1.1 Ernst Hairer, Christian Lubich, Gerhard Wanner. “Geometric numerical integration illustrated by the Störmer–Verlet method”. Acta Numerica 12 (2003), 399–450. DOI:10.1017/S0962492902000144。大学课程提供的原论文,§1.2、1.4、2.1—2.2 及 §5.1。