Skip to content

BEACH Agent User Guide

Reference guide for AI agents operating BEACH simulations. Intended to be loaded from CLAUDE.md with @import docs//BEACH/en/agent-user-guide.html. Normal BEACH users do not need to read this page. Start from BEACH Documentation instead.


BEACH (BEM + Accumulated CHarge) is a hybrid boundary-element-method plus particle-tracking simulator for charge accumulation on insulator surfaces.

  • Fortran core: particle dynamics, electric-field solver, collision detection, charge deposition
  • Python layer: configuration management, post-processing, visualization
  • Version: 1.4.0

Terminal window
# 1. Install
pip install beach-bem
# 2. Create a configuration file
beachx config init
# 3. Validate the configuration
beachx lint beach.toml
# 4. Run the simulation
beach beach.toml
# 5. Inspect results
beachx inspect outputs/latest
ItemRequirement
Fortran compilergfortran, or compatible
fpmv0.10+
Python3.10+
Main Python dependenciesmatplotlib >= 3.8, numpy >= 1.24
Terminal window
make check # development build check with fixed dev version
make build # build with git describe version
make run CONFIG=beach.toml # run with fixed dev version
make install-generic # portable gfortran build
make install-camphor # Intel compiler optimized build
make test # L1: Python + quick Fortran tests

make check / make test / make run use BEACH_VERSION_MODE=dev and keep the version macro passed to Fortran stable. Because the fpm compile-flag hash does not change when the git hash changes, incremental compilation during development is easier to reuse. When an executable with the git hash is required, use make build VERSION_MODE=git or make install.

Terminal window
fpm run --profile release --flag "-fopenmp" -- beach.toml
Terminal window
FPM_FC=mpiifort fpm run --profile release \
--flag "-fpp -DUSE_MPI -qopenmp" \
--runner "mpirun -n 4" -- beach.toml
Terminal window
make test-l0 # L0: static/schema/build check
make test # L1: normal development loop
make test-l2 # L2: contract/integration
make test-l3 # L3: heavy/release gate
make test-heavy # heavy Fortran targets only
make test-fortran-far-correction # explicit oracle far-correction diagnostics
make test-full # unfiltered fpm test
make test-mpi # MPI テスト
pytest -q # Python テストのみ

make test is the L1 alias and is the normal default for the inner AI/development loop. Long-running FMM targets are run explicitly with make test-l3 / make test-heavy / make test-fortran-heavy / make test-full. m2l_root_oracle far-correction diagnostics are opt-in through make test-fortran-far-correction or make test-full. Individual targets can be checked with FPM_ACTION=test ./build.sh --target <name>.


  1. beach.toml: the normal file to edit, read directly by the Fortran executable
  2. beachx lint: validates TOML parsing, JSON Schema, high-level notation, and known constraints
  3. Fortran parser: normalizes high-level notation into final keys such as box_min / box_max / center
ParameterTypeDefaultDescription
dtfloat1.0e-9Time step [s]
rng_seedint12345Random seed
batch_countint1Number of batches in normal runs. During resume, cumulative target batch count
batch_durationfloat-Batch duration [s], mutually exclusive with batch_duration_step
batch_duration_stepfloat-Resolved as batch_duration = dt * batch_duration_step
max_stepint400Maximum integration steps per particle
tol_relfloat1.0e-8Monitoring metric, not an early-stop condition
q_floorfloat1.0e-30Denominator floor for relative-change calculation
softeningfloat1.0e-6Electric-field softening length [m]
ParameterTypeDefaultChoicesDescription
field_solverstring”auto”direct, treecode, fmm, autoElectric-field evaluation method
field_bc_modestring”free”free, periodic2Boundary condition; periodic2 requires fmm
field_periodic_image_layersint1>= 0Number of periodic2 image-shell layers
field_periodic_far_correctionstring”none”auto, none, m2l_root_oracleFar correction; auto is treated as none for compatibility
field_periodic_ewald_alphafloat0.0>= 0Ewald splitting parameter, 0 means automatic
field_periodic_ewald_layersint4>= 0Ewald shell depth
tree_thetafloat0.5(0, 1]Tree-method MAC parameter
tree_leaf_maxint16>= 1Maximum number of elements per leaf node
tree_min_nelemint256>= 1Threshold for auto -> treecode switch

