この記事は著者が韓国語で書いた原文の翻訳です。 原文(한국어)を読む
[論文レビュー] GMRESが1000回回っても止まらなかった — 全速度 melt pool のための物理ベース・ブロック前処理
固有値が1に集まるのは厳密なSchur補元のときだけです。AMGでSを粗く解くと外側の反復が再び開きます。
レーザーで金属を溶かす melt pool を陰的に回しました。最初のタイムステップで GMRES が 1000 回回っても、残差は 1e-2 に張り付いたままです。Mach を 1e-3 に下げると音速は流速の 1000 倍になります。ヤコビアンはその比で病みました。Weston・Nourgaliev・Delplanque・Barker(2019)は、速度–圧力 Schur 補元を前処理にしてこの停滞を解きました。今日はその前処理を 2 場の toy に移し、Mach を変えても反復数がどこに張り付くかを記録します。
Mach スライダーを下げると、上のトラックの音響波だけが で速くなり、下の対流トレーサは のままです。
では音響波がトラックを 100 周する間に、トレーサは一目盛りしか動きません。 では比が 1000:1 です。残差が 1e-2 に張り付いた夜と同じ隙間です。
この論文が立つ場所
- 著者: B. Weston, R. Nourgaliev, J.-P. Delplanque, A. T. Barker (LLNL / UC Davis)
- ジャーナル: Journal of Computational Physics, 397, 108847 (2019)
- タイトル: Preconditioning a Newton-Krylov solver for all-speed melt pool flow physics
- 一言: 相変化を含む全速度(all-speed)圧縮性 Navier–Stokes を完全陰的 JFNK で解き、原始変数ブロック Schur 補元前処理で低 Mach の剛性を抑える。
既存の前処理 — element-block SOR、monolithic AMG、block Gauss–Seidel — はいずれも、タイムステップや Mach が極端になると反復数が爆発しました。論文が出したのは vP-vT Schur 補元です。物理結合のブロックの形を、前処理行列へそのまま移したものです。
M がゼロに向かうとヤコビアンが病む理由#
全速度とは、一つのコードで非圧縮()から超音速までを解くことです。問題は低 Mach 極限です。音響波速度 と流速 の比が と広がります。 なら、音は流体より 1000 倍速いのです。
完全陰的にすると、この二つのスケールが一つのヤコビアンに混ざります。圧力–速度結合ブロックが で大きくなり、行列の条件数が爆発します。Krylov ソルバーは固有値が広く散らばった行列の上で這うように進みます。これが GMRES の止まらなかった理由です。
コードの四点に を置くと がすぐ出ます。 なら 。 なら 。 なら 。 なら です。圧力–速度ブロックの一マスが百万倍になります。格子数は 、間隔は で四つの場合とも同じです。行列の大きさも のままです。変わるのは を掛けたスペクトルだけです。
音響 CFL で時間刻みを絞ると です。 を 1 から に下げると、許される刻みは 1000 分の 1 になります。完全陰的はその制限を外し、代わりに条件数を へ渡します。同じ剛性を前処理が逆に増やした場所は、音速 CFL 10 のブロック前処理に別に書いてあります。
JFNK(Jacobian-Free Newton–Krylov)はヤコビアンを陽に作らず、行列–ベクトル積だけを Fréchet 差分で近似します。
は非線形残差、 は Krylov ベクトル、 は小さな有限数です。行列を保存しないのでメモリは減ります。前処理が無いと、低 Mach ではその差分が散らばった固有値の上をそのまま歩きます。
保存変数を捨て原始変数 へ#
最初の一手は変数の置換です。保存変数 の代わりに原始変数 を解きます。低 Mach では原始変数のほうがはるかに良く条件付けされるからです。
は変数変換ヤコビアンです。残差 は依然として保存則を満たすように書かれているので、変数を変えても質量・運動量・エネルギーの保存は壊れません。ここで自由度を場ごとに束ね、 ブロック行列に整列します。
各ブロックは一つの原始場(速度・圧力・温度)に対応します。この整列が次の分解の足場です。
ブロック LU と速度–圧力 Schur 補元#
圧力–温度結合()は弱いです。両者を捨てるとブロック LU 分解が綺麗になり、残る核は速度–圧力 Schur 補元です。
は速度を消去したのちに圧力だけを残した有効方程式です。SIMPLE 系の圧力補正方程式と同じ骨格です。前処理 をこのブロック上三角の形に取ると、 の固有値が 1 の近くに集まります。厳密な を使えば の がそのまま となり、 は冪零(unipotent)下三角と相似で、すべての固有値が厳密に 1 です。GMRES は二、三回で終わります。
その二、三回は停止条件とも噛み合います。下のコードの許容残差は rtol=1e-8、反復の上限は maxiter=500、restart の長さは 2n=128 です。固有値が一点に集まれば Krylov 部分空間は二歩で閉じます。集まらなければ、先に 500 回の上限へ当たります。
Python — Mach を下げながら GMRES 反復数を数える#
温度を外し、2 場 の toy で核だけを再現します。ブロック系は 、。前処理は厳密な Schur 補元 です。
import numpy as np
from scipy.sparse import diags, eye, bmat
from scipy.sparse.linalg import gmres, LinearOperator, splu
n = 64
dx = 1.0 / n
def fwd_diff():
# 周期境界の前進差分 (圧力勾配演算子)
D = diags([-1.0, 1.0], [0, 1], shape=(n, n)).tolil()
D[-1, 0] = 1.0
return (D / dx).tocsr()
G = fwd_diff()
Dv = (-G.T).tocsr() # 発散 = -G^T -> Dv*G ~ ラプラシアン
def all_speed_system(M):
beta = 1.0 / M**2 # 低 Mach 剛性係数
A = bmat([[eye(n), beta * G], [Dv, eye(n)]]).tocsr()
return A, beta
def schur_preconditioner(beta):
# 速度-圧力 Schur 補元 S = M_PP - M_Pv M_vv^{-1} M_vP = I - beta Dv G
S = (eye(n) - beta * (Dv @ G)).tocsc()
luS = splu(S)
def apply(r):
ru, rp = r[:n], r[n:]
zp = luS.solve(rp) # S z_p = r_p
zu = ru - beta * (G @ zp) # z_u = r_u - beta G z_p
return np.concatenate([zu, zp])
return LinearOperator((2 * n, 2 * n), matvec=apply)
def count_iters(M, use_prec):
A, beta = all_speed_system(M)
b = np.random.default_rng(0).standard_normal(2 * n)
P = schur_preconditioner(beta) if use_prec else None
it = {"k": 0}
x, info = gmres(A, b, M=P, rtol=1e-8, maxiter=500, restart=2 * n,
callback=lambda xk: it.__setitem__("k", it["k"] + 1))
return it["k"]
print(f"{'Mach':>8} {'no-prec':>8} {'Schur':>6}")
for M in [1.0, 1e-1, 1e-2, 1e-3]:
print(f"{M:>8.0e} {count_iters(M, False):>8d} {count_iters(M, True):>6d}")前処理なしでは が小さくなるほど反復数が数十・数百へと跳ね上がり、 では 500 回の上限の中に入りません。Schur 側は を LU で一度解いておき、GMRES が二、三回で残差を 1e-11 まで落とします。()と ()で Schur の反復数が同じなのは、固有値が 1 に集まった数値です。
インタラクティブ — 音響と対流、開いていく二つの速度
トラックはすでに上で回しました。 の 100:1 は そのものです。陽的 CFL が で刻みを踏みつぶす場所も、その画面の速度差と同じです。ヤコビアンが受け取るのは、その比を二乗した です。 で 、 で です。
インタラクティブ — 前処理が残差を崩す場所
ここからは実際の GMRES 残差です。Mach スライダーを動かすと、前処理の有無の二曲線が描き直されます。
橙色(前処理なし)は を下げるほど平らになって止まります。シアン(Schur 前処理)は がどこでも二、三回で 1e-11 まで落ちます。二曲線の差は で最も大きくなります。 のマスを、物理結合を写した前処理がまとめて吸収した結果です。
自分で書いて疑わしかった三つ
厳密な が無料なのは toy だけです。 ここでは を LU で厳密に解き、二回で収束しました。実戦では の は密な逆行列で、作ることができません。論文は を近似で解き(AMG 一回の V-cycle など)、その近似の質が外側の反復数を左右します。反復数が Mach に張り付かないコストはここに隠れています。
結合をどこまで捨てるか。 論文は を捨てても頑健性は崩れないと言います。これは melt pool の物性に合わせた仮定です。強い圧縮性熱結合(爆燃・燃焼)では、同じ切り捨てが収束を止めることがあります。前処理を単純にするかは物理が決めます。
JFNK の Fréchet 差分 。 が小さすぎれば丸め誤差が、大きすぎれば打ち切り誤差が行列–ベクトル積を汚します。前処理が良くても、この が外れると Newton が停滞します。OpenFOAM の分離型(SIMPLE)から完全結合の陰的へ移るとき、最初に出会う場所です。
結び — 前処理はタダではない
GMRES が 1000 回、残差 1e-2 で止まった夜は、ヤコビアンをより強く解いて終わりませんでした。結合構造そのものを写した前処理が要りました。Schur 補元は速度を消した圧力の方程式であり、それを厳密に解けば固有値が 1 に集まります。実戦の の中の は密なので、論文は AMG 一回の V-cycle で近似します。その近似が粗いと、外側の反復が二、三回から再び開きます。
ヤコビアンを保存せず行列–ベクトル積だけを使う分かれ道は、演算子オーバーロードの自動微分と接しています。JFNK はその積を Fréchet 差分 で置き換えます。 が外れると、前処理が良くても Newton はその場で止まります。同じ toy で を AMG により粗く解いたとき、外側の反復が二、三回からどれだけ開くかが次の測定です。
関連記事
役に立ったらシェアしてください。