ATLAS Offline Software
Loading...
Searching...
No Matches
G4AtlasWorkerRunManager.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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
30static std::mutex workerInitMutex;
31
32G4AtlasWorkerRunManager::G4AtlasWorkerRunManager()
33 : G4WorkerRunManager()
34 , AthMessaging("G4AtlasWorkerRunManager")
35{}
36
37
38G4AtlasWorkerRunManager* 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
47void G4AtlasWorkerRunManager::Initialize()
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);
54 G4RunManager::Initialize();
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(std::move(errMsg),std::move(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
93void 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
117void G4AtlasWorkerRunManager::InitializePhysics()
118{
119 const std::string methodName = "G4AtlasWorkerRunManager::InitializePhysics";
120
121 // Call the base class
122 G4RunManager::InitializePhysics();
123}
124
125
126bool 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
160void 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
167void 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
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Class to provide easy MsgStream access and capabilities.