auto estimation table (when tree_theta / tree_leaf_max are unspecified):

Element countthetaleaf_max
< 15000.4012
1500-99990.5016
10000-499990.5820
50000+0.6524
ParameterTypeDefaultDescription
b0float[3][0, 0, 0]Uniform magnetic field [T]
reservoir_potential_modelstring”none”none, infinity_barrier
phi_inftyfloat0.0Infinity reference potential [V]
injection_face_phi_grid_nint3Injection-face potential grid resolution NxN
raycast_max_bounceint16Maximum number of ray reflections for photo_raycast
ParameterTypeDefaultDescription
sheath_injection_modelstring”none”none, zhao_auto, zhao_a, zhao_b, zhao_c, floating_no_photo
sheath_alpha_degfloat60.0Solar elevation angle [deg]
sheath_photoelectron_ref_density_cm3float64.0Reference photoelectron density [cm^-3]
sheath_reference_coordinatefloat-Sheath reference-plane coordinate [m]
sheath_electron_drift_modestring”normal”normal, full
sheath_ion_drift_modestring”normal”normal, full
ParameterTypeDefaultDescription
use_boxboolfalseEnable box boundary
box_minfloat[3][-1, -1, -1]Lower limit [m]
box_maxfloat[3][1, 1, 1]Upper limit [m]
bc_{x,y,z}_{low,high}string”open”open, reflect, periodic

periodic2 constraint: exactly two axes are periodic, and the remaining one axis is open/reflect.

[[particles.species]] Section - Particle Species (at least one required)

Section titled “[[particles.species]] Section - Particle Species (at least one required)”
ParameterTypeDefaultDescription
enabledbooltrueEnable this species
source_modestring”volume_seed”volume_seed, reservoir_face, photo_raycast
q_particlefloat-1.602e-19Particle charge [C]
m_particlefloat9.109e-31Particle mass [kg]
pos_lowfloat[3][-0.4, -0.4, 0.2]Lower generation-position limit [m]
pos_highfloat[3][0.4, 0.4, 0.5]Upper generation-position limit [m]
drift_velocityfloat[3][0, 0, -8e5]Drift velocity [m/s]
temperature_kfloat20000Temperature [K], mutually exclusive with temperature_ev
temperature_evfloat-Temperature [eV]
ParameterTypeDefaultDescription
npcls_per_stepint0Number of particles generated per batch
w_particlefloat1.0Macro-particle weight

Constraint: sum of npcls_per_step across all species >= 1.

reservoir_face Mode (Physical Flux Injection)

Section titled “reservoir_face Mode (Physical Flux Injection)”
ParameterTypeDefaultDescription
number_density_cm3float-Upstream density [cm^-3], mutually exclusive with number_density_m3
number_density_m3float-Upstream density [m^-3]
w_particlefloat-Macro-particle weight, mutually exclusive with target_macro_particles_per_batch
target_macro_particles_per_batchint-Target number of macro particles per batch; -1 reuses the species[1] weight
inject_facestringrequiredx_low, x_high, y_low, y_high, z_low, z_high

Constraint: use_box = true and batch_duration > 0 are required. pos_low/pos_high are placed on the specified face.

photo_raycast Mode (Photoelectron Emission)

