ATLAS Offline Software
G4AtlasWorkerRunManager.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Hide multi-threading classes from builds without G4MT
6 #include "G4Types.hh"
7 #ifdef G4MULTITHREADED
8 
10 
11 #include "G4StateManager.hh"
12 #include "G4Event.hh"
13 #include "G4LogicalVolumeStore.hh"
14 #include "G4GeometryManager.hh"
15 #include "G4MTRunManager.hh"
16 #include "G4TransportationManager.hh"
17 #include "G4VUserDetectorConstruction.hh"
18 #include "G4UImanager.hh"
19 
21 #include "GaudiKernel/ISvcLocator.h"
22 #include "GaudiKernel/Bootstrap.h"
23 #include "GaudiKernel/IMessageSvc.h"
24 #include "GaudiKernel/GaudiException.h"
25 
26 
27 #include <mutex>
28 
29 static std::mutex workerInitMutex;
30 
31 G4AtlasWorkerRunManager::G4AtlasWorkerRunManager()
32  : G4WorkerRunManager()
33  , AthMessaging("G4AtlasWorkerRunManager")
34  // TODO: what if we need to make these configurable?
35  , m_detGeoSvc("DetectorGeometrySvc", "G4AtlasWorkerRunManager")
36  , m_fastSimTool("FastSimulationMasterTool")
37 {}
38 
39 
40 G4AtlasWorkerRunManager* G4AtlasWorkerRunManager::GetG4AtlasWorkerRunManager()
41 {
42  // Grab thread-local pointer from base class
43  auto* wrm = G4RunManager::GetRunManager();
44  if(wrm) { return static_cast<G4AtlasWorkerRunManager*>(wrm); }
45  else { return new G4AtlasWorkerRunManager; }
46 }
47 
48 
50 {
51  // Locking this initialization to protect currently thread-unsafe services
52  std::lock_guard<std::mutex> lock(workerInitMutex);
53 
54  // Setup geometry and physics via the base class
56 
57  /*
58  ** The following fragment of code applies all UI commangs from the master command stack.
59  ** It has been moved over here from G4InitTool::initThread() because in its previous
60  ** location the code had no effect (invalid application state).
61  **
62  ** Having this code here is OK, but placing it here we are changing some assumptions
63  ** implemented in the design of Geant4. This has to do with the handling of multiple
64  ** (G4)Runs in the same job. If a second run is executed and no physics or geometry
65  ** changes happened between the two runs [Worker]::Initialize() is not called. But UI
66  ** commands need to be called anyway, which is not going to happen with our implementation.
67  **
68  ** If ATLAS ever decides to run multiple G4 runs in the same job, all the MT initialization
69  ** will have to be thoroughly reviewed.
70  */
71  ATH_MSG_DEBUG("G4 Command: Trying at the end of Initialize()");
72  const std::string methodName = "G4AtlasWorkerRunManager::Initialize";
73  G4MTRunManager* masterRM = G4MTRunManager::GetMasterRunManager();
74  std::vector<G4String> cmds = masterRM->GetCommandStack();
75  G4UImanager* uimgr = G4UImanager::GetUIpointer();
76  for(const auto& it : cmds) {
77  int retVal = uimgr->ApplyCommand(it);
78  CommandLog(retVal, it);
79  if(retVal!=fCommandSucceeded) {
80  std::string errMsg{"Failed to apply command <"};
81  errMsg += (it + ">. Return value " + std::to_string(retVal));
82  throw GaudiException(errMsg,methodName,StatusCode::FAILURE);
83  }
84  }
85 
86  // Does some extra setup that we need.
87  ConstructScoringWorlds();
88  // Run initialization in G4RunManager.
89  // Normally done in BeamOn.
90  RunInitialization();
91 }
92 
93 void G4AtlasWorkerRunManager::InitializeGeometry()
94 {
95  const std::string methodName = "G4AtlasWorkerRunManager::InitializeGeometry";
96 
97  // I don't think this does anything
98  if(G4RunManager::IfGeometryHasBeenDestroyed()) {
99  G4TransportationManager::GetTransportationManager()->ClearParallelWorlds();
100  }
101 
102  // Get the world volume and give it to the kernel
103  G4RunManagerKernel* masterKernel = G4MTRunManager::GetMasterRunManagerKernel();
104  G4VPhysicalVolume* worldVol = masterKernel->GetCurrentWorld();
105  kernel->WorkerDefineWorldVolume(worldVol, false);
106  // We don't currently use parallel worlds in ATLAS, but someday we might
107  kernel->SetNumberOfParallelWorld(masterKernel->GetNumberOfParallelWorld());
108 
109  // Construct sensitive detectors and magnetic field
110  userDetector->ConstructSDandField();
111  userDetector->ConstructParallelSD();
112 
113  // Mark g4 geo as initialized
114  geometryInitialized = true;
115 }
116 
117 void G4AtlasWorkerRunManager::InitializePhysics()
118 {
119  const std::string methodName = "G4AtlasWorkerRunManager::InitializePhysics";
120 
121  // Call the base class
122  G4RunManager::InitializePhysics();
123 
124  // Setup the fast simulations
125  if(m_fastSimTool.retrieve().isFailure()) {
126  throw GaudiException("Could not retrieve FastSims master tool",
127  methodName, StatusCode::FAILURE);
128  }
129  if(m_fastSimTool->initializeFastSims().isFailure()) {
130  throw GaudiException("Failed to initialize FastSims for worker thread",
131  methodName, StatusCode::FAILURE);
132  }
133 }
134 
135 
136 bool G4AtlasWorkerRunManager::ProcessEvent(G4Event* event)
137 {
138 
139  G4StateManager* stateManager = G4StateManager::GetStateManager();
140  stateManager->SetNewState(G4State_GeomClosed);
141 
142  currentEvent = event;
143 
144  //eventManager->SetVerboseLevel(3);
145  //eventManager->GetTrackingManager()->SetVerboseLevel(3);
146  eventManager->ProcessOneEvent(currentEvent);
147  if (currentEvent->IsAborted()) {
148  ATH_MSG_WARNING( "G4AtlasWorkerRunManager::SimulateFADSEvent: " <<
149  "Event Aborted at Detector Simulation level" );
150  currentEvent = nullptr;
151  return true;
152  }
153 
154  this->AnalyzeEvent(currentEvent);
155  if (currentEvent->IsAborted()) {
156  ATH_MSG_WARNING( "G4AtlasWorkerRunManager::SimulateFADSEvent: " <<
157  "Event Aborted at Analysis level" );
158  currentEvent = nullptr;
159  return true;
160  }
161 
162  this->StackPreviousEvent(currentEvent);
163  bool abort = currentEvent->IsAborted();
164  currentEvent = nullptr;
165 
166  return abort;
167 }
168 
169 
170 void G4AtlasWorkerRunManager::RunTermination()
171 {
172  // Not sure what I should put here...
173  // Maybe I can just use the base class?
174  G4WorkerRunManager::RunTermination();
175 }
176 
177 void G4AtlasWorkerRunManager::CommandLog(int returnCode, const std::string& commandString) const
178 {
179  switch(returnCode) {
180  case 0: { ATH_MSG_DEBUG("G4 Command: " << commandString << " - Command Succeeded"); } break;
181  case 100: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Command Not Found!"); } break;
182  case 200: {
183  auto* stateManager = G4StateManager::GetStateManager();
184  ATH_MSG_DEBUG("G4 Command: " << commandString << " - Illegal Application State (" <<
185  stateManager->GetStateString(stateManager->GetCurrentState()) << ")!");
186  } break;
187  case 300: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Range!"); } break;
188  case 400: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Unreadable!"); } break;
189  case 500: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Candidates!"); } break;
190  case 600: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Alias Not Found!"); } break;
191  default: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Unknown Status!"); } break;
192  }
193 
194 }
195 
196 #endif // G4MULTITHREADED
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
skel.it
it
Definition: skel.GENtoEVGEN.py:423
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
Herwig7_QED_EvtGen_Common.cmds
string cmds
Definition: Herwig7_QED_EvtGen_Common.py:11
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
G4AtlasWorkerRunManager.h
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
jobOptions.Initialize
Initialize
Definition: jobOptions.pA.py:28
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
CI_EMPFlowData22test.returnCode
returnCode
Definition: CI_EMPFlowData22test.py:16
IGeoModelSvc.h