数値計算結果の可視化
数値計算では、計算結果を図として確認することが重要です。ただし、本書の中心は可視化ライブラリの使い方ではなく、物理モデル、数値計算法、Rustによる実装、そして結果の検証です。
そのため本書では、まず次の流れを標準とします。
- Rustで計算する。
- 結果をCSVやバイナリ形式のファイルに保存する。
- 表形式データは
gnuplotで可視化する。 - 図を見て、解析解、保存量、収束性、境界条件などを確認する。
gnuplotはテキストファイルでプロット手順を管理できるため、表形式データの確認には十分です。多次元配列では、必要な断面、射影、集計量を取り出して可視化します。複雑なデータ加工や論文用の細かい図が必要になった場合だけ、Pythonのmatplotlibなどを使います。
基本方針
本書では、計算と可視化を分離します。Rustのプログラムは、画面への出力だけでなく、後から確認できる形でデータを保存します。
この方針には、次の利点があります。
- 入力パラメータ、乱数seed、実行条件、出力ファイルを後から確認できる。
- 同じデータから何度でも図を作り直せる。
- 図の作成手順を
plot.gpのような短いテキストファイルとして管理できる。 - AI agentに、入出力コードやプロット用スクリプトの作成を任せやすい。
可視化は、計算結果を検査するための手段です。図がきれいに描けることと、数値計算が正しいことは同じではありません。
CSVファイルへの出力
CSVは多くのツールで読み込めるため、時系列や表形式の小さなデータに適しています。次の例では、時刻t、位置x、速度vをoutput.csvに保存します。
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut file = File::create("output.csv")?;
writeln!(file, "t,x,v")?;
for i in 0..=100 {
let t = i as f64 * 0.1;
let x = t.sin();
let v = t.cos();
writeln!(file, "{t},{x},{v}")?;
}
Ok(())
}
実行すると、次のようなCSVファイルが生成されます。
t,x,v
0,0,1
0.1,0.09983341664682815,0.9950041652780258
0.2,0.19866933079506122,0.9800665778412416
実際のシミュレーションでは、必要に応じてmetadata.jsonのような別ファイルに、パラメータ、乱数seed、格子サイズ、刻み幅、実行日時なども保存するとよいでしょう。
多次元配列とバイナリ形式
格子上の場、画像、波動関数、相関関数などの多次元配列を扱う場合、CSVはあまり適していません。ファイルサイズが大きくなりやすく、形状やデータ型の情報も別に管理する必要があるためです。
このような場合は、HDF5やNumPy形式(.npy、.npz)などのバイナリ形式を検討します。これらは広く使われており、Python、Julia、C/C++、Fortranなど複数の言語から読み書きしやすい形式です。
したがって、データ形式は次のように使い分けます。
- 時系列や少数列の表形式データ: CSV
- 多次元配列や大きなデータ: HDF5、NumPy形式などのバイナリ形式
- 実行条件やパラメータ: JSON、TOML、YAMLなどのメタデータファイル
gnuplotによる可視化
gnuplotでは、プロット手順をテキストファイルとして保存できます。例えば、次の内容をplot.gpとして保存します。
set terminal svg size 900,600
set output "plot.svg"
set datafile separator ","
set key autotitle columnhead
set xlabel "t"
set ylabel "value"
set grid
plot "output.csv" using 1:2 with lines linewidth 2, \
"" using 1:3 with lines linewidth 2
次のコマンドで図を生成します。
gnuplot plot.gp
この例では、output.csvの1列目を横軸、2列目と3列目を縦軸として描画し、plot.svgを出力します。CSVのヘッダー行は凡例として使われます。
gnuplotスクリプトは短く、差分も読みやすいため、agentic codingと相性がよいです。例えば、AI agentには次のように依頼できます。
output.csvには t, energy, error が入っています。
energyの時間変化とerrorの対数プロットを別々のSVGに保存するgnuplotスクリプトを書いてください。
軸ラベル、grid、出力ファイル名も入れてください。
ただし、生成された図を確認するのは人間の役割です。軸、単位、列の対応、期待される保存量や収束性が正しいかを確認してください。
matplotlibを使う場合
Pythonのmatplotlibは、データ加工や複雑な図を作る場合に有用です。例えば、複数ファイルの集計、フィッティング、統計量の計算、論文用の細かな体裁調整を行う場合にはmatplotlibを使うと便利です。
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("output.csv")
fig, ax = plt.subplots()
ax.plot(df["t"], df["x"], label="x")
ax.plot(df["t"], df["v"], label="v")
ax.set_xlabel("t")
ax.set_ylabel("value")
ax.grid(True)
ax.legend()
fig.savefig("plot.png", dpi=150)
一方で、単純な折れ線グラフや散布図であれば、まずgnuplotで十分です。可視化のためにPython環境を必須にしないことを、本書の標準方針とします。
Rust製ライブラリを使う場合
Rustだけで図の生成まで完結させたい場合は、plottersを使うこともできます。また、3D可視化やインタラクティブな表示が必要な場合には、three-dなどのグラフィックスライブラリが選択肢になります。
ただし、これらは本書の標準経路ではありません。Rust側に可視化処理を深く組み込むと、数値計算の本体と図の作成が混ざりやすくなります。まずは計算結果を保存し、外部ツールで可視化する構成を基本にしてください。
まとめ
本書では、次の方針を採ります。
Important
- Rustは計算と結果保存を担当する。
- 標準の可視化は、表形式データならCSVと
gnuplotを使う。- 多次元配列や大きなデータは、HDF5やNumPy形式などのバイナリ形式で保存する。
matplotlibは、複雑なデータ加工や図が必要な場合の補助として使う。plottersやthree-dは、Rustだけで完結させたい場合や3D可視化が必要な場合の発展的な選択肢とする。- 図は検証の入口であり、物理的・数値的な正しさは別途確認する。
次節では、本書全体の構成と学習の進め方について解説します。