Section titled “photo_raycast Mode (Photoelectron Emission)”
ParameterTypeDefaultDescription
emit_current_density_a_m2floatrequiredEmission current density [A/m^2]
rays_per_batchintrequiredNumber of rays per batch
deposit_opposite_charge_on_emitboolfalseDeposit opposite-sign charge on the emitting element
photo_escape_modelstring"none"none / boltzmann_cutoff. The latter Boltzmann-suppresses PE escape current at positive potential barriers
normal_drift_speedfloat0.0Normal-direction drift speed [m/s]
ray_directionfloat[3]inward normalRay direction vector
ParameterTypeDefaultDescription
modestring”auto”auto, obj, template
obj_pathstringexamples/simple_plate.objOBJ file path
surface_modelstring”insulator”Surface model for the whole OBJ mesh (insulator, conductor, dielectric)
epsilon_rfloat1.0Relative permittivity for the whole OBJ mesh (>= 1)
obj_scalefloat1.0Scale factor
obj_rotationfloat[3][0, 0, 0]Rotation angles [deg], extrinsic x->y->z
obj_offsetfloat[3][0, 0, 0]Translation [m]

Transform order: scale -> rotate -> offset

[[mesh.templates]] - Procedural Mesh Generation

Section titled “[[mesh.templates]] - Procedural Mesh Generation”

Common: enabled (bool), kind (enum), surface_model (enum), epsilon_r (float), center (float[3])

conductor is redistributed as an equipotential floating conductor per mesh_id. The current implementation supports only sim.field_bc_mode = "free". OBJ input reads the entire file as mesh_id = 1, so separated conductor parts in a single OBJ are also treated as the same floating conductor. To treat them as independent conductors, split their mesh_id values, for example by using template input. dielectric is currently metadata that retains per-object epsilon_r; physical branches for dielectric polarization are an extension point.

kindMain parameters
planesize_x, size_y, nx, ny
plate_holesize_x, size_y, radius, n_theta, n_r
diskradius, n_theta, n_r
annulusradius, inner_radius, n_theta, n_r
boxsize (float[3]), nx, ny, nz
cylinderradius, height, n_theta, n_z, cap, cap_top, cap_bottom
sphereradius, n_lon, n_lat
ParameterTypeDefaultDescription
write_filesbooltrueEnable file output
write_mesh_potentialboolfalseOutput element potentials to mesh_potential.csv
write_potential_historyboolfalseOutput potential history
dirstring”outputs/latest”Output directory
history_strideint1History output interval [batches], disabled at 0
resumeboolfalseResume from a checkpoint
restart_fromstringnoneCheckpoint read source when resume=true. New output is saved to dir

Output destination: the directory specified by output.dir, default outputs/latest/

FileFormatContents
summary.txtText (key-value)Run metadata and statistics
charges.csvCSV: elem_idx, charge_CFinal element charge
mesh_triangles.csvCSV: elem_idx, v0x, v0y, v0z, v1x, v1y, v1z, v2x, v2y, v2z, charge_C, mesh_idTriangle vertices, charge, and mesh_id
mesh_sources.csvCSV: mesh_id, source_kind, template_kind, surface_model, epsilon_r, elem_countMesh source metadata
rng_state.txtTextRandom state, for resume
FileConditionFormat
charge_history.csvhistory_stride > 0CSV: batch, elem_idx, charge_C
potential_history.csvwrite_potential_history = true and history_stride > 0CSV: batch, elem_idx, potential_V
mesh_potential.csvwrite_mesh_potential = trueCSV: elem_idx, potential_V
macro_residuals.csvWhen reservoir_face is usedCSV: injection residual state
performance_profile.csvWhen the BEACH_PROFILE=1 environment variable is setCSV: measured times for each region
  • rng_state_rank00000.txt, rng_state_rank00001.txt, …
  • macro_residuals_rank00000.csv, macro_residuals_rank00001.csv, …

