Fortran 中 Verlet 算法的错误顺序错误

Incorrect Order of Error of Verlet Algorithm in Fortran

我正在尝试使用 Fortran 中的 Verlet 方法(Original Verlet)来模拟谐波振荡器。 我的研究表明错误的阶数应该是 2,但我的计算显示是 1 的阶数。

我在我的源代码中找不到我的错误。我该怎么办?

编辑: 我使用的算法如下:

x(t+Δt) = 2x(t) - x(t-Δt) + Δt² F(t)/m

v(t) = {x(t+Δt) -x(t-Δt)}/2Δt

其中x(t)代表位置,v(t)代表速度,F(t)代表力。我认出这是描述的原始 Verlet here

根据this site,错误的顺序至少应该是O(Δt²) 但是我在gnuplot 中绘制的程序顺序错误(下图)没有O(Δt²) 的顺序.

program newton_verlet

implicit none

real*16, parameter :: DT   = 3.0
real*16, parameter :: T0   = 0.0
real*16, parameter :: TEND = 2.0
integer, parameter :: NT   = int(TEND/DT + 0.5)

real*16, parameter :: M    = 1.0
real*16, parameter :: X0   = 1.0
real*16, parameter :: V0   = 0.0

real*16 x,v,t,xold,xnew,vnew,ek,ep,et,f,h
integer it,n

do n=0,20
h = DT/2**n

x = X0
v = V0

ek = 0.5*M*v*v
ep = x*x/2
et = ek + ep

xold = x - v*h

do it = 1,2**n
!   f = -x
   f = -x

   xnew = 2.0*x - xold + f*h*h/M
   v = (xnew-xold)/(2.0*h)

   ek = 0.5*M*v*v
   ep = 0.5*xnew*xnew
   et = ek + ep
   xold = x
   x = xnew

end do
write(*,*) h,abs(x-cos(DT))+abs(v+sin(DT))
end do

end program

以上程序计算了时间步长h的计算误差。

根据 Wiki page for Verlet integrators,似乎我们需要使用更准确的方法来设置 xold 的初始值(即包括力项)以得到 2 阶的全局误差。确实,如果我们将 xold 修改为

program newton_verlet
implicit none
real*16, parameter :: DT   = 3.0
real*16, parameter :: M    = 1.0
real*16, parameter :: X0   = 1.0
real*16, parameter :: V0   = 0.0

real*16 x,v,xold,xnew,f,h
integer it,n

do n = 0, 20

    h = DT / 2**n

    x = X0
    v = V0
    f = -x

    ! xold = x - v * h                     !! original
    xold = x - v * h + f * h**2 / (2 * M)  !! modified

    do it = 1, 2**n

        f = -x

        xnew = 2 * x - xold + f * h * h / M

        xold = x
        x = xnew
    end do

    write(*,*) log10( h ), log10( abs(x - cos(DT)) )
end do

end program

全局误差变为 2 阶(请参见下面的对数-对数图)。