@@ -47,13 +47,21 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
4747 for (int i = blockIdx .x * blockDim .x + threadIdx .x ; i < activeSize; i += blockDim .x * gridDim .x ) {
4848 const int globalSlot = (*active)[i];
4949 Track ¤tTrack = electrons[globalSlot];
50- const auto volume = currentTrack.navState .Top ();
50+ auto energy = currentTrack.energy ;
51+ auto pos = currentTrack.pos ;
52+ auto dir = currentTrack.dir ;
53+ auto navState = currentTrack.navState ;
54+ const auto volume = navState.Top ();
5155 const int volumeID = volume->id ();
5256 // the MCC vector is indexed by the logical volume id
5357 const int lvolID = volume->GetLogicalVolume ()->id ();
5458 const int theMCIndex = MCIndex[lvolID];
5559
5660 auto survive = [&](bool push = true ) {
61+ currentTrack.energy = energy;
62+ currentTrack.pos = pos;
63+ currentTrack.dir = dir;
64+ currentTrack.navState = navState;
5765 if (push) activeQueue->push_back (globalSlot);
5866 };
5967
@@ -63,9 +71,9 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
6371 // Init a track with the needed data to call into G4HepEm.
6472 G4HepEmElectronTrack elTrack;
6573 G4HepEmTrack *theTrack = elTrack.GetTrack ();
66- theTrack->SetEKin (currentTrack. energy );
74+ theTrack->SetEKin (energy);
6775 theTrack->SetMCIndex (theMCIndex);
68- theTrack->SetOnBoundary (currentTrack. navState .IsOnBoundary ());
76+ theTrack->SetOnBoundary (navState.IsOnBoundary ());
6977 theTrack->SetCharge (Charge);
7078 G4HepEmMSCTrackData *mscData = elTrack.GetMSCTrackData ();
7179 mscData->fIsFirstStep = currentTrack.initialRange < 0 ;
@@ -80,8 +88,8 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
8088
8189 // Compute safety, needed for MSC step limit.
8290 double safety = 0 ;
83- if (!currentTrack. navState .IsOnBoundary ()) {
84- safety = BVHNavigator::ComputeSafety (currentTrack. pos , currentTrack. navState );
91+ if (!navState.IsOnBoundary ()) {
92+ safety = BVHNavigator::ComputeSafety (pos, navState);
8593 }
8694 theTrack->SetSafety (safety);
8795
@@ -102,9 +110,9 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
102110
103111 bool restrictedPhysicalStepLength = false ;
104112 if (BzFieldValue != 0 ) {
105- const double momentumMag = sqrt (currentTrack. energy * (currentTrack. energy + 2.0 * Mass));
113+ const double momentumMag = sqrt (energy * (energy + 2.0 * Mass));
106114 // Distance along the track direction to reach the maximum allowed error
107- const double safeLength = fieldPropagatorBz.ComputeSafeLength (momentumMag, Charge, currentTrack. dir );
115+ const double safeLength = fieldPropagatorBz.ComputeSafeLength (momentumMag, Charge, dir);
108116
109117 constexpr int MaxSafeLength = 10 ;
110118 double limit = MaxSafeLength * safeLength;
@@ -145,22 +153,20 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
145153 vecgeom::NavStateIndex nextState;
146154 if (BzFieldValue != 0 ) {
147155 geometryStepLength = fieldPropagatorBz.ComputeStepAndNextVolume <BVHNavigator>(
148- currentTrack.energy , Mass, Charge, geometricalStepLengthFromPhysics, currentTrack.pos , currentTrack.dir ,
149- currentTrack.navState , nextState, propagated, safety);
156+ energy, Mass, Charge, geometricalStepLengthFromPhysics, pos, dir, navState, nextState, propagated, safety);
150157 } else {
151- geometryStepLength =
152- BVHNavigator::ComputeStepAndNextVolume (currentTrack.pos , currentTrack.dir , geometricalStepLengthFromPhysics,
153- currentTrack.navState , nextState, kPush );
154- currentTrack.pos += geometryStepLength * currentTrack.dir ;
158+ geometryStepLength = BVHNavigator::ComputeStepAndNextVolume (pos, dir, geometricalStepLengthFromPhysics, navState,
159+ nextState, kPush );
160+ pos += geometryStepLength * dir;
155161 }
156162
157163 // Set boundary state in navState so the next step and secondaries get the
158- // correct information (currentTrack. navState = nextState only if relocated
164+ // correct information (navState = nextState only if relocated
159165 // in case of a boundary; see below)
160- currentTrack. navState .SetBoundaryState (nextState.IsOnBoundary ());
166+ navState.SetBoundaryState (nextState.IsOnBoundary ());
161167
162168 // Propagate information from geometrical step to MSC.
163- theTrack->SetDirection (currentTrack. dir .x (), currentTrack. dir .y (), currentTrack. dir .z ());
169+ theTrack->SetDirection (dir.x (), dir.y (), dir.z ());
164170 theTrack->SetGStepLength (geometryStepLength);
165171 theTrack->SetOnBoundary (nextState.IsOnBoundary ());
166172
@@ -169,7 +175,7 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
169175
170176 // Collect the direction change and displacement by MSC.
171177 const double *direction = theTrack->GetDirection ();
172- currentTrack. dir .Set (direction[0 ], direction[1 ], direction[2 ]);
178+ dir.Set (direction[0 ], direction[1 ], direction[2 ]);
173179 if (!nextState.IsOnBoundary ()) {
174180 const double *mscDisplacement = mscData->GetDisplacement ();
175181 vecgeom::Vector3D<Precision> displacement (mscDisplacement[0 ], mscDisplacement[1 ], mscDisplacement[2 ]);
@@ -186,18 +192,18 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
186192 // Apply displacement, depending on how close we are to a boundary.
187193 // 1a. Far away from geometry boundary:
188194 if (reducedSafety > 0.0 && dispR <= reducedSafety) {
189- currentTrack. pos += displacement;
195+ pos += displacement;
190196 } else {
191197 // Recompute safety.
192- safety = BVHNavigator::ComputeSafety (currentTrack. pos , currentTrack. navState );
198+ safety = BVHNavigator::ComputeSafety (pos, navState);
193199 reducedSafety = sFact * safety;
194200
195201 // 1b. Far away from geometry boundary:
196202 if (reducedSafety > 0.0 && dispR <= reducedSafety) {
197- currentTrack. pos += displacement;
203+ pos += displacement;
198204 // 2. Push to boundary:
199205 } else if (reducedSafety > kGeomMinLength ) {
200- currentTrack. pos += displacement * (reducedSafety / dispR);
206+ pos += displacement * (reducedSafety / dispR);
201207 }
202208 // 3. Very small safety: do nothing.
203209 }
@@ -209,7 +215,7 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
209215 atomicAdd (&scoringPerVolume->chargedTrackLength [volumeID], elTrack.GetPStepLength ());
210216
211217 // Collect the changes in energy and deposit.
212- currentTrack. energy = theTrack->GetEKin ();
218+ energy = theTrack->GetEKin ();
213219 double energyDeposit = theTrack->GetEnergyDeposit ();
214220 atomicAdd (&globalScoring->energyDeposit , energyDeposit);
215221 atomicAdd (&scoringPerVolume->energyDeposit [volumeID], energyDeposit);
@@ -234,13 +240,13 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
234240 double sinPhi, cosPhi;
235241 sincos (phi, &sinPhi, &cosPhi);
236242
237- gamma1.InitAsSecondary (/* parent= */ currentTrack );
243+ gamma1.InitAsSecondary (pos, navState );
238244 newRNG.Advance ();
239245 gamma1.rngState = newRNG;
240246 gamma1.energy = copcore::units::kElectronMassC2 ;
241247 gamma1.dir .Set (sint * cosPhi, sint * sinPhi, cost);
242248
243- gamma2.InitAsSecondary (/* parent= */ currentTrack );
249+ gamma2.InitAsSecondary (pos, navState );
244250 // Reuse the RNG state of the dying track.
245251 gamma2.rngState = currentTrack.rngState ;
246252 gamma2.energy = copcore::units::kElectronMassC2 ;
@@ -256,10 +262,10 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
256262
257263 // Kill the particle if it left the world.
258264 if (nextState.Top () != nullptr ) {
259- BVHNavigator::RelocateToNextVolume (currentTrack. pos , currentTrack. dir , nextState);
265+ BVHNavigator::RelocateToNextVolume (pos, dir, nextState);
260266
261267 // Move to the next boundary.
262- currentTrack. navState = nextState;
268+ navState = nextState;
263269 survive ();
264270 }
265271 continue ;
@@ -313,14 +319,21 @@ __device__ void ElectronInteraction(int const globalSlot, SOAData const & /*soaD
313319 GlobalScoring *globalScoring, ScoringPerVolume *scoringPerVolume)
314320{
315321 Track ¤tTrack = particles[globalSlot];
316- const auto volume = currentTrack.navState .Top ();
322+ auto energy = currentTrack.energy ;
323+ const auto pos = currentTrack.pos ;
324+ auto dir = currentTrack.dir ;
325+ const auto navState = currentTrack.navState ;
326+ const auto volume = navState.Top ();
317327 // the MCC vector is indexed by the logical volume id
318328 const int lvolID = volume->GetLogicalVolume ()->id ();
319329 const int theMCIndex = MCIndex[lvolID];
320330
321- auto survive = [&] { activeQueue->push_back (globalSlot); };
331+ auto survive = [&] {
332+ currentTrack.dir = dir;
333+ currentTrack.energy = energy;
334+ activeQueue->push_back (globalSlot);
335+ };
322336
323- const double energy = currentTrack.energy ;
324337 const double theElCut = g4HepEmData.fTheMatCutData ->fMatCutData [theMCIndex].fSecElProdCutE ;
325338
326339 RanluxppDouble newRNG{currentTrack.rngState .Branch ()};
@@ -331,20 +344,20 @@ __device__ void ElectronInteraction(int const globalSlot, SOAData const & /*soaD
331344 double deltaEkin = (IsElectron) ? G4HepEmElectronInteractionIoni::SampleETransferMoller (theElCut, energy, &rnge)
332345 : G4HepEmElectronInteractionIoni::SampleETransferBhabha (theElCut, energy, &rnge);
333346
334- double dirPrimary[] = {currentTrack. dir .x (), currentTrack. dir .y (), currentTrack. dir .z ()};
347+ double dirPrimary[] = {dir.x (), dir.y (), dir.z ()};
335348 double dirSecondary[3 ];
336349 G4HepEmElectronInteractionIoni::SampleDirections (energy, deltaEkin, dirSecondary, dirPrimary, &rnge);
337350
338351 Track &secondary = secondaries.electrons .NextTrack ();
339352 atomicAdd (&globalScoring->numElectrons , 1 );
340353
341- secondary.InitAsSecondary (/* parent= */ currentTrack );
354+ secondary.InitAsSecondary (pos, navState );
342355 secondary.rngState = newRNG;
343356 secondary.energy = deltaEkin;
344357 secondary.dir .Set (dirSecondary[0 ], dirSecondary[1 ], dirSecondary[2 ]);
345358
346- currentTrack. energy = energy - deltaEkin;
347- currentTrack. dir .Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
359+ energy -= deltaEkin;
360+ dir.Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
348361 survive ();
349362 } else if constexpr (ProcessIndex == 1 ) {
350363 // Invoke model for Bremsstrahlung: either SB- or Rel-Brem.
@@ -355,24 +368,24 @@ __device__ void ElectronInteraction(int const globalSlot, SOAData const & /*soaD
355368 : G4HepEmElectronInteractionBrem::SampleETransferRB (&g4HepEmData, energy, logEnergy,
356369 theMCIndex, &rnge, IsElectron);
357370
358- double dirPrimary[] = {currentTrack. dir .x (), currentTrack. dir .y (), currentTrack. dir .z ()};
371+ double dirPrimary[] = {dir.x (), dir.y (), dir.z ()};
359372 double dirSecondary[3 ];
360373 G4HepEmElectronInteractionBrem::SampleDirections (energy, deltaEkin, dirSecondary, dirPrimary, &rnge);
361374
362375 Track &gamma = secondaries.gammas .NextTrack ();
363376 atomicAdd (&globalScoring->numGammas , 1 );
364377
365- gamma.InitAsSecondary (/* parent= */ currentTrack );
378+ gamma.InitAsSecondary (pos, navState );
366379 gamma.rngState = newRNG;
367380 gamma.energy = deltaEkin;
368381 gamma.dir .Set (dirSecondary[0 ], dirSecondary[1 ], dirSecondary[2 ]);
369382
370- currentTrack. energy = energy - deltaEkin;
371- currentTrack. dir .Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
383+ energy -= deltaEkin;
384+ dir.Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
372385 survive ();
373386 } else if constexpr (ProcessIndex == 2 ) {
374387 // Invoke annihilation (in-flight) for e+
375- double dirPrimary[] = {currentTrack. dir .x (), currentTrack. dir .y (), currentTrack. dir .z ()};
388+ double dirPrimary[] = {dir.x (), dir.y (), dir.z ()};
376389 double theGamma1Ekin, theGamma2Ekin;
377390 double theGamma1Dir[3 ], theGamma2Dir[3 ];
378391 G4HepEmPositronInteractionAnnihilation::SampleEnergyAndDirectionsInFlight (
@@ -382,12 +395,12 @@ __device__ void ElectronInteraction(int const globalSlot, SOAData const & /*soaD
382395 Track &gamma2 = secondaries.gammas .NextTrack ();
383396 atomicAdd (&globalScoring->numGammas , 2 );
384397
385- gamma1.InitAsSecondary (/* parent= */ currentTrack );
398+ gamma1.InitAsSecondary (pos, navState );
386399 gamma1.rngState = newRNG;
387400 gamma1.energy = theGamma1Ekin;
388401 gamma1.dir .Set (theGamma1Dir[0 ], theGamma1Dir[1 ], theGamma1Dir[2 ]);
389402
390- gamma2.InitAsSecondary (/* parent= */ currentTrack );
403+ gamma2.InitAsSecondary (pos, navState );
391404 // Reuse the RNG state of the dying track.
392405 gamma2.rngState = currentTrack.rngState ;
393406 gamma2.energy = theGamma2Ekin;
0 commit comments