9本の矢に閉じ込めたMaxwell–Boltzmann — LBM平衡分布が多項式である理由
エルミート2次切り捨てがD2Q9を作り、同じ切り捨てがLBMを低速流に縛る
1986年、Frisch・Hasslacher・Pomeauが格子の上に粒子を放ってNavier–Stokesを真似させました。LGCA(Lattice Gas Cellular Automaton)です。5年も持ちませんでした — 格子1セルに粒子が0個か1個という整数条件が、どうしても消えないノイズを作り出したからです。1992年、McNamaraとZanettiは整数を実数に置き換えます。粒子の分布関数 で格子を埋める。ノイズは消えました — その代わり、新しい問いが残ります。9個の実数で、無限次元のMaxwell–Boltzmannをどう真似られるのか。本記事はその答えを追います — エルミート多項式の2次切り捨てがLBMの平衡分布を作り、同じ切り捨てがLBMを低速流に縛り付けるという事実までを。
整数から実数へ — 1986年のLGCAの死とLBMの誕生#
LGCAの発想は単純で美しいものでした。正方格子、6方向の粒子、たった1つの衝突則。マクロに平均すればNavier–Stokesが戻ってきます。しかしブール粒子(0または1)は統計的ノイズを増幅しました。時間平均を長く取ればノイズは死にますが、それと同時に、見たかったtransient流れも消えてしまいます。
McNamara・Zanettiは整数粒子の代わりに実数分布 を各格子点に置きます。 は時刻 、位置 で格子方向 に向かって動く粒子の 期待個数。ノイズは構造的に消えます。1ステップの進行は、collision(衝突)とstreaming(伝送)の2段階で完結します。
はrelaxation time(緩和時間)、 が 平衡分布関数 です。衝突項が非平衡部分を の時間スケールで削り、streamingが削られた分布を格子1セル隣へ運びます。しかし、 とは一体何で、なぜ9個の実数で足りるのでしょうか。
Maxwell–Boltzmannが抱える時限爆弾#
連続運動論において、平衡分布はMaxwell–Boltzmannです。
は粒子の分子速度、 はマクロ流速、 は空間次元、 は温度、 は気体定数です。この式の爆弾は が 連続変数 であることです。格子上で9個や19個の離散方向だけを残すには、どうにかしてこの連続分布を間引かなければなりません。
素朴な試み — ガウシアン積分を矩形和で近似する。失敗します。Navier–Stokesが必要とするモーメント — 、、運動量テンソル 、エネルギー — が格子和とずれます。保存が崩れた瞬間にLBMは使い物になりません。
正解は関数展開です。Maxwell–Boltzmannを 直交多項式級数 で展開し、必要なモーメントだけ残してその先を切り捨てる。その直交多項式がHermite(エルミート)です。
エルミート多項式が分布を細切れにする#
確率論的エルミート多項式 は標準ガウシアン重み の下で直交します。
最初の数項は 、、、 です。1次元Maxwell–Boltzmannを等温( に無次元化)に置くと、指数の母関数の助けで次の恒等式がただちに従います。
各項が世界の一片を捉えます。 は静止ガウシアン。 は小さなdrift。 は平均運動エネルギー補正。 が大きくなるほど非対称な裾の効果が支配的になります。LBMが狙うのはこの和を 有限次数 で打ち切ることです。
下のシミュレーションで実際に動かしてみましょう。drift を 0.4 まで上げて切り捨て次数 を選ぶと、最初の3つのモーメント(密度・運動量・エネルギー)がMaxwell–Boltzmannと正確に一致します。 を 1.0 を超えて押し上げると、破線が一気に外れていきます。これがLBMのマッハ数制約 の出どころを、1枚の図で示しています。
2次切り捨ての意味 — 保存されるモーメント#
Navier–Stokesの1次粘性応力まで再現するには、どのモーメントが必要でしょうか。正確な答えは — 、、そして運動量フラックス までの 3つのモーメント次数。 が の2次なので、分布関数に 項が入っている必要があります。
したがってエルミート級数を で切ります。
これがLBM平衡分布の 連続形 です。 以上は非粘性流れの高次モーメント(熱伝導)には役立ちますが、標準isothermal LBMには余剰です。切り捨てた項たちがLBMの2つの有名な限界を作ります — 等温仮定と、マッハ数 0.3 の天井です。
D2Q9はどうやって作られたか#
連続積分 を格子和 に置き換えるにはquadrature(直交積分公式)が要ります。核心は — 次切り捨てまで正確なquadratureは、その次数の多項式を正確に積分すれば十分 という点です。
2次元で 項まで正確にするには、ガウシアン重みに対して5次多項式まで正確なquadratureが必要です(運動量テンソルが 項を生むため)。Gauss–Hermite 3点 quadratureが、ちょうどその仕事をします。
1Dで点が3つ 、重み 。2Dではテンソル積で 点 — これがD2Q9です。格子単位にスケーリングし直すと で、格子速度ベクトルは整数座標 になります。格子重み はGauss–Hermite重みにガウシアン因子を吸収させた値です。
| index | ||
|---|---|---|
| 0 | ||
| 1–4 | ||
| 5–8 |
格子上の平衡分布は、連続形に を代入したものです。
この1行があらゆるisothermal LBMコードの心臓です。単純な多項式ですが、その中にMaxwell–Boltzmannの最初の3モーメントが封印されています。
Python — BGK衝突の1ステップ#
1つの格子セルで衝突を1ステップ回してみます。
import numpy as np
cx = np.array([0, 1, 0, -1, 0, 1, -1, -1, 1])
cy = np.array([0, 0, 1, 0, -1, 1, 1, -1, -1])
w = np.array([4/9, 1/9, 1/9, 1/9, 1/9, 1/36, 1/36, 1/36, 1/36])
def equilibrium(rho, ux, uy):
"""D2Q9平衡 — 9つの多項式"""
ciu = cx * ux + cy * uy # 内積
usq = ux * ux + uy * uy
return w * rho * (1 + 3 * ciu + 4.5 * ciu**2 - 1.5 * usq)
def bgk_collision(f, tau):
rho = f.sum()
ux = (cx * f).sum() / rho
uy = (cy * f).sum() / rho
feq = equilibrium(rho, ux, uy)
return f - (f - feq) / tau, rho, ux, uy
# 非平衡な初期分布
f = w * 1.0
f[1] += 0.05; f[3] -= 0.04 # 東側へわずかに偏らせる
for step in range(20):
f, rho, ux, uy = bgk_collision(f, tau=0.8)
err = np.linalg.norm(f - equilibrium(rho, ux, uy))
print(f"step {step:2d}: rho={rho:.4f}, u=({ux:+.4f},{uy:+.4f}), ||delta||={err:.2e}")20ステップほど回すと残差は を下回り、9個の が平衡多項式に沿って位置を取ります。各ステップで生き残るものは何か — と です。衝突は非平衡モーメントだけを削ります。
上のシミュレーションで スライダーを 0.55 近くまで下げると、1〜2ステップで残差が0に達します。粘性は なので、 では粘性が0になり、格子が不安定になります。逆に を大きくすると粘性は増えますが、平衡へ引き寄せられる速度は遅くなります。このtrade-offがLBMソルバー調整の核心です。
覚えておく3行#
- LBMの平衡分布 は、Maxwell–Boltzmannをエルミート多項式級数で展開して2次で切った形です — その切り捨てが ・・運動量フラックスの3モーメントを正確に保存します。
- D2Q9格子は、2次切り捨ての平衡分布を正確に積分するGauss–Hermite 3点quadratureの2Dテンソル積から 導出 されます。9は自然数ではなく、直交積分の産物です。
- 切り捨て次数が平衡分布の限界を決めます — 等温仮定、マッハ数 の天井は、すべて「 で切った」という1行から自動的に従います。
役に立ったらシェアしてください。