プログラム forward.cに 注釈をつけながら説明する。 Fortran、 Pascalの例文も同じ考え方で作ってある。
ここでは、z (時刻 t+Δtでの変数Zの値)と、 zold (時刻 t での変数Zの値)を 別々の(Cなどの言語の立場での)変数にしてみた。 前方差分だけに限れば、この2つを同じ変数にしてしまっても問題ない (なぜか考えてみよう)。しかし、後方差分その他への変更のしやすさを考えて、 区別しておくことにする。
/*
Simple decay
dZ/dt = aZ
by forward difference
written by K. Masuda, 1994-05-23, 1996-05-29, 1996-06-03
*/
*コンパイラとともに用意されたヘッダファイルのとりこみ
(printfなどを使う準備)
#include
(expなどを使う準備)
#include
int main(){
*変数の宣言。
変数はすべて宣言する。
実数型変数は、倍精度を使うことにする。
double a, deltat, t, tzero,
z, zold, zzero, ztrue;
int kt, nt;
*以下実行部。
*以下はC文法上は変数への代入文だが、実質的には定数を与えている。
(注意: C言語では実数型定数は特に指定しなくても倍精度となる。)
. 方程式の係数 a
a = -1.0;
. 時間発展の開始時刻
tzero = 0.0;
. Zの初期値 (時刻 tzero での値)
zzero = 1.0;
. 時間ステップ (解析解では結果の出力間隔)
deltat = 0.1;
. 終了までの時間ステップ数
nt = 100;
*対象とする問題や計算の条件を示す定数の値を書き出しておく。
gnuplotでコメント扱いするため、各行の頭に「#」を入れている。
printf関数のカッコの中の1つめの文字列の中に含まれた「%」で始まる
文字列は、書式指定である。%20.10lfの20は数値を表わす全体の桁数、
10は小数部の桁数を示す。
printf("#Problem dZ/dt = aZ\n");
printf("#Forward difference\n");
printf("# a %20.10lf\n",a);
printf("# tzero %20.10lf\n",tzero);
printf("# zzero %20.10lf\n",zzero);
printf("#deltat %20.10lf\n",deltat);
printf("# nt %20d\n",nt);
printf("#tfinal %20.10lf\n",tzero+nt*deltat);
*シミュレーションの最初の時刻(tzero)での変数の値(初期値)の設定と出力。
t = tzero;
z = zzero;
ztrue = zzero;
. 各列の見出しも、「#」つきで書き出しておく。
printf("# time simulated true\n");
printf("%20.10lf%20.10lf%20.10lf\n", t, z, ztrue);
. 時刻 Δt での計算の準備として、z の値を zold に入れる
zold = z;
*時間発展の計算。ステップ数 nt だけ、ループ内容を繰り返す。
for(kt = 1; kt <= nt; kt++)
{
. これから計算する時刻
t = tzero + kt * deltat;
. これが前方差分の1ステップの計算
z = zold + deltat * a * zold;
. この問題は真の解がわかっているので計算しておく
ztrue = zzero * exp( a * (t - tzero) );
. 値を書き出す
printf("%20.10lf%20.10lf%20.10lf\n", t, z, ztrue);
. 時刻 t (次のステップでは時刻 t - Δt になる)の z の値を zold に入れる
zold = z;
}
*終わり。
}