コンテンツにスキップ

Python 後処理 API リファレンス

BEACH の Python パッケージ (beach) は、Fortran シミュレーション結果の読み込み・解析・可視化を担う後処理レイヤです。 Fortran 実行系が出力するファイル群(summary.txt, charges.csv, mesh_triangles.csv 等)を読み込み、電位再構成、Coulomb 力計算、電場計算、電気力線追跡、3D 可視化を Python 側で行います。

最初の図を作るだけなら、先に 後処理チュートリアル を参照してください。

モジュール役割
beach.fortran_results.io出力ディレクトリの読み込み (load_fortran_result, list_fortran_runs)
beach.fortran_results.facade高水準ファサード Beach クラス
beach.fortran_results.potential電位再構成 (compute_potential_mesh, compute_potential_points, compute_potential_slices)
beach.fortran_results.coulombCoulomb 力/トルク計算 (calc_coulomb)
beach.fortran_results.kernelFortran FMM field kernel の共有ライブラリ呼び出し (FieldKernel, calc_object_forces_kernel)
beach.fortran_results.sceneobject の一時移動・回転と編集後 scene の field-kernel 評価
beach.fortran_results.field_lines電場計算・電気力線追跡・3D 描画 (compute_electric_field_points, trace_field_lines, plot_field_lines_3d)
beach.fortran_results.mobilityCoulomb mobility 解析 (analyze_coulomb_mobility)
beach.fortran_results.plotting各種プロット (plot_charge_mesh, plot_charges, plot_potential_mesh 等)
beach.fortran_results.animation履歴アニメーション (animate_history_mesh)
beach.fortran_results.historycharge_history.csv のバッチステップ別アクセス (FortranChargeHistory)
beach.fortran_results.types公開データ型 (FortranRunResult, CoulombInteraction 等)
beach.fortran_results.constants物理定数 (K_COULOMB)

すべての公開シンボルは beach トップレベルおよび beach.fortran_results からインポートできます。

from beach import Beach, calc_coulomb, compute_electric_field_points, trace_field_lines

出力ディレクトリを 1 つ束ねて、主要な解析・可視化メソッドを提供する高水準インターフェースです。

b = Beach("outputs/latest")

Beach("outputs/latest", config_path="path/to/beach.toml") のように設定ファイルを明示できます。config_path=None の場合は output_dir/beach.toml, 親ディレクトリ, 祖父ディレクトリの順に自動探索します。config-aware な object / kernel 解析では、この beach.toml から object kind/order、sim.softening、periodic2、tree パラメータを解決します。

パラメータデフォルト説明
output_dirstr | Path"outputs/latest"Fortran 出力ディレクトリ
名前戻り型説明
resultFortranRunResult読み込み済み結果(遅延ロード)
mesh_idstuple[int, ...]利用可能な mesh ID 一覧
メソッド委譲先概要
reload()load_fortran_resultディスクから再読み込み
get_mesh(*mesh_ids, step)内部mesh ID で MeshSelection を取得
get_mesh_charge(*mesh_ids, step)内部mesh ID で要素電荷配列を取得
calc_coulomb(target, source, ...)calc_coulombCoulomb 力/トルク計算
calc_object_forces_kernel(...)calc_object_forces_kernelFortran field kernel による object 別合力計算
scene(step, ...)BeachScene.from_resultobject を一時的に移動・回転する what-if scene
analyze_coulomb_mobility(...)analyze_coulomb_mobilityオブジェクト別 mobility 解析
compute_potential(...)compute_potential_mesh重心での電位再構成
compute_potential_points(points, ...)compute_potential_points任意点での電位
compute_potential_slices(...)compute_potential_slicesXY/YZ/XZ 断面の電位
compute_electric_field(points, ...)compute_electric_field_points任意点での電場ベクトル
trace_field_lines(seed_points, ...)trace_field_lines電気力線の RK4 追跡
plot_mesh(...)plot_charge_mesh電荷密度の 3D メッシュ描画
plot_potential(...)plot_potential_mesh電位の 3D メッシュ描画
plot_potential_slices(...)plot_potential_slices電位断面の描画
plot_field_lines(seed_points, ...)plot_field_lines_3d電気力線の 3D 描画
plot_bar()plot_charges要素電荷棒グラフ
plot_mesh_source_boxplot(...)plot_mesh_source_boxplotmesh source 別箱ひげ図
plot_coulomb_force_matrix(...)plot_coulomb_force_matrixCoulomb 力行列プロット
animate_mesh(...)animate_history_mesh電荷/電位履歴アニメーション

