31
31
template <bool IsElectron>
32
32
static __device__ __forceinline__ void TransportElectrons (Track *electrons, const adept::MParray *active,
33
33
Secondaries &secondaries, adept::MParray *activeQueue,
34
- GlobalScoring *globalScoring,
35
- ScoringPerVolume *scoringPerVolume, SOAData soaData )
34
+ Interactions interactions, GlobalScoring *globalScoring,
35
+ ScoringPerVolume *scoringPerVolume)
36
36
{
37
37
#ifdef VECGEOM_FLOAT_PRECISION
38
38
const Precision kPush = 10 * vecgeom::kTolerance ;
@@ -57,9 +57,6 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
57
57
if (push) activeQueue->push_back (globalSlot);
58
58
};
59
59
60
- // Signal that this globalSlot doesn't undergo an interaction (yet)
61
- soaData.nextInteraction [i] = -1 ;
62
-
63
60
// Init a track with the needed data to call into G4HepEm.
64
61
G4HepEmElectronTrack elTrack;
65
62
G4HepEmTrack *theTrack = elTrack.GetTrack ();
@@ -285,151 +282,150 @@ static __device__ __forceinline__ void TransportElectrons(Track *electrons, cons
285
282
continue ;
286
283
}
287
284
288
- soaData. nextInteraction [i] = winnerProcessIndex;
285
+ interactions. queues [ winnerProcessIndex]-> push_back (globalSlot) ;
289
286
290
287
survive (false );
291
288
}
292
289
}
293
290
294
291
// Instantiate kernels for electrons and positrons.
295
292
__global__ void TransportElectrons (Track *electrons, const adept::MParray *active, Secondaries secondaries,
296
- adept::MParray *activeQueue, GlobalScoring *globalScoring,
297
- ScoringPerVolume *scoringPerVolume, SOAData soaData )
293
+ adept::MParray *activeQueue, Interactions interactions, GlobalScoring *globalScoring,
294
+ ScoringPerVolume *scoringPerVolume)
298
295
{
299
- TransportElectrons</* IsElectron*/ true >(electrons, active, secondaries, activeQueue, globalScoring, scoringPerVolume ,
300
- soaData );
296
+ TransportElectrons</* IsElectron*/ true >(electrons, active, secondaries, activeQueue, interactions, globalScoring ,
297
+ scoringPerVolume );
301
298
}
302
299
__global__ void TransportPositrons (Track *positrons, const adept::MParray *active, Secondaries secondaries,
303
- adept::MParray *activeQueue, GlobalScoring *globalScoring,
304
- ScoringPerVolume *scoringPerVolume, SOAData soaData )
300
+ adept::MParray *activeQueue, Interactions interactions, GlobalScoring *globalScoring,
301
+ ScoringPerVolume *scoringPerVolume)
305
302
{
306
- TransportElectrons</* IsElectron*/ false >(positrons, active, secondaries, activeQueue, globalScoring, scoringPerVolume ,
307
- soaData );
303
+ TransportElectrons</* IsElectron*/ false >(positrons, active, secondaries, activeQueue, interactions, globalScoring ,
304
+ scoringPerVolume );
308
305
}
309
306
310
307
template <bool IsElectron, int ProcessIndex>
311
- __device__ void ElectronInteraction (int const globalSlot, SOAData const & /* soaData */ , int const /* soaSlot */ ,
312
- Track *particles, Secondaries secondaries, adept::MParray *activeQueue,
313
- GlobalScoring *globalScoring, ScoringPerVolume *scoringPerVolume)
308
+ __device__ void ElectronInteraction (Track *particles, const adept::MParray *active, Secondaries secondaries ,
309
+ adept::MParray *activeQueue, GlobalScoring *globalScoring ,
310
+ ScoringPerVolume *scoringPerVolume)
314
311
{
315
- Track ¤tTrack = particles[globalSlot];
316
- const auto volume = currentTrack.navState .Top ();
317
- // the MCC vector is indexed by the logical volume id
318
- const int lvolID = volume->GetLogicalVolume ()->id ();
319
- const int theMCIndex = MCIndex[lvolID];
320
-
321
- auto survive = [&] { activeQueue->push_back (globalSlot); };
322
-
323
- const double energy = currentTrack.energy ;
324
- const double theElCut = g4HepEmData.fTheMatCutData ->fMatCutData [theMCIndex].fSecElProdCutE ;
325
-
326
- RanluxppDouble newRNG{currentTrack.rngState .Branch ()};
327
- G4HepEmRandomEngine rnge{¤tTrack.rngState };
328
-
329
- if constexpr (ProcessIndex == 0 ) {
330
- // Invoke ionization (for e-/e+):
331
- double deltaEkin = (IsElectron) ? G4HepEmElectronInteractionIoni::SampleETransferMoller (theElCut, energy, &rnge)
332
- : G4HepEmElectronInteractionIoni::SampleETransferBhabha (theElCut, energy, &rnge);
333
-
334
- double dirPrimary[] = {currentTrack.dir .x (), currentTrack.dir .y (), currentTrack.dir .z ()};
335
- double dirSecondary[3 ];
336
- G4HepEmElectronInteractionIoni::SampleDirections (energy, deltaEkin, dirSecondary, dirPrimary, &rnge);
337
-
338
- Track &secondary = secondaries.electrons .NextTrack ();
339
- atomicAdd (&globalScoring->numElectrons , 1 );
340
-
341
- secondary.InitAsSecondary (/* parent=*/ currentTrack);
342
- secondary.rngState = newRNG;
343
- secondary.energy = deltaEkin;
344
- secondary.dir .Set (dirSecondary[0 ], dirSecondary[1 ], dirSecondary[2 ]);
345
-
346
- currentTrack.energy = energy - deltaEkin;
347
- currentTrack.dir .Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
348
- survive ();
349
- } else if constexpr (ProcessIndex == 1 ) {
350
- // Invoke model for Bremsstrahlung: either SB- or Rel-Brem.
351
- double logEnergy = std::log (energy);
352
- double deltaEkin = energy < g4HepEmPars.fElectronBremModelLim
353
- ? G4HepEmElectronInteractionBrem::SampleETransferSB (&g4HepEmData, energy, logEnergy,
354
- theMCIndex, &rnge, IsElectron)
355
- : G4HepEmElectronInteractionBrem::SampleETransferRB (&g4HepEmData, energy, logEnergy,
356
- theMCIndex, &rnge, IsElectron);
357
-
358
- double dirPrimary[] = {currentTrack.dir .x (), currentTrack.dir .y (), currentTrack.dir .z ()};
359
- double dirSecondary[3 ];
360
- G4HepEmElectronInteractionBrem::SampleDirections (energy, deltaEkin, dirSecondary, dirPrimary, &rnge);
361
-
362
- Track &gamma = secondaries.gammas .NextTrack ();
363
- atomicAdd (&globalScoring->numGammas , 1 );
364
-
365
- gamma .InitAsSecondary (/* parent=*/ currentTrack);
366
- gamma .rngState = newRNG;
367
- gamma .energy = deltaEkin;
368
- gamma .dir .Set (dirSecondary[0 ], dirSecondary[1 ], dirSecondary[2 ]);
369
-
370
- currentTrack.energy = energy - deltaEkin;
371
- currentTrack.dir .Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
372
- survive ();
373
- } else if constexpr (ProcessIndex == 2 ) {
374
- // Invoke annihilation (in-flight) for e+
375
- double dirPrimary[] = {currentTrack.dir .x (), currentTrack.dir .y (), currentTrack.dir .z ()};
376
- double theGamma1Ekin, theGamma2Ekin;
377
- double theGamma1Dir[3 ], theGamma2Dir[3 ];
378
- G4HepEmPositronInteractionAnnihilation::SampleEnergyAndDirectionsInFlight (
379
- energy, dirPrimary, &theGamma1Ekin, theGamma1Dir, &theGamma2Ekin, theGamma2Dir, &rnge);
380
-
381
- Track &gamma1 = secondaries.gammas .NextTrack ();
382
- Track &gamma2 = secondaries.gammas .NextTrack ();
383
- atomicAdd (&globalScoring->numGammas , 2 );
384
-
385
- gamma1.InitAsSecondary (/* parent=*/ currentTrack);
386
- gamma1.rngState = newRNG;
387
- gamma1.energy = theGamma1Ekin;
388
- gamma1.dir .Set (theGamma1Dir[0 ], theGamma1Dir[1 ], theGamma1Dir[2 ]);
389
-
390
- gamma2.InitAsSecondary (/* parent=*/ currentTrack);
391
- // Reuse the RNG state of the dying track.
392
- gamma2.rngState = currentTrack.rngState ;
393
- gamma2.energy = theGamma2Ekin;
394
- gamma2.dir .Set (theGamma2Dir[0 ], theGamma2Dir[1 ], theGamma2Dir[2 ]);
395
-
396
- // The current track is killed by not enqueuing into the next activeQueue.
312
+ int activeSize = active->size ();
313
+ for (int i = blockIdx .x * blockDim .x + threadIdx .x ; i < activeSize; i += blockDim .x * gridDim .x ) {
314
+ const int globalSlot = (*active)[i];
315
+ Track ¤tTrack = particles[globalSlot];
316
+ const auto volume = currentTrack.navState .Top ();
317
+ // the MCC vector is indexed by the logical volume id
318
+ const int lvolID = volume->GetLogicalVolume ()->id ();
319
+ const int theMCIndex = MCIndex[lvolID];
320
+
321
+ auto survive = [&] { activeQueue->push_back (globalSlot); };
322
+
323
+ const double energy = currentTrack.energy ;
324
+ const double theElCut = g4HepEmData.fTheMatCutData ->fMatCutData [theMCIndex].fSecElProdCutE ;
325
+
326
+ RanluxppDouble newRNG{currentTrack.rngState .Branch ()};
327
+ G4HepEmRandomEngine rnge{¤tTrack.rngState };
328
+
329
+ if constexpr (ProcessIndex == 0 ) {
330
+ // Invoke ionization (for e-/e+):
331
+ double deltaEkin = (IsElectron) ? G4HepEmElectronInteractionIoni::SampleETransferMoller (theElCut, energy, &rnge)
332
+ : G4HepEmElectronInteractionIoni::SampleETransferBhabha (theElCut, energy, &rnge);
333
+
334
+ double dirPrimary[] = {currentTrack.dir .x (), currentTrack.dir .y (), currentTrack.dir .z ()};
335
+ double dirSecondary[3 ];
336
+ G4HepEmElectronInteractionIoni::SampleDirections (energy, deltaEkin, dirSecondary, dirPrimary, &rnge);
337
+
338
+ Track &secondary = secondaries.electrons .NextTrack ();
339
+ atomicAdd (&globalScoring->numElectrons , 1 );
340
+
341
+ secondary.InitAsSecondary (/* parent=*/ currentTrack);
342
+ secondary.rngState = newRNG;
343
+ secondary.energy = deltaEkin;
344
+ secondary.dir .Set (dirSecondary[0 ], dirSecondary[1 ], dirSecondary[2 ]);
345
+
346
+ currentTrack.energy = energy - deltaEkin;
347
+ currentTrack.dir .Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
348
+ survive ();
349
+ } else if constexpr (ProcessIndex == 1 ) {
350
+ // Invoke model for Bremsstrahlung: either SB- or Rel-Brem.
351
+ double logEnergy = std::log (energy);
352
+ double deltaEkin = energy < g4HepEmPars.fElectronBremModelLim
353
+ ? G4HepEmElectronInteractionBrem::SampleETransferSB (&g4HepEmData, energy, logEnergy,
354
+ theMCIndex, &rnge, IsElectron)
355
+ : G4HepEmElectronInteractionBrem::SampleETransferRB (&g4HepEmData, energy, logEnergy,
356
+ theMCIndex, &rnge, IsElectron);
357
+
358
+ double dirPrimary[] = {currentTrack.dir .x (), currentTrack.dir .y (), currentTrack.dir .z ()};
359
+ double dirSecondary[3 ];
360
+ G4HepEmElectronInteractionBrem::SampleDirections (energy, deltaEkin, dirSecondary, dirPrimary, &rnge);
361
+
362
+ Track &gamma = secondaries.gammas .NextTrack ();
363
+ atomicAdd (&globalScoring->numGammas , 1 );
364
+
365
+ gamma .InitAsSecondary (/* parent=*/ currentTrack);
366
+ gamma .rngState = newRNG;
367
+ gamma .energy = deltaEkin;
368
+ gamma .dir .Set (dirSecondary[0 ], dirSecondary[1 ], dirSecondary[2 ]);
369
+
370
+ currentTrack.energy = energy - deltaEkin;
371
+ currentTrack.dir .Set (dirPrimary[0 ], dirPrimary[1 ], dirPrimary[2 ]);
372
+ survive ();
373
+ } else if constexpr (ProcessIndex == 2 ) {
374
+ // Invoke annihilation (in-flight) for e+
375
+ double dirPrimary[] = {currentTrack.dir .x (), currentTrack.dir .y (), currentTrack.dir .z ()};
376
+ double theGamma1Ekin, theGamma2Ekin;
377
+ double theGamma1Dir[3 ], theGamma2Dir[3 ];
378
+ G4HepEmPositronInteractionAnnihilation::SampleEnergyAndDirectionsInFlight (
379
+ energy, dirPrimary, &theGamma1Ekin, theGamma1Dir, &theGamma2Ekin, theGamma2Dir, &rnge);
380
+
381
+ Track &gamma1 = secondaries.gammas .NextTrack ();
382
+ Track &gamma2 = secondaries.gammas .NextTrack ();
383
+ atomicAdd (&globalScoring->numGammas , 2 );
384
+
385
+ gamma1.InitAsSecondary (/* parent=*/ currentTrack);
386
+ gamma1.rngState = newRNG;
387
+ gamma1.energy = theGamma1Ekin;
388
+ gamma1.dir .Set (theGamma1Dir[0 ], theGamma1Dir[1 ], theGamma1Dir[2 ]);
389
+
390
+ gamma2.InitAsSecondary (/* parent=*/ currentTrack);
391
+ // Reuse the RNG state of the dying track.
392
+ gamma2.rngState = currentTrack.rngState ;
393
+ gamma2.energy = theGamma2Ekin;
394
+ gamma2.dir .Set (theGamma2Dir[0 ], theGamma2Dir[1 ], theGamma2Dir[2 ]);
395
+
396
+ // The current track is killed by not enqueuing into the next activeQueue.
397
+ }
397
398
}
398
399
}
399
400
400
401
__global__ void IonizationEl (Track *particles, const adept::MParray *active, Secondaries secondaries,
401
402
adept::MParray *activeQueue, GlobalScoring *globalScoring,
402
- ScoringPerVolume *scoringPerVolume, SOAData const soaData )
403
+ ScoringPerVolume *scoringPerVolume)
403
404
{
404
- InteractionLoop<0 >(&ElectronInteraction<true , 0 >, active, soaData, particles, secondaries, activeQueue, globalScoring,
405
- scoringPerVolume);
405
+ ElectronInteraction<true , 0 >(particles, active, secondaries, activeQueue, globalScoring, scoringPerVolume);
406
406
}
407
407
__global__ void BremsstrahlungEl (Track *particles, const adept::MParray *active, Secondaries secondaries,
408
408
adept::MParray *activeQueue, GlobalScoring *globalScoring,
409
- ScoringPerVolume *scoringPerVolume, SOAData const soaData )
409
+ ScoringPerVolume *scoringPerVolume)
410
410
{
411
- InteractionLoop<1 >(&ElectronInteraction<true , 1 >, active, soaData, particles, secondaries, activeQueue, globalScoring,
412
- scoringPerVolume);
411
+ ElectronInteraction<true , 1 >(particles, active, secondaries, activeQueue, globalScoring, scoringPerVolume);
413
412
}
414
413
415
414
__global__ void IonizationPos (Track *particles, const adept::MParray *active, Secondaries secondaries,
416
415
adept::MParray *activeQueue, GlobalScoring *globalScoring,
417
- ScoringPerVolume *scoringPerVolume, SOAData const soaData )
416
+ ScoringPerVolume *scoringPerVolume)
418
417
{
419
- InteractionLoop<0 >(&ElectronInteraction<false , 0 >, active, soaData, particles, secondaries, activeQueue,
420
- globalScoring, scoringPerVolume);
418
+ ElectronInteraction<false , 0 >(particles, active, secondaries, activeQueue, globalScoring, scoringPerVolume);
421
419
}
422
420
__global__ void BremsstrahlungPos (Track *particles, const adept::MParray *active, Secondaries secondaries,
423
421
adept::MParray *activeQueue, GlobalScoring *globalScoring,
424
- ScoringPerVolume *scoringPerVolume, SOAData const soaData )
422
+ ScoringPerVolume *scoringPerVolume)
425
423
{
426
- InteractionLoop<1 >(&ElectronInteraction<false , 1 >, active, soaData, particles, secondaries, activeQueue,
427
- globalScoring, scoringPerVolume);
424
+ ElectronInteraction<false , 1 >(particles, active, secondaries, activeQueue, globalScoring, scoringPerVolume);
428
425
}
429
426
__global__ void AnnihilationPos (Track *particles, const adept::MParray *active, Secondaries secondaries,
430
427
adept::MParray *activeQueue, GlobalScoring *globalScoring,
431
- ScoringPerVolume *scoringPerVolume, SOAData const soaData )
428
+ ScoringPerVolume *scoringPerVolume)
432
429
{
433
- InteractionLoop<2 >(&ElectronInteraction<false , 2 >, active, soaData, particles, secondaries, activeQueue,
434
- globalScoring, scoringPerVolume);
430
+ ElectronInteraction<false , 2 >(particles, active, secondaries, activeQueue, globalScoring, scoringPerVolume);
435
431
}
0 commit comments