ATLAS Offline Software
Loading...
Searching...
No Matches
AthenaStackingAction.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6
7// Local includes
9
10// Truth includes
15
16// Geant4 includes
17#include "G4Track.hh"
18#include "G4Event.hh"
19#include "G4EventManager.hh"
20#include "G4NeutrinoE.hh"
21#include "G4NeutrinoMu.hh"
22#include "G4NeutrinoTau.hh"
23#include "G4AntiNeutrinoE.hh"
24#include "G4AntiNeutrinoMu.hh"
25#include "G4AntiNeutrinoTau.hh"
26#include "G4Gamma.hh"
27#include "G4Neutron.hh"
28
30#include "CxxUtils/fpcompare.h"
31
32// System includes
33#include <memory>
34#include <string>
35
36namespace G4UA
37{
38
39 //---------------------------------------------------------------------------
40 // Constructor
41 //---------------------------------------------------------------------------
43 m_config(config),
46 {
47 // calculate this division only once
48 if (m_config.applyNRR)
49 m_oneOverWeightNeutron = 1./m_config.russianRouletteNeutronWeight;
50
51 // calculate this division only once
52 if (m_config.applyPRR)
53 m_oneOverWeightPhoton = 1./m_config.russianRoulettePhotonWeight;
54 }
55
56 //---------------------------------------------------------------------------
57 // Classify a new track
58 //---------------------------------------------------------------------------
59 G4ClassificationOfNewTrack
61 {
62 // Kill neutrinos if enabled
63 if(m_config.killAllNeutrinos && isNeutrino(track)) {
64 return fKill;
65 }
66
67 // Kill super-low-E photons
68 const double safeCut = 0.00005;
69 double totalE = track->GetTotalEnergy();
70 if(isGamma(track) && totalE < safeCut) {
71 return fKill;
72 }
73
74 // TODO: Why is this here? Can I remove it?
75 G4Event* ev = G4EventManager::GetEventManager()->GetNonconstCurrentEvent();
76 AtlasG4EventUserInfo* atlasG4EvtUserInfo __attribute__ ((unused)) =
77 static_cast<AtlasG4EventUserInfo*> (ev->GetUserInformation());
78
79 // Neutron Russian Roulette
80 if (m_config.applyNRR && isNeutron(track) &&
81 CxxUtils::fpcompare::equal(track->GetWeight(), 1.0) && // do not re-Roulette particles
82 track->GetKineticEnergy() < m_config.russianRouletteNeutronThreshold) {
83 // shoot random number
84 if ( CLHEP::RandFlat::shoot() > m_oneOverWeightNeutron ) {
85 // Kill (w-1)/w neutrons
86 return fKill;
87 }
88 // TODO There may be another way to set the weights via
89 // another G4 interface avoiding the const_cast, but the
90 // changes are more major and will need more careful validation.
91 G4Track* mutableTrack ATLAS_THREAD_SAFE = const_cast<G4Track*> (track);
92 // Weight the rest 1/w neutrons with a weight of w
93 mutableTrack->SetWeight(m_config.russianRouletteNeutronWeight);
94 }
95
96 // Photon Russian Roulette
97 if (m_config.applyPRR && isGamma(track) && track->GetOriginTouchable() &&
98 track->GetOriginTouchable()->GetVolume()->GetName().substr(0, 3) == "LAr" && // only for photons created in LAr
99 CxxUtils::fpcompare::equal(track->GetWeight(), 1.0) && // do not re-Roulette particles
100 track->GetKineticEnergy() < m_config.russianRoulettePhotonThreshold) {
101 // shoot random number
102 if ( CLHEP::RandFlat::shoot() > m_oneOverWeightPhoton ) {
103 // Kill (w-1)/w photons
104 return fKill;
105 }
106 // TODO There may be another way to set the weights via
107 // another G4 interface avoiding the const_cast, but the
108 // changes are more major and will need more careful validation.
109 G4Track* mutableTrack ATLAS_THREAD_SAFE = const_cast<G4Track*> (track);
110 // Weight the rest 1/w neutrons with a weight of w
111 mutableTrack->SetWeight(m_config.russianRoulettePhotonWeight);
112 }
113
114 // Handle primary particles
115 if(track->GetParentID() == 0) { // Condition for Primaries
116 // Extract the PrimaryParticleInformation
117 PrimaryParticleInformation* primaryPartInfo = this->getPrimaryParticleInformation(track);
118 // Fill some information for this track
119 if(primaryPartInfo) {
120 if (!m_config.isISFJob) {
121 // don't do anything
122 auto part = primaryPartInfo->GetHepMCParticle();
123 if (part) {
124 // OK, we got back to HepMC
125 std::unique_ptr<TrackInformation> ti = std::make_unique<TrackInformation>(part);
126 ti->SetPrimaryGenParticle(part);
127 ti->SetGenerationZeroGenParticle(part);
128 ti->SetRegenerationNr(0);
129 ti->SetClassification(TrackInformation::Primary);
130 // regNr=0 and classify=Primary are default values anyway
134 track->SetUserInformation(ti.release());
135 }
136 // TODO What does this condition mean?
137 else if(primaryPartInfo->GetParticleUniqueID() >= 0 && primaryPartInfo->GetParticleBarcode() >= 0) {
138 // PrimaryParticleInformation should at least provide a barcode
139 std::unique_ptr<TrackBarcodeInfo> bi = std::make_unique<TrackBarcodeInfo>(primaryPartInfo->GetParticleUniqueID(), primaryPartInfo->GetParticleBarcode());
143 track->SetUserInformation(bi.release());
144 }
145 } // no ISFParticle attached
146 } // has PrimaryParticleInformation
147 }
148 // Secondary track; decide whether to save or kill
149 else if( isGamma(track) &&
150 m_config.photonEnergyCut > 0 &&
151 totalE < m_config.photonEnergyCut )
152 {
153 return fKill;
154 }
155 return fUrgent;
156 }
157
159 {
160 const G4DynamicParticle* dp = track->GetDynamicParticle();
161 if(dp) {
162 const G4PrimaryParticle* pp = nullptr;
163 pp = dp->GetPrimaryParticle();
164 if(pp) {
165 // Extract the PrimaryParticleInformation
166 return dynamic_cast<PrimaryParticleInformation*>
167 ( pp->GetUserInformation() );
168 }
169 }
170 return nullptr;
171 }
172
173 //---------------------------------------------------------------------------
174 // Identify track definition
175 //---------------------------------------------------------------------------
176 bool AthenaStackingAction::isNeutrino(const G4Track* track) const
177 {
178 auto particleDef = track->GetParticleDefinition();
179 return (particleDef == G4NeutrinoE::NeutrinoEDefinition() ||
180 particleDef == G4AntiNeutrinoE::AntiNeutrinoEDefinition() ||
181 particleDef == G4NeutrinoMu::NeutrinoMuDefinition() ||
182 particleDef == G4AntiNeutrinoMu::AntiNeutrinoMuDefinition() ||
183 particleDef == G4NeutrinoTau::NeutrinoTauDefinition() ||
184 particleDef == G4AntiNeutrinoTau::AntiNeutrinoTauDefinition());
185 }
186
187 //---------------------------------------------------------------------------
188 bool AthenaStackingAction::isGamma(const G4Track* track) const
189 {
190 return track->GetParticleDefinition() == G4Gamma::Gamma();
191 }
192
193 //---------------------------------------------------------------------------
194 bool AthenaStackingAction::isNeutron(const G4Track* track) const
195 {
196 return track->GetParticleDefinition() == G4Neutron::Neutron();
197 }
198
199} // namespace G4UA
if(pathvar)
__attribute__((always_inline)) inline uint16_t TileCalibDrawerBase
void unused(Args &&...)
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
This class is attached to G4Event objects as UserInformation.
Config m_config
Configuration options.
AthenaStackingAction(const Config &config)
Constructor with configuration.
bool isNeutrino(const G4Track *) const
Identify track as a neutrino.
bool isNeutron(const G4Track *) const
Identify track as a neutron.
virtual G4ClassificationOfNewTrack ClassifyNewTrack(const G4Track *track) override
Classify a new track.
bool isGamma(const G4Track *) const
Identify track as a photon.
PrimaryParticleInformation * getPrimaryParticleInformation(const G4Track *track) const
obtain the PrimaryParticleInformation from the current G4Track
This class is attached to G4PrimaryParticle objects as UserInformation.
HepMC::ConstGenParticlePtr GetHepMCParticle() const
return a pointer to the GenParticle used to create the G4PrimaryParticle
Workaround x86 precision issues for FP inequality comparisons.
int ev
Definition globals.cxx:25
bool equal(double a, double b)
Compare two FP numbers, working around x87 precision issues.
Definition fpcompare.h:114
Configuration option struct for AthenaStackingAction.