Fortran 出力ディレクトリを読み込み、FortranRunResult を返します。

from beach import load_fortran_result
result = load_fortran_result("outputs/latest")
print(f"要素数: {result.mesh_nelem}, バッチ数: {result.batches}")
print(f"吸収: {result.absorbed}, 脱出: {result.escaped}")

必須ファイル: summary.txt, charges.csv オプションファイル: mesh_triangles.csv, mesh_sources.csv, charge_history.csv, mesh_potential.csv

フィールド説明
directoryPath出力ディレクトリパス
mesh_nelemintメッシュ要素数
processed_particlesint処理済み粒子数
absorbedint吸収粒子数
escapedint脱出粒子数
batchesint処理済みバッチ数
escaped_boundaryint境界脱出粒子数
survived_max_stepintmax_step 到達粒子数
last_rel_changefloat最終相対電荷変化量
chargesndarray (mesh_nelem,)要素電荷配列 [C]
trianglesndarray (mesh_nelem, 3, 3) | None三角形頂点座標 [m]
mesh_idsndarray (mesh_nelem,) | None要素 mesh ID
mesh_sourcesdict[int, MeshSource] | Nonemesh 種別・surface model・epsilon_r メタデータ
mesh_potential_vndarray (mesh_nelem,) | NoneFortran 出力の重心電位 [V]
historyFortranChargeHistory | None電荷履歴アクセサ

4.1 compute_potential_mesh(result, *, softening, self_term, periodic2, reference_point)

Section titled “4.1 compute_potential_mesh(result, *, softening, self_term, periodic2, reference_point)”

三角形重心での電位を再構成します。Fortran が mesh_potential.csv を出力済みで条件が一致する場合はそちらを優先します。

パラメータデフォルト単位説明
resultFortranRunResult | object(必須)-結果オブジェクト
softeningfloat | NoneNonemNonesim.softening を自動参照
self_termstr"auto"-自己相互作用: "auto" / "area_equivalent" / "exclude" / "softened_point"
periodic2Mapping | NoneNone-2 軸周期設定(後述)。None で自動判定
reference_pointIterable[float] | str | NoneNonem基準電位点。"species1_injection_center" で species 1 注入面中心

戻り値: ndarray (mesh_nelem,) [V]

4.2 compute_potential_points(result, points, *, softening, chunk_size, periodic2, reference_point)

Section titled “4.2 compute_potential_points(result, points, *, softening, chunk_size, periodic2, reference_point)”

任意 3D 点での電位を計算します。

パラメータデフォルト単位説明
pointsndarray (n_points, 3)(必須)mサンプリング点座標
softeningfloat | NoneNonemNone で自動
chunk_sizeint2048-チャンク分割数
periodic2Mapping | NoneNone-None で自動判定
reference_pointIterable[float] | str | NoneNonem基準電位点

戻り値: ndarray (n_points,) [V]

4.3 compute_potential_slices(result, *, box_min, box_max, grid_n, xy_z, yz_x, xz_y, ...)

Section titled “4.3 compute_potential_slices(result, *, box_min, box_max, grid_n, xy_z, yz_x, xz_y, ...)”

XY/YZ/XZ 平面上の電位断面を計算します。

戻り値: dict[str, PotentialSlice2D] (キー: "xy", "yz", "xz")

5.1 calc_coulomb(result, target, source, *, step, softening, torque_origin, periodic2)

