クイックスタート¶
インストール¶
pip install emout
PyVista による 3D 可視化も標準インストールに含まれます。
Dask によるリモート実行は Python 3.10 以上で自動的に有効になります(別途インストール不要)。
シミュレーションデータの読み込み¶
import emout
data = emout.Emout("output_dir")
Emout はディレクトリ内の HDF5 ファイルとパラメータファイル(plasma.inp または plasma.toml)を読み込み、
EMSES のファイル名規則から変数名を自動で決めます:
属性 |
ファイルパターン |
説明 |
|---|---|---|
|
|
静電ポテンシャル |
|
|
種1 の数密度 |
|
|
種1 の電流密度 (x成分) |
|
|
電場 (x成分) |
|
|
磁場 (z成分) |
|
|
再配置された電場 (x成分) |
|
|
2D ベクトル(自動結合) |
|
|
3D ベクトル(自動結合) |
|
|
流入電流データ(pandas DataFrame、 |
|
|
流出電流データ(pandas DataFrame、 |
|
|
導体電位データ(pandas DataFrame、 |
HDF5 由来の各属性は時系列オブジェクトで、タイムステップを指定すると NumPy 互換の配列が返ります:
len(data.phisp) # タイムステップ数
data.phisp[0].shape # (nz, ny, nx)
data.phisp[-1] # 最終ステップ
周期電場の再配置¶
末尾が先頭の周期重複点 e[N] = e[0] である電場では、次のオプションで
境界を挟む隣接点同士を補間します。一様でない周期場でも平均を保ち、
rex / rey / rez の境界だけ補間式が変わる問題を避けられます。
data = emout.Emout("output_dir", electric_relocation="periodic")
ex_at_centres = data.rex[-1]
修正モードは元の電場 HDF5 から .emout/relocated/periodic/rex00_0000.h5 などへ
独立したキャッシュを作ります。既存の rex00_0000.h5 を削除・上書きせず、
リモートで再オープンするときもモードを引き継ぎます。従来の式とキャッシュを使う既定値は
electric_relocation="legacy" です。この設定は emout の再配置場に適用され、
外部の trace solver が独自に読み込む場の設定を変更するものではありません。
最初のプロット¶
# 最終ステップの xz 平面(y = ny/2)の電位 2D カラーマップ
data.phisp[-1, :, data.inp.ny // 2, :].plot()
2D または 1D にスライスした後、.plot() を呼ぶだけで SI 単位付きの図が表示されます。
注意: スライスの軸順序は
(t, z, y, x)— NumPy の一般的な(x, y, z)慣習とは逆です。 上のdata.phisp[-1, :, data.inp.ny // 2, :]はt=-1(最終ステップ)、z=:(全範囲)、y=ny/2(固定)、x=:(全範囲)を意味し、 結果として xz 平面が得られます。emoutのインデックスは常にこの順なので、 他のコードから持ち込んだスライスはまずこの順に並べ替えてください。
ベクトル場と成分ごとの値¶
データの役割に応じて、次の型を使います。
型 |
役割 |
|---|---|
|
1成分のグリッドデータ。NumPy配列に座標・単位情報を付けたもの |
|
同じ形・座標を持つ2〜3成分の場。スライス・描画・成分ごとの演算に対応 |
|
1点の値、集計結果、グリッド情報のない配列など。物理的な成分名を保持 |
|
任意のオブジェクトへの要素別操作。物理的な成分名やグリッドは扱わない |
data.exz や data.exyz は従来どおり VectorData を返します。
スライスの軸順序は (t, z, y, x) です。スライス後は残った軸の順序を使い、
下の2次元の field は (z, x) の順にインデックスを指定します。
import numpy as np
field = data.exz[-1, :, data.inp.ny // 2, :]
field.components["x"] # Physical x component
field.components["z"] # Physical z component
field.component_axes # ("x", "z")
field.to_numpy() # Shape: (component, z, x)
(-field).plot()
np.add(field, 1.0) # Component-wise NumPy arithmetic
sample = field[0, 0] # ComponentValues: one point
means = field.mean() # ComponentValues: per-component means
means.components["z"]
means.objs # Existing element-wise access remains available
成分名を持つオペランド同士の演算では、保存順にかかわらず同じ物理成分を対応付けます。
たとえば data.exz と data.ezx の加算では x同士、z同士を加算します。
成分の集合、配列の形、グリッド座標が異なる場同士の演算は ValueError になります。
通常のNumPy配列は各成分にブロードキャストされ、Group のオペランドは従来どおり位置で対応付けます。
要素数の異なる Group 同士の演算も ValueError になり、末尾の要素を黙って捨てることはありません。
演算は保持している値に対して行い、異なる単位系を自動で換算するものではありません。
読み込んだ Data にブール配列・整数配列による添字や None による新しい軸を使うと、
結果は座標情報を持たない通常のNumPy配列になります。ベクトル場なら、各成分の配列を
ComponentValues にまとめて返します。グリッドを保ったままプロット領域をマスクするには、
.masked() を使います(プロットガイド)。
VectorData2d と VectorData3d は引き続き VectorData の別名です。
.objs、.attrs、.x_data、.y_data、.z_data も維持します。
これらの *_data は保存順の1番目・2番目・3番目という従来の意味なので、
exz の .y_data は z成分です。物理成分を指定するときは .components["z"] を使ってください。
.components は読み取り専用の対応表ですが、含まれる配列自体は従来どおり扱えます。
共有するグリッドの座標配列は .axis(i) で取得できます。i は現在の配列の軸番号です。
追加出力の結合¶
出力が複数のディレクトリに分かれている場合(途中で再投入したジョブなど):
# 自動検出
data = emout.Emout("output_dir", ad="auto")
# 手動指定
data = emout.Emout("output_dir", append_directories=["output_dir_2", "output_dir_3"])
結合したグリッド系列の添字・iteration・len() は、後続系列の先頭を接続点の重複として
一度だけ数えます。time_series(x, y, z) の既定の skip_overlap=False は全フレームを連結するので、
統計量や FFT に使う時系列には skip_overlap=True を指定してください。
単一系列でも同じ引数を使えます。
values = data.phisp.time_series(32, 32, 10, skip_overlap=True)
# Equivalent values: data.phisp[:, 10, 32, 32].to_numpy()
粒子データ¶
粒子の出力は種ごとに 1 つのオブジェクトにまとまっています:
p4 = data.p4 # 種4
p4.x, p4.y, p4.z # 位置の時系列
p4.vx, p4.vy, p4.vz # 速度の時系列
p4.tid # トレース ID
# pandas Series に変換
data.p4.vx[0].val_si.to_series().hist(bins=200)