時間発展問題の数値計算

減衰問題への前方差分の適用

○ 趣旨

前に述べた減衰( a < 0 )または増大( a > 0 )現象を表わす微分方程式

d Z / d t = a Z
の数値解を差分で求め、グラフにしてみよう。

数値解の解析解(真の解)からの誤差の符号は、

で、それぞれどうなるか? [ 答を暗記する必要は全くない。実験してみる過程に意味がある。]

また、誤差、つまり「数値解 - 解析解」のグラフを作ってみよう。

○ プログラム例の実行

プログラムは、 forward.p, forward.f, forward.c である。 内容の説明は FortranPascalC、それぞれ別の記事に書く。 まず、例文のプログラムを自分のところにコピーして動かしてみよう。 また、Fortran の場合を例にあげるが、PascalやCでも同様である。)

まずforward.fを作業ディレクトリに持ってくる
(ファイル名は変えてもよいが、Fortranの場合 .f で終わるようにする)。
% f77 forward.f
% a.out
すると、端末に数値が表示されるはずである。 (このうち、「#」で始まる行は、数値計算の条件を設定するために与えた定数 [プログラム言語の立場では変数であるが、数値実験の立場ではパラメータ (parameter)という]の値を表示しているものである。 計算結果、数学的に求めた真の解[の、計算機の数値の精度の範囲での近似] である。)

ファイルに書いてあとで見るためには、

% a.out > forward.out
% less forward.out
などとすればよい。

(出力を書き出すファイルは単なるテキストファイルなので、 ファイル名はなんでもよいが、最後の部分がf, c, p, o, s, a, e, r, ps, tex などは、何かのプログラムで予約された意味があるので避けよう。 outはoutputの略で、forward.outは「forward.fの出したもの」のつもり。 もちろん、「a.out」という組み合わせだけは予約された意味があるので注意。)

○ gnuplotによる作図

出力結果をファイルにリダイレクト(redirect)して gnuplotでグラフ化してみよう。 gnuplotは、単に

% gnuplot
で起動する。 「gnuplot>」および、継続行の場合の「>」は gnuplotが出してくる プロンプトで、キーボードから入れる文字ではない。 終了は(「gnuplot>」プロンプトに対し) quit または exit である。

たとえば、次のようにすると、差分計算の結果を点のような記号で、真の解 (時間についてはサンプリングされたものだが)を線で表示するので、 両者の系統的なずれを見ることができる。「1:2」はデータの1列めを横軸、 2列めを縦軸にとって表示することを示している。

gnuplot> plot "forward.out" using 1:2 with points, \
>             "forward.out" using 1:3 with lines
gnuplot> quit

(注: 上の plot 文は、コンマのあと続けて2回めの "forward.out"を 書いてしまってもよい。その場合、「\」は不要。 「\」はバックスラッシュで、キーボードによっては「¥」になっている。 これは、gnuplotで一つのコマンドを複数行にまたがって書くときに、続きが あることを示している。 また、続きの行の頭の「>」はgnuplotが出してくるもので、 キーボードから入れる文字ではない。)

ここでは2つのデータが同じファイルにあったが、複数のファイルからのデータを いっしょにプロットする場合も、

plot "ファイル名1",  "ファイル名2", "ファイル名3" ...
のように、ダブルクォートでくくったファイル名を列挙すればよい。 同時に使えるファイル数の限度は、実際上、gnuplot内のコマンド行の長さに 制約され、経験によれば20個程度である。

その他、gnuplotの使い方に関しては 別記事参照。

○数値実験パラメータの変更

プログラムの中で、次の定数を、代入文の右辺に書いてある。 [プログラム言語の立場では左辺が変数、右辺が定数であり、 FortranのPARAMETER文は使っていないが、 数値実験の立場で、このようなものを実験のパラメータ(parameter)という]。

tzero  =  0.0d0  時間発展の開始時刻
deltat =  0.1d0  時間ステップ (解析解では結果の出力間隔)
nt     = 100     終了までの時間ステップ数
zzero  =  1.0d0  初期値
a      = -1.0d0  方程式の係数 a
この値をいろいろと変えて比較してみよう。
% cp forward.f  forw01.f
% mule forw01.f        編集開始(エディタの例としてmuleをあげている)

c-x c-s                保存 (muleのコマンド)
c-x c-c                muleの終了

% f77 forw01.f
% a.out > forw01.out   最後にコンパイルされたものが実行される
できれば、具体的(自然・社会科学的)問題と、量の次元や単位に注意して、 関連づけてみよう。

パラメータの値を、プログラム中に定数として書くと、 変更するたびにコンパイルしなおさなければならない。 ほんとうは、これらの値は、READ文で読むほうが望ましい。 しかし、READ文の前に、何を入れたらいいのか人に伝える(プロンプトを出す) WRITE文もほしくなる。ところが、画面に出すべきプロンプトと、ファイルに redirectすることが多い計算結果の出力の行き先を区別するためには、 標準入出力以外のファイルの読み書き あるいは 標準エラー出力 を使わなくてはならない。 ここではプログラムで使う入出力機能を標準入出力だけに限ることを優先し、 妥協として、定数はプログラム中に書く方針をとることにした。

○ プログラム作成のヒント .. 出力について

WRITE文の変数並びの変数の数はいくつでもよい。 ただし、書き出す変数並びと書式が対応している必要がある。 Fortranの場合で言えば、

        WRITE(*,710) t, z, ztrue
  710 FORMAT(' ',3F20.10)
        WRITE(*,710) t, z, ztrue, z-ztrue
  710 FORMAT(' ',4F20.10)
のように、write文とformat文を対応づけて変える。 上の例は、第4列に「誤差」の値を書き出すようにしたもので、
% a.out > forward.out2
と、ファイルに計算結果を書き出しておき、 gnuplotで
gnuplot> plot "forward.out2" using 1:4 with points
などという形で作図することができる。


1996-06-03; 2000-07-15; 2002-07-11; 2005-01-07
増田 耕一 (MASUDA Kooiti)
[目次へ]