Skip to content

Commit d917412

Browse files
author
Sakib Rahman
committed
Add unit tests for view_initial, is_generator_primary, for_each_primary
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)
1 parent 198f317 commit d917412

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

test/celeritas/ext/GeantTrackReconstruction.test.cc

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,113 @@ TEST_F(GeantTrackReconstructionTest, multi_flush_view)
390390
EXPECT_EQ(222, recon.view(ParticleId{1}, id2).GetTrackID());
391391
}
392392

393+
//---------------------------------------------------------------------------//
394+
/*!
395+
* Verify view_initial restores handover-time kinematics and primary particle.
396+
*/
397+
TEST_F(GeantTrackReconstructionTest, view_initial)
398+
{
399+
GeantTrackReconstruction recon(particles_, step_);
400+
recon.init_event();
401+
402+
// Create primary with known kinematics
403+
auto primary_track = std::make_unique<G4Track>(
404+
new G4DynamicParticle(particles_[1], G4ThreeVector(0, 0, 1), 500.0),
405+
3.14,
406+
G4ThreeVector(10, 20, 30));
407+
primary_track->SetTrackID(42);
408+
primary_track->SetParentID(0);
409+
410+
PrimaryId pid = recon.acquire(*primary_track, ParticleId{1});
411+
412+
// Modify the track to simulate post-transport state
413+
G4Track& track = recon.view(ParticleId{1}, pid);
414+
track.SetPosition(G4ThreeVector(99, 99, 99));
415+
track.SetKineticEnergy(0.0);
416+
417+
// view_initial should restore original handover state
418+
G4Track& initial = recon.view_initial(ParticleId{1}, pid);
419+
EXPECT_EQ(42, initial.GetTrackID());
420+
EXPECT_EQ(0, initial.GetParentID());
421+
EXPECT_DOUBLE_EQ(500.0, initial.GetKineticEnergy());
422+
EXPECT_DOUBLE_EQ(3.14, initial.GetGlobalTime());
423+
EXPECT_DOUBLE_EQ(10, initial.GetPosition().x());
424+
EXPECT_DOUBLE_EQ(20, initial.GetPosition().y());
425+
EXPECT_DOUBLE_EQ(30, initial.GetPosition().z());
426+
EXPECT_DOUBLE_EQ(0, initial.GetMomentumDirection().x());
427+
EXPECT_DOUBLE_EQ(0, initial.GetMomentumDirection().y());
428+
EXPECT_DOUBLE_EQ(1, initial.GetMomentumDirection().z());
429+
}
430+
431+
//---------------------------------------------------------------------------//
432+
/*!
433+
* Verify is_generator_primary distinguishes generator primaries from
434+
* re-offloaded secondaries.
435+
*/
436+
TEST_F(GeantTrackReconstructionTest, is_generator_primary)
437+
{
438+
GeantTrackReconstruction recon(particles_, step_);
439+
recon.init_event();
440+
441+
// Generator primary (parent_id == 0)
442+
auto gen_track = std::make_unique<G4Track>(
443+
new G4DynamicParticle(particles_[0], G4ThreeVector(1, 0, 0)),
444+
0.0,
445+
G4ThreeVector());
446+
gen_track->SetTrackID(1);
447+
gen_track->SetParentID(0);
448+
PrimaryId gen_id = recon.acquire(*gen_track, ParticleId{0});
449+
450+
// Re-offloaded secondary (parent_id != 0)
451+
auto sec_track = std::make_unique<G4Track>(
452+
new G4DynamicParticle(particles_[1], G4ThreeVector(0, 1, 0)),
453+
0.0,
454+
G4ThreeVector());
455+
sec_track->SetTrackID(2);
456+
sec_track->SetParentID(1);
457+
PrimaryId sec_id = recon.acquire(*sec_track, ParticleId{1});
458+
459+
EXPECT_TRUE(recon.is_generator_primary(gen_id));
460+
EXPECT_FALSE(recon.is_generator_primary(sec_id));
461+
}
462+
463+
//---------------------------------------------------------------------------//
464+
/*!
465+
* Verify for_each_primary iterates all acquired primaries with restored state.
466+
*/
467+
TEST_F(GeantTrackReconstructionTest, for_each_primary)
468+
{
469+
GeantTrackReconstruction recon(particles_, step_);
470+
recon.init_event();
471+
472+
// Register 5 primaries cycling through particle types (gamma, e-, e+)
473+
int const expected_ids[] = {10, 20, 30, 40, 50};
474+
std::vector<std::unique_ptr<G4Track>> src_tracks;
475+
for (size_type i = 0; i < 5; ++i)
476+
{
477+
auto pidx = i % particles_.size();
478+
src_tracks.push_back(std::make_unique<G4Track>(
479+
new G4DynamicParticle(particles_[pidx], G4ThreeVector()),
480+
0.0,
481+
G4ThreeVector()));
482+
src_tracks.back()->SetTrackID(expected_ids[i]);
483+
PrimaryId pid = recon.acquire(
484+
*src_tracks.back(), ParticleId{static_cast<size_type>(pidx)});
485+
EXPECT_EQ(i, pid.unchecked_get());
486+
}
487+
488+
std::vector<int> visited_ids;
489+
recon.for_each_primary([&visited_ids](G4Track& track) {
490+
visited_ids.push_back(track.GetTrackID());
491+
});
492+
493+
ASSERT_EQ(5, visited_ids.size());
494+
for (size_type i = 0; i < 5; ++i)
495+
{
496+
EXPECT_EQ(expected_ids[i], visited_ids[i]);
497+
}
498+
}
499+
393500
//---------------------------------------------------------------------------//
394501
} // namespace test
395502
} // namespace celeritas

0 commit comments

Comments
 (0)