juliaでルンゲクッタ法を実装してローレンツアトラクタを描画してみた

julia

juliaでルンゲクッタ法を実装して、ローレンツアトラクタを描画してみました。

ルンゲクッタ法の解説については、以前rustで実装したので、そちらをご覧ください

Rustで作ったルンゲクッタ法のソースコードをそのまま、juliaに移植した感じです。

今回は、1階3連立の常微分方程式を計算するようにしたので、ソースは長く見えますが、同じことの繰り返しをしているだけです。

4次のルンゲクッタ法のアルゴリズム

juliaの4次のルンゲクッタ法(Runge-Kutta)のアルゴリズムこんな感じです。

$$
\begin{eqnarray}
&&y’=f(t,y),y(t_0)=y_0\\
&&y_{n+1}=y_n+\frac{h}{6}(k_1+2k_2+2k_3+k_4)\\
&&t_{n+1}=t_n+h\\
\\
&&k_1=f(t_n,y_n) \cr
&&k_2=f(t_n+\frac{h}{2},y_n+\frac{h}{2}k_1)\cr
&&k_3=f(t_n=\frac{h}{2},y_n+\frac{h}{2}k_3)\cr
&&k_4=f(t_n+h,y_n+hk_3)
\end{eqnarray}
$$

これをjuliaのソースコードに起こし込んでいきます。

function rk4(t,x,y,z,h)
    k1x = fx(t, x, y, z) * h
    k1y = fy(t, x, y, z) * h
    k1z = fz(t, x, y, z) * h
    k2x = fx(t + 0.5 * h,x + 0.5 * k1x,y + 0.5 * k1y,z + 0.5 * k1z) * h
    k2y = fy(t + 0.5 * h,x + 0.5 * k1x,y + 0.5 * k1y,z + 0.5 * k1z) * h
    k2z = fz(t + 0.5 * h,x + 0.5 * k1x,y + 0.5 * k1y,z + 0.5 * k1z) * h
    k3x = fx(t + 0.5 * h,x + 0.5 * k2x,y + 0.5 * k2y,z + 0.5 * k2z) * h
    k3y = fy(t + 0.5 * h,x + 0.5 * k2x,y + 0.5 * k2y,z + 0.5 * k2z) * h
    k3z = fz(t + 0.5 * h,x + 0.5 * k2x,y + 0.5 * k2y,z + 0.5 * k2z) * h
    k4x = fx(t + h, x + k3x, y + k3y, z + k3z) * h
    k4y = fx(t + h, x + k3x, y + k3y, z + k3z) * h
    k4z = fz(t + h, x + k3x, y + k3y, z + k3z) * h
    nx = x + (k1x + 2.0 * k2x + 2.0 * k3x + k4x) / 6.0
    ny = y + (k1y + 2.0 * k2y + 2.0 * k3y + k4y) / 6.0
    nz = z + (k1z + 2.0 * k2z + 2.0 * k3z + k4z) / 6.0
    return nx,ny,nz
end

ローレンツ方程式は次のように与えます。

function fx(t,x,y,z)
    a*(-x+y)
end
function fy(t,x,y,z)
    -x*z+b*x-y
end
function fz(t,x,y,z)
    x*y-z*c
end

ローレンツ方程式を計算していく

ルンゲクッタ法のアルゴリズムとローレンツ方程式を実装できたので、これを計算してきます。

計算を実行する関数を作る

計算する関数を作ります。

nが回数、dが刻み幅、icが初期条件

function rungekutta(n,d,ic)
    t=0.0
    x0,y0,z0=ic
    x=[x0]
    y=[y0]
    z=[z0]
    for i=1:n
        nx,ny,nz = rk4(t,x[i],y[i],z[i],d)
        push!(x,nx)
        push!(y,ny)
        push!(z,nz)
        t=t+delta
    end
    return x,y,z
end

forループを使って、繰り返し計算して、結果をそれぞれ収納していきます。

実際に計算する

係数をa=10,b=28,c=8/3として、初期値をx=1.1,y=0.5,z=0.5とします。

刻み幅を0.001、計算回数を100,000回としましょう

using Plots
a = 10.0
b=28.0
c =8/3

function main()
    ic = (1.1,0.5,0.5)
    x,y,z =rungekutta(100000,0.001,ic)
    plot(x,y,z)

end

これで、main関数を実行すると、計算を実行して、グラフ描画してくれます。

描画する

描画は今回は、Plots.jlを使って描画してます。

まとめ

今回は、juliaで4次のルンゲクッタ法のアルゴリズムを実装して、ローレンツ方程式を計算して、描画してみました。精度よく、計算できているんじゃないでしょうか?

juliaには、DifferentialEquations.jlっていう常微分方程式を計算するパッケージがあります。これを使うと結構簡単に計算することができます。

今回プログラムは50行ぐらい書きましたが、パッケージを使えば15行ぐらいのソースで計算できます。

自分で実装してみるのは、向学のためにはいいのかななんて(笑)

コメント

タイトルとURLをコピーしました