ATLAS Offline Software
G4CaloTransportTool.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 #include "G4CaloTransportTool.h"
6 
7 // Geant4 includes for for particle extrapolation
8 #include "G4FieldTrack.hh"
9 #include "G4FieldTrackUpdator.hh"
10 #include "G4LogicalVolumeStore.hh"
11 #include "G4Navigator.hh"
12 #include "G4PVPlacement.hh"
13 #include "G4PathFinder.hh"
14 #include "G4TransportationManager.hh"
15 
17  const std::string& name,
18  const IInterface* parent)
19  : base_class(type, name, parent) {}
20 
22 
23  // Delete the world volume if we created it
25  delete m_worldVolume;
26 
27  // Delete the navigators and propagators for each thread
28  for (auto& mapPair : m_propagatorHolder.getMap()) {
29  delete mapPair.second->GetNavigatorForPropagating();
30  delete mapPair.second;
31  }
32 
33  return StatusCode::SUCCESS;
34 }
35 
37  ATH_MSG_INFO("Initializing G4PropagatorInField for thread "
38  << G4Threading::G4GetThreadId());
39 
40  if (!m_worldVolume) {
41  // If not set, get either the simplified or full world volume
43 
44  if (!m_worldVolume) {
45  G4Exception("G4CaloTransportTool", "FailedToGetWorldVolume",
46  FatalException,
47  "G4CaloTransportTool: Failed to get world volume.");
48  abort();
49  }
50  ATH_MSG_INFO("Using world volume: " << m_worldVolume->GetName());
51  ATH_MSG_INFO("Transport will be stopped at volume: "
52  << m_transportLimitVolume.value());
53  ATH_MSG_INFO("Maximum allowed number of steps in particle transport: "
54  << m_maxSteps.value());
55  }
56 
57  // Check if we already have propagator set up for the current thread
58  auto propagator = m_propagatorHolder.get();
59  // If not, we create one
60  if (!propagator) {
61  propagator = makePropagator();
62  m_propagatorHolder.set(propagator);
63  } else {
64  ATH_MSG_ERROR("G4CaloTransportTool::initializePropagator() Propagator already initialized!");
65  }
66 
67  return StatusCode::SUCCESS;
68 }
69 
71 
72  if (m_useSimplifiedGeo) {
73 
74  ATH_MSG_INFO("Creating simplified world volume for particle transport");
75  // Get the logical world volume of the simplified geometry by name
76  G4LogicalVolume* logVol = G4LogicalVolumeStore::GetInstance()->GetVolume(
77  m_simplifiedWorldLogName.value());
78 
79  // Create the physical volume of the simplified world
80  return new G4PVPlacement(
81  nullptr, // no rotation
82  G4ThreeVector(0, 0, 0), // world centre at (0,0,0)
83  logVol, // logical volume
84  "simplifiedWorldPhysVol", // name of physical volume
85  nullptr, // mother volume
86  false, // not used
87  999, // copy number
88  false); // overlap check
89 
90  } else {
91  ATH_MSG_INFO("Using full geometry for particle transport");
92  return G4TransportationManager::GetTransportationManager()
93  ->GetNavigatorForTracking()
94  ->GetWorldVolume();
95  }
96 }
97 
98 G4PropagatorInField* G4CaloTransportTool::makePropagator() {
99  // Create a new navigator
100  G4Navigator* navigator = new G4Navigator();
101  // Set world volume in which the navigator will operate
102  navigator->SetWorldVolume(m_worldVolume);
103  // Get the global field manager
104  G4FieldManager* fieldMgr =
105  G4TransportationManager::GetTransportationManager()->GetFieldManager();
106  // Create a new magnetic field propagator
107  G4PropagatorInField* propagator =
108  new G4PropagatorInField(navigator, fieldMgr);
109 
110  return propagator;
111 }
112 
113 void G4CaloTransportTool::doStep(G4FieldTrack& fieldTrack) {
114 
115  // Get the propagator and navigator for the current thread
116  auto propagator = m_propagatorHolder.get();
117  auto navigator = propagator->GetNavigatorForPropagating();
118 
119  G4double retSafety = -1.0;
120  G4double currentMinimumStep = 10.0 * CLHEP::m;
121 
122  G4VPhysicalVolume* currentPhysVol =
123  navigator->LocateGlobalPointAndSetup(fieldTrack.GetPosition(), nullptr);
124 
125  G4ThreeVector direction = fieldTrack.GetMomentumDirection();
126  // Must be called before calling the computeStep method
127  navigator->LocateGlobalPointAndSetup(fieldTrack.GetPosition(), &direction);
128 
129  if (fieldTrack.GetCharge() == 0) {
130  /* Neutral particles: transport with navigator */
131 
132  // Compute the step length
133  G4double stepLength = navigator->ComputeStep(
134  fieldTrack.GetPosition(), fieldTrack.GetMomentumDirection(),
135  currentMinimumStep, retSafety);
136 
137  // Update the position of the track from the computed step length
138  fieldTrack.SetPosition(fieldTrack.GetPosition() +
139  stepLength *
140  fieldTrack.GetMomentumDirection().unit());
141 
142  } else {
143  /* Charged particles: transport with magnetic field propagator */
144  propagator->ComputeStep(fieldTrack, currentMinimumStep, retSafety,
145  currentPhysVol);
146  }
147 
148  return;
149 }
150 
151 std::vector<G4FieldTrack> G4CaloTransportTool::transport(
152  const G4Track& G4InputTrack) {
153 
154  // Get the navigator for the current thread
155  auto navigator = m_propagatorHolder.get()->GetNavigatorForPropagating();
156 
157  // Create a vector to store the output steps
158  std::vector<G4FieldTrack> outputStepVector;
159  // Initialize the tmpFieldTrack with the input track
160  G4FieldTrack tmpFieldTrack('0');
161  G4FieldTrackUpdator::Update(&tmpFieldTrack, &G4InputTrack);
162  // Fill with the initial particle position
163  outputStepVector.push_back(tmpFieldTrack);
164 
165  // Iterate until we reach the maximum number of steps or the requested volume
166  for (unsigned int iStep = 0; iStep < m_maxSteps; iStep++) {
167  // Perform a single Geant4 step
168  doStep(tmpFieldTrack);
169  // Fill the output vector with the updated track
170  outputStepVector.push_back(tmpFieldTrack);
171  // Get the name of the volume in which the particle is located
172  auto volumn = navigator->LocateGlobalPointAndSetup(tmpFieldTrack.GetPosition(), nullptr);
173  if (volumn != nullptr) {
174  std::string volName = volumn->GetName();
175  // We stop the track navigation once we have reached the provided volume
176  if (volName.find(m_transportLimitVolume) != std::string::npos)
177  break;
178  } else {
179  G4ExceptionDescription description;
180  description <<"at step " << iStep << "/" << m_maxSteps.value() << " with position " << tmpFieldTrack.GetPosition() << " and momentum " << tmpFieldTrack.GetMomentum();
181  G4Exception("G4CaloTransportTool::transport",
182  "Cannot get LocateGlobalPointAndSetup",
183  JustWarning,
184  description);
185  }
186  }
187 
188  return outputStepVector;
189 }
G4CaloTransportTool::finalize
virtual StatusCode finalize() override final
Definition: G4CaloTransportTool.cxx:21
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
G4CaloTransportTool::m_transportLimitVolume
Gaudi::Property< std::string > m_transportLimitVolume
Definition: G4CaloTransportTool.h:53
G4CaloTransportTool::m_simplifiedWorldLogName
Gaudi::Property< std::string > m_simplifiedWorldLogName
Definition: G4CaloTransportTool.h:51
G4CaloTransportTool::m_worldVolume
G4VPhysicalVolume * m_worldVolume
Definition: G4CaloTransportTool.h:46
thread_utils::ThreadLocalHolder::getMap
const ThreadMap_t & getMap() const
Constant access for iteration, etc.
Definition: ThreadLocalHolder.h:73
G4CaloTransportTool::m_maxSteps
Gaudi::Property< unsigned int > m_maxSteps
Definition: G4CaloTransportTool.h:55
thread_utils::ThreadLocalHolder::set
void set(T *obj)
Assign the object of the current thread.
Definition: ThreadLocalHolder.h:67
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
test_pyathena.parent
parent
Definition: test_pyathena.py:15
thread_utils::ThreadLocalHolder::get
T * get()
Get the object of the current thread.
Definition: ThreadLocalHolder.h:60
G4CaloTransportTool::G4CaloTransportTool
G4CaloTransportTool(const std::string &, const std::string &, const IInterface *)
Definition: G4CaloTransportTool.cxx:16
G4CaloTransportTool.h
G4CaloTransportTool::transport
virtual std::vector< G4FieldTrack > transport(const G4Track &G4InputTrack) override final
Definition: G4CaloTransportTool.cxx:151
G4CaloTransportTool::makePropagator
G4PropagatorInField * makePropagator()
Definition: G4CaloTransportTool.cxx:98
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
G4CaloTransportTool::m_propagatorHolder
thread_utils::ThreadLocalHolder< G4PropagatorInField > m_propagatorHolder
Definition: G4CaloTransportTool.h:57
G4CaloTransportTool::getWorldVolume
G4VPhysicalVolume * getWorldVolume()
Definition: G4CaloTransportTool.cxx:70
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
G4CaloTransportTool::initializePropagator
StatusCode initializePropagator() override final
Definition: G4CaloTransportTool.cxx:36
G4CaloTransportTool::doStep
void doStep(G4FieldTrack &fieldTrack)
Definition: G4CaloTransportTool.cxx:113
G4CaloTransportTool::m_useSimplifiedGeo
Gaudi::Property< bool > m_useSimplifiedGeo
Definition: G4CaloTransportTool.h:49
description
std::string description
glabal timer - how long have I taken so far?
Definition: hcg.cxx:88