時間発展問題の数値計算

減衰問題への前方差分の適用: Fortranによる例文

プログラム forward.f に注釈をつけながら説明する。 PascalCの例文も同じ考え方で作ってある。

ここでは、z (時刻 t+Δtでの変数Zの値)と、 zold (時刻 t での変数Zの値)を 別々の(Fortranなどの言語の立場での)変数にしてみた。 前方差分だけに限れば、この2つを同じ変数にしてしまっても問題ない (なぜか考えてみよう)。しかし、後方差分その他への変更のしやすさを考えて、 区別しておくことにする。

      PROGRAM decay
C
C Simple decay
C     dZ/dt = aZ
C by forward difference
C written by K. Masuda, 1994-05-23

*まず変数の宣言。
      IMPLICIT NONE
これは、変数はすべて宣言する、という指定である。つまり、宣言しない変数を
使うとコンパイル段階でエラーになるようにしておく。
      REAL*8   a, deltat, t, tzero,
     &         z, zold, zzero, ztrue
実数型変数はいずれも倍精度で宣言した。
      INTEGER  kt, nt

*以下はFortran文法上は変数への代入文だが、実質的には定数を与えている。
. 方程式の係数 a
      a      = -1.0d0
. 時間発展の開始時刻
      tzero  =  0.0d0
. Zの初期値 (時刻 tzero での値)
      zzero  =  1.0d0
. 時間ステップ (解析解では結果の出力間隔)
      deltat =  0.1d0
. 終了までの時間ステップ数
      nt     = 100

*対象とする問題や計算の条件を示す定数の値を書き出しておく。
  WRITE文のカッコの中
  . 1つめの要素はファイル参照番号(星印なら標準出力)。
  . 2つめは、FORMAT(=書式)文の番号(星印なら変数の型ごとに標準の書式を仮定)。
  gnuplotでコメント扱いするため、各行の頭に「#」を入れている。
  FORMAT文の要素 Aは文字型、Iは整数型、Fは実数型変数用の書式。
      WRITE (*,600) 'Problem dZ/dt = aZ'
      WRITE (*,600) 'Forward difference'
      WRITE (*,610) 'a',a
      WRITE (*,610) 'tzero',tzero
      WRITE (*,610) 'zzero',zzero
      WRITE (*,610) 'deltat',deltat
      WRITE (*,620) 'nt',nt
      WRITE (*,610) 'tfinal',tzero+nt*deltat
  600 FORMAT('#',A)
  610 FORMAT('#',A6,1X,F20.10)
  620 FORMAT('#',A6,1X,I20)

*シミュレーションの最初の時刻(tzero)での変数の値(初期値)の設定と出力。
      t = tzero
      z = zzero
      ztrue = zzero
. 各列の見出しも、「#」つきで書き出しておく。
      WRITE (*,700) 'time', 'simulated', 'true'
  700 FORMAT('#',3A20)
      WRITE (*,710) t, z, ztrue
  710 FORMAT(' ',3F20.10)
. 時刻 Δt での計算の準備として、z の値を zold に入れる
      zold = z

*時間発展の計算。ステップ数 nt だけ、ループ内容を繰り返す。
  DO..ENDDOは、Fortran77標準ではないが、90標準に含まれ、教室でも使える。
      DO kt = 1, nt
. これから計算する時刻
        t = tzero + kt * deltat
. これが前方差分の1ステップの計算
        z = zold + deltat * a * zold
. この問題は真の解がわかっているので計算しておく
        ztrue = zzero  * exp( a * (t - tzero) )
. 値を書き出す
        WRITE (*,710) t, z, ztrue
. 時刻 t (次のステップでは時刻 t - Δt になる)の z の値を zold に入れる
        zold = z
      END DO

*終わり。
      STOP
      END

ページ公開 2002年 (微修正 2015-06-13)
増田 耕一 (MASUDA Kooiti)
[減衰問題への前方差分、本文へ]