Add transient subcell (TAS) collision-partner selection method (CPU + KOKKOS) - #31
Open
stanmoore1 wants to merge 50 commits into
Open
Add transient subcell (TAS) collision-partner selection method (CPU + KOKKOS)#31stanmoore1 wants to merge 50 commits into
stanmoore1 wants to merge 50 commits into
Conversation
jimmy adding
prep for add to prod
minor fix
fixes to setup logic
kokkos versions of subcell collisions
need 3d kokkos structure
…w Collide structure
Merge brings the subcell branch up to date with master (~763 commits).
Conflict resolution and porting decisions:
- src/collide.cpp/h: collisions_one_subcell() rewritten on top of master's
refactored Collide class (NEARCP/GASTALLY templating, setup(), gas
collision tally hooks). The port also fixes several defects in the
original prototype:
* restored 'else error' in modify_params (unknown collide_modify
keyword previously hung in an infinite loop)
* restored memory->destroy(recomb_ijflag) in destructor (leak)
* removed unused npmax x npmax subcell_list allocation and unused
vmax array
* subcell grid size now uses sqrt/cbrt with tolerance so exact
squares/cubes are not rounded down (pow(27,1/3) -> 2 bug)
* subcell indices clamped to grid bounds to guard round-off for
particles on upper cell faces
* subcell binning rebuilt after reactions delete/create particles
(previously stale linked lists could select deleted particles or
read uninitialized subcell IDs; grow block also grew the wrong
arrays -> heap overflow)
* added rejection of immediate re-collision of same pair (Bird's
previous-collision-partner exclusion), falling back to expanding
shell search, consistent with nearcp's nn_last_partner scheme
* simplified data structs: per-particle subcell IDs derived from a
single flattened ID; head-insertion linked list removes
subcell_mostrecent and all per-cell memsets of particle-length
arrays; shell enumeration uses clamped loop bounds
* subcell + nearcp, subcell + ambipolar, subcell + multi-group all
error out cleanly
- src/KOKKOS/*: taken from master wholesale; the unreviewed Kokkos
subcell prototype (debug printf scatter) is dropped for now and
CollideVSSKokkos::init() errors out if subcell is enabled
- removed scratch files: JAB_readme.txt, src/jab_bird_partnerselection.txt,
src/jab_testproblem/, src/KOKKOS/jab_collide_vss_kokkos.*,
examples/collide/in.collide_3D_sub_test
Co-Authored-By: Stan Moore <stanmoore1@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
Co-Authored-By: Stan Moore <stanmoore1@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
Make the 2d/3d example trios (default, nearcp, subcell) directly comparable and physically self-consistent: - 2d examples previously had inconsistent nrho/fnum vs the created particle count, yielding a nearly collisionless gas (~10 collision attempts per step); now nrho*V/fnum matches the created particle count - gas state documented in headers: Ar at 273.15 K, lambda ~ 2.4e-6 m, grid cells ~ 4x lambda (the coarse-cell regime where near-neighbor partner selection matters), timestep ~ tau/3 - variants differ only in the collide_modify line - add reference logs for 1 and 4 MPI ranks (results identical) Co-Authored-By: Stan Moore <stanmoore1@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
Co-Authored-By: Stan Moore <stanmoore1@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
Implements Collide::collisions_one_subcell in CollideVSSKokkos so the subcell partner-selection method runs on the Kokkos backends (CPU threads and GPU), previously it errored out under the KOKKOS package. Design mirrors the existing nearcp Kokkos path: the parallel_for/reduce runs one grid cell per thread, and the transient subcell binning is kept thread-private by indexing per-cell scratch as (icell,*) view rows, just like d_nn_last_partner. Five 2D device views hold the per-cell subcell state (id, count, first, next, ring), each sized (nglocal, maxcellcount) and reallocated alongside d_plist including in the react-retry path. Partner selection (find_nn_subcell) and rebinning (rebin_subcell) are DIM-templated KOKKOS_INLINE_FUNCTIONs that reproduce the CPU shell search and previous-partner exclusion exactly. The react retry/backup machinery is reused unchanged; subcell scratch needs no backup since it is rebuilt per cell and after each reaction. Validation (SPARTA_KOKKOS_EXACT, 1 thread, 1 MPI rank) reproduces the non-Kokkos results bit-for-bit for the 2d and 3d subcell examples and for a dissociating-gas case that exercises particle creation and the retry path; multithread and production-RNG runs are physically consistent (equilibrium temperature and collision rate preserved). The standard and nearcp Kokkos paths are unchanged and still match the CPU. Co-Authored-By: Stan Moore <stanmoore1@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
stanmoore1
force-pushed
the
claude/subcell-method-evaluation-yk2nuh
branch
from
July 6, 2026 21:24
427f7cf to
9529c04
Compare
The collide_{2D,3D}{,_nn,_sub} reference logs were regenerated on a
sandbox whose libm/compiler produce slightly different floating-point
results than the ubuntu-22.04 CI image, so the committed gold-standard
logs did not match fresh CI runs and the regression tests failed.
This is a cross-platform FP difference, not a bug:
- no crashes; all cases run to completion
- kinetic energy is exactly conserved (equilibrium temperature is
bit-identical every step; elastic VSS collisions conserve energy)
- the deviation hits the standard, nearcp, and subcell examples
identically, so it is not specific to the new subcell method
- the pre-existing collideInterspecies example reproduces its
committed log exactly on the CI machine, confirming the CI platform
is deterministic and the sandbox was the outlier
Replace the 12 reference logs with the logs produced by the CI machine
itself (openmpi, 1 and 4 ranks) so future CI runs match.
Co-Authored-By: Stan Moore <stanmoore1@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
Resolves two conflicts against master's new collide_modify {scheme}
keyword (NTC vs majorant collision frequency):
- src/collide.cpp modify_params: keep both the {subcell} and {scheme}
keyword clauses
- doc/collide_modify.txt: merge both keywords into the syntax list and
defaults, and keep both the Bird94 (MCF/NTC) and Bird09 (subcell)
references
The subcell method composes with the MCF scheme automatically, since
the attempt count is computed by attempt_collision(), which subcell
already calls; verified subcell + 'scheme mcf' runs correctly.
Co-Authored-By: Stan Moore <stanmoore1@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
The transient subcell method as published (Almgren-Bell, Moore & Gallis,
CSRI Summer Proceedings 2022) selects the partner purely at random from
the minimal-radius subcell set, with no previous-partner test. This
implementation adds the test, matching Bird's nearest-neighbor scheme
and the nearcp option; correct the comment, which wrongly attributed the
test to the published subcell method, and record why it is kept.
Measured on an equilibrium Ar box and a Fourier heat-flow problem
(cell ~ lambda/3, ~60 particles/cell, 2 seeds x 90k averaging steps):
same-pair repeat fraction, test disabled:
random selection 0.2%, nearcp 3.2%, subcell 7.3%
thermal conductivity vs random selection:
subcell with test +1.00% +- 0.95% (1.1 sigma)
subcell without test +7.40% +- 0.93% (8.0 sigma)
difference -5.96% +- 0.94% (6.3 sigma)
Repeat collisions of a pair are statistically equivalent to a single
collision, so a 7% repeat fraction lowers the effective collision rate
by ~7% and inflates the conductivity by a comparable amount, which is
what is observed. With ~1 particle per subcell the partner comes from a
small stable neighborhood, so subcell repeats are more frequent than
nearcp repeats and the test matters more, not less.
Co-Authored-By: Stan Moore <stanmoore1@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
Review feedback on the upstream PR (sjplimp) noted the subcell
paragraph never said what happens when the keyword is set to {no},
which is the default. Add that, matching how the nearcp paragraph is
written, and rewrap the following text.
Co-Authored-By: Stan Moore <stanmoore1@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
Review feedback on the upstream PR (sjplimp) asked whether the partner-selection keywords could be folded into one keyword. They are mutually exclusive choices of the same thing, so combine them: collide_modify partners random collide_modify partners nearcp Nlimit collide_modify partners subcell The scheme keyword is deliberately left alone. It sets how many collisions are attempted in a cell, not which particles are paired, and it composes with any partners style, so folding it in would make valid combinations such as mcf + subcell inexpressible. The subcell keyword is removed outright since it has never appeared in a release. nearcp is retained as a deprecated alias, since it is used by examples/cylinder and by the LANL ATS-5 SPARTA benchmark input; "nearcp yes Nlimit" maps to "partners nearcp Nlimit" and "nearcp no Nlimit" to "partners random". The new form also drops the old wart of having to supply an ignored Nlimit when near-neighbor selection is off. Since a single knob now sets both internal flags, the two can no longer both be set from an input script; the init() check is kept as a guard against a derived class setting them directly. Verified with the same binary that "partners nearcp 30" and "nearcp yes 30" produce bit-for-bit identical results, as do "partners random" and "nearcp no 30". KOKKOS matches non-KOKKOS bit-for-bit under SPARTA_KOKKOS_EXACT for the nearcp and subcell examples. The examples/collide inputs are updated to the new syntax, so their reference logs no longer match the commands they echo and need to be reblessed on the CI reference platform. Note that those logs were last generated on Jul 8, before the master merge that brought in the MCF scheme, so they are already stale independent of this change. Co-Authored-By: Stan Moore <stanmoore1@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
stanmoore1
force-pushed
the
claude/subcell-method-evaluation-yk2nuh
branch
from
July 24, 2026 20:23
ef7db3f to
17d30cb
Compare
Brings in 15 commits through 912c9e1 (PR sparta#663). No conflicts; the merge is a clean fast-forward of unrelated subsystems (fix ablate, read_isurf validation, fix emit face/surf, KOKKOS fix ave/grid sync). Verified the collide_modify partners parser still behaves after the merge: partners random/subcell/nearcp accepted, partners nearcp 0 and partners bogus rejected, the deprecated nearcp alias still accepted, and the removed subcell keyword still rejected. Co-authored-by: Stan Moore <stanmoore1@gmail.com> Claude-Session: https://claude.ai/code/session_01EibVA6xVmY79EpNi1XeqiB
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Adds Bird's transient adaptive subcell (TAS) collision-partner selection method as an alternative to the existing
nearcpnear-neighbor option, enabled with a newcollide_modify subcell yeskeyword. Each timestep the particles in a collision cell are binned into a transient grid of subcells (~1 particle/subcell), and a collision partner is drawn from the same subcell, or from expanding shells of neighbor subcells if the home subcell is empty. Likenearcp, this keeps the mean collision separation (MCS) small even when cells are much larger than the local mean free path, which allows accurate simulations on coarser grids with fewer particles.The method was prototyped on the long-lived
subcellbranch. This PR brings that branch up to date withmaster, rewrites the CPU implementation on top of the currentCollidestructure (fixing a number of bugs found in the prototype), documents and exercises it with examples, and adds a validated KOKKOS port so it runs on CPU threads and GPUs.Author(s)
Stan Moore, Sandia National Laboratories, with an original CPU prototype from the
subcellbranch. Implementation completed, corrected, KOKKOS-ported, and verified with assistance from Claude Code.Backward Compatibility
Fully backward compatible. The feature is opt-in via the new
collide_modify subcellkeyword, which defaults tono. Withsubcell no, all code paths (standard random,nearcp, ambipolar, both CPU and KOKKOS) are byte-for-byte unchanged — verified against the existing blessed example logs and againstmasterbehavior. No input syntax changes for existing decks.subcellis mutually exclusive withnearcp, and (for now) errors out cleanly if combined with the ambipolar approximation or with multiple collision groups.Implementation Notes
Algorithm (
src/collide.cpp,Collide::collisions_one_subcell). Templated on dimension. Per cell:Nsub = floor(N^(1/dim))subcells per direction so the subcell count does not exceed the particle count; particles are binned into a head-insertion linked list (subcell_first/subcell_next/subcell_count, flattenedsubcell_id); the first particle is random over the cell, the partner is random within its subcell, else random over an expanding, grid-clipped shell of subcells (subcell_ring). A previous-collision-partner exclusion (reusing the existingnn_last_partnermachinery) prevents an unphysical immediate re-collision of the same pair, choosing a different/next-nearest partner instead, per Bird. The transient binning is discarded after each cell, so memory overhead is negligible, and it is rebuilt after any reaction that adds/removes a particle so the subcell lists stay consistent withplist.KOKKOS port (
src/KOKKOS/collide_vss_kokkos.cpp). Mirrors the existingnearcpKokkos path: theparallel_for/parallel_reduceruns one grid cell per thread, and the subcell scratch is kept thread-private by indexing it as(icell, *)view rows — exactly liked_nn_last_partner. Five 2D device views hold the per-cell subcell state, sized(nglocal, maxcellcount)and reallocated alongsided_plistincluding in the react-retry path. Partner selection (find_nn_subcell) and rebinning (rebin_subcell) are DIM-templatedKOKKOS_INLINE_FUNCTIONs that reproduce the CPU shell search and exclusion exactly. The existing react retry/backup machinery is reused unchanged; the subcell scratch needs no backup since it is rebuilt per cell and after each reaction.Bugs fixed relative to the prototype: infinite loop on an unknown
collide_modifykeyword (missing finalelse error); a destructor memory leak (recomb_ijflag); a heap overflow in the particle-creation growth path (grew the wrong arrays); stale subcell lists after reactions could select deleted or uninitialized particles;pow(N,1/3)integer-truncation of the subcell count (nowcbrt/sqrtwith a tolerance); an unusednpmax*npmaxallocation (hundreds of MB for large cells) and an unusedvmaxarray; and out-of-range subcell indices for particles on a cell's upper face (now clamped). Development scratch files and stray debug code from the prototype were removed.Verification.
subcell no,examples/collide/in.collideInterspeciesreproduces the repository's blessed logs column-for-column; the standard andnearcpKOKKOS paths still match the CPU.-DSPARTA_KOKKOS_EXACT=ON, the subcell method reproduces the non-KOKKOS results bit-for-bit (Natt, Ncoll, temperature identical every stats step) for the 2d and 3d subcell examples and for a dissociating-gas case that exercises particle creation and the retry path (Np grows 10000→10751, Nreact and T all match). Multithread and production-RNG runs are physically consistent.nearcp0.9991, subcell 0.9984 of the analytic rate (the small deficits are the expected effect of suppressing repeat collisions); equilibrium temperature exactly conserved.nearcp's MCS grows with the cell.Performance vs near-neighbor.
Selection cost — collide-section seconds for 300 steps, 80k-particle 3d box, serial:
Subcell costs about the same as
nearcp 30and, unlikenearcp, is O(1) per selection independent of cell population (noNlimitto tune) while its partner quality does not degrade as cells coarsen.Coarse-grid accuracy — Fourier heat conduction between 223/323 K diffuse walls (Kn≈0.024), wall heat-flux error vs a fine-grid (cell≈λ/3) reference (±2–3% statistical noise):
On cells ~13× coarser than the λ/3 rule, standard selection is off by 27% while subcell stays within noise of the reference. Because it holds accuracy on coarse grids, subcell lets the grid and particle count shrink together: a coarse-grid subcell run with 12.8× fewer particles matched the fine reference to +2.6%, ran ~15× faster per step, and used half the particle memory — consistent with the ~2× overall efficiency reported by Gallis & Torczynski for the sophisticated-DSMC scheme.
Post Submission Checklist
doc/collide_modify.txt)examples/collide/in.collide_{2D,3D}{,_nn,_sub}with reference logs for 1 and 4 MPI ranks)Further Information, Files, and Links
nearcpcounterpart); ambipolar and multi-group support is left as follow-up.src/MAKE/Makefile.asanis included as a convenience AddressSanitizer build config used during verification (analogous to the existingMakefile.serial_debug); reviewers who prefer not to ship it can drop that one file with no effect on the feature.🤖 Generated with Claude Code
Generated by Claude Code