Section titled “5.1 calc_coulomb(result, target, source, *, step, softening, torque_origin, periodic2)”

target メッシュグループが source から受ける Coulomb 力とトルクを計算します。

パラメータデフォルト単位説明
resultFortranRunResult | object(必須)-結果オブジェクト
targetint | MeshSelection | Iterable(必須)-ターゲットメッシュグループ (group A)
sourceint | MeshSelection | Iterable(必須)-ソースメッシュグループ (group B)
stepint | None-1-履歴ステップ。-1 で最新、None で最終電荷
softeningfloat0.0mソフトニング長
torque_originstr"target_center"-トルク基準点: "target_center" / "source_center" / "origin"
periodic2Mapping | NoneNone-2 軸周期境界設定。None で自動判定

戻り値: CoulombInteraction

periodic2 パラメータによる周期クーロン和

Section titled “periodic2 パラメータによる周期クーロン和”

periodic2 が指定された場合、ソース電荷の画像シェル ix in [-nimg, nimg], iy in [-nimg, nimg] を 2 軸周期方向に生成し、最近接セル和としてクーロン力/トルクを計算します。

periodic2=None(デフォルト)の場合は、出力ディレクトリ近傍の beach.toml を探索し、sim.field_bc_mode="periodic2" が設定されていれば自動的に周期設定を適用します。これは compute_potential_mesh 等の他の関数と同じ自動判定ロジックです。

フィールド単位説明
group_a_mesh_idstuple[int, ...]-ターゲット mesh ID
group_b_mesh_idstuple[int, ...]-ソース mesh ID
stepint | None-使用した履歴ステップ
softeningfloatm使用したソフトニング長
torque_origin_mndarray (3,)mトルク基準点
force_on_a_Nndarray (3,)Ngroup A に作用する正味力
force_on_b_Nndarray (3,)Ngroup B に作用する正味力
torque_on_a_Nmndarray (3,)N mgroup A に作用する正味トルク
torque_on_b_Nmndarray (3,)N mgroup B に作用する正味トルク
mean_force_on_a_per_element_Nndarray (3,)Nターゲット要素あたり平均力
mean_torque_on_a_per_element_Nmndarray (3,)N mターゲット要素あたり平均トルク
from beach import Beach
b = Beach("outputs/latest")
# mesh_id=0 が mesh_id=1 から受ける Coulomb 力
interaction = b.calc_coulomb(target=0, source=1)
print(f"Force on target: {interaction.force_on_a_N} [N]")
print(f"Torque on target: {interaction.torque_on_a_Nm} [N m]")
# periodic2 を明示指定する場合
interaction_p = b.calc_coulomb(
target=0, source=1,
periodic2={"axes": [0, 1], "lengths": [0.01, 0.01], "image_layers": 2},
)

6.1 compute_electric_field_points(result, points, *, softening, chunk_size, periodic2)

Section titled “6.1 compute_electric_field_points(result, points, *, softening, chunk_size, periodic2)”

任意 3D 点での電場ベクトルを、表面電荷からクーロン則で直接計算します。

計算式: E(r) = K * sum_j q_j * (r - r_j) / |r - r_j|^3

ここで r_j は三角形要素 j の重心、q_j は要素電荷です。

パラメータデフォルト単位説明
resultFortranRunResult | object(必須)-結果オブジェクト
pointsndarray (n_points, 3)(必須)mサンプリング点座標
softeningfloat | NoneNonemソフトニング長。Nonesim.softening を自動参照
chunk_sizeint2048-チャンクサイズ
periodic2Mapping | NoneNone-2 軸周期設定。None で自動判定

戻り値: ndarray (n_points, 3) [V/m]

periodic2 モードでは、サンプリング点を周期セルに wrap した上で、ソース電荷の画像シェルを ix in [-nimg, nimg], iy in [-nimg, nimg] で重畳します。

