微分方程式の数値解析 #5

落体の運動方程式をEuler法により数値的に解くFORTRANプログラム。

program ode
  implicit none
  double precision, parameter :: g = 9.80665      ! gravitational acceleration
  double precision, parameter :: t0 = 0           ! initial t
  double precision, parameter :: y0 = 0           ! initial position at t0
  double precision, parameter :: v0 = 0           ! initial velocity at t0
  double precision :: t
  double precision :: y = y0
  double precision :: v = v0
  double precision :: yn
  double precision, parameter :: udiv = 1         ! division unit
  integer, parameter :: ndiv = 1000               ! number of divisions per udiv
  double precision, parameter :: h = udiv / ndiv  ! delta-t
  integer, parameter :: niter = 2 / udiv * ndiv   ! number of iterations
  integer, parameter :: pdiv = ndiv / 10          ! print interval
  integer :: n
  do n = 0, niter
    t = t0 + n * h
    if (mod(n, pdiv) == 0) print '(5F13.8)', t, y, exacty(t), v, exactv(t)
    yn = nexty(t, y, v, h)
    v = nextv(t, y, v, h)
    y = yn
  end do
contains
  double precision function f1(t, y, v)
    double precision, intent(in) :: t, y, v
    f1 = v
  end function f1
  double precision function f2(t, y, v)
    double precision, intent(in) :: t, y, v
    f2 = g
  end function f2
  double precision function exacty(t)
    double precision, intent(in) :: t
    exacty = y0 + v0 * (t - t0) + g * (t - t0) ** 2 / 2
  end function exacty
  double precision function exactv(t)
    double precision, intent(in) :: t
    exactv = v0 + g * (t - t0)
  end function exactv
  double precision function nexty(t, y, v, h)
    double precision, intent(in) :: t, y, v, h
    double precision :: k1
    k1 = f1(t, y, v)
    nexty = y + h * k1
  end function nexty
  double precision function nextv(t, y, v, h)
    double precision, intent(in) :: t, y, v, h
    double precision :: k1
    k1 = f2(t, y, v)
    nextv = v + h * k1
  end function nextv
end program ode

t_0=0,y_0=0,v_0=0,h=1e-3の場合の結果は、

   0.00000000   0.00000000   0.00000000   0.00000000   0.00000000
...snip
   1.00000000   4.89842176   4.90332508   9.80665016   9.80665016
...snip
   2.00000000  19.60349367  19.61330032  19.61330032  19.61330032

であり、落下距離の真値との誤差は、
初期時刻からの経過時間が1[s]で-0.00490[m]、2[s]で-0.00981[m]となり、
経過時間に比例していることが分かる。
また、刻み幅を半分にしたt_0=0,y_0=0,v_0=0,h=5e-4の場合、

   0.00000000   0.00000000   0.00000000   0.00000000   0.00000000
...snip
   1.00000000   4.90087342   4.90332508   9.80665016   9.80665016
...snip
   2.00000000  19.60839700  19.61330032  19.61330032  19.61330032

誤差は経過時間1[s]で-0.00245[m]、2[s]で-0.00490[m]となり、
同一時刻で刻み幅に比例した大きさとなっている。