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
31// System includes
32#include <memory>
33#include <string>
34
35namespace G4UA
36{
37
38 //---------------------------------------------------------------------------
39 // Constructor
40 //---------------------------------------------------------------------------
45 {
46 // calculate this division only once
47 if (m_config.applyNRR)
48 m_oneOverWeightNeutron = 1./m_config.russianRouletteNeutronWeight;
49
50 // calculate this division only once
51 if (m_config.applyPRR)
52 m_oneOverWeightPhoton = 1./m_config.russianRoulettePhotonWeight;
53 }
54
55 //---------------------------------------------------------------------------
56 // Classify a new track
57 //---------------------------------------------------------------------------
58 G4ClassificationOfNewTrack
60 {
61 // Kill neutrinos if enabled
62 if(m_config.killAllNeutrinos && isNeutrino(track)) {
63 return fKill;
64 }
65
66 // Kill super-low-E photons
67 const double safeCut = 0.00005;
68 double totalE = track->GetTotalEnergy();
69 if(isGamma(track) && totalE < safeCut) {
70 return fKill;
71 }
72
73 // TODO: Why is this here? Can I remove it?
74 G4Event* ev = G4EventManager::GetEventManager()->GetNonconstCurrentEvent();
75 AtlasG4EventUserInfo* atlasG4EvtUserInfo __attribute__ ((unused)) =
76 static_cast<AtlasG4EventUserInfo*> (ev->GetUserInformation());
77
78 // Neutron Russian Roulette
79 if (m_config.applyNRR && isNeutron(track) &&
80 track->GetWeight() < m_config.russianRouletteNeutronWeight && // do not re-Roulette particles
81 track->GetKineticEnergy() < m_config.russianRouletteNeutronThreshold) {
82 // shoot random number
83 if ( CLHEP::RandFlat::shoot() > m_oneOverWeightNeutron ) {
84 // Kill (w-1)/w neutrons
85 return fKill;
86 }
87 // TODO There may be another way to set the weights via
88 // another G4 interface avoiding the const_cast, but the
89 // changes are more major and will need more careful validation.
90 G4Track* mutableTrack ATLAS_THREAD_SAFE = const_cast<G4Track*> (track);
91 // Weight the rest 1/w neutrons with a weight of w
92 mutableTrack->SetWeight(m_config.russianRouletteNeutronWeight);
93 }
94
95 // Photon Russian Roulette
96 if (m_config.applyPRR && isGamma(track) && track->GetOriginTouchable() &&
97 track->GetOriginTouchable()->GetVolume()->GetName().substr(0, 3) == "LAr" && // only for photons created in LAr
98 track->GetWeight() < m_config.russianRoulettePhotonWeight && // do not re-Roulette particles
99 track->GetKineticEnergy() < m_config.russianRoulettePhotonThreshold) {
100 // shoot random number
101 if ( CLHEP::RandFlat::shoot() > m_oneOverWeightPhoton ) {
102 // Kill (w-1)/w photons
103 return fKill;
104 }
105 // TODO There may be another way to set the weights via
106 // another G4 interface avoiding the const_cast, but the
107 // changes are more major and will need more careful validation.
108 G4Track* mutableTrack ATLAS_THREAD_SAFE = const_cast<G4Track*> (track);
109 // Weight the rest 1/w neutrons with a weight of w
110 mutableTrack->SetWeight(m_config.russianRoulettePhotonWeight);
111 }
112
113 // Handle primary particles
114 if(track->GetParentID() == 0) { // Condition for Primaries
115 // Extract the PrimaryParticleInformation
116 PrimaryParticleInformation* primaryPartInfo = this->getPrimaryParticleInformation(track);
117 // Fill some information for this track
118 if(primaryPartInfo) {
119 if (!m_config.isISFJob) {
120 // don't do anything
121 auto part = primaryPartInfo->GetHepMCParticle();
122 if (part) {
123 // OK, we got back to HepMC
124 std::unique_ptr<TrackInformation> ti = std::make_unique<TrackInformation>(part);
125 ti->SetRegenerationNr(0);
126 ti->SetClassification(TrackInformation::Primary);
127 // regNr=0 and classify=Primary are default values anyway
131 track->SetUserInformation(ti.release());
132 }
133 // TODO What does this condition mean?
134 else if(primaryPartInfo->GetParticleUniqueID() >= 0 && primaryPartInfo->GetParticleBarcode() >= 0) {
135 // PrimaryParticleInformation should at least provide a barcode
136 std::unique_ptr<TrackBarcodeInfo> bi = std::make_unique<TrackBarcodeInfo>(primaryPartInfo->GetParticleUniqueID(), primaryPartInfo->GetParticleBarcode());
140 track->SetUserInformation(bi.release());
141 }
142 } // no ISFParticle attached
143 } // has PrimaryParticleInformation
144 }
145 // Secondary track; decide whether to save or kill
146 else if( isGamma(track) &&
147 m_config.photonEnergyCut > 0 &&
148 totalE < m_config.photonEnergyCut )
149 {
150 return fKill;
151 }
152 return fUrgent;
153 }
154
156 {
157 const G4DynamicParticle* dp = track->GetDynamicParticle();
158 if(dp) {
159 const G4PrimaryParticle* pp = nullptr;
160 pp = dp->GetPrimaryParticle();
161 if(pp) {
162 // Extract the PrimaryParticleInformation
163 return dynamic_cast<PrimaryParticleInformation*>
164 ( pp->GetUserInformation() );
165 }
166 }
167 return nullptr;
168 }
169
170 //---------------------------------------------------------------------------
171 // Identify track definition
172 //---------------------------------------------------------------------------
173 bool AthenaStackingAction::isNeutrino(const G4Track* track) const
174 {
175 auto particleDef = track->GetParticleDefinition();
176 return (particleDef == G4NeutrinoE::NeutrinoEDefinition() ||
177 particleDef == G4AntiNeutrinoE::AntiNeutrinoEDefinition() ||
178 particleDef == G4NeutrinoMu::NeutrinoMuDefinition() ||
179 particleDef == G4AntiNeutrinoMu::AntiNeutrinoMuDefinition() ||
180 particleDef == G4NeutrinoTau::NeutrinoTauDefinition() ||
181 particleDef == G4AntiNeutrinoTau::AntiNeutrinoTauDefinition());
182 }
183
184 //---------------------------------------------------------------------------
185 bool AthenaStackingAction::isGamma(const G4Track* track) const
186 {
187 return track->GetParticleDefinition() == G4Gamma::Gamma();
188 }
189
190 //---------------------------------------------------------------------------
191 bool AthenaStackingAction::isNeutron(const G4Track* track) const
192 {
193 return track->GetParticleDefinition() == G4Neutron::Neutron();
194 }
195
196} // namespace G4UA
if(febId1==febId2)
__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
int ev
Definition globals.cxx:25
Configuration option struct for AthenaStackingAction.