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->SetRegenerationNr(0);
127 ti->SetClassification(TrackInformation::Primary);
128 // regNr=0 and classify=Primary are default values anyway
132 track->SetUserInformation(ti.release());
133 }
134 // TODO What does this condition mean?
135 else if(primaryPartInfo->GetParticleUniqueID() >= 0 && primaryPartInfo->GetParticleBarcode() >= 0) {
136 // PrimaryParticleInformation should at least provide a barcode
137 std::unique_ptr<TrackBarcodeInfo> bi = std::make_unique<TrackBarcodeInfo>(primaryPartInfo->GetParticleUniqueID(), primaryPartInfo->GetParticleBarcode());
141 track->SetUserInformation(bi.release());
142 }
143 } // no ISFParticle attached
144 } // has PrimaryParticleInformation
145 }
146 // Secondary track; decide whether to save or kill
147 else if( isGamma(track) &&
148 m_config.photonEnergyCut > 0 &&
149 totalE < m_config.photonEnergyCut )
150 {
151 return fKill;
152 }
153 return fUrgent;
154 }
155
157 {
158 const G4DynamicParticle* dp = track->GetDynamicParticle();
159 if(dp) {
160 const G4PrimaryParticle* pp = nullptr;
161 pp = dp->GetPrimaryParticle();
162 if(pp) {
163 // Extract the PrimaryParticleInformation
164 return dynamic_cast<PrimaryParticleInformation*>
165 ( pp->GetUserInformation() );
166 }
167 }
168 return nullptr;
169 }
170
171 //---------------------------------------------------------------------------
172 // Identify track definition
173 //---------------------------------------------------------------------------
174 bool AthenaStackingAction::isNeutrino(const G4Track* track) const
175 {
176 auto particleDef = track->GetParticleDefinition();
177 return (particleDef == G4NeutrinoE::NeutrinoEDefinition() ||
178 particleDef == G4AntiNeutrinoE::AntiNeutrinoEDefinition() ||
179 particleDef == G4NeutrinoMu::NeutrinoMuDefinition() ||
180 particleDef == G4AntiNeutrinoMu::AntiNeutrinoMuDefinition() ||
181 particleDef == G4NeutrinoTau::NeutrinoTauDefinition() ||
182 particleDef == G4AntiNeutrinoTau::AntiNeutrinoTauDefinition());
183 }
184
185 //---------------------------------------------------------------------------
186 bool AthenaStackingAction::isGamma(const G4Track* track) const
187 {
188 return track->GetParticleDefinition() == G4Gamma::Gamma();
189 }
190
191 //---------------------------------------------------------------------------
192 bool AthenaStackingAction::isNeutron(const G4Track* track) const
193 {
194 return track->GetParticleDefinition() == G4Neutron::Neutron();
195 }
196
197} // 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.