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 #include "G4HadronicProcessStore.hh"
20 
22 #include "GaudiKernel/ISvcLocator.h"
23 #include "GaudiKernel/Bootstrap.h"
24 #include "GaudiKernel/IMessageSvc.h"
25 #include "GaudiKernel/GaudiException.h"
26 
27 
28 #include <mutex>
29 
30 static std::mutex workerInitMutex;
31 
32 G4AtlasWorkerRunManager::G4AtlasWorkerRunManager()
33  : G4WorkerRunManager()
34  , AthMessaging("G4AtlasWorkerRunManager")
35 {}
36 
37 
38 G4AtlasWorkerRunManager* G4AtlasWorkerRunManager::GetG4AtlasWorkerRunManager()
39 {
40  // Grab thread-local pointer from base class
41  auto* wrm = G4RunManager::GetRunManager();
42  if(wrm) { return static_cast<G4AtlasWorkerRunManager*>(wrm); }
43  else { return new G4AtlasWorkerRunManager; }
44 }
45 
46 
48 {
49  // Locking this initialization to protect currently thread-unsafe services
50  std::lock_guard<std::mutex> lock(workerInitMutex);
51 
52  // Setup geometry and physics via the base class
53  G4HadronicProcessStore::Instance()->SetVerbose(0);
55 
56  /*
57  ** The following fragment of code applies all UI commangs from the master command stack.
58  ** It has been moved over here from G4InitTool::initThread() because in its previous
59  ** location the code had no effect (invalid application state).
60  **
61  ** Having this code here is OK, but placing it here we are changing some assumptions
62  ** implemented in the design of Geant4. This has to do with the handling of multiple
63  ** (G4)Runs in the same job. If a second run is executed and no physics or geometry
64  ** changes happened between the two runs [Worker]::Initialize() is not called. But UI
65  ** commands need to be called anyway, which is not going to happen with our implementation.
66  **
67  ** If ATLAS ever decides to run multiple G4 runs in the same job, all the MT initialization
68  ** will have to be thoroughly reviewed.
69  */
70  ATH_MSG_DEBUG("G4 Command: Trying at the end of Initialize()");
71  const std::string methodName = "G4AtlasWorkerRunManager::Initialize";
72  G4MTRunManager* masterRM = G4MTRunManager::GetMasterRunManager();
73  std::vector<G4String> cmds = masterRM->GetCommandStack();
74  G4UImanager* uimgr = G4UImanager::GetUIpointer();
75  for(const auto& it : cmds) {
76  int retVal = uimgr->ApplyCommand(it);
77  CommandLog(retVal, it);
78  if(retVal!=fCommandSucceeded) {
79  std::string errMsg{"Failed to apply command <"};
80  errMsg += (it + ">. Return value " + std::to_string(retVal));
81  throw GaudiException(errMsg,methodName,StatusCode::FAILURE);
82  }
83  }
84 
85  // Does some extra setup that we need.
86  ConstructScoringWorlds();
87  // Run initialization in G4RunManager.
88  // Normally done in BeamOn.
89  if (m_quietMode) { SetVerboseLevel(0); } // HACK
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 
125 
126 bool G4AtlasWorkerRunManager::ProcessEvent(G4Event* event)
127 {
128 
129  G4StateManager* stateManager = G4StateManager::GetStateManager();
130  stateManager->SetNewState(G4State_GeomClosed);
131 
132  currentEvent = event;
133 
134  //eventManager->SetVerboseLevel(3);
135  //eventManager->GetTrackingManager()->SetVerboseLevel(3);
136  eventManager->ProcessOneEvent(currentEvent);
137  if (currentEvent->IsAborted()) {
138  ATH_MSG_WARNING( "G4AtlasWorkerRunManager::SimulateFADSEvent: " <<
139  "Event Aborted at Detector Simulation level" );
140  currentEvent = nullptr;
141  return true;
142  }
143 
144  this->AnalyzeEvent(currentEvent);
145  if (currentEvent->IsAborted()) {
146  ATH_MSG_WARNING( "G4AtlasWorkerRunManager::SimulateFADSEvent: " <<
147  "Event Aborted at Analysis level" );
148  currentEvent = nullptr;
149  return true;
150  }
151 
152  this->StackPreviousEvent(currentEvent);
153  bool abort = currentEvent->IsAborted();
154  currentEvent = nullptr;
155 
156  return abort;
157 }
158 
159 
160 void G4AtlasWorkerRunManager::RunTermination()
161 {
162  // Not sure what I should put here...
163  // Maybe I can just use the base class?
164  G4WorkerRunManager::RunTermination();
165 }
166 
167 void G4AtlasWorkerRunManager::CommandLog(int returnCode, const std::string& commandString) const
168 {
169  switch(returnCode) {
170  case 0: { ATH_MSG_DEBUG("G4 Command: " << commandString << " - Command Succeeded"); } break;
171  case 100: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Command Not Found!"); } break;
172  case 200: {
173  auto* stateManager = G4StateManager::GetStateManager();
174  ATH_MSG_DEBUG("G4 Command: " << commandString << " - Illegal Application State (" <<
175  stateManager->GetStateString(stateManager->GetCurrentState()) << ")!");
176  } break;
177  case 300: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Range!"); } break;
178  case 400: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Unreadable!"); } break;
179  case 500: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Candidates!"); } break;
180  case 600: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Alias Not Found!"); } break;
181  default: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Unknown Status!"); } break;
182  }
183 
184 }
185 
186 #endif // G4MULTITHREADED
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
skel.it
it
Definition: skel.GENtoEVGEN.py:407
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
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
IGeoModelSvc.h