This page documents the particle pipeline exactly as orchestrated in the current solver flow.
src/runloop.c; the advection terms are those in UpdateParticlePosition. Flagged for owner validation of the scientific interpretation.Order inside the coupled step, as implemented in AdvanceSimulation (src/runloop.c):
The advect-then-interpolate ordering is deliberate and is the single most important property of this loop. A particle carries the state interpolated at \(t_n\) into step 2, and UpdateParticlePosition displaces it by three contributions - convective velocity, drift along the diffusivity gradient, and a stochastic Brownian kick:
\[ \mathbf{X}^{n+1} = \mathbf{X}^{n} + \left( \mathbf{u}_p^{\,n} + \nabla D^{\,n} \right) \Delta t + \Delta \mathbf{X}_{\mathrm{brownian}}, \]
where \(\nabla D\) is the interpolated diffusivity gradient carried on the swarm and \(\Delta\mathbf{X}_{\mathrm{brownian}}\) comes from CalculateBrownianDisplacement, scaled by the particle's interpolated diffusivity. Step 5 then supplies the state at \(t_{n+1}\) from the flow field FlowSolver has just computed, ready for the next step. Interpolation therefore closes each step rather than opening it.
Particles are not advected without a valid interpolated state: both PerformInitializedParticleSetup and PerformLoadedParticleSetup settle the swarm and run one interpolation at \(t=0\) before the step loop begins, so the first physical advection already has interpolated velocity, diffusivity, and diffusivity gradient available.
Each stage relies on valid DMSwarm_CellID, interpolation weights, and synchronized ghost data.
Step 5 dispatches through InterpolateEulerFieldToSwarm, which selects between two interpolation paths based on SimCtx.interpolationMethod:
See Trilinear Interpolation and Particle-Grid Projection for method details and configuration.
Commonly used swarm fields include:
position)velocity)DMSwarm_CellID)DMSwarm_location_status)Diffusivity, Psi)Status transitions (NEEDS_LOCATION, ACTIVE_AND_LOCATED, MIGRATING_OUT, LOST) determine whether particles are walked, migrated, or skipped in settlement passes.
Current scalar model path:
This presently implements IEM-style relaxation for Psi, with the mixing constant C_IEM set by scalar_transport.iem_constant (default 2.0; 10. scalar_transport). Psi starts at zero unless models.physics.particles.fields gives it an initial value (1.1 Configured Particle Values (fields)); without one, the relaxation has nothing to act on (1. IEM Mixing Update In Current Code).
Post statistics currently include global kernels such as:
Additional health indicators are available from migration counters and settlement-pass counts stored in SimCtx fields updated by location logic. For particle-enabled runs, the runtime also writes <run.analysis.metrics>/search_metrics.csv with per-step and cumulative loss plus aggregated search-attempt, traversal, tie-break, boundary-clamp, bbox-guess, and pass-depth signals. The examples/search_robustness/ bundle is the dedicated end-to-end reference for interpreting that artifact.
a t (diffusivity-gradient-drift-paired-2026-09-18); and Trilinear interpolation of the TGV3D field converged at order 1.97. Only one gradient, and zero or uniform carriers, were measured. The examples are listed in 3. Particle Verification Family.models.physics.particles.random_seed (default 12345) plus the MPI rank, so identical inputs on the same number of ranks give identical trajectories, while a different rank count gives a different, equally valid, realization. A restart does not continue the sequence it stopped in: it draws a fresh sequence determined by the seed and the restart step.Recommended extension pattern:
For configuration contract changes, update: