フォートランにはデフォルトでいくつかの関数が用意されているが,ユーザー が独自に関数を定義して用いたい場合は「関数副プログラム」というものをつかって関数を定義することが出来る.使い方は
t function f(a1,a2,....aN) ...... f=..... return end
function文 | f=.... | 関数副プログラムの定義をおこなう |
t | 型宣言:real*8, integerなど |
---|---|
a1,a2,...aN | 仮引数:型宣言をすること |
b=f(c1,c2,....cn)のように引数を代入して行う.
たとえば, 1からnまでの総和を求める関数副プログラムは
integer function souwa(n) implicit none integer i,n souwa=0 do i=1,n souwa=souwa+i enddo return end implicit none integer souwa,n read(5,*) n write(6,*) souwa(n) end
注意点
n!を計算する関数副プログラム fact(n)を作成せよ.
オイラー法における誤差はΔtに比例する(一ステップの誤差はΔtの二乗に比例するため:これはなぜか?).すなわち誤差を10分の1にしたければΔtを1/10にする必要がある.これは計算にかかる時間が10倍になることを意味する.これでは時間がかかってしょうがない.そこでΔtの2乗,4乗に誤差が比例するようなアルゴリズムが存在する.4乗に比例するものはルンゲクッタ法と呼ばれ広く用いられている.
ルンゲクッタ法に入る前に誤差がΔtの2乗に比例するアルゴリズムについて考えてみよう.
![]() |
(1) |
という微分方程式が与えられたものとする.タイムステップがΔtのとき,n+1ステップ目のyの値yn+1は,ynを用いて
![]() |
(2) |
と書くことができる.ここでy''は二次の微係数で
![]() |
(3) |
となる.2項出てくることに注意.これを用いると先ほどの式は
![]() |
(4) |
のようにかきかえられる.ここでポイントは,我々はft,fyを知らないと言うことである.なので別の式でさらに書き替えないといけない.そのため式(8)が,以下のように書けるものと仮定する.
![]() |
(5) |
ここでf1,f2は
![]() |
![]() |
![]() |
(6) |
![]() |
![]() |
![]() |
(7) |
である.f2の中身に注意.f1,f2はそれぞれtnでの傾き,および傾きk1でΔt秒進んだとしたときのt+Δt秒後の傾きを表す.この二つの傾きを適当に重ね合わせることによりΔtの二乗の精度にすることができる.(11)式をテーラー展開すると,λ1,λ2,α,βの間の関係式が
![]() |
![]() |
![]() |
(8) |
![]() |
![]() |
![]() |
(9) |
![]() |
![]() |
![]() |
(10) |
と求めることができる.求めるべき数が4つあるのに式が3つしか存在しない.なのでいろいろな値の組み合わせが
![]() |
(11) |
![]() |
(12) |
といったようにありうる.いずれの場合も二次の精度まで正しく計算できる.つまり一ステップの誤差はΔtの3乗に比例する. 今回は(11)式を採用し,以下の(13)-(15)式で積分を行う.
![]() |
(13) |
![]() |
![]() |
![]() |
(14) |
![]() |
![]() |
![]() |
(15) |
式(13),(14),(15)を用いて先週の宿題を解け.オイラー法の場合と精度を比較せよ.
先ほどのアルゴリズムの誤差はΔtの二乗である.これを4乗に高めたのがルンゲクッタ法である.
さきほどと同じ考え方を使うと,ルンゲクッタ法のアルゴリズムは以下のようになる.
![]() |
(16) |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(17) |
式(16),(17)を用いて,ルンゲクッタ法を用いて先の例の積分を行え.3つの場合の誤差を比較せよ.
先ほどのルンゲクッタ法は多変数に拡張できる.例えば,x=x(t)とy=y(t)がそれぞれ
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(18) |
にしたがって進化する場合は,以下のようにアルゴリズムを組めばよい.
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(19) |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(20) |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(21) |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(22) |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(23) |
質点の投げ上げの数値シミュレーションを行う.今回解く方程式は以下の連立微分方程式となる.
![]() |
(24) |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
(25) |
式(25)で与えられる連立微分方程式を解け.g=1,t=0でx=0.D0, y=1.D0 とすること.Δt=1.D-2でt=2となるまで積分せよ.
gnuplotを用いて簡単なアニメーションを作ることができる.先ほどの練習問題5の結果を可視化しよう.連立微分方程式を解いた結果を,時間,0., x(座標) y(速度)と4つの数値を並べてファイルに書き出す.さらに,以下の内容でanim.txtというファイルを作成する.
CCCCCCCCCCCC この下からanim.txt CCCCCCCCCCCCCCCCCCCset xrange [-1:1] set yrange [0:1] if (n>200) exit plot "ファイル名" using 2:3 every 1:1:n:0:n:0 with points pt 7 ps 2 pause 0.05 n=n+1 rereadCCCCCCCCCCCC この上までanim.txt CCCCCCCCCCCCCCCCCCC
gnuplotを起動し,以下のコマンドによってアニメーションを見ることができる.
gnuplot> n=1 gnuplot> load 'anim.txt'
アニメが観察できたら,初速(y)を変化させて行ってみる.t=0で y=1.45 としたらどうなるだろうか?