1972年、Alar ToomreとJüri Toomreの兄弟は、奇妙な形の銀河——2本の長い「尾」を引くアンテナ銀河など——が、2つの銀河のすれ違いが起こす潮汐の痕だということを、たった120個のテスト粒子とFORTRANと16mmフィルムのコマ撮りで示した。計算機が貧弱だった時代に、物理の本質だけを抜き出した見事な仕事だ。
僕の手元には、彼らの何億倍も速い計算機がある。ブラウザのWebGPUで16,384体の重力を毎フレーム直接計算(2.7億ペア/ステップ)できる。だから簡単に再現できると思っていた。できなかった。銀河をぶつけると、尾が伸びるどころか、円盤が丸ごと爆発四散した。この記事は、その犯人を追いつめた一晩の記録だ。
N体シミュレーションの計算量は、工夫をしなければ粒子数の2乗で増える。普通は近似(Barnes-Hutツリーなど)を入れるところだけど、GPUの並列性に任せて全ペアを毎回正直に計算することにした。WGSLのcompute shaderで、各粒子が他の全粒子からの重力を足し合わせる。
ブラウザで動かす前に、Nodeから同じWGSLを実行できる環境(npm install webgpu、DawnのNodeバインディング)で数値検証をした。2体の円軌道で距離誤差0.3%、エネルギーが理論値と4桁一致。孤立した円盤銀河(中心の大質量+回転する星々)も安定に回る。装置は健全——のはずだった。
2つの銀河を斜めにすれ違わせた。すると、接近したあたりで両方の円盤が全面的に飛び散った。尾どころではない。均一な塵になった。
容疑者1: ソフトニング。重力は距離の2乗に反比例するから、2つの中心質量が偶然すごく接近すると数値的に発散する。中心同士にだけ大きい緩和パラメータを入れる修正を書いた——が、置換スクリプトの失敗を見落として、修正が入っていない古いコードで実験していた。つまりこの仮説は検証すらできていなかった(置換したら必ずgrepで確認、という教訓が残った)。
容疑者2: 積分法。円盤の最内周の星は1周期がたった18ステップしかない。オイラー法はエネルギーを注入し続けるから、これが犯人だと思った。ところが孤立円盤で運動エネルギーの時系列を測ると、1000ステップで±3%、単調増加なし。よく考えると僕の実装は「全粒子の速度を更新してから、全粒子の位置を更新する」ので、これはsemi-implicit Euler——シンプレクティック積分だった。エネルギーは注入されない。積分は無罪。
数値の容疑者が消えたので、最後に残った「初期条件」を紙の上で調べた。2つの銀河を質点とみなして、相対軌道のエネルギーEと角運動量Lを手で計算する。高校物理の延長の、ケプラー問題だ。
旧初期条件:
E = v²/2 − μ/r = −1.45 → 束縛軌道(離心率0.93の細い楕円)
近点距離 r_p = a(1−e) ≈ 0.50
円盤の半径 = 0.48
近点距離が円盤半径と同じ。つまり僕が設定していたのは「すれ違い」ではなく、相手の円盤のド真ん中に突っ込むほぼ正面衝突だった。同じ質量の銀河が円盤のど真ん中を貫通すれば、星々は四方八方に散る。爆発は、バグではなく正しい物理だった。シミュレータは最初から正直に「その初期条件ならこうなる」と答え続けていて、疑うべきは僕の側の軌道設計だった。
Toomre兄弟の論文の初期条件は、放物線軌道(E=0)で、近点が円盤半径の1.5〜2倍。「ぶつける」のではなく「かすめさせる」。それに合わせて設計し直す。
新初期条件(Toomre流):
E = 0 になる相対速度 v = √(2μ/r₀) = 3.30
角運動量から近点距離 r_p = L²/2μ ≈ 0.88 = 円盤半径の1.8倍
結果が冒頭の画像だ。近点通過の直後、円盤の相手側の星は強く引かれて橋になり、反対側の星は取り残されて尾になる。一部の星は相手の銀河に乗り移り(粒子交換)、それでも両方の銀河はコアを保ったまま離れていく。全部、教科書に書いてあるとおりの潮汐力学が、一晩の試行錯誤の最後に一発で現れた。
僕は当初、Toomre兄弟の偉さを「あの計算資源で120粒子を回したこと」だと思っていた。違った。潮汐尾が出るかどうかは粒子数でも積分精度でもなく、E・L・近点距離という3つの数字の設計でほぼ決まる。彼らの仕事の本体は、計算機を回す前の、紙の上の軌道力学だった。
シミュレーションが壊れたとき、数値手法を疑うのは正しい習慣だ。でも診断が「数値は無罪」と言ったら、次に疑うべきは自分の初期条件で、そのとき必要になるのは新しいライブラリではなく、ケプラー問題を手で解く古い物理だった。