import numpy as np
from beach import Beach
b = Beach("outputs/latest")
# グリッド点での電場計算
x = np.linspace(0.0, 0.01, 50)
y = np.linspace(0.0, 0.01, 50)
xx, yy = np.meshgrid(x, y)
zz = np.full_like(xx, 0.005)
points = np.column_stack([xx.ravel(), yy.ravel(), zz.ravel()])
efield = b.compute_electric_field(points)
print(f"Shape: {efield.shape}") # (2500, 3)
print(f"E-field [V/m]: {efield[0]}")

7.1 trace_field_lines(result, seed_points, *, ds, max_steps, softening, periodic2, direction, box_min, box_max)

Section titled “7.1 trace_field_lines(result, seed_points, *, ds, max_steps, softening, periodic2, direction, box_min, box_max)”

シード点から電場方向(または逆方向)に RK4 積分で電気力線を追跡します。

パラメータデフォルト単位説明
resultFortranRunResult | object(必須)-結果オブジェクト
seed_pointsndarray (n_seeds, 3)(必須)m力線の開始点座標
dsfloat | NoneNonem積分ステップサイズ。None でメッシュ平均辺長 x 0.5 から自動設定
max_stepsint500-各方向の最大積分ステップ数
softeningfloat | NoneNonemソフトニング長。None で自動
periodic2Mapping | NoneNone-2 軸周期設定。None で自動判定
directionstr"both"-追跡方向: "forward" (電場方向) / "backward" (逆方向) / "both" (両方向)
box_minIterable[float] | NoneNonem境界ボックス下限。力線がこの外に出たら打ち切り
box_maxIterable[float] | NoneNonem境界ボックス上限

戻り値: list[ndarray] — 各要素は shape (n_points_i, 3) の力線座標 [m]

  • 4 次 Runge-Kutta 法 (RK4) で電場の単位ベクトル方向に ds ずつ進行
  • 各 RK4 ステージで電場ノルムが 1e-30 未満になったら打ち切り
  • direction="both" の場合は forward と backward を接合(シード点の重複を除去)
  • box_min / box_max を超えた時点で打ち切り
  • Python 側での直接和計算であり、大規模メッシュ(数万要素以上)では計算時間が長くなります
  • Fortran の treecode/fmm は使用しません。Python 側の電場計算は要素重心の点電荷による direct 和のみです
  • periodic2 では explicit image shell のみを再構成し、oracle residual(Ewald 遠方補正)は Python 側では再現しません
import numpy as np
from beach import Beach
b = Beach("outputs/latest")
# シード点を手動指定
seeds = np.array([
[0.005, 0.005, 0.008],
[0.005, 0.005, 0.002],
])
lines = b.trace_field_lines(seeds, max_steps=1000)
print(f"力線数: {len(lines)}")
for i, line in enumerate(lines):
print(f" 力線 {i}: {line.shape[0]} 点")

7.2 plot_field_lines_3d(result, seed_points, *, ...)

Section titled “7.2 plot_field_lines_3d(result, seed_points, *, ...)”

電気力線を 3D 描画し、オプションでメッシュ表面を電荷密度で着色してオーバーレイします。

パラメータデフォルト説明
resultFortranRunResult | object(必須)結果オブジェクト
seed_pointsndarray (n_seeds, 3)(必須)シード点 [m]
dsfloat | NoneNone積分ステップサイズ [m]
max_stepsint500最大ステップ数
softeningfloat | NoneNoneソフトニング長 [m]
periodic2Mapping | NoneNone周期設定
directionstr"both"追跡方向
box_minIterable[float] | NoneNone境界ボックス下限 [m]
box_maxIterable[float] | NoneNone境界ボックス上限 [m]
show_meshboolTrueメッシュオーバーレイの表示
mesh_alphafloat0.25メッシュ面の透明度
mesh_cmapstr"coolwarm"メッシュの面電荷密度カラーマップ
line_colorstr | NoneNone力線の固定色。Noneline_cmap による色分け
line_cmapstr"plasma"力線のカラーマップ(line_color=None 時)
line_widthfloat1.2力線の線幅
view_elevfloat24.0仰角 [deg]
view_azimfloat-58.0方位角 [deg]
titlestr"Electric field lines"プロットタイトル
figsizetuple[float, float](9, 7)Figure サイズ [inch]

