Java 非能量守恒的Velocity-verlet算法

Java 非能量守恒的Velocity-verlet算法,java,algorithm,Java,Algorithm,我的印象是,如果被建模的系统能够做到这一点,那么算法应该节约能源。我正在模拟太阳系,这应该可以节约能源。这个程序保存角动量并产生稳定的轨道,但总能量(动能+重力势)在某个基线附近振荡。振荡是显著的。有没有常见的原因导致这种情况发生 该模型假设行星是点质量,圆形轨道(我也尝试过椭圆轨道,能量仍然振荡),并使用牛顿力学。我想不出这个节目还有什么其他特点可能会影响结果 如果只是预期能量会振荡,是什么导致了这些评论: 对于一个全引力N体问题,我不认为任何数值积分都是辛的。即使对于绕中心旋转的单点,Vel

我的印象是,如果被建模的系统能够做到这一点,那么算法应该节约能源。我正在模拟太阳系,这应该可以节约能源。这个程序保存角动量并产生稳定的轨道,但总能量(动能+重力势)在某个基线附近振荡。振荡是显著的。有没有常见的原因导致这种情况发生

该模型假设行星是点质量,圆形轨道(我也尝试过椭圆轨道,能量仍然振荡),并使用牛顿力学。我想不出这个节目还有什么其他特点可能会影响结果

如果只是预期能量会振荡,是什么导致了这些评论:
对于一个全引力N体问题,我不认为任何数值积分都是辛的。即使对于绕中心旋转的单点,Velocity Verlet也不是辛的(很容易检查,因为它有一个g=v^2/R的平凡解析解)。所以我建议尝试一个高阶积分(比如Runge-Kutta),如果能量偏差几乎消失(这意味着计算通常是正确的),你可以重新调整组合动能的比例,以保持总能量的显式守恒。具体来说,计算更新后的Ekin_实际值和Ekin_期望值=Etotal_初始电位,并通过sqrt(Ekin_期望值/Ekin_实际值)缩放所有速度。

查阅Haier等人的Verlet Störmer论文(Störmer/Verlet方法说明的几何数值积分)。网上应该有几个来源

简而言之,辛积分器保留了哈密顿量和能量,但它是一个修正的哈密顿量。如果该方法已正确初始化,则修改为O阶扰动(h²),其中h为步长。不正确的初始化会产生O(h)的扰动,而观察到的振荡仍应具有O(h²)的振幅

因此,由物理公式计算的振荡能量的观测模式是完全正常和预期的。如果能量(迅速)偏离这种相对稳定的模式,就会出现误差


从二阶Verlet方法得到一个四阶辛积分器是一种简单但效率稍低的方法

Verlet(h)


其中
b0=1/(2-2^(1/3))=1.35120719196…
b1=2*b0-1=1.70241438392…
。这就是所谓的“合成方法”。

请提供算法的源代码,以及您认为算法无法生成预期输出的示例…@WillemVanOnsem我不确定它是否失败。我希望我能上传我拥有的总能量的图表,但我不知道如何上传。我将添加算法部分,但我非常确定算法本身是正确的,如果能量不应该振荡,那么它是由其他特性/假设引起的。这取决于算法。基本上,如果你用数值方法求解微分方程,并且你的系统中有一些运动积分,那么你应该使用所谓的结构保持算法或辛算法。其他算法是耗散的,不保留这种结构。@DariuszSendkowski是的,velocity verlet是辛的。这就是为什么我想知道能量振荡的原因。我不认为速度verlet对于圆周运动是完全辛的(但对于匀速加速的)。如果使用稳定的起始条件g=v^2/r,并通过δt演化二维向量,则与圆的位置偏差将与g*δt^2成比例。除非你用的是极坐标?另外,你是否只考虑了来自太阳的引力,还是所有其他行星的引力?这是相当错误的。维莱特总是辛的。你的意思是,离散动力学的守恒量不是连续动力学的物理量,而是以步长为参数对其进行修改。然而,RK4不是辛的,但保留了4阶的第一次积分,这对于“短”积分间隔来说,比Verlet的误差阶2更精确。我不认为任何Verlet是辛的。正如你提到的那篇文章(这篇文章很好)所解释的,速度和位置的“交错”更新非常重要,也就是说,“在步骤的中间”更新速度。它被称为“蛙跳”,正确的初始化,蛙跳和速度Verlet给出相同的位置,而蛙跳的速度在中间。Velocity Verlet是两种辛Euler方法变体的组合,因此它本身也是辛的。记住,辛变换是关于辛2-形式的保持,而不是别的。Noether定理给出了系统对称性的守恒定律。vv不只是“二阶辛”吗,因为它实际上不计算a(1/2),而是从a0和a1混合而来?这意味着只有当a(p)是二阶的时候,它才能完全保持相空间面积,但对于引力n体问题,情况并非如此,我可能确实误解了这一点。也许“二阶辛”只是指二阶和辛,而不考虑(pos)依赖关系。
Verlet4(h) {
  Verlet(b0*h);
  Verlet(-b1*h);
  Verlet(b0*h);
}