Skip to content

Commit 8d8251e

Browse files
add tracking cuts (apt-sim#336)
This PR adds the tracking cuts for electrons/positrons. For this, the annihilation of stopped positrons is moved after the discrete interaction kernels. Then, particles in the discrete interaction below the tracking cut are also marked as `stopped`. The energy of electrons is deposited, positrons are annihilated similarly to those that are stopped from continuous energy loss. It seems that the tracking cut does not have any impact on the performance in ttbar events or testEM3. Still, we should add it for consistency and it might have an impact for other settings. ToDo: - [ ] high-statistics physics validation
1 parent 8d758c5 commit 8d8251e

File tree

1 file changed

+60
-45
lines changed

1 file changed

+60
-45
lines changed

include/AdePT/kernels/electrons.cuh

+60-45
Original file line numberDiff line numberDiff line change
@@ -283,46 +283,6 @@ static __device__ __forceinline__ void TransportElectrons(adept::TrackManager<Tr
283283
const double theElCut = g4HepEmData.fTheMatCutData->fMatCutData[auxData.fMCIndex].fSecElProdCutE;
284284
const double theGammaCut = g4HepEmData.fTheMatCutData->fMatCutData[auxData.fMCIndex].fSecGamProdCutE;
285285

286-
if (stopped) {
287-
if (!IsElectron) {
288-
// Annihilate the stopped positron into two gammas heading to opposite
289-
// directions (isotropic).
290-
291-
// Apply cuts
292-
if (ApplyCuts && (copcore::units::kElectronMassC2 < theGammaCut)) {
293-
// Deposit the energy here and don't initialize any secondaries
294-
energyDeposit += 2 * copcore::units::kElectronMassC2;
295-
} else {
296-
Track &gamma1 = secondaries.gammas->NextTrack();
297-
Track &gamma2 = secondaries.gammas->NextTrack();
298-
299-
adept_scoring::AccountProduced(userScoring, /*numElectrons*/ 0, /*numPositrons*/ 0, /*numGammas*/ 2);
300-
301-
const double cost = 2 * currentTrack.Uniform() - 1;
302-
const double sint = sqrt(1 - cost * cost);
303-
const double phi = k2Pi * currentTrack.Uniform();
304-
double sinPhi, cosPhi;
305-
sincos(phi, &sinPhi, &cosPhi);
306-
307-
gamma1.InitAsSecondary(pos, navState, globalTime);
308-
newRNG.Advance();
309-
gamma1.parentID = currentTrack.parentID;
310-
gamma1.rngState = newRNG;
311-
gamma1.eKin = copcore::units::kElectronMassC2;
312-
gamma1.dir.Set(sint * cosPhi, sint * sinPhi, cost);
313-
314-
gamma2.InitAsSecondary(pos, navState, globalTime);
315-
// Reuse the RNG state of the dying track.
316-
gamma2.parentID = currentTrack.parentID;
317-
gamma2.rngState = currentTrack.rngState;
318-
gamma2.eKin = copcore::units::kElectronMassC2;
319-
gamma2.dir = -gamma1.dir;
320-
}
321-
}
322-
// Particles are killed by not enqueuing them into the new activeQueue.
323-
// continue;
324-
}
325-
326286
if (!stopped) {
327287
if (nextState.IsOnBoundary()) {
328288
// For now, just count that we hit something.
@@ -334,18 +294,15 @@ static __device__ __forceinline__ void TransportElectrons(adept::TrackManager<Tr
334294
cross_boundary = true;
335295
}
336296
// Particle left the world, don't enqueue it
337-
// continue;
338297
} else if (!propagated || restrictedPhysicalStepLength) {
339298
// Did not yet reach the interaction point due to error in the magnetic
340299
// field propagation. Try again next time.
341300
survive();
342301
reached_interaction = false;
343-
// continue;
344302
} else if (winnerProcessIndex < 0) {
345303
// No discrete process, move on.
346304
survive();
347305
reached_interaction = false;
348-
// continue;
349306
}
350307
}
351308

@@ -358,7 +315,6 @@ static __device__ __forceinline__ void TransportElectrons(adept::TrackManager<Tr
358315
if (G4HepEmElectronManager::CheckDelta(&g4HepEmData, theTrack, currentTrack.Uniform())) {
359316
// A delta interaction happened, move on.
360317
survive();
361-
// continue;
362318
} else {
363319
// Perform the discrete interaction, make sure the branched RNG state is
364320
// ready to be used.
@@ -395,6 +351,16 @@ static __device__ __forceinline__ void TransportElectrons(adept::TrackManager<Tr
395351
}
396352

397353
eKin -= deltaEkin;
354+
355+
// if below tracking cut, deposit energy for electrons (positrons are annihilated later) and stop particles
356+
if (eKin < g4HepEmPars.fElectronTrackingCut) {
357+
if (IsElectron) {
358+
energyDeposit += eKin;
359+
}
360+
stopped = true;
361+
break;
362+
}
363+
398364
dir.Set(dirPrimary[0], dirPrimary[1], dirPrimary[2]);
399365
survive();
400366
break;
@@ -429,6 +395,16 @@ static __device__ __forceinline__ void TransportElectrons(adept::TrackManager<Tr
429395
}
430396

431397
eKin -= deltaEkin;
398+
399+
// if below tracking cut, deposit energy for electrons (positrons are annihilated later) and stop particles
400+
if (eKin < g4HepEmPars.fElectronTrackingCut) {
401+
if (IsElectron) {
402+
energyDeposit += eKin;
403+
}
404+
stopped = true;
405+
break;
406+
}
407+
432408
dir.Set(dirPrimary[0], dirPrimary[1], dirPrimary[2]);
433409
survive();
434410
break;
@@ -480,7 +456,46 @@ static __device__ __forceinline__ void TransportElectrons(adept::TrackManager<Tr
480456
}
481457
}
482458

483-
// Redord the step. Edep includes the continuous energy loss and edep from secondaries which were cut
459+
if (stopped) {
460+
if (!IsElectron) {
461+
// Annihilate the stopped positron into two gammas heading to opposite
462+
// directions (isotropic).
463+
464+
// Apply cuts
465+
if (ApplyCuts && (copcore::units::kElectronMassC2 < theGammaCut)) {
466+
// Deposit the energy here and don't initialize any secondaries
467+
energyDeposit += 2 * copcore::units::kElectronMassC2;
468+
} else {
469+
Track &gamma1 = secondaries.gammas->NextTrack();
470+
Track &gamma2 = secondaries.gammas->NextTrack();
471+
472+
adept_scoring::AccountProduced(userScoring, /*numElectrons*/ 0, /*numPositrons*/ 0, /*numGammas*/ 2);
473+
474+
const double cost = 2 * currentTrack.Uniform() - 1;
475+
const double sint = sqrt(1 - cost * cost);
476+
const double phi = k2Pi * currentTrack.Uniform();
477+
double sinPhi, cosPhi;
478+
sincos(phi, &sinPhi, &cosPhi);
479+
480+
gamma1.InitAsSecondary(pos, navState, globalTime);
481+
newRNG.Advance();
482+
gamma1.parentID = currentTrack.parentID;
483+
gamma1.rngState = newRNG;
484+
gamma1.eKin = copcore::units::kElectronMassC2;
485+
gamma1.dir.Set(sint * cosPhi, sint * sinPhi, cost);
486+
487+
gamma2.InitAsSecondary(pos, navState, globalTime);
488+
// Reuse the RNG state of the dying track.
489+
gamma2.parentID = currentTrack.parentID;
490+
gamma2.rngState = currentTrack.rngState;
491+
gamma2.eKin = copcore::units::kElectronMassC2;
492+
gamma2.dir = -gamma1.dir;
493+
}
494+
}
495+
// Particles are killed by not enqueuing them into the new activeQueue.
496+
}
497+
498+
// Record the step. Edep includes the continuous energy loss and edep from secondaries which were cut
484499
if (energyDeposit > 0 && auxData.fSensIndex >= 0)
485500
adept_scoring::RecordHit(userScoring, currentTrack.parentID,
486501
IsElectron ? 0 : 1, // Particle type

0 commit comments

Comments
 (0)