戻り値: (figure, axes) — matplotlib の Figure / Axes3D

  • 各力線は線として描画。line_color=None の場合は力線ごとに line_cmap で色分け
  • 力線の中間点に方向矢印(quiver)を描画
  • シード点を赤色の散布点として描画
  • show_mesh=True の場合、三角形メッシュを面電荷密度 q / A で着色し半透明で重ねる
import numpy as np
from beach import Beach
b = Beach("outputs/latest")
seeds = np.array([
[0.005, 0.005, 0.008],
[0.003, 0.007, 0.006],
[0.007, 0.003, 0.006],
])
fig, ax = b.plot_field_lines(
seeds,
max_steps=800,
direction="both",
show_mesh=True,
mesh_alpha=0.3,
line_cmap="viridis",
view_elev=30,
view_azim=-45,
)
fig.savefig("field_lines.png", dpi=150)

電位再構成、Coulomb 力計算、電場計算、電気力線追跡のすべてで共通の periodic2 パラメータが利用できます。

デフォルトの None では、出力ディレクトリ近傍の beach.toml を探索し、sim.field_bc_mode="periodic2" が設定されている場合に自動的に周期境界設定を適用します。 設定ファイルが見つからない場合や field_bc_modeperiodic2 でない場合は自由空間モードで計算します。

periodic2 は以下のキーを持つ Mapping で指定します。

キー必須デフォルト説明
axeslist[int] (長さ 2)必須-周期軸の 0-based インデックス (例: [0, 1] は x, y 軸)
lengthslist[float] (長さ 2)必須-各周期軸のボックス長 [m]。正の値
originslist[float] (長さ 2)-[0.0, 0.0]各周期軸のボックス原点 [m]
box_minlist[float] (長さ 3)--origins の代替。3D ボックス下限から周期軸の原点を抽出
image_layersint-1画像シェルの層数。各周期軸で [-N, N] を評価
far_correctionstr-"none""auto" / "none" / "m2l_root_oracle"auto は互換用に "none" として扱う。Python 側は設定互換のために保持するが、oracle residual 自体は再現しない
ewald_alphafloat-0.0Ewald 分解パラメータ(予約)
ewald_layersint-4Ewald 打切り深さ(予約)

originsbox_min が両方指定された場合は origins が優先されます。

p2 = {
"axes": [0, 1],
"lengths": [0.01, 0.01],
"image_layers": 2,
}
potential = b.compute_potential(periodic2=p2)
efield = b.compute_electric_field(points, periodic2=p2)
interaction = b.calc_coulomb(target=0, source=1, periodic2=p2)
lines = b.trace_field_lines(seeds, periodic2=p2)

8.3 Python 側の periodic2 実装の制限

Section titled “8.3 Python 側の periodic2 実装の制限”
  • Python 側では explicit image shell による直接和のみで周期和を再構成します
  • Fortran 側 FMM の明示 m2l_root_oracle による Ewald 遠方補正は Python 側では再現されません。far_correction は設定の互換性のために保持されますが、Python direct 和の計算には影響しません
  • 大きな image_layers を指定するほど精度は向上しますが、計算量は (2*N+1)^2 倍に増加します

9.1 analyze_coulomb_mobility(result, *, step, softening, config_path, gravity, support_normal, ...)

Section titled “9.1 analyze_coulomb_mobility(result, *, step, softening, config_path, gravity, support_normal, ...)”

オブジェクト単位で Coulomb 力による滑り・転がり・浮上の傾向を解析します。

戻り値: CoulombMobilityAnalysis (.recordsCoulombMobilityRecord のタプルを格納)

make build-kernel で生成した build/libbeach_field_kernel.soctypes 経由で読み込み、シミュレーションと同じ Fortran FMM core で電場・電位を評価します。config_path または自動探索された beach.toml から、softening、periodic2、tree 設定を読みます。

