Execution and Development Workflow
The project is centered on the Fortran runtime. Python handles post-processing, visualization, and utility
workflows. For normal users, the recommended path is to install beach-bem and run the beach command.
1. User Setup (Recommended)
Section titled “1. User Setup (Recommended)”1.1 Check Tools
Section titled “1.1 Check Tools”make --versiongfortran --versionfpm --versionpython --version1.2 Install from PyPI
Section titled “1.2 Install from PyPI”python -m pip install -U pip setuptools wheelpython -m pip install beach-bemDuring pip install, make install installs both the Python CLI and the Fortran runtime binary.
Pip builds use INSTALL_PROFILE=auto by default and fall back to generic when needed.
Set BEACH_PIP_FALLBACK_GENERIC=0 to disable that fallback.
export PATH="$HOME/.local/bin:$PATH"To try the development version directly from Git:
python -m pip install "git+https://github.com/Nkzono99/BEACH.git"2. Development Workflow
Section titled “2. Development Workflow”2.1 Python Editable Install
Section titled “2.1 Python Editable Install”python -m pip install -U pip setuptools wheelpython -m pip install -e . --no-build-isolation2.2 Fortran Runtime (make)
Section titled “2.2 Fortran Runtime (make)”make checkmake run CONFIG=examples/beach.tomlmake check is the standard development build check. It uses BEACH_VERSION_MODE=dev to pass a stable
version string such as 1.4.0-dev to the Fortran side, so changes to the git hash do not invalidate fpm’s
compile-flag hash and incremental builds stay reusable.
make build and make install embed a git-hash version by default. Override the version mode when needed.
make build VERSION_MODE=devmake build VERSION_MODE=plainmake build VERSION_MODE=gitInstall profiles can also be selected explicitly.
make install-genericmake install-camphor2.3 Direct fpm Execution
Section titled “2.3 Direct fpm Execution”fpm run --profile release --flag "-fopenmp" -- examples/beach.tomlFor normal development, prefer make run / make check through build.sh. The wrapper passes
__BEACH_VERSION__ and __BEACH_VERSION_MODE__ consistently.
2.4 Tests
Section titled “2.4 Tests”make test-l0 # L0: static/schema/build checkmake test # L1: normal development loopmake test-l2 # L2: contract/integrationmake test-l3 # L3: heavy/release gatemake test-heavy # heavy Fortran targets onlymake test-fortran-far-correction # explicit oracle far-correction diagnosticsmake test-full # unfiltered fpm testThe test suite is tiered for the development loop.
- L0:
git diff --check, JSON schema parse check,make check - L1: L0 + Python tests + lightweight Fortran test targets (
make test/make test-l1) - L2: L1 + contract/integration targets such as the C field-kernel contract
- L3: L2 + heavy FMM targets for release gates, nightly checks, and integration before
main
make test-fortran aliases the lightweight Fortran targets. Heavy FMM targets such as
test_dynamics_fmm and test_coulomb_fmm_core_basic are excluded from normal make test and must be run with
make test-l3, make test-heavy, make test-fortran-heavy, or make test-full.
The m2l_root_oracle far-correction diagnostics are even heavier and require
make test-fortran-far-correction or unfiltered make test-full.
Run a single target with:
FPM_ACTION=test ./build.sh --target test_versionOn KUDPC login nodes, do not run make test*, fpm test, or equivalent build/test payloads directly.
Submit them to compute nodes with tssrun or sbatch.
3. Run Flow
Section titled “3. Run Flow”Usually, edit beach.toml and pass that file directly to beach. See
beachx config / High-Level Notation Guide for the high-level notation layer.
- Prepare
beach.toml. - Check it with
beachx lint beach.toml. - Run the simulation with
beach beach.toml. - Inspect files under
output.dir. - Visualize with Python CLI commands or the
BeachAPI.
See Input Parameters Reference for the beach.toml specification.
3.1 Shortest Example
Section titled “3.1 Shortest Example”mkdir run_periodic2cd run_periodic2beachx config initbeachx lint beach.tomlbeach beach.toml3.2 Direct beach.toml Use
Section titled “3.2 Direct beach.toml Use”- Prepare
beach.toml(see Input Parameters Reference). - Use high-level notation if useful; the Fortran parser resolves it while loading.
- Run the simulation with
beach beach.toml. - Inspect
output.dir. - Visualize with a Python CLI command or the
BeachAPI.
4. Run Commands
Section titled “4. Run Commands”4.1 Recommended: beach
Section titled “4.1 Recommended: beach”beach beach.tomlWithout arguments, beach reads beach.toml from the current directory.
4.2 Thread Count
Section titled “4.2 Thread Count”OMP_NUM_THREADS=8 beach beach.toml4.3 MPI + OpenMP
Section titled “4.3 MPI + OpenMP”After installing an MPI build, launch beach through the MPI runner.
mpirun -n 4 beach examples/beach.toml4.4 Profiling
Section titled “4.4 Profiling”Enable coarse phase profiling with:
BEACH_PROFILE=1 OMP_NUM_THREADS=8 beach examples/beach.tomlFor scaling comparisons, use the rank_max_s value on the simulation_total row in performance_profile.csv.
Visualization example:
beachx profile outputs/latest/performance_profile.csv \ --save outputs/latest/performance_profile.png5. Output Files
Section titled “5. Output Files”Primary outputs:
summary.txtcharges.csvmesh_potential.csvwhenwrite_mesh_potential = truemesh_triangles.csvmesh_sources.csvcharge_history.csvwhenhistory_stride > 0potential_history.csvwhenwrite_potential_history = trueandhistory_stride > 0performance_profile.csvwhenBEACH_PROFILE=1rng_state.txtmacro_residuals.csv
mesh_triangles.csv includes mesh_id for each element. mesh_sources.csv maps each mesh_id to the source
template kind, surface model, epsilon_r, and element count. conductor is relaxed as a floating conductor
only with field_bc_mode = "free". dielectric is metadata-only in the current implementation; summary.txt
also prints a note when it appears. Enabling mesh_potential.csv stores centroid potential [V] with the same
element ordering.
MPI runs (world_size > 1) write rank-local RNG state and residual files.
rng_state_rank00000.txt,rng_state_rank00001.txt, …macro_residuals_rank00000.csv,macro_residuals_rank00001.csv, …
6. Workload Estimation
Section titled “6. Workload Estimation”For reservoir_face / photo_raycast, particle counts per batch are dynamic, so estimating the workload first
is recommended.
beachx workload examples/beach.toml --threads 8Rank-local estimate with residuals:
beachx workload examples/beach.toml \ --threads 8 \ --mpi-ranks 4 \ --mpi-rank 0 \ --macro-residuals outputs/latest/macro_residuals_rank00000.csv7. Resume Runs
Section titled “7. Resume Runs”[output]dir = "outputs/latest"resume = trueRerunning beach with the same output.dir reads summary.txt, charges.csv, and RNG state and continues
from the checkpoint. Use restart_from when the checkpoint directory and the new output directory differ.
[output]dir = "outputs/continuation"resume = truerestart_from = "../parent_run/outputs/latest"In that case, checkpoint files are read from restart_from, while the new summary.txt, charges.csv,
history files, and RNG state are written under dir.
sim.batch_count is the cumulative target batch count. If an existing checkpoint has batches=100 and the new
batch_count=150, only 50 additional batches run. If batch_count is smaller than the completed checkpoint
batch count, execution stops.
For MPI resume, the mpi_world_size in summary.txt must match the current number of ranks.
8. Python Post-processing
Section titled “8. Python Post-processing”8.1 CLI
Section titled “8.1 CLI”beachx inspect outputs/latest \ --save-bar outputs/latest/charges_bar.png \ --save-mesh outputs/latest/charges_mesh.png \ --save-potential-mesh outputs/latest/potential_mesh.png \ --potential-self-term area-equivalent
# Draw a sim.field_bc_mode = "periodic2" mesh wrapped into the periodic cell.beachx inspect outputs/latest \ --save-mesh outputs/latest/charges_mesh_periodic.png \ --save-potential-mesh outputs/latest/potential_mesh_periodic.png \ --apply-periodic2-mesh
# Tile the periodic mesh by n layers. For 1, this draws 3x3 = 9 copies.beachx inspect outputs/latest \ --save-mesh outputs/latest/charges_mesh_tiled.png \ --periodic2-repeat 1 \ --apply-periodic2-mesh
beachx animate outputs/latest \ --quantity charge \ --save-gif outputs/latest/charge_history.gif \ --total-frames 200
beachx slices outputs/latest \ --grid-n 200 \ --vmin -20 --vmax 20 \ --save outputs/latest/potential_slices.png
beachx coulomb outputs/latest \ --component z \ --save outputs/latest/coulomb_force_z.png
beachx mobility outputs/latest \ --density-kg-m3 2500 \ --mu-static 0.4 \ --save-csv outputs/latest/mobility_summary.csv
# Use the same field kernel as the Fortran FMM core to output net charge, force, and torque per object.make build-kernelbeachx kernel-forces outputs/latest \ --save-csv outputs/latest/object_forces_kernel.csvbeachx coulomb reads object kind and order from nearby beach.toml mesh.templates when available, and by
default places all objects along the target axis for visualization. Use --target-kinds sphere to restrict the
target set. beachx mobility treats plane as the support by default and writes object force/torque plus
lift_ratio, slide_ratio, and roll_ratio to CSV. Mass-derived indicators need --density-kg-m3 and geometry
from beach.toml. beachx kernel-forces calls the Fortran FMM core through libbeach_field_kernel, using
sim.softening, sim.field_bc_mode, periodic2, and tree settings from beach.toml. Build the library with
make build-kernel; if it is elsewhere, pass --library or set BEACH_FIELD_KERNEL_LIB. Use
--config path/to/beach.toml when no config exists near the output directory.
Legacy aliases such as beach-inspect, beach-animate-history, beach-plot-coulomb-force-matrix,
beach-plot-potential-slices, beach-estimate-workload, and beach-plot-performance-profile remain available
for now, but are deprecated.
8.2 Python API
Section titled “8.2 Python API”from beach import Beach
beach = Beach("outputs/latest")print(beach.result.absorbed, beach.result.escaped)# History is always lazy-loaded.history_step10 = beach.result.history_at(10)if beach.result.history is not None: print(beach.result.history.batch_indices)
beach.plot_bar()beach.plot_mesh()beach.plot_potential()beach.plot_mesh(apply_periodic2_mesh=True)beach.plot_potential(apply_periodic2_mesh=True)beach.plot_potential_slices( box_min=[0.0, 0.0, 0.0], box_max=[1.0, 1.0, 10.0], grid_n=200, vmin=-20.0, vmax=20.0,)beach.animate_mesh("outputs/latest/charge_history.gif", quantity="charge", total_frames=200)
mesh1 = beach.get_mesh(1)mesh2, mesh3 = beach.get_mesh(2, 3)mesh1_step10 = beach.get_mesh(1, step=10)charge_step10 = beach.get_mesh_charge(1, step=10)
interaction = beach.calc_coulomb(target=[mesh1, mesh2], source=[mesh3], step=10)print(interaction.force_on_a_N, interaction.torque_on_a_Nm)
fig_force, ax_force = beach.plot_coulomb_force_matrix( component="z",)fig_force.savefig("outputs/latest/coulomb_force_z.png", dpi=150)
mobility = beach.analyze_coulomb_mobility( density_kg_m3=2500.0, mu_static=0.4,)for record in mobility.records: print(record.label, record.lift_ratio, record.slide_ratio)9. MPI Path Test (Developers)
Section titled “9. MPI Path Test (Developers)”FPM_FC=mpiifort \fpm test --target test_mpi_hybrid \ --flag "-fpp -DUSE_MPI -qopenmp" \ --runner "mpirun -n 2"10. Easy-to-Misread Implementation Behaviors
Section titled “10. Easy-to-Misread Implementation Behaviors”- A normal run advances exactly
sim.batch_countbatches. A resume run advances from the checkpoint batch count untilsim.batch_countis reached. sim.tol_relis a monitoring value. It is not used as an early-stop condition in the current implementation.- The Fortran electric field uses element-centroid point-charge approximation plus
sim.softening.
For a camphor MPI job example, see examples/job_scripts/camphor_mpi_hybrid_job.sh.