『pythonで学ぶ流体力学の数値計算法』 Chapter 2-6をJuliaで
最終更新:2020/11/28
『pythonで学ぶ流体力学の数値計算法』 Chapter 2-6のコードを, 練習を兼ねてJuliaで書いてみました. 詳細なことを書くと著作権的にだめな気もするので, 詳しい解説などはありません.
Julia Version 1.5.0
Murman-Cole法
以下のBurgers方程式を解く.
\begin{align}
\frac{\partial q}{\partial t} + q\frac{\partial q}{\partial x} = 0
\end{align}
初期条件(函数init
)
\begin{align}
\mathrm{I.C.} \:\:q=
\begin{cases}q_{1} & x \lt 0\\ q_{2} & x \geq 0\end{cases}
\end{align}
保存型で表すと以下になる.
\begin{align}
\frac{\partial q}{\partial t} +
\frac{\partial}{\partial x} \left( \frac{1}{2}q^2 \right)= 0
\end{align}
Murman-Cole法では, これを以下のように離散化する. (函数do_computing
)
\begin{align}
q_{j}^{n+1} =
q_{j}^{n} - \frac{\Delta t}{\Delta x}
(\tilde{f}_{j+1/2}^{\,n} - \tilde{f}_{j-1/2}^{\,n}),
\end{align}
ここで, (函数MC
)
\begin{align}
\tilde{f}_{j+1/2}^{\,n} =
\begin{cases}
\frac{1}{2}q_{j}^2 & (q_{j}+q_{j+1})/2 \gt 0\\
\frac{1}{2}q_{j+1}^2 & (q_{j}+q_{j+1})/2 \leq 0
\end{cases}.
\end{align}
必要な函数群. 関数名を, 教科書と同じにした.
Julia
# 初期化函数 function init(q1, q2, Δx, jmax) xs = -1.0 x = collect(range(xs, xs+Δx*(jmax-1), length=jmax)) q = @. q1 * (x<0.0) + q2 * (x>=0.0) return x, q end # メイン関数 function do_computing(x, q, Δt, Δx, nmax, ff; order=1, interval=2) jmax = length(x) res = zeros(jmax, nmax) res[:, 1] = q for n in 2:nmax qold = q[:] for j in order+1:nmax-order-1 ff1 = ff(qold, Δt, Δx, j) ff2 = ff(qold, Δt, Δx, j-1) q[j] = qold[j] - (ff1-ff2)*Δt/Δx end res[:, n] = q end return res end # Murman-Cole法の数値流束 function MC(q, Δt, Δx, j) ur = q[j+1] ul = q[j] fr = 0.5*ur^2 fl = 0.5*ul^2 c = 0.5*(ur + ul) return 0.5*(fr + fl - sign(c)*(fr-fl)) end
プログラムの実行と結果.
Julia
# パラメータ q1 = 1.0; q2 = 0.0; Δt = 0.05; Δx = 0.1; nmax = 21; jmax = 21; # 実行 x, q = init(q1, q2, Δx, jmax) res = do_computing(x, q, Δt, Δx, nmax, MC) # 図示 pyplot(fmt=:svg, size=(400, 250)) plot(x, res[:, 1:5:end], labels=["t=0" "t=5" "t=10" "t=15" "t=20"], color_palette=palette([:red, :blue], 5)) xlabel!("x") ylabel!("q") PyPlot.savefig("img/2_6_1.png", dpi=300)
教科書と同じ結果担ったように見える.
様々な初期値
p.62 リスト2.13にある初期値を試してみる. 例えば, ケース1なら以下のパラメータを変えるだけ.
Julia
q1 = 2.0; q2 = 1.0; # 実行 x, q = init(q1, q2, Δx, jmax) res = do_computing(x, q, Δt, Δx, nmax, MC)
ケース1:\( q_{1}=2.0,\:q_{2}=1.0 \)
ケース2:\( q_{1}=1.0,\:q_{2}=2.0 \)
ケース3:\( q_{1}=1.0,\:q_{2}=-1.0 \)
ケース4:\( q_{1}=-1.0,\:q_{2}=1.0 \)
Godunov法
Godunov法を使って, ケース4を計算する. 新たに以下の数値流束を定義.
Julia
function GODUNOV(q, Δt, Δx, j) qm = 0.5 * (q[j] + abs(q[j])) qp = 0.5 * (q[j+1] - abs(q[j+1])) return max(0.5*qm^2, 0.5*qp^2) end
計算結果.
不連続がひろがっていく様子がわかる. これは, 物理的にも正しい現象である ( ということが解説されている ) . 前節のケース4の結果は, 数学的には正しいが, 物理的に実現する 現象ではない.
コード(click)
Juliaq1 = -1.0; q2 = 1.0; Δt = 0.05; Δx = 0.1; nmax = 21; jmax = 21; x, q = init(q1, q2, Δx, jmax) res = do_computing(x, q, Δt, Δx, nmax, GODUNOV) # 図示 pyplot(fmt=:svg, size=(400, 250)) plot(x, res[:, 1:2:11], labels=["t=0" "t=2" "t=4" "t=6" "t=8" "t=10"], color_palette=palette([:red, :blue], 6)) xlabel!("x") ylabel!("q") PyPlot.savefig("img/2_6_godunov.png", dpi=300)