Terminal window
beachx lint [beach.toml] # check schema and semantic constraints
beachx config init [beach.toml] # create a new beach.toml
beachx config validate [beach.toml] # validate high-level notation and constraints
beachx config diff left.toml right.toml # compare configurations
Terminal window
beachx inspect [output_dir] # print summary
beachx inspect outputs/latest --show # display plots
beachx inspect outputs/latest --save-bar charges.png
beachx inspect outputs/latest --save-mesh charges_mesh.png
beachx inspect outputs/latest --save-potential-mesh potential_mesh.png
beachx inspect outputs/latest --apply-periodic2-mesh
beachx inspect outputs/latest --periodic2-repeat 1
Terminal window
beachx animate [output_dir] # 履歴アニメーション
beachx animate outputs/latest --quantity charge # 電荷 (デフォルト)
beachx animate outputs/latest --quantity potential # ポテンシャル
beachx animate outputs/latest --save-gif charge.gif
beachx animate outputs/latest --total-frames 200
beachx animate outputs/latest --frame-stride 2 --fps 15
Terminal window
beachx slices [output_dir]
beachx slices outputs/latest --grid-n 200
beachx slices outputs/latest --xy-z 0.5 --yz-x 0.5 --xz-y 0.5
beachx slices outputs/latest --vmin -20 --vmax 20
beachx slices outputs/latest --save slices.png
Terminal window
beachx coulomb [output_dir]
beachx coulomb outputs/latest --component z
beachx coulomb outputs/latest --target-kinds sphere
beachx coulomb outputs/latest --save forces.png
Terminal window
beachx mobility [output_dir]
beachx mobility outputs/latest --density-kg-m3 2500
beachx mobility outputs/latest --mu-static 0.4
beachx mobility outputs/latest --save-csv mobility.csv
Terminal window
beachx workload beach.toml
beachx workload beach.toml --threads 8

from beach import Beach
run = Beach("outputs/latest")
# 電荷分布の可視化
fig, ax = run.plot_charges(step=-1)
fig, ax = run.plot_mesh()
fig, ax = run.plot_mesh_source_boxplot(quantity="charge", step=-1)
# ポテンシャル解析
fig, ax = run.plot_potential()
slices = run.compute_potential_slices(grid_n=200)
fig, axes = run.plot_potential_slices(slices)
# クーロン力解析
fig, ax = run.plot_coulomb_force_matrix(component="z")
result = run.analyze_coulomb_mobility(density_kg_m3=2500, mu_static=0.4)
# 電場・電界線
field = run.compute_electric_field_points(points)
lines = run.trace_field_lines(seed_points, direction="forward")
fig = run.plot_field_lines_3d(lines)
# アニメーション
run.animate_mesh(quantity="charge", save_path="charge.gif")
FunctionPurpose
plot_mesh()3D mesh visualization
plot_potential()3D potential mesh
plot_charges()Bar chart of element charge
plot_mesh_source_boxplot()Box plot by mesh source
animate_mesh()Mesh animation from history
compute_potential_mesh()Element-potential reconstruction
compute_potential_points()Potential evaluation at arbitrary points
compute_potential_slices()Section-data calculation
compute_electric_field_points()Electric-field vector evaluation
plot_potential_slices()2D section plots
plot_coulomb_force_matrix()Force-matrix heatmap
analyze_coulomb_mobility()Mobility analysis
trace_field_lines()Field-line integration
plot_field_lines_3d()Field-line plus mesh drawing

The Fortran parser normalizes helper keys in beach.toml into runtime keys while loading the file.

  • sim.box_origin + sim.box_size -> sim.box_min / sim.box_max
  • inject_region_mode = "face_fraction" + uv_low / uv_high -> pos_low / pos_high
  • mesh.templates placement_mode = "box_anchor" -> center
  • mesh.groups.* scale_from / placement_mode -> actual size and coordinates for each template

Runtime settings belong under sim, particles, mesh, and output.


