post-processing について
数値シミュレーションの出力を分析するポスト処理スキルです。フィールド抽出、統計、派生量の計算、参照データとの比較、レポート作成を案内し、実データにあるフィールドや格子情報の確認を重視します。
主な機能
- 01フィールドとラインプロファイルの抽出
- 02時系列と分布の分析
- 03派生量の計算
- 04参照データとの比較
- 05サマリーレポートの作成
- 06収束とデータ妥当性の確認
活用シーン
- 01シミュレーションの特定フィールドを調べる
- 02残差の収束や定常状態を評価する
- 03解析解または実験データと結果を比較する
- 04シミュレーション分析レポートを作成する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ heshamfs/ materials-simulation-skills --skill post-processingインストール後、Claude Code で/post-processingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
CHANGELOG.mdevals/evals.jsonevals/files/analytical.jsonfield_output.jsonhistory.jsonprofile.jsonreferences/comparison_metrics.mddata_formats.mdderived_quantities_guide.mdstatistical_methods.mdscripts/comparison_tool.pyderived_quantities.pyfield_extractor.pyprofile_extractor.pyreport_generator.pystatistical_analyzer.pytime_series_analyzer.py詳細
後処理スキル
シミュレーション出力データを分析し、有用な情報を抽出します。
目標
フィールドの抽出、統計分析、派生量の計算、可視化、参照データとの比較を通じて、生のシミュレーション出力を実用的な知見に変換します。
収集する入力情報
後処理スクリプトを実行する前に、次の情報を集めます。
-
出力データの場所
- シミュレーション出力ファイル(JSON、CSV、HDF5、VTK)へのパス
- 対象とする時間ステップ/スナップショットのインデックス
- 抽出するフィールド名
フィールド名は必ずファイルから読み取り、推測しないでください。 抽出する前に、出力ファイルを開くか、
field_extractor.py --input <file> --list --jsonを実行し、fieldsの下に実際に表示されるフィールド名だけを使用してください。ファイルに存在しないtemperatureなどのフィールドを作り出したり、グリッドサイズを推測したりしないでください。データから実際のshape/countを読み取ってください。 -
分析の種類
- フィールド抽出(特定の時刻における空間データ)
- 時系列(量の時間的な変化)
- ラインプロファイル(領域を通る1D断面)
- 統計的要約(平均、標準偏差、分布)
- 派生量(勾配、積分、フラックス)
- 参照データとの比較
-
出力要件
- 出力形式(JSON、CSV、表形式)
- 可視化の要件
- レポート形式
スクリプト
| スクリプト | 目的 | 主な入力 |
|---|---|---|
field_extractor.py | 出力ファイルからフィールドデータを抽出 | --input, --field, --timestep |
time_series_analyzer.py | 時間的な変化を分析 | --input, --quantity, --window |
profile_extractor.py | ラインプロファイルを抽出 | --input, --field, --start, --end |
statistical_analyzer.py | フィールド統計量を計算 | --input, --field, --region |
derived_quantities.py | 派生量を計算 | --input, --quantity, --params |
comparison_tool.py | 参照データと比較 | --simulation, --reference, --metric |
report_generator.py | 要約レポートを生成 | --input, --template, --output |
ワークフロー
1. データの一覧確認
まず、利用可能なデータを確認します。
# List available fields and timesteps
python scripts/field_extractor.py --input results/ --list --json
2. フィールドの抽出
特定の時間ステップで空間フィールドデータを抽出します。
# Extract concentration field at timestep 100
python scripts/field_extractor.py \
--input results/field_0100.json \
--field concentration \
--json
# Extract multiple fields
python scripts/field_extractor.py \
--input results/field_0100.json \
--field "phi,concentration,temperature" \
--json
3. 時系列分析
量の時間的な変化を分析します。
# Extract total energy vs time
python scripts/time_series_analyzer.py \
--input results/history.json \
--quantity total_energy \
--json
# Compute moving average with window
python scripts/time_series_analyzer.py \
--input results/history.json \
--quantity mass \
--window 10 \
--json
# Detect steady state (relative-variation test; best for physical quantities)
python scripts/time_series_analyzer.py \
--input results/history.json \
--quantity residual \
--detect-steady-state \
--tolerance 1e-6 \
--json
# Convergence by absolute threshold (physically correct test for residuals)
python scripts/time_series_analyzer.py \
--input results/history.json \
--quantity residual \
--absolute-threshold 1e-6 \
--json
4. ラインプロファイルの抽出
領域を通る1Dプロファイルを抽出します。
# Extract profile along x-axis at y=0.5
python scripts/profile_extractor.py \
--input results/field_0100.json \
--field concentration \
--start "0,0.5,0" \
--end "1,0.5,0" \
--points 100 \
--json
# Interface profile (through center)
python scripts/profile_extractor.py \
--input results/field_0100.json \
--field phi \
--axis x \
--slice-position 0.5 \
--json
5. 統計分析
フィールドデータの統計量を計算します。
# Global statistics
python scripts/statistical_analyzer.py \
--input results/field_0100.json \
--field concentration \
--json
# Statistics in a specific spatial region (1D/2D fields only).
# Coordinates are derived from the field shape and grid spacing
# (explicit dx/dy, or Lx/Ly via dx = Lx/(nx-1)); only the variables
# x, y, z compared against numbers, joined by and/or, are allowed.
python scripts/statistical_analyzer.py \
--input results/field_0100.json \
--field phi \
--region "x>0.3 and x<0.7" \
--json
# Distribution analysis
python scripts/statistical_analyzer.py \
--input results/field_0100.json \
--field phi \
--histogram \
--bins 50 \
--json
6. 派生量
生データから物理量を計算します。
# Compute interface area
python scripts/derived_quantities.py \
--input results/field_0100.json \
--quantity interface_area \
--threshold 0.5 \
--json
# Compute gradient magnitude
python scripts/derived_quantities.py \
--input results/field_0100.json \
--quantity gradient_magnitude \
--field phi \
--json
# Compute volume fractions
python scripts/derived_quantities.py \
--input results/field_0100.json \
--quantity volume_fraction \
--field phi \
--threshold 0.5 \
--json
# Compute flux through boundary
python scripts/derived_quantities.py \
--input results/field_0100.json \
--quantity boundary_flux \
--field concentration \
--boundary "x=0" \
--json
7. 参照データとの比較
シミュレーション結果を参照データと比較します。
# Compare to analytical solution
python scripts/comparison_tool.py \
--simulation results/profile.json \
--reference reference/analytical.json \
--metric l2_error \
--json
# Compare to experimental data
python scripts/comparison_tool.py \
--simulation results/history.json \
--reference experimental_data.csv \
--metric rmse \
--interpolate \
--json
# Compare two simulations
python scripts/comparison_tool.py \
--simulation results_fine/field.json \
--reference results_coarse/field.json \
--metric max_difference \
--json
8. レポートの生成
レポートを自動生成します。
# Generate summary report
python scripts/report_generator.py \
--input results/ \
--output report.json \
--json
# Generate with specific sections
python scripts/report_generator.py \
--input results/ \
--sections "summary,statistics,convergence" \
--output report.json \
--json
代表的な後処理パイプライン
シミュレーションを総合的に分析する場合:
python scripts/field_extractor.py --input results/ --list --json # 1. inventory
python scripts/statistical_analyzer.py --input results/field_final.json --field phi --json # 2. final-state stats
python scripts/time_series_analyzer.py --input results/history.json --quantity residual --detect-steady-state --json # 3. convergence
python scripts/derived_quantities.py --input results/field_final.json --quantity volume_fraction --field phi --json # 4. derived quantities
python scripts/comparison_tool.py --simulation results/profile.json --reference benchmark/expected.json --metric l2_error --json # 5. compare to reference
python scripts/report_generator.py --input results/ --output analysis_report.json --json # 6. summary report
解釈のガイドライン
時系列解析
アナライザーが報告する2つのシグナル(convergence.{rate,type} と
steady_state.reached)は異なる問いに答えており、正当に食い違うこともあるため、
数量の種類に応じて収束の解釈を変えてください。
残差/誤差の数量(例:residual、error):
- 絶対値と許容値の比較によって収束を判定します。残差が目標許容値(例:
1e-6)以下であれば収束しています。--absolute-threshold <tol>を使用すると、 残差に対して物理的に正しい判定を行うconvergence_thresholdブロックを取得できます。 - 相対的な
--detect-steady-stateテストが答えるのは「残差の変化が止まったか」であり、 「収束したか」ではありません。残差がまだ減少している場合、steady_state.reached = falseとなるのは想定どおりであり、失敗ではありません。 - 残差の停滞は、定常状態ではなく、ソルバーが停滞していることを意味します
(
convergence.type = "stalled")。 - シグナルを総合的に判断する:
convergence.typeがfast/linearで、 最終残差が小さい(またはconvergence_threshold.reached = true)場合は、steady_state.reached = falseであっても、実行は収束したと報告してください。
物理量(例:energy、volume_fraction、mass、
interface_area):
- エネルギーの単調減少:系が平衡に近づいています。
- プラトー(
steady_state.reached = true):定常状態に達しています。 - 振動:時間刻みが大きすぎる可能性があります。
- 突然のジャンプ:数値的不安定性の可能性があります。
統計解析
- 二峰性分布の秩序変数:二相混合
- 高分散:不均一な微細構造
- 歪んだ分布:相分率が非対称
比較指標
| 指標 | 解釈 |
|---|---|
| L2 誤差 < 1% | 優れた一致 |
| L2 誤差 1-5% | 良好な一致 |
| L2 誤差 5-10% | 中程度の一致 |
| L2 誤差 > 10% | 一致度が低いため、調査が必要 |
出力形式
すべてのスクリプトは、機械可読な出力を得るための --json フラグをサポートしています。
ほとんどのスクリプトは、スクリプトによってキーが異なるフラットなトップレベルオブジェクトを
出力します。たとえば、単一フィールドに対して field_extractor.py --include-data を実行すると、
次のように出力されます。
{
"field": "concentration",
"found": true,
"data": [[0.1, 0.9], [0.3, 0.6]],
"shape": [2, 2],
"min": 0.1,
"max": 0.9,
"mean": 0.475,
"count": 4,
"source_file": "results/field_0100.json",
"timestep_info": {"timestep": 100, "time": 1.5}
}
エンベロープ形式に関する注意(スクリプト間で統一されていません):
field_extractor.py、statistical_analyzer.py、time_series_analyzer.py、profile_extractor.py、comparison_tool.pyは、source_fileキーと スクリプト固有の結果キーを含むフラットなオブジェクトを出力します。derived_quantities.pyは、ペイロードを{ "inputs": {...}, "results": {...} }のエンベロープで囲みます。report_generator.pyは、トップレベルのreport_versionおよびgeneratorキーと、要求されたレポートセクションを出力します。
どのスクリプトもトップレベルの script、version、input_file キーは出力しません。
また、フィールド統計(min/max/mean/count)はトップレベルに現れ、
data オブジェクトの下にネストされることはありません。
検証チェックリスト
後処理の結果を信頼または報告する前に、以下の具体的な証拠を作成して記録してください (このスキルのスクリプトと出力キーに関連付けてください)。
- まず実際のフィールドを一覧表示しました。
field_extractor.py --list --jsonを実行し、実際のfields名とshapeを記録しました。それ以降の--field引数はすべてその一覧に含まれており(temperatureを仮定したり、グリッドサイズを推測したりしていません)。 - 量の種類に応じた適切な収束テストを使用しました。 残差/誤差については、
steady_state.reachedに頼らず、--absolute-threshold <tol>(|x_final| <= tolのテスト)によるconvergence_threshold.reachedとfinal_valueを記録しました。物理量については、--detect-steady-stateによるsteady_state.{reached,relative_variation,value}を記録しました。 - 2つの収束シグナルを照合しました。
convergence.typeとconvergence.rateをsteady_state.reachedとともに記録し、convergence.type = "stalled"は定常状態ではなくソルバーの停滞として解釈されること、また、残差が減少し続けている状態でsteady_state.reached = falseでも失敗とは報告されないことを確認しました。 - 許容誤差と照らして保存則を確認しました。 保存積分値(
derived_quantities.py --quantity mass/integral、またはvolume_fraction)を最初と最後のタイムステップで記録し、ドリフトが対象のダイナミクスについて文書化された許容誤差内であることを確認しました(Cahn-Hilliard の保存秩序変数では約0、Allen-Cahn では変化が予想されます)。 - グリッド間隔が物理的な値であることを確認しました。
derived_quantities.pyが出力するspacingブロック(dx/dy/dz)を記録し、明示的なdx/dy、または適切なLx/(nx-1)の導出に基づいていることを確認しました。また、stderr にWARNING: explicit dx ... inconsistent with Lxという行が出力されていないことも確認しました。 - 非有限値によって結果が損なわれていないことを確認しました。 導出量のスクリプトで
Field contains non-finite value(NaN/Inf)が発生していないこと、および報告されたmin/maxが物理的に妥当であること(たとえば、秩序変数が想定範囲内に収まっていること)を確認しました。 - 比較誤差を文書化された区分に照らして評価しました。
comparison_tool.pyの指標値(例:l2_error)を記録し、このスキルの一致度区分に当てはめました(1%未満は非常に良好、…10%超は不良のため要調査)。その前に、シミュレーションと参照データが同じ軸に揃えられているか、または同じ軸に補間されていることを確認しました。
よくある落とし穴と誤った正当化
| 安易な近道 | それが誤りである理由/すべきこと |
|---|---|
"steady_state.reached = false なので、ソルバーは収束しませんでした。" | 相対定常状態テストが確認するのは「変化が止まったかどうか」であり、残差がまだ減少中なら false になります。残差には --absolute-threshold <tol> を使用し、convergence_threshold.reached を確認してください。convergence.type/rate と照合してください。 |
| "残差がプラトーに達したので、定常状態に到達しました。" | 残差が横ばいなのは、収束ではなくソルバーの停滞です(convergence.type = "stalled"、rate > 0.99)。収束したと判断する前に、プラトーの値が実際に許容誤差以下であることを確認してください。 |
"temperature を抽出するか、256×256 のグリッドだと仮定すればいいでしょう。" | フィールド名と形状は保証されません。まず field_extractor.py --list --json を実行し、ファイルが実際に報告する fields と shape のみを使用してください。 |
| "2 つのグリッド/実行結果が一致したので、結果はメッシュに依存しません。" | 2 つのフィールドに対する comparison_tool.py が示すのは両者の差の上限にすぎず、漸近領域にあることは証明できません。メッシュ非依存性を主張する前に、3 つ以上の解像度を使って観測次数を推定してください。 |
| "体積分率が安定しているので、質量は保存されています。" | 安定した volume_fraction(しきい値処理された個数)は、保存される積分量ではありません。最初と最後の時間ステップ間の --quantity integral/mass のドリフトを許容誤差と照らし合わせて確認してください。また、ドリフトが約 0 になると期待できるのは、保存系(Cahn-Hilliard)のダイナミクスの場合に限られます。 |
"導出量にはデフォルトの dx=1.0 で問題ありません。" | ファイルに間隔がない場合、スクリプトは dx=dy=dz=1.0 を使用するため、長さ/面積/フラックス/積分量は物理単位ではなくグリッド単位になります。--dx/--dy(またはファイル内の Lx/Ly)を指定し、出力された spacing ブロックを確認してください。 |
| "実行が完了して JSON が出力されたので、数値は正しいです。" | 完了したからといって正しいとは限りません。報告する前に、保存量のドリフト、収束判定、有効な値であること、比較誤差の範囲を確認してください。 |
セキュリティ
入力の検証
- ユーザー指定のフィールド名は、細工されたフィールド名によるインジェクションを防ぐため、
[a-zA-Z_][a-zA-Z0-9_.-]*に照らして検証されます statistical_analyzer.pyは、使用前に--regionの条件を厳格な許可リストと照合して検証します。数値リテラルに対して比較演算子(< <= > >= == !=)を使用する座標変数x、y、zのみを受け付け、条件はand/orで結合できます。それ以外はすべてコード 2 で終了します。解析された条件は実際の座標マスクとして適用されるため(eval/execは使用しません)、報告される統計量は要求された領域を表しますprofile_extractor.pyは、フィールド名を同じパターンで検証し、点の座標は最大 3 次元の有限数値であることを検証しますcomparison_tool.pyの--metric値は、固定の許可リスト(l1_error、l2_error、linf_error、rmse、mae、max_difference、correlation、r_squared)と照合して検証されます。不明なメトリックはエラーになりますreport_generator.pyの--sectionsは、既知のセクション名(summary、statistics、convergence、validation、files、parameters、all)と照合して検証されます。不明なセクションはコード 2 で終了します--bins(statistical_analyzer)、--points(profile_extractor)、--window(time_series_analyzer)は、上限付きの正の整数として検証されます。範囲外の値はコード 2 で終了します
ファイルアクセス
- すべての JSON および CSV 読み込み関数は、解析前に 500 MB を超えるファイルを拒否します
- 読み込まれる JSON ファイルのルート要素は、オブジェクト(dict)でなければなりません
report_generator.pyは、リソースの枯渇を防ぐため、ディレクトリ一覧の項目数を 10,000 件に制限します- スクリプトはユーザー指定のシミュレーション出力ファイル(JSON、CSV)を読み込みますが、明示的に指定された範囲を超えてディレクトリをたどることはありません
- エージェントが Write を使用してレポートを保存しない限り、出力先は stdout(JSON)です
ツールの制限
- Read:スクリプトのソース、参照資料、シミュレーション出力ファイルの確認に使用します
- Write:分析結果、比較レポート、生成した要約の保存に使用します。書き込み先はユーザーの作業ディレクトリに限定されます
- Grep/Glob:シミュレーション出力ファイルの特定や参照資料の検索に使用します
- スキルの
allowed-toolsでは、信頼できないシミュレーション出力ファイルの処理中にエージェントが任意のコマンドを実行しないよう、Bashを除外しています
安全対策
eval()、exec()、動的コード生成は使用しません。領域の解析にはコードの評価ではなく正規表現マッチングを使用します- すべてのサブプロセス呼び出しで、
shell=Trueを使用せず、明示的な引数リストを使用します - ツールの対象範囲を縮小し(Bash を使用不可)、エージェントの操作を読み取り/書き込みのみに制限します
- インジェクションを防ぐため、フィールド名と領域式は使用前にサニタイズします
参考資料
詳細については、以下をご覧ください。
references/data_formats.md- 対応する入出力形式references/statistical_methods.md- 統計分析手法references/derived_quantities_guide.md- 物理量の計算references/comparison_metrics.md- 誤差指標とその解釈
要件
- Python 3.10+
- 数値演算用の NumPy
- コア機能にその他の外部依存関係はありません
バージョン履歴
正式な記録については CHANGELOG.md をご覧ください。
- v1.1.3 (2026-06-24):スクリプトの実際の出力キー(フィールド一覧、残差と物理量の収束、信号の整合性確認、保存量のドリフト、格子間隔の妥当性確認、非有限値のガード、比較誤差帯)に基づく「検証チェックリスト」と、「よくある落とし穴と合理化」の表をセキュリティセクションの前に追加しました。ドキュメントのみの変更で、スクリプトの動作に変更はありません。
- v1.1.2 (2026-06-23):評価スイートを自己完結型にし、判別力を高めました。実際のフィクスチャを
evals/files/にコピーし(10x10 格子上のphi/concentrationフィールドのみ。残差系列は 5e-6 で終了)、すべての評価プロンプトがそれらのファイルを正確に参照するよう書き換えました。また、検証済みのスクリプト出力(絶対残差しきい値 1e-6 に到達していないという正しい判定を含む)を固定する、決定的なscript_checksを追加しました。フィールド名を推測せず、出力ファイルから読み取るよう案内を追加しました。 - v1.1.1 (2026-06-23):
statistical_analyzer.pyに実際の座標に基づく--regionフィルタリングを実装しました。report_generator.pyがネストされたfields.*.valuesの出力を読み取るよう修正しました。derived_quantities.pyの格子間隔ではdx/dy/dzを明示的に優先するようにしました。収束モードとして--absolute-thresholdを追加し、残差と物理量の解釈に関する案内を追加しました。出力形式の例とバージョンメタデータを修正し、--bins/--windowの範囲検証を追加しました。 - v1.1.0 (2026-03-26):説明、評価スイート、セキュリティレビューを最適化し、メタデータと CHANGELOG を標準化しました。
- v1.0.0 (2026-02-25):初回リリース。