【注: この行のように【】でかこまれた段落は脚注のようなものです。】
空間分布をもつ量の時間発展を考える必要がある問題がある。 そのなかで比較的簡単な例として、ここでは、 「量 q の流れが、量 q の空間微分(傾き、勾配)に比例する」 という問題を考えてみよう。 量を物質の濃度としたとき、これは拡散問題である。 量を温度としたとき、これは熱伝導問題である。
【温度の流れというのは無理があるが、エネルギーが「温度×熱容量」 (熱容量は定数)と書けるとし、エネルギーの流れを考えるのである。 なお、温度はふつう T と書くが、Fortran では T と t の区別が つかないので、変数名として T は避けることにし、 ここでは温度も q としておく。】
式の上では偏微分方程式というものになるが、こわがらないでほしい。
話を簡単にするために、q は、y 方向、z 方向にはどこまで行っても 変わらないとしよう。そうすると、x 方向の流れと傾きだけを考えればよい。 これが、空間1次元の拡散問題である。 建物の壁を通しての熱伝導を考えるとよいだろう。
ある面の単位断面積あたり、単位時間あたりに q が通過する量を、 q のフラックス密度(flux density)という。 ここでは、xの正の方向に向かうフラックス密度を F と書いておく。 Fが、q の空間微分に比例するということは、
F = - κ ∂q/∂x ... (1)
のように書くことができる。ここで、「∂」は偏微分記号である。 今の例では、qは空間座標xと時間tの関数q(x,t)だと考えている。 この場合、 tの値を固定してxだけを変化させた場合のxによる微分を「xによる偏微分」といい、 ∂q/∂xのように書く。 xの値を固定してtだけを変化させた場合のtによる微分を「tによる偏微分」といい、 ∂q/∂tのように書く。 (もっと一般的には、数量は3次元の空間座標と時刻の関数だと考えることが多い。 ただし、 とくに気象の場合は鉛直座標として高さ、気圧などなん通りもの量が使われるので、 偏微分を使う場合は、数量が何の関数であるのかを明示してから話を始める 必要がある。)
q の大きいほうから小さいほうへqが動くのがふつうなので、κが正になる ように、負の符号をつけた。κを拡散係数という。 SI(国際)単位を採用する場合には、 時間の単位は秒、長さの単位は m なので、 拡散係数の単位は m2 / s である。 対象によっては、これと違う時間や長さの単位を使ったほうが計算につごうが よい場合もある。その場合も、 拡散係数の単位は「(長さの単位)2/(時間の単位)」である。
Fe = - k ∂T/∂x ... (2)
Fe = c ρ FT ... (3)
FT = - κ ∂T/∂x ... (4)
【また、流体の運動に関する動粘性係数は、運動量の拡散係数に相当する。】
ところで、Fだけがqの時間変化の原因であるとすると、qの時間変化は どのように書くことができるだろうか。 幅 Δx、Δy、Δz の箱をとって考えてみる。 x方向の両端の座標を、x, x+Δxとする。 箱の中の q の総量は、およそ q Δx Δy Δz である。 箱の壁を通しての、時間Δtの間の q の出入りは、およそ { - F(x+Δx) + F(x) } Δy Δz Δt である。
{q(t+Δt) - q(t)} Δx Δy Δz = { - F(x+Δx) + F(x) } Δy Δz Δt
{q(t+Δt) - q(t)}/Δt = -{F(x+Δx) - F(x)}/Δx
Δt → 0, Δx → 0 とすれば、
∂q/∂t = -∂F/∂x ... (5)
(1)と(5)を組み合わせて F を消すと
∂q/∂t = κ ∂2q/∂x2 ... (6)
∂q/∂t = ∂/∂x { κ ∂q/∂x } ... (7)
この問題の答えを具体的に求めるためには、 t = 0 での各空間点でのqの値(初期条件)のほかに、 t > 0 での領域の両端の q に関するなんらかの条件(境界条件)が必要である。 その一例としては、常に、
微分方程式(6)を差分近似してシミュレーションを行なう。 「前方差分」その他の差分法の用語に関する教材は [別ページ]参照。
拡散問題は減衰問題に似ているので、時間に関して中央差分を使うのは 危険である。ここでは前方差分を使う場合を例に示す。 つまり、dq/dtを
{q(x, t+Δt) - q(x, t)}/Δt
空間に関しては、x方向に順次積分するわけではないし、 xの正・負の両方向を公平に扱うのが望ましいので、中央差分をとる。 1階差分をすなおにとると(ここで時刻はtで固定するので関数のtへの依存性は省略して書く)、
{q(x+Δx) - q(x-Δx)}/2Δx
{q(x+Δx/2) - q(x-Δx/2)}/Δx = QX(x) [と臨時に名づける]
{QX(x+Δx/2) - QX(x-Δx/2)}Δx = {q(x+Δx) - 2 q(x) + q(x-Δx)}/(Δx)2
以上の考え方をプログラムにしたものを用意した。
Unix用(改行コードLFのみ) | Windows用(改行コードCRLF) | ||
---|---|---|---|
時間発展シミュレーション | Fortran | kakusan.f |
kakusan.f |
C | kakusan.c |
kakusan.c | |
Pascal | kakusan.p |
kakusan.p |
kappa = 1.0e-6 拡散係数、単位例 m2 / s deltat = 25.0 時間間隔 s deltax = 0.01 空間間隔 m nt = 100 時間ステップ数
q0 = 20.0 q1 = 30.0
また、初期条件は、領域全体でq1
と同じ値とした。
(ただし、x = 0
の壁では境界条件を優先することにした。)
たとえば、へやの外の気温が 30℃で、中の気温をある時刻から 20℃に
たもつことができたと仮定したとき、
厚さ10 cmの中の温度分布を求める問題と考えてもよいだろう。
また、実際に求めたいのは温度分布よりも
壁を通じての熱伝導による熱フラックス密度(時間あたり、面積あたりに通過
するエネルギー量)かもしれないが、このプログラムでは直接にそれを求めて
はいない。
REAL*8 q(0:nx)
nx
は、上でPARAMETER (nx=10)
nx
を変数にすると、Fortranコンパイラは、
配列のための記憶領域をどれだけとったらよいのかわからないので、
コンパイルすることができない。直接REAL*8 q(0:10)
プログラムの実行方法(FortranまたはCの場合)は次のようになる。
ただし、kakusan.txt
は計算結果を書き出すファイル名の例である。
(Windows上では「./a.out
」のところは 「./a
」とすればよいはず。)
例文の左端の「%
」は、OS (シェル)の出すプロンプト文字を代表させたもので、
たとえば「bash$
」かもしれない。
ユーザーが打ちこむ文字には含まれない。
% g77 kakusan.f % ./a.out > kakusan.txt
% gcc kakusan.c -lm % ./a.out > kakusan.txt
実行できたら、
プログラムを編集し、
拡散係数kappa
, 空間間隔deltax
,
時間間隔deltat
, 時間ステップ数nt
などを
書き変えて動かしてみてほしい。
(deltat
をある程度大きくすると結果が拡散問題に対応しなくなると思う。)
境界条件を変えてみるのもよいだろう。
結果を比較したい場合は、出力ファイル名をうまくつけて区別してほしい。
数値モデルの計算結果は、大量の数値になることが多い。 結果が正しく数値と読める形で出力されているかどうかという意味では 数字を目で見て確かめる必要もある。 (数値と読めない形になってしまう例だが、 Fortranでは、計算の結果の桁数が多すぎて決められた書式におさまらない ときは、「*****」のような形で表示される。)
多くの数値を目で見て確認するために、図にしてみることがよく行なわれる。 今の問題は、空間1次元だが、時間を合わせると2次元であり、 計算結果は2次元時空間に分布するデータとして見ることもできる。 [別ページ]の図は、 上記とほぼ同じだが、数量の桁が大きく違う(ほか細かい違いもある)例文の計算結果の 等値線表示(横軸が時間、縦軸が空間)である。 作図したソフトウェアは、 1993-1996年度に増田が都立大学で作った グラフィックス(GKS)の教材である。
gnuplot
による作図プログラム例を次のように用意した。
Unix用(改行コードLFのみ) | Windows用(改行コードCRLF) | ||
---|---|---|---|
作図 (gnuplot) | 時間変化グラフ | kakusan_time.gplt |
kakusan_time.gplt |
時間・空間(x)等値線 | kakusan_cont.gplt |
kakusan_cont.gplt | |
空間(x)分布グラフ | kakusan_x.gplt |
kakusan_x.gplt | |
出力データの形式変更 (Awk) | 等値線用 | kakusan_txv.awk |
kakusan_txv.awk |
空間(x)分布グラフ用 | kakusan_txv_sepa.awk |
kakusan_txv_sepa.awk |
kakusan.{c,f,p}の出力形式は、gnuplotで
いろいろな深さの温度の時間発展のグラフを作るのに便利なようにしてある。
gnuplotの中で
gnuplot> plot "kakusan.txt" using 1:2, "kakusan.txt" using 1:5
q
(温度)の時間変化が同じ図に表示されるはずである。
(「gnuplot>
」はgnuplotが出すプロンプトであり、
ユーザーが打ちこむ文字には含まれない。)
また、例として用意したgnuplot用のスクリプト(コマンド群)ファイル
kakusan_time.gplt
を次のような形で呼び出せば、
多数の位置の温度変化をいっしょにグラフにできるようにしてある。gnuplot> load "kakusan_time.gplt"
kakusan.txt
に固定してある。
複数のシミュレーションを比較する場合は、
スクリプトファイルを編集して使ってほしい。kakusan.txt
を読んでこの形式に変換するプログラム
kakusan_txv.awk
を用意した。
次のようにして実行する。 % gawk -f kakusan_txv.awk kakusan.txt > kakusan_txv.txt
kakusan_txv.txt
で固定しているが
必要に応じて変更してほしい。
"unset surface
" などの指定は、
gnuplotのバージョンによっては "set nosurface
"などの形に変える
必要があるかもしれない。gnuplot> load "kakusan_cont.gplt"
kakusan_txv.txt
から分ける方法もあるが、
ここでは、kakusan.txt
から組みかえるプログラム
kakusan_txv_sepa.awk
を用意した。
ただし、作図に必要な時間ステップについてファイルを作ったほうがよいので、
時間間隔をinterval
で指定するようにした。
書き出されるのは、時刻の値がinterval
で割り切れる場合に限る。
例として、tの間隔500ごとに書き出すことにしてみる。
% gawk -v interval=500 -f kakusan_txv_sepa.awk kakusan.txt
kakusan_500.0.txt
などの複数のファイルができる。
それをgnuplotで次のようにして作図することができる。gnuplot> load "kakusan_x.gplt"
set style data
" の指定は、
gnuplotのバージョンによっては "set data style
"の形に変える
必要があるかもしれない。今回の教材用のAwkプログラムは、
ここで作成したkakusan.txt
の
時間ステップ、数値の桁数、空間座標値の記録のしかた
などに対応するように作ったものであり、汎用的ではない。
他のデータに適用する際にはあちこち変更が必要になると思う。
実際、地中熱伝導の例に適用する場合は
基本的に同じプログラムを細かく調整した。