プログラム forward.pに 注釈をつけながら説明する。 Fortran、 Cの例文も同じ考え方で作ってある。 ただし、このプログラムは 1996年度東京都立大学ワークステーション教室のDEC Pascalで動作を 確認したが、他の機種やコンパイラでは変更が必要かもしれない。
ここでは、z (時刻 t+Δtでの変数Zの値)と、 zold (時刻 t での変数Zの値)を 別々の(Pascalなどの言語の立場での)変数にしてみた。 前方差分だけに限れば、この2つを同じ変数にしてしまっても問題ない (なぜか考えてみよう)。しかし、後方差分その他への変更のしやすさを考えて、 区別しておくことにする。
PROGRAM decay(output); { Simple decay dZ/dt = aZ by forward difference written by K. Masuda, 1994-05-31, revised 1995-04-26, 1996-06-03 } *まず変数の宣言。 Pascalでは、変数はすべて宣言する。 VAR a, deltat, t, tzero, z, zold, zzero, ztrue: DOUBLE; 実数型変数はいずれも倍精度で宣言した。 kt, nt: INTEGER; *以下実行部。 BEGIN *以下はPascal文法上は変数への代入文だが、実質的には定数を与えている。 (注意: 定数のあとについている「d0」は、倍精度の定数であることを示す DEC Pascalコンパイラでの約束である。Pascal言語一般に通用するものでは ない。DEC Pascalでは、これをつけないと、単精度の定数になってしまう。) . 方程式の係数 a a := -1.0d0; . 時間発展の開始時刻 tzero := 0.0d0; . Zの初期値 (時刻 tzero での値) zzero := 1.0d0; . 時間ステップ (解析解では結果の出力間隔) deltat := 0.1d0; . 終了までの時間ステップ数 nt := 100; *対象とする問題や計算の条件を示す定数の値を書き出しておく。 gnuplotでコメント扱いするため、各行の頭に「#」を入れている。 writeln手続きのカッコの中は、いずれも書き出す変数あるいは定数である。 なお、数値の後にコロンでくぎってつけてある数字は、書式指定で、 1つめは数値を表わす全体の桁数、2つめは小数部の桁数を示す。 writeln( '#', 'Problem dZ/dt = aZ'); writeln( '#', 'Forward difference'); writeln( '#', 'a ',' ', a:20:10 ); writeln( '#', 'tzero ',' ', tzero:20:10 ); writeln( '#', 'zzero ',' ', zzero:20:10 ); writeln( '#', 'deltat',' ',deltat:20:10 ); writeln( '#', 'nt ',' ', nt:20 ); writeln( '#', 'tfinal',' ',(tzero+nt*deltat):20:10 ); *シミュレーションの最初の時刻(tzero)での変数の値(初期値)の設定と出力。 t := tzero; z := zzero; ztrue := zzero; . 各列の見出しも、「#」つきで書き出しておく。 writeln( '#','time ', 'simulated ', 'true ' ); writeln( ' ', t:20:10, z:20:10, ztrue:20:10 ); . 時刻 Δt での計算の準備として、z の値を zold に入れる zold := z; *時間発展の計算。ステップ数 nt だけ、ループ内容を繰り返す。 FOR kt := 1 TO nt DO BEGIN . これから計算する時刻 t := tzero + kt * deltat; . これが前方差分の1ステップの計算 z := zold + deltat * a * zold; . この問題は真の解がわかっているので計算しておく ztrue := zzero * exp( a * (t - tzero) ); . 値を書き出す writeln( ' ', t:20:10, z:20:10, ztrue:20:10 ); . 時刻 t (次のステップでは時刻 t - Δt になる)の z の値を zold に入れる zold := z; END; *終わり。 END.