式としては以下の様な常微分方程式である. $$ \left\{ \begin{array}{rcl} \displaystyle \frac{d u}{dt} & = & \sigma (-u + v), \\ \displaystyle \frac{d v}{dt} & = & u (-w + r) - v, \\ \displaystyle \frac{d w}{dt} & = & u v - b w . \end{array} \right. $$
ただし、パラメータ(ザルツマンのパラメータ)は、 $ \sigma = 10, $ $ r = 28, $ $ b = 8/3 . $
const σ, r, b = 10, 28, 8/3 # まずパラメータを設定してしまおう. 定数の場合、const を宣言しておくと参照が速い!
方程式の右辺を定義してしまおう.
function f(U)
(u, v, w) = U # こうやって成分毎に受け取ることも出来る.
return [
σ * (-u + v)
u * (- w + r) - v
u*v - b*w
]
end
Runge-Kutta 法による時間発展も、定義してしまおう.
Δt = 0.01
function RK(U)
f1 = f(U)
f2 = f(U + Δt/2 * f1)
f3 = f(U + Δt/2 * f2)
f4 = f(U + Δt * f3)
return U + Δt * (f1 + 2*f2 + 2*f3 + f4)/6
end
初期値を適当に用意する
U0 = [1.0, 1, 1]
早速、計算してみよう
U = copy(U0)
sq_U = copy(U0)
for i in 1:3000
U = RK(U)
sq_U = hcat(sq_U, U)
end
試しに結果の数字をちょろっと見てみる.
sq_U
あまり変なことにはなっていなさそうなので、プロットしてみよう.
using Plots
gr()
plot(sq_U', fmt = :png) # 描画点が多く、web browser に負荷が大きいので、画像形式を png にして負荷を下げよう
ふ~む、少しわかりにくい挙動だな.では、相図にして見てみよう.
X, Y, Z = sq_U[1,:], sq_U[2,:], sq_U[3,:]
plot(X, Y, Z, fmt = :png)
これは有名なバタフライ図というやつだな. 大きく分けて二つの状態を行き来していることが相図から見て取れる.
問題は、その状態間を行き来する条件が微妙そうなことだ. それが初期値の微妙な差の影響をどれだけ受けるか、ちょっと試してみよう.
そこで、初期値をいれたら解を出力する形で関数を作ろう. ちなみに、上の数値解をみると v(t) をみるとわかりやすそうなので、出力は v(t) だけでいいかな.
function v_out(init_U, N) # 初期値とステップ数だけを与えれば良いとしよう.
U = copy(init_U)
sq_U = copy(init_U)
for i in 1:N
U = RK(U)
sq_U = hcat(sq_U, U)
end
return sq_U[2,:] # v の数値近似解のみを出力、でいいかな.
end
ではまず、先の結果をあらためて.
result0 = v_out(U0,3000) # 初期値を U0, ステップ数 3000 での、v の数値解全体.
次に、初期値を少しだけ変えてみよう.
U1 = U0 + [0,0,0.01] # 初期値の第3成分を 1% だけ変えてみる.
result1 = v_out(U1, 3000) # そして、この初期値のもとでやはり 3000ステップほど計算.
result0 と result1 は数字を見る限り、あとの方ではかなり異なるようだ. そうしたことを、プロットを通じて見てみよう.
plot( [result0 result1] , fmt = :png) # matrix 形式で渡せば、同時にプロットしてくれる.
どうやら、1600ステップあたりからズレがはっきりと出て、その後の挙動はお互いに似ても似つかない ことが見て取れる.
この二つの出力の関係性のなさ、を、次のプロットを通して感じ取ってみよう.
plot( result0, result1, fmt = :png ) # 横軸を result0, 縦軸を result 1 としている.
上のプロットから横軸と縦軸の関係性が「読み取れれば」お互いの相関は強いし、「読み取れなければ」相関は薄い、ということになるのは直感的に分かるだろう.さて、上のプロットはどちらを示しているだろうか.
result2 = v_out(U0 + [0,0,0.001], 3000) # やりかたは同じ.
先に関係性をみてみよう
plot( result0, result2, fmt = :png)
どうやらこれでも、少し先へ行くと出力の関係性が失われるようだ. 念のため、時系列プロットもしてみよう.
plot( [result0, result2] , fmt = :png )
どうやら、1750 ステップあたりで関係性が切れているようだ.
result3 = v_out( U0 + [0,0,0.0001], 3000)
plot(result0, result3, fmt = :png)
ふ~む、やはり関係性が失われるようだ.
plot( [result0, result3], fmt = :png )
時系列データのプロットからもそれはみてとれる.この場合、2200ステップぐらいで関係性を喪失するようだ.
result4 = v_out( U0 + [0,0,0.0000001], 3000)
plot( result0, result4, fmt = :png )
やはり関係性は失われる.図がさっぱりしているのは、関係性が失われる時刻が遅いからだろう.
plot( [result0, result4], fmt = :png )
やはり、関係性が失われる時刻がだいぶ遅い.とはいえ、その後はもう全然関係ないと言って良い感じだ.
上の例で、初期値の差の小ささと、解の関係性が失われるまでの時間には、正の相関がありそうだ. つまり、初期値の差が小さくなればなるほど、解の関係性が失われるまでの時間は長くなる、ということだ.
そこで、この二つの量を大雑把にで良いので計測し、グラフを描いて、どういう関係があるのか、その関係式を推測してみよう.