[sim]
dt = 1.0e-8
batch_count = 10
max_step = 500
use_box = true
box_min = [0, 0, 0]
box_max = [1, 1, 1]
[[particles.species]]
source_mode = "volume_seed"
npcls_per_step = 100
[mesh]
mode = "template"
[[mesh.templates]]
kind = "plane"
size_x = 1.0
size_y = 1.0
nx = 10
ny = 10
[output]
dir = "outputs/test"
[sim]
batch_count = 200
field_solver = "fmm"
field_bc_mode = "periodic2"
use_box = true
box_min = [0.0, 0.0, 0.0]
box_max = [1.0, 1.0, 10.0]
bc_x_low = "periodic"
bc_x_high = "periodic"
bc_y_low = "periodic"
bc_y_high = "periodic"
bc_z_low = "open"
bc_z_high = "open"
[[particles.species]]
source_mode = "volume_seed"
q_particle = -1.602176634e-19
m_particle = 9.10938356e-31
npcls_per_step = 10
[[particles.species]]
source_mode = "volume_seed"
q_particle = 1.602176634e-19
m_particle = 1.672482821616e-27
npcls_per_step = 10
Terminal window
beach beach.toml
beachx inspect outputs/latest --save-mesh charges.png
beachx animate outputs/latest --quantity charge --save-gif charge.gif
beachx slices outputs/latest --save slices.png
beachx coulomb outputs/latest --save forces.png
beachx mobility outputs/latest --density-kg-m3 2500 --mu-static 0.4

FeatureRequired conditions
reservoir_faceuse_box=true, batch_duration>0, inject_face specified
photo_raycastuse_box=true, batch_duration>0, emit_current_density_a_m2>0, rays_per_batch>=1
periodic2field_solver=fmm, exactly two periodic axes, use_box=true
Sheath modelCompatible with reservoir_potential_model = "none"
Resumewrite_files=true, checkpoint file exists, in the restart_from directory when specified, MPI size matches
Performance profilingEnvironment variable BEACH_PROFILE=1
MPI runCompiled with -DUSE_MPI, MPI compiler wrapper used

BEACH/
├── app/main.f90 # Fortran entry point
├── src/ # Fortran library modules
│ ├── config/ # configuration parser
│ ├── core/ # simulator main loop
│ ├── mesh/ # triangle mesh management
│ ├── particles/ # particle dynamics (Boris pusher)
│ ├── physics/ # electric-field solvers (direct, treecode, FMM)
│ └── runtime/ # output and restart
├── beach/ # Python package
│ ├── cli/ # CLI subcommands
│ ├── config/ # configuration validation
│ └── fortran_results/ # post-processing and visualization
├── schemas/ # JSON Schema for validation
│ └── beach.schema.json # beach.toml schema
├── examples/ # sample configurations and scripts
├── tests/ # test suite
├── docs/ # documentation
├── fpm.toml # Fortran package manifest
├── pyproject.toml # Python package metadata
├── Makefile # build automation
├── SPEC.md # Fortran implementation specification
└── AGENTS.md # agent configuration

DocumentContents
SPEC.mdFortran implementation specification, authoritative
docs//BEACH/en/output-guide.htmlHow to read output files
docs//BEACH/en/configuration-recipes.htmlCommon configuration recipes
docs//BEACH/en/parameters.htmlDetailed parameter specification
docs//BEACH/en/workflow.htmlExecution workflow and I/O
docs//BEACH/en/algorithms.htmlAlgorithm overview
docs//BEACH/en/field-solvers.htmlField solvers and periodic2 field boundary
docs//BEACH/en/particle-charge-loop.htmlParticle tracking, collision, and charge accumulation
docs//BEACH/en/fmm-core.htmlFMM math and Ewald
docs//BEACH/en/batch-duration-stability.htmlbatch_duration stability
docs//BEACH/en/configuration.htmlbeachx config and high-level notation
docs//BEACH/en/postprocess-tutorial.htmlPost-processing tutorial
docs//BEACH/en/python-postprocess-api.htmlPython API reference
schemas/beach.schema.jsonJSON Schema for IDE validation