Step death record restore handover#2368
Closed
rahmans1 wants to merge 18 commits into
Closed
Conversation
This was referenced Apr 17, 2026
Test summary 6 020 files 9 757 suites 19m 7s ⏱️ Results for commit 9017363. ♻️ This comment has been updated with latest results. |
d917412 to
8d28604
Compare
added 5 commits
April 17, 2026 20:58
Add ParticleId to AcquiredData so the Celeritas particle type is preserved alongside track ID, parent ID, user info, and creator process. Update acquire() to accept ParticleId. Fix view() to subtract the flush-local start_ offset from primary_id before indexing g4_track_data_, which was incorrect after the first clear() call when start_ advances past zero. Add for_each_primary() template that iterates all acquired primaries and invokes a callback with the restored G4Track. Prompt: "Store ParticleId in AcquiredData and pass it through acquire(); fix the multi-flush bug in view() where primary_id was used as a raw index without subtracting start_; add for_each_primary() to iterate all acquired primaries with their restored G4Tracks" Assisted-by: Claude Code (claude-sonnet-4-6)
The primary_id field was missing from operator|=, operator bool, all(), and resize() in StepSelection/StepStateDataImpl. This caused primary_id to be silently dropped even when selected, resulting in empty primary_id vectors in DetectorStepOutput and incorrect trackID on reconstructed G4Tracks. Prompt: "Fix primary_id being silently dropped from step data despite being selected, causing hits to carry trackID=0" Assisted-by: Claude Code (claude-opus-4-6)
Add selection_.primary_id = setup.track so that primary_id is collected alongside particle type in step data. Without this, HitProcessor receives empty primary_id vectors and cannot restore the original G4 track ID on reconstructed tracks before calling ProcessHits. Prompt: "Enable primary_id in GeantSd step selection so hits carry the correct G4 track ID for MC-truth association" Assisted-by: Claude Code (claude-opus-4-6)
Update GeantTrackReconstruction tests to pass ParticleId to acquire() and add a multi_flush_view test verifying that view() returns the correct track after clear() advances the start_ offset. Prompt: "Add unit tests for the new acquire(G4Track&, ParticleId) signature and verify view() flush-local indexing across multiple clear() cycles" Assisted-by: Claude Code (claude-opus-4-6)
The acquire() signature was updated to store the particle type in AcquiredData alongside the G4Track, but the call site in LocalTransporter::Push was not updated. Move the particle_id lookup before the acquire() call so the value is available to pass. Prompt: "acquire() call-site was missing ParticleId after signature change; move particle_id lookup before acquire() so it can be passed" Assisted-by: Claude Code (claude-sonnet-4-6)
b4b0e0a to
8a54e13
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #2368 +/- ##
===========================================
- Coverage 87.26% 87.26% -0.01%
===========================================
Files 1386 1386
Lines 43985 44086 +101
Branches 13483 13502 +19
===========================================
+ Hits 38385 38473 +88
- Misses 4374 4386 +12
- Partials 1226 1227 +1
🚀 New features to boost your workflow:
|
added 9 commits
April 18, 2026 18:57
Remove the event-scoped start_ offset and init_event() from GeantTrackReconstruction. Primary IDs are now 0-based indices directly into g4_track_data_, eliminating the subtract-start arithmetic in view(), acquire(), and for_each_primary(). clear() remains at the end of Flush() so that track data is available during hit processing and reset before the next flush. Remove the erroneous primary_id += G4TrackID line in Push() that corrupted the acquire index. Prompt: "Fix CI-failing UserActionIntegration tests caused by primary_id indexing bugs. Remove the event-scoped start_ offset and init_event() from GeantTrackReconstruction and replace with flush-local 0-based direct indexing into g4_track_data_. Keep clear() at end of Flush() so data is available during hit processing. Remove the erroneous primary_id += G4TrackID corruption in LocalTransporter::Push(). Update multi_flush_view test to expect flush-local id=0 after clear()." Assisted-by: Claude Code (claude-opus-4-6)
…patch Add TrackDeathRecord struct to DetectorStepOutput to hold the terminal GPU state (position, direction, energy, time, primary_id, particle) of killed tracks. Add track_death flag to StepParamsData and StepInterface::Filters, and add corresponding death_* fields to StepStateDataImpl that are conditionally allocated when track_death is enabled. Also add copy_deaths() template declarations (host and device specializations) for compacting valid death records from the scratch buffer, a deaths vector in DetectorStepOutput for the compacted results, and a death_valid_id field in StepStateData for GPU compaction indexing. Prompt: "Add TrackDeathRecord struct, death_* state fields, copy_deaths declarations, deaths output vector, and death_valid_id compaction index to capture the final state of GPU-killed tracks, gated on a new track_death flag in StepParamsData and StepInterface::Filters" Assisted-by: Claude Code (claude-opus-4-6)
…yExecutor At the post-step gather, write position, direction, energy, time, particle, and primary ID into death_* state fields for any track whose status is killed. Clear death_track_id at the pre-step gather so each track produces exactly one death record. The death gather runs before the detector-filter early returns so tracks that die outside sensitive detectors are still captured. Add DeathScratchCopyExecutor to compact death records from full slot arrays into contiguous scratch storage indexed by death_valid_id. Prompt: "In StepGatherExecutor post-step, write death_* fields for killed tracks before the detector filter so tracks dying outside SDs are captured; clear death_track_id at pre-step so each track records exactly one death. Add DeathScratchCopyExecutor to compact death records into scratch storage." Assisted-by: Claude Code (claude-sonnet-4-6)
Verify that death record fields (track_id, primary_id, particle, pos, dir, energy, time) are allocated when track_death is set in StepParamsData and not allocated when it is unset. Prompt: "Test that StepStateData death fields are conditionally allocated based on the track_death flag in StepParamsData" Assisted-by: Claude Code (claude-opus-4-6)
Add copy_deaths<MemSpace::host> that scans death_track_id and compacts valid entries into DetectorStepOutput::deaths. Add copy_deaths<MemSpace::device> that uses thrust::copy_if to populate death_valid_id, launches a gather-death-scratch kernel via DeathScratchCopyExecutor, then copies each field device-to-host and assembles TrackDeathRecord entries. Propagate the track_death flag from StepInterface::Filters through StepParams into StepParamsData, and enable it unconditionally in GeantSd::filters(). Prompt: "Implement copy_deaths for host (linear scan) and device (thrust compact + kernel + D2H copy), propagate track_death from StepInterface::Filters through StepParams into StepParamsData, and set track_death=true in GeantSd::filters()" Assisted-by: Claude Code (claude-sonnet-4-6)
Replace two identical OpaqueId validity predicates (HasDetector, HasDeath) with a single templated IsValid<T> functor. Both performed the same static_cast<bool>() check on different OpaqueId types. Prompt: "Deduplicate the HasDetector and HasDeath functors in DetectorSteps.cu that both check OpaqueId validity with static_cast<bool>. Replace them with a single generic IsValid<T> template predicate." Assisted-by: Claude Code (claude-opus-4-6)
Replace two-pass approach (count deaths then reserve+fill) with a single loop using push_back and aggregate initialization of TrackDeathRecord. Prompt: "Simplify the host copy_deaths implementation in DetectorSteps.cc from a two-pass count-then-fill loop to a single-pass push_back with aggregate initialization of TrackDeathRecord." Assisted-by: Claude Code (claude-opus-4-6)
Test that copy_deaths correctly compacts sparse death records (3 of 8 slots populated) into contiguous output with correct field values, and that it clears output when death fields are not allocated. Prompt: "Add unit tests for copy_deaths: one that populates 3 of 8 track slots with death records and verifies compaction produces 3 correct TrackDeathRecords, and one that verifies copy_deaths clears output when track_death is disabled." Assisted-by: Claude Code (claude-opus-4-6)
Disable volume_instance_ids in death_fields_allocated and copy_deaths_host test setup since these tests set num_volume_levels=0, which triggers the vi_depth > 0 assertion when volume_instance_ids is selected. The assertion only fires in debug builds (CELERITAS_DEBUG=ON), which is why it passed locally but failed in CI. Prompt: "Fix CI failure in death record tests where this->selection() inherits volume_instance_ids=true but num_volume_levels=0, triggering the vi_depth > 0 assertion in StepData.hh resize. Disable volume_instance_ids in the test-local selection since death records do not use volume instances." Assisted-by: Claude Code (claude-opus-4-6)
8a54e13 to
976d311
Compare
With multiple primaries per event, track slots can be reused across stepper iterations within a single Flush(). The per-iteration copy_deaths() clears and re-scans slot-indexed death records, so a primary that dies in iteration N loses its record when the slot is reused in iteration N+1. Add an accumulated_deaths_ vector to HitProcessor that appends death records from each stepper iteration. The last_deaths() accessor returns this accumulator, and clear_deaths() resets it after consumption. Also add the copy_deaths() call to both operator() overloads so death gathering runs per iteration. Prompt: "With multiple primaries per event, death records are lost when track slots are reused across stepper iterations because copy_deaths clears per iteration. Accumulate deaths in HitProcessor across all iterations so every killed primary gets a death record for PreUserTrackingAction dispatch." Assisted-by: claude (claude-opus-4-6)
Store initial kinematic state (position, direction, energy, time) and the G4PrimaryParticle pointer in AcquiredData at handover time. Add restore_initial() to reconstruct the full handover state on a G4Track, view_initial() to prepare a track for PreUserTrackingAction dispatch, and is_generator_primary() to filter generator-level primaries from re-offloaded secondaries. Prompt: "Store handover-time kinematics and G4PrimaryParticle pointer so PreUserTrackingAction sees the original track state and MC-truth frameworks identify generator primaries" Assisted-by: Claude Code (claude-opus-4-6)
Test that view_initial restores handover-time kinematics (position, direction, energy, time) and track/parent IDs. Verify is_generator_primary returns true for parent_id==0 and false for re-offloaded secondaries. Check for_each_primary iterates all acquired tracks with correct restored state. Prompt: "Add unit tests for the new GeantTrackReconstruction methods: view_initial should restore original handover kinematics, is_generator_primary should distinguish generator primaries from re-offloaded secondaries by parent_id, and for_each_primary should iterate all acquired primaries with restored track state." Assisted-by: Claude Code (claude-opus-4-6)
This commit means that you must (please!) install pre-commit on your development machine and run `pre-commit install --install-hooks`. For more information, see https://celeritas-project.github.io/celeritas/user/development/style.html#formatting Autogenerated: https://pre-commit.ci
976d311 to
9017363
Compare
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.
Title
Save and restore initial handover state for PreUserTrackingAction dispatch
Depends on: #2367
Pre-requisite for: #2363
Description
G4PrimaryParticlepointer inAcquiredDatarestore_initial()to prepare a track with handover-time stateview_initial()onGeantTrackReconstructionfor PreUserTrackingAction dispatchis_generator_primary()to filter by parent_id == 0for_each_primary()template iteratorAssisted by: Claude-Opus-4-6 and Claude-Sonnet-4-6