MMSソース項の自動導出(シンボリック計算) — トラブルシューティングガイド
より充実した内容を mms-source-term.html でご覧いただけます。
ソース項のバグは「ソルバーのバグ」と区別がつかない
MMSで次数が出なくて3日悩んだんですが、結局ソルバーじゃなくて自分が導出したソース項の符号ミスでした…。
それはMMS実務者全員が一度は通る道だよ。MMSは「ソース項が正しい」ことを前提にソルバーを審査する仕組みだから、ソース項側に誤りがあると審査自体が冤罪を生む。だからソース項の導出パイプラインには、ソルバーとは独立の検証を必ず付ける。このページでは、シンボリック導出〜コード生成〜注入の各段階で起きるトラブルを症状別に整理するよ。
前提の整理:製造解 \( u_m \) と演算子 \( L \) からソース項 \( s = L(u_m) \) を数式処理系(SymPy等)で導出し、生成コード(C/Fortran/UDF)としてソルバーに注入する——この一連の流れの中の欠陥を突き止めるのが本ページの範囲です。導出の基礎手順は統合版を参照してください。
最初にやるべき独立検証——数値微分との乱数点照合
導出したソース項の正しさは、シンボリック微分とは独立な方法で数値的に確認できます。領域内の乱数点 \( \mathbf{x}_i \)(10点程度)で、①生成コードのソース項値 \( s(\mathbf{x}_i) \) と、②製造解への演算子適用を高精度有限差分で数値評価した値を比較します。中心差分の刻みを \( h = 10^{-5} \) 程度に取れば相対誤差 \( 10^{-8} \) 前後で一致するはずで、それより大きくずれる点が1つでもあれば導出かコード生成に誤りがあります。この照合は数分で書けて、符号ミス・係数ミス・項の欠落をほぼ確実に捕捉します。MMSランを回す前の必須ゲートにしてください。
症状1: 照合が合わない——項別分解で犯人を絞る
ソース項全体の照合が合わないときは、演算子を項に分解して項ごとに照合します。例えば移流拡散反応方程式なら
$$ s = \underbrace{\frac{\partial u_m}{\partial t}}_{s_1} + \underbrace{\mathbf{a}\cdot\nabla u_m}_{s_2} - \underbrace{\nabla\cdot(k\nabla u_m)}_{s_3} + \underbrace{r\,u_m}_{s_4} $$
と分けて \( s_1 \)〜\( s_4 \) を個別に数値微分と照合すれば、誤りのある項が特定できます。頻出の犯人は次の通りです。
| 誤りの型 | 典型例 | 検出のコツ |
|---|---|---|
| 符号規約の不一致 | \( s \) を右辺に置くか左辺に置くか、拡散項の符号 | ソルバーの方程式を「ソース項が右辺に来る形」に書き直してから導出 |
| 係数の定義違い | 動粘性 \( \nu \) と粘性係数 \( \mu \)、\( \rho \) で割った形かどうか、熱拡散率 \( \alpha \) と熱伝導率 \( k \) | ソルバー入力ファイルの物性名と単位を導出スクリプトの記号表に対応付けて明記 |
| 項の欠落 | 時間微分項の入れ忘れ(定常のつもりが非定常ラン)、保存形の \( u\,\nabla\cdot\mathbf{a} \) 部分 | 項数を数える。分解照合で欠落項はゼロとの比較になり即発覚 |
| 座標系の食い違い | 軸対称・円筒座標の \( 1/r \) 項をデカルト式で導出 | ソルバーの離散化座標系で演算子を書き下してから微分する |
| テンソル成分の取り違え | 応力テンソルの対称化忘れ、\( \nabla\mathbf{u} \) の行・列規約 | 成分ごとに照合。2Dの小さい系で全成分を書き出して目視確認 |
症状2: 導出は正しいのに生成コードが遅い・壊れる
NS級の方程式では生成式が数千演算に達し、コード生成段階で新種の問題が出ます。
- コンパイル不能・行長超過 — Fortranの行継続限界や、コンパイラの式の複雑さ制限に当たる。
sympy.cse()で共通部分式に分解し、中間変数の列として出力する - 実行が極端に遅い — 同じ三角関数が数百回評価されている。これもCSEで解決。
pow(x, 2)頻発は乗算への書き換え指定で改善 - 値が微妙に合わない(相対誤差 \( 10^{-10} \) 台) — simplifyによる式変形で演算順序が変わった丸めの差。実害はないが、照合の合格判定は相対誤差 \( 10^{-8} \) 程度に緩めて運用する
- 桁落ちで大きく合わない — 大きな項同士の差になる形が生成された。
simplify/factorで相殺を解消してから出力し直す
症状3: コードは正しいのにソルバー内で効いていない
UDF・ユーザーサブルーチンでの注入段階には、導出と無関係の落とし穴があります。
- 評価座標の取り違え — セル中心で評価すべきところに節点座標を渡している(またはその逆)。有限体積ではセル中心、FEMでは積分点が正解
- 体積積分の規約 — ソルバーが期待するのは「単位体積あたりのソース」か「セル合計」か。2乗メッシュ細分でソース項の効きが4倍変われば規約違いのサイン
- 時刻の渡し忘れ — 非定常ソース項に前ステップの時刻が渡っている。時間1次のずれとして観測次数に出る
- 適用領域の漏れ — マルチゾーンモデルで一部ゾーンにUDFが割り当てられていない。誤差の空間分布を可視化するとゾーン境界で不連続に見える
診断には誤差の空間分布の可視化(\( |u_h - u_m| \) のコンター)が最強です。導出ミスは誤差が全域に載り、注入ミスは特定領域・境界・ゾーンに構造を持って現れます。
組織的な進め方——項の段階的有効化
最初からフルの方程式でMMSをやるから、どこが悪いか分からなくなるんですね…。
その通りで、ベテランほど簡単な方程式から段階的に積み上げる。①純拡散(Poisson)で次数確認→②移流を足す→③非線形項を足す→④連成項を足す、と1段ずつ。各段階で「前の段階では次数が出ていた」という事実があるから、壊れたら直前に足した項が犯人と即断できる。導出スクリプトも項別に関数化しておけば、この積み上げがそのまま回帰テストになる。フルNSでいきなり検証を始めるのは、飛び込み台の一番上から練習を始めるようなものだよ。
ソース項パイプラインの品質チェックリスト
- 乱数点での数値微分照合をパスしたか(相対誤差 ≤ 1e-8 目安)
- ソルバーの方程式形(符号・係数・座標系・保存形/非保存形)と導出式の対応表を作ったか
- CSE適用後のコードで照合を再実行したか(生成段階の検証)
- ソース項の評価位置(セル中心/積分点)と体積規約を確認したか
- 誤差の空間分布を可視化したか(構造の有無で導出ミス/注入ミスを切り分け)
- 項の段階的有効化の履歴(どの段階まで次数が出たか)を記録したか
関連記事:MMSソース項の自動導出(統合版)、NS方程式MMSのトラブルシュート、MMS収束次数のトラブルシュート。
関連トピック
なった
詳しく
報告