Case Design Workflow
This page turns the tested official tutorial into a research case: choose geometry, sources, and boundaries, then set time steps and particle sampling to obtain comparable results. Look up types, defaults, and combination constraints in the input parameter reference.
Starting point: Complete the 10-minute tutorial. In the working directory that contains
beach.toml and outputs/tutorial, copy the baseline configuration.
cp beach.toml case.tomlbeachx lint case.tomlChange one decision at a time and rerun beachx lint case.toml after every change. Keep the tutorial output as the
baseline; step 8 assigns a different output directory to the new case.
1. Define the purpose and acceptance criteria
Section titled “1. Define the purpose and acceptance criteria”Before editing the configuration, write down one sentence for each of these questions:
- Which particles arrive from which environment, and which surface do they reach?
- Is the quantity of interest charge, potential, absorption, escape, or runtime?
- Which conservation check, reference solution, or convergence tolerance must the result pass?
The official tutorial is a teaching case for inter-batch charging feedback. Its particle weight and
batch_duration=0 do not describe the time evolution of a particular physical environment. Defining acceptance
criteria first limits mesh resolution, particle count, and solver accuracy to what the study actually needs.
2. Choose the geometry
Section titled “2. Choose the geometry”Use built-in shapes with mode="template" for simple geometry. Use a triangular OBJ for measured or CAD-derived
geometry. When separate objects, especially separate conductors, need distinct identities, use separate templates so
that they receive separate mesh_id values.
kind | Shape | Main dimensions | Main resolution keys |
|---|---|---|---|
plane | XY rectangle | size_x, size_y | nx, ny |
plate_hole, plane_hole | Rectangle with a circular hole; the latter is an alias | size_x, size_y, radius | n_theta, n_r |
disk | Disk | radius | n_theta, n_r |
annulus | Annulus | radius, inner_radius | n_theta, n_r |
box | Closed rectangular surface | size | nx, ny, nz |
cylinder | z-axis cylinder | radius, height, cap | n_theta, n_z |
sphere | Sphere | radius | n_lon, n_lat |
For example, to replace the tutorial plane with a sphere, replace only the existing [[mesh.templates]] block:
[[mesh.templates]]kind = "sphere"enabled = truesurface_side = "outward_closed"center = [0.5, 0.5, 0.5]radius = 0.2n_lon = 24n_lat = 12For OBJ input, remove the existing [[mesh.templates]] block and replace [mesh] with:
[mesh]mode = "obj"obj_path = "mesh/object.obj" # replace with the actual OBJ pathsurface_side = "outward_closed"Use outward_closed only for a consistently oriented, closed two-manifold. For an open surface, select normal_plus
or normal_minus from the OBJ face normals and the vacuum side. See the
built-in shape and OBJ reference for placement transforms, element counts, and
shape constraints. examples/beach.toml shows
multiple built-in shapes.
3. Choose the surface model
Section titled “3. Choose the surface model”| Goal | surface_model | Scope of the current model |
|---|---|---|
| Retain charge at the hit location | insulator | Does not solve surface conduction, bulk leakage, or dielectric polarization |
| Conserve object charge and equalize its potential | conductor | Floating conductor in free space; requires field_boundary.mode="free" |
The tutorial uses insulator. To change a target to a conductor, change this one line in that template or in [mesh]
for OBJ input:
surface_model = "conductor"dielectric, epsilon_r, and resistive surfaces are not available in the current input. A conductor case needs its own
validation of object potential and total charge; the tutorial result is not its baseline. See
How surfaces charge for model meanings and constraints.
4. Choose the particle source
Section titled “4. Choose the particle source”Choose a path from where particles are supplied. When changing source_mode, replace that species entry with the
minimum configuration from the dedicated guide so that keys specific to the old mode do not remain.
source_mode | Use in a new case | Physical supply | Macro-sampling control |
|---|---|---|---|
volume_seed | Place a specified count inside the box for initial populations or orbit tests | Does not represent a surface flux | npcls_per_step |
plane_source | Supply particles one way from an internal rectangle | Flux × area × batch_duration | w_particle or target_macro_particles_per_batch |
photo_raycast | Emit from the first surface hit by illumination rays | Current density × projected area × batch_duration | rays_per_batch and ray hit rate |
reservoir_face | Compatibility input for deprecated existing configurations only | Do not use for a new case | Do not use for a new case |
To keep the tutorial volume_seed path but change its supply and region, adjust only these values in the existing
species entry:
npcls_per_step = 500pos_low = [0.2, 0.2, 0.8]pos_high = [0.8, 0.8, 0.8]drift_velocity = [0.0, 0.0, -1.0e6]Inflow from external plasma through a complete nonperiodic box face uses [particles.species.boundary_inflow], not
another source_mode. The current schema also requires source_mode="volume_seed" and npcls_per_step=0 for a species
that uses only boundary inflow. See Choose where particles enter for selection,
Inflow through a simulation boundary for boundary inflow, and
Photoelectron emission and lifecycle for photoelectrons.
5. Choose the box, field boundary, and particle boundaries
Section titled “5. Choose the box, field boundary, and particle boundaries”First make the [domain] box contain the mesh and every reachable particle trajectory. Then select the field closure
with field_boundary.mode and the outward particle action on nonperiodic faces with [particle_boundary].
| Decision | Selection |
|---|---|
| Free-space field of finite objects | periodic_axes=[], field_boundary.mode="free" |
| Field repeated infinitely in x/y | periodic_axes=["x", "y"], field_boundary.mode="periodic2" |
| Particle reaching a nonperiodic face | open, reflect, or redistributed_reflect |
domain.periodic_axes is the only public setting for periodic topology. Neither [particle_boundary] nor a species
override can add, remove, or replace a periodic axis. Because periodic2 currently requires periodic x/y and
nonperiodic z, start a new periodic case from the complete
examples/periodic2_basic/beach.toml
and periodic2 electrostatics. See
Particle escape and return for particle-boundary behavior.
6. Choose the solver
Section titled “6. Choose the solver”sim.field_solver | When to select it | How to check it |
|---|---|---|
direct | Small cases and reference solutions | Use as the baseline for approximate solvers |
treecode | Medium free-space cases | Vary the opening condition and compare observables |
fmm | Large cases, many targets, and ordinary periodic2 production | Vary tree_theta and tree_leaf_max, then compare with Direct |
auto | Select by element count for a free-space case | Read the resolved solver from output |
Keep the tutorial reference run at field_solver="direct". Before adopting a faster solver, measure its difference from
Direct in a reduced case with the same mesh and particle conditions. See Field evaluation for
compatibility and selection, and Use FMM for FMM configuration and accuracy tuning.
7. Set time scales and particle sampling
Section titled “7. Set time scales and particle sampling”First choose physical conditions such as density, temperature, and flux, then decide how many macro-particles will
represent them. The weight w_particle is the number of physical particles represented by one simulated particle.
| Decision | Setting | How to choose it |
|---|---|---|
| Particle orbit step | sim.dt | Halve it and compare impact locations and absorption rates |
| Tracking limit per particle | sim.max_step | Increase it until unresolved particles, survived_max_step, have a sufficiently small effect |
| Surface-charge update interval | sim.batch_duration | Use positive seconds for flux-driven sources and compare with half the interval |
| Simulation duration | sim.batch_count | With a fixed interval, batch_duration × batch_count is the physical end time |
When halving the orbit step, double max_step to preserve the available tracking time.
With batch_duration_step, the relation is batch_duration = dt × batch_duration_step, so changing dt alone also
changes the charge-update interval. Specifying batch_duration in seconds initially makes these two controls independent
and their effects easier to compare. The two ways to specify the batch interval are mutually exclusive.
How to increase sampling depends on the selected source.
| Source | Change to improve statistics | Physical conditions to hold fixed |
|---|---|---|
volume_seed | Increase npcls_per_step and decrease w_particle by the same factor | Physical particles per batch, npcls_per_step × w_particle |
plane_source / boundary_inflow | Increase target_macro_particles_per_batch, or decrease fixed w_particle; do not specify both | Distribution, density or flux, area, and batch_duration |
photo_raycast | Increase rays_per_batch | Photoelectric current density, illumination direction, geometry, and batch_duration |
Despite its name, npcls_per_step is a count per batch. For example, changing the tutorial’s
npcls_per_step=200, w_particle=2.0e5 to 400, 1.0e5 doubles the sample count while preserving the number of physical
particles supplied. Increasing only the particle count also increases the supplied charge and changes the physical case.
The photoelectron macro-particle count also depends on the ray hit fraction.
For the tutorial, which does not assign physical seconds, keep batch_duration=0 and compare results by batch.
See Choosing batch_duration for interval comparisons and adaptive stepping in
flux-driven research cases.
8. Separate the output and run the case
Section titled “8. Separate the output and run the case”Finally, change only dir in the existing [output] table so that the baseline result is not overwritten.
dir = "outputs/case"On HPC systems, do not run the simulation directly on a login node; run beach case.toml inside a compute-node
allocation.
beachx lint case.tomlbeach case.tomlbeachx inspect outputs/caseSee Run and resume a simulation for local execution, MPI, checkpoints, and resume.
The minimum pass condition is status=ok from lint, process exit code 0, batches from inspect equal to
sim.batch_count, and the presence of summary.txt and charges.csv. This proves completion, not physical correctness.
See Inspect output files for interpreting each output.
9. Validate the result
Section titled “9. Validate the result”For the observable defined in step 1, check at least the following:
processed_particles = absorbed + escaped; itsescaped_boundary,survived_max_step, andmultiple_box_events_soft_discardedcomponents are explained; and the surface/emission charge ledger closes- Refining the mesh does not change the conclusion
- Varying
dt,max_step,batch_duration, batch count, and particle count keeps the conclusion within tolerance - A small Treecode or FMM result agrees with the Direct reference
- Statistical variation across random seeds or repeated runs remains within tolerance
- The conclusion stays within the scope of the selected surface model, boundaries, and particle source
Compare the same physical quantity at the same physical time before and after a change, and do not vary several numerical controls at once. Follow Validating simulation results for concrete commands and acceptance criteria.