from beach import Beach, FieldKernel
run = Beach("outputs/latest")
with FieldKernel.from_result(run) as kernel:
e = kernel.eval_e([[0.0, 0.0, 0.01]])

共有ライブラリを別パスに置く場合は library_path= または環境変数 BEACH_FIELD_KERNEL_LIB を指定します。

10.2 calc_object_forces_kernel(result, ...)

Section titled “10.2 calc_object_forces_kernel(result, ...)”

各 object について自身の source 電荷をゼロにしたうえで、sum(q_i E_not_self(r_i)) とトルクを計算します。Fortran kernel 経路を使い、beach.toml で明示された periodic2 設定(m2l_root_oracle を含む)を渡すため、Python direct 和の calc_coulomb よりシミュレーション側の場定義に近い診断です。

from beach import Beach
run = Beach("outputs/latest")
records = run.calc_object_forces_kernel()
for record in records:
print(record.mesh_id, record.total_charge_C, record.force_N)

Beach.scene() は、出力済みの帯電 mesh を Python 側で一時編集する what-if view です。 move / rotate は新しい scene を返し、各要素の電荷は同じ要素に付いたまま重心・頂点だけを剛体変換します。その後 calc_object_forces_kernel を呼ぶと、編集後の geometry を source/target として Fortran field kernel に渡します。

from beach import Beach
run = Beach("outputs/latest", config_path="examples/beach.toml")
scene = run.scene()
moved = scene.move(2, by=[1.0e-3, 0.0, 0.0]).rotate(
2,
axis=[0.0, 0.0, 1.0],
angle_deg=15.0,
)
records = moved.calc_object_forces_kernel(target_mesh_ids=[2])
print(records[0].force_N, records[0].torque_Nm)

Python 側の剛体変換は既定では NumPy で処理します。Numba を使いたい場合は任意依存として pip install ".[accel]" を入れ、run.scene(transform_backend="numba") を指定できます。FMM・periodic2・遠方補正の意味を決める主計算は引き続き Fortran kernel 側で行います。

fig, ax = b.plot_mesh(cmap="coolwarm") # 電荷密度
fig, ax = b.plot_potential(reference_point="species1_injection_center") # 電位
fig, axes = b.plot_potential_slices(
box_min=[0, 0, 0], box_max=[0.01, 0.01, 0.01],
xy_z=0.005,
)
gif_path = b.animate_mesh("charge_animation.gif", quantity="charge", fps=10)
fig, ax = b.plot_coulomb_force_matrix(component="z")

v1.0.0 以降は beachx 統一 CLI を推奨します。

コマンド説明
beachx inspect <output_dir>出力ディレクトリの要約表示
beachx animate <output_dir>電荷/電位履歴のアニメーション GIF 生成
beachx workload <config.toml>ワークロード見積もり
beachx slices <output_dir>電位断面の描画
beachx profile <output_dir>パフォーマンスプロファイルの描画
beachx coulomb <output_dir>Coulomb 力行列の描画
beachx mobility <output_dir>Coulomb mobility 解析
beachx kernel-forces <output_dir>Fortran field kernel による object 別合力 CSV 出力
beachx lint <config.toml>TOML / JSON Schema / BEACH 制約の設定検査
beachx config validate <config.toml>設定ファイルのバリデーション
beachx model close-pack密充填モデルの生成

以下の旧エントリポイントは後方互換のため残されていますが、将来のバージョンで削除される可能性があります。

コマンド説明
beach-inspect <output_dir>出力ディレクトリの要約表示
beach-animate-history <output_dir>電荷/電位履歴のアニメーション GIF 生成
beach-estimate-workload <config.toml>ワークロード見積もり
beach-plot-potential-slices <output_dir>電位断面の描画
beach-plot-performance-profile <output_dir>パフォーマンスプロファイルの描画
beach-plot-coulomb-force-matrix <output_dir>Coulomb 力行列の描画
シンボル単位説明
K_COULOMB8.9875517923e9N m^2 / C^2クーロン定数