@@ -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