Belle II Software development
ExtManager.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <simulation/kernel/ExtManager.h>
10#include <simulation/kernel/RunManager.h>
11#include <simulation/kernel/MagneticField.h>
12#include <simulation/kernel/DetectorConstruction.h>
13#include <simulation/kernel/ExtPhysicsList.h>
14
15#include <vector>
16#include <string>
17
18#include <G4UImanager.hh>
19#include <G4RunManager.hh>
20#include <G4EventManager.hh>
21#include <G4RegionStore.hh>
22#include <G4ProductionCutsTable.hh>
23#include <G4ErrorPropagatorData.hh>
24#include <G4ErrorPropagator.hh>
25#include <G4StateManager.hh>
26#include <G4TransportationManager.hh>
27#include <G4FieldManager.hh>
28#include <G4CachedMagneticField.hh>
29#include <G4Mag_UsualEqRhs.hh>
30#include <G4ErrorMag_UsualEqRhs.hh>
31#include <G4MagIntegratorStepper.hh>
32#include <G4NystromRK4.hh>
33#include <G4HelixExplicitEuler.hh>
34#include <G4HelixSimpleRunge.hh>
35#include <G4EquationOfMotion.hh>
36#include <G4ChordFinder.hh>
37#include <G4LossTableManager.hh>
38#include <G4VisExecutive.hh>
39#include <G4VExceptionHandler.hh>
40
41#include <framework/logging/Logger.h>
42
43using namespace Belle2;
44using namespace Belle2::Simulation;
45
47
49class StepExceptionHandler: public G4VExceptionHandler {
50public:
56 virtual bool Notify(const char* origin, const char* code, G4ExceptionSeverity, const char* description)
57 {
58 // Is this an exception for low-momentum track that would over-curl in B field?
59 if (strstr(description, "Error returned: 3") != nullptr) {
60 B2DEBUG(1, "In " << origin << ", " << code << ": " << description);
61 //FIXME: This is an exception for Gean4 navigation error from the basf2 side, reported as BII-6782
62 } else if (strstr(code, "GeomNav0003") != nullptr) {
63 B2DEBUG(20, "In " << origin << ", " << code << ": " << description);
64 // END FIXME
65 } else {
66 B2ERROR("In " << origin << ", " << code << ": " << description);
67 }
68 return false;
69 }
70};
71
73{
74 if (m_Manager == nullptr) m_Manager = new ExtManager;
75 return m_Manager;
76}
77
79 m_G4State(G4StateManager::GetStateManager()->GetCurrentState()),
80 m_Propagator(nullptr),
81 m_G4RunMgr(nullptr),
82 m_TrackingAction(nullptr),
83 m_SteppingAction(nullptr),
84 m_MagneticField(nullptr),
85 m_UncachedField(nullptr),
86 m_MagFldEquation(nullptr),
87 m_Stepper(nullptr),
88 m_ChordFinder(nullptr),
89 m_StdStepper(nullptr),
90 m_ForwardEquationOfMotion(nullptr),
91 m_BackwardEquationOfMotion(nullptr),
92 m_VisManager(nullptr)
93{
94 // This flag will be PreInit if FullSimModule is not present
95 G4ErrorPropagatorData::GetErrorPropagatorData()->SetState(G4ErrorState_PreInit);
96 // Create a private handler for G4Exceptions during PropagateOneStep
98}
99
101{
103 if (m_Propagator) { delete m_Propagator; m_Propagator = NULL; }
104}
105
107{
108 if (m_G4RunMgr) {
109 m_G4RunMgr->SetUserAction((G4UserTrackingAction*)NULL);
110 m_G4RunMgr->SetUserAction((G4UserSteppingAction*)NULL);
111 }
112 if (mode == G4ErrorMode_PropBackwards) {
113 if (m_StdStepper) {
114 m_StdStepper->SetEquationOfMotion(m_BackwardEquationOfMotion);
115 }
116 }
117 if (m_Propagator == NULL) m_Propagator = new G4ErrorPropagator();
118 m_Propagator->SetStepN(0);
119 G4ErrorPropagatorData::GetErrorPropagatorData()->SetState(G4ErrorState_Propagating);
120}
121
122G4int ExtManager::PropagateOneStep(G4ErrorTrajState* currentTS, G4ErrorMode mode)
123{
124 G4ErrorPropagatorData::GetErrorPropagatorData()->SetMode(mode);
125 // Remember the existing G4Exception handler
126 G4VExceptionHandler* savedHandler = G4StateManager::GetStateManager()->GetExceptionHandler();
127 // Set our own exception handler temporarily
128 G4StateManager::GetStateManager()->SetExceptionHandler(m_StepExceptionHandler);
129 // Propagate one step via geant4e
130 G4int result = m_Propagator->PropagateOneStep(currentTS);
131 // Restore the saved exception handler
132 G4StateManager::GetStateManager()->SetExceptionHandler(savedHandler);
133 return result;
134}
135
136void ExtManager::EventTermination(G4ErrorMode mode)
137{
138 G4ErrorPropagatorData::GetErrorPropagatorData()->SetState(G4ErrorState_Init);
139 if (m_G4RunMgr) {
140 m_G4RunMgr->SetUserAction(m_TrackingAction);
141 m_G4RunMgr->SetUserAction(m_SteppingAction);
142 }
143 if (mode == G4ErrorMode_PropBackwards) {
144 if (m_StdStepper) {
145 m_StdStepper->SetEquationOfMotion(m_ForwardEquationOfMotion);
146 }
147 }
148}
149
151{
152 if (G4ErrorPropagatorData::GetErrorPropagatorData()->GetState() == G4ErrorState_PreInit) return;
153
154 if (m_G4RunMgr) {
155 m_G4RunMgr->SetUserAction(m_TrackingAction);
156 m_G4RunMgr->SetUserAction(m_SteppingAction);
157 } else {
158 // Copied from FullSimModule
159 //We used one Geant4 run for all Belle2 runs so end the geant4 run here
160 RunManager& myRunMgr = RunManager::Instance();
161 myRunMgr.endRun();
162 //And clean up the run manager
163 if (m_VisManager) delete m_VisManager;
164 myRunMgr.destroy();
165 // Delete the objects associated with transport in magnetic field
166 if (m_ChordFinder) delete m_ChordFinder;
167 if (m_Stepper) delete m_Stepper;
171 }
173 G4ErrorPropagatorData::GetErrorPropagatorData()->SetState(G4ErrorState_PreInit);
174}
175
176void ExtManager::Initialize(const char caller[], const std::string& magneticFieldName,
177 double magneticCacheDistance,
178 double deltaChordInMagneticField,
179 bool enableVisualization,
180 int trackingVerbosity,
181 const std::vector<std::string>& uiCommands)
182{
183
184 int status = (m_G4State == G4State_PreInit) ? 0 : 2;
185
186 if (G4ErrorPropagatorData::GetErrorPropagatorData()->GetState() == G4ErrorState_Init) {
187 status += 1;
188 if (status == 1) {
189 B2INFO("ExtManager::Initialize(): " << caller << " will run without FullSim; the extrapolator has already been initialized");
190 } else {
191 B2INFO("ExtManager::Initialize(): " << caller << " will run with FullSim; the extrapolator has already been initialized");
192 }
193 return;
194 }
195
196 G4FieldManager* fieldManager = G4TransportationManager::GetTransportationManager()->GetFieldManager();
197 if (status == 2) {
198 m_G4RunMgr = G4RunManager::GetRunManager();
199 m_TrackingAction = const_cast<G4UserTrackingAction*>(m_G4RunMgr->GetUserTrackingAction());
200 m_SteppingAction = const_cast<G4UserSteppingAction*>(m_G4RunMgr->GetUserSteppingAction());
201 } else { // status == 0
202
203 RunManager& myRunMgr = RunManager::Instance();
204
205 // This is duplicated from FullSimModule::initialize() to use the Geant4/Geant4e
206 // machinery for extrapolation only (no simulation)
207
208 // Create the magnetic field for the geant4e extrapolation
209 if (magneticFieldName != "none") {
211 if (magneticCacheDistance > 0.0) {
213 m_MagneticField = new G4CachedMagneticField(m_UncachedField, magneticCacheDistance);
214 }
215 fieldManager->SetDetectorField(m_MagneticField);
216 if (magneticFieldName != "default") {
217
218 //We only use Magnetic field so let's try the specialized steppers
219 m_MagFldEquation = new G4Mag_UsualEqRhs(m_MagneticField);
220 if (magneticFieldName == "nystrom") {
221 m_Stepper = new G4NystromRK4(m_MagFldEquation);
222 } else if (magneticFieldName == "expliciteuler") {
223 m_Stepper = new G4HelixExplicitEuler(m_MagFldEquation);
224 } else if (magneticFieldName == "simplerunge") {
225 m_Stepper = new G4HelixSimpleRunge(m_MagFldEquation);
226 } else {
227 B2FATAL("Unknown magnetic field option: " << magneticFieldName);
228 }
229
230 //Set a minimum stepsize (stepMinimum): The chordfinder should not attempt to limit
231 //the stepsize to something less than 10µm (which is the default value of Geant4).
232 m_ChordFinder = new G4ChordFinder(m_MagneticField, 1e-2 * CLHEP::mm, m_Stepper);
233 fieldManager->SetChordFinder(m_ChordFinder);
234 } else {
235 fieldManager->CreateChordFinder(m_MagneticField);
236 }
237
238 //Change DeltaCord (the max. miss-distance between the trajectory curve and its linear chord(s) approximation, if asked.
239 G4ChordFinder* chordFinder = fieldManager->GetChordFinder();
240 B2DEBUG(1, "Geant4 default deltaChord = " << chordFinder->GetDeltaChord());
241 chordFinder->SetDeltaChord(deltaChordInMagneticField * CLHEP::mm);
242 B2DEBUG(1, "DeltaChord after reset = " << chordFinder->GetDeltaChord());
243 //This might be a good place to optimize the Integration parameters (DeltaOneStep, DeltaIntersection, MinEpsilon, MaxEpsilon)
244 }
245
246 //Set the verbosity level of Geant4 according to the logging settings of the module
247 int g4VerboseLevel = 0;
248 switch (LogSystem::Instance().getCurrentLogLevel()) {
249 case LogConfig::c_Debug : g4VerboseLevel = 2;
250 break;
251 case LogConfig::c_Info : g4VerboseLevel = 1;
252 break;
253 default: g4VerboseLevel = 0;
254 }
255 G4EventManager::GetEventManager()->SetVerboseLevel(g4VerboseLevel);
256 G4RunManager::GetRunManager()->SetVerboseLevel(g4VerboseLevel);
257 G4EventManager::GetEventManager()->GetTrackingManager()->SetVerboseLevel(
258 trackingVerbosity); //turned out to be more useful as a parameter.
259 G4LossTableManager::Instance()->SetVerbose(g4VerboseLevel);
260
261 if (enableVisualization) {
262 m_VisManager = new G4VisExecutive;
263 m_VisManager->Initialize();
264 }
265
266 //Apply the Geant4 UI commands
267 if (uiCommands.size() > 0) {
268 G4UImanager* uiManager = G4UImanager::GetUIpointer();
269 for (std::vector<std::string>::const_iterator iter = uiCommands.begin(); iter != uiCommands.end(); ++iter) {
270 uiManager->ApplyCommand(*iter);
271 }
272 }
273
274 // Construct the detector and bare-bones physics list
275 myRunMgr.SetUserInitialization(new DetectorConstruction());
276 G4Region* region = (*(G4RegionStore::GetInstance()))[0];
277 region->SetProductionCuts(G4ProductionCutsTable::GetProductionCutsTable()->GetDefaultProductionCuts());
278 myRunMgr.SetUserInitialization(new ExtPhysicsList());
279 myRunMgr.Initialize();
280 B2INFO("ExtManager::Initialize(): Perform Geant4 final initialization: Geometry optimization, ExtPhysicsList calculations...");
281 myRunMgr.beginRun(0);
282 B2INFO("ExtManager::Initialize(): done, Geant4 ready (for extrapolation only)");
283 G4StateManager::GetStateManager()->SetNewState(G4State_Idle);
284 }
285
286 // Prepare for the possibility of back-extrapolation
287 if (m_MagneticField != NULL) {
288 m_StdStepper = const_cast<G4MagIntegratorStepper*>(fieldManager->GetChordFinder()->GetIntegrationDriver()->GetStepper());
289 m_ForwardEquationOfMotion = m_StdStepper->GetEquationOfMotion();
290 m_BackwardEquationOfMotion = new G4ErrorMag_UsualEqRhs(m_MagneticField);
291 }
292
293 G4ErrorPropagatorData::GetErrorPropagatorData()->SetState(G4ErrorState_Init);
294 if (status == 0) {
295 B2INFO("ExtManager::Initialize(): " << caller << " will run without FullSim and has initialized the extrapolator");
296 } else {
297 B2INFO("ExtManager::Initialize(): " << caller << " will run with FullSim and has initialized the extrapolator");
298 }
299 return;
300}
301
Class responsible to connect to geometry to simulation.
@ c_Info
Info: for informational messages, e.g.
Definition: LogConfig.h:27
@ c_Debug
Debug: for code development.
Definition: LogConfig.h:26
static LogSystem & Instance()
Static method to get a reference to the LogSystem instance.
Definition: LogSystem.cc:31
It is the main interface for the user to define the setup and start the propagation.
Definition: ExtManager.h:50
G4VisManager * m_VisManager
Pointer to the visualization manager (if used)
Definition: ExtManager.h:137
G4RunManager * m_G4RunMgr
Pointer to the simulation's G4RunManager (if any)
Definition: ExtManager.h:101
G4MagIntegratorStepper * m_Stepper
Pointer to the equation-of-motion stepper (if not the default)
Definition: ExtManager.h:122
G4VExceptionHandler * m_StepExceptionHandler
Pointer to the G4VExceptionHandler used in PropagateOneStep()
Definition: ExtManager.h:110
static ExtManager * GetManager()
Get pointer to the instance of this singleton class (create if needed)
Definition: ExtManager.cc:72
G4MagIntegratorStepper * m_StdStepper
Pointer to the standard equation-of-motion stepper.
Definition: ExtManager.h:128
void RunTermination()
Terminate a run and set state to G4ErrorState_Init.
Definition: ExtManager.cc:150
void EventTermination(G4ErrorMode)
Terminate an event and set state to G4ErrorState_Init.
Definition: ExtManager.cc:136
static ExtManager * m_Manager
Stores pointer to the singleton class.
Definition: ExtManager.h:92
G4MagneticField * m_UncachedField
Pointer to the uncached magnetic field (might be superseded by its cached version)
Definition: ExtManager.h:116
G4Mag_UsualEqRhs * m_MagFldEquation
Pointer to the equation of motion in the magnetic field (if not the default)
Definition: ExtManager.h:119
G4MagneticField * m_MagneticField
Pointer to the (un)cached magnetic field.
Definition: ExtManager.h:113
G4UserTrackingAction * m_TrackingAction
Pointer to the simulation's TrackingAction (if any)
Definition: ExtManager.h:104
G4EquationOfMotion * m_ForwardEquationOfMotion
Pointer to the forward-propagation equation of motion.
Definition: ExtManager.h:131
G4ApplicationState m_G4State
Initial state of the G4RunManager (=PreInitif FullSimModule not present)
Definition: ExtManager.h:95
G4UserSteppingAction * m_SteppingAction
Pointer to the simulation's SteppingAction (if any)
Definition: ExtManager.h:107
void InitTrackPropagation(G4ErrorMode)
Initialize for propagation of a track and set state to G4ErrorState_Propagating.
Definition: ExtManager.cc:106
ExtManager()
constructor is hidden: user calls ExtManager::GetManager() instead
Definition: ExtManager.cc:78
G4EquationOfMotion * m_BackwardEquationOfMotion
Pointer to the equation of motion that accommodates back-propagation.
Definition: ExtManager.h:134
void Initialize(const char[], const std::string &, double, double, bool, int, const std::vector< std::string > &)
Initialize Geant4 and Geant4e.
Definition: ExtManager.cc:176
G4int PropagateOneStep(G4ErrorTrajState *currentTS, G4ErrorMode mode=G4ErrorMode_PropForwards)
Propagate a track by one step.
Definition: ExtManager.cc:122
G4ChordFinder * m_ChordFinder
Pointer to the equation-of-motion chord finder (if not the default)
Definition: ExtManager.h:125
G4ErrorPropagator * m_Propagator
Stores pointer to the propagator.
Definition: ExtManager.h:98
Standalone physics list for the geant4e extrapolator.
The Class for the Belle2 magnetic field implementation for Geant4.
Definition: MagneticField.h:28
The run manager controls the flow of the Geant4 program and manages the event loop(s) within a run.
Definition: RunManager.h:32
void beginRun(int runNumber)
Prepares Geant4 for a new run.
Definition: RunManager.cc:49
void destroy()
Destroys the RunManager at the end of the simulation.
Definition: RunManager.cc:85
void endRun()
Terminates a Geant4 run.
Definition: RunManager.cc:79
void Initialize()
Initialize the Kernel.
Definition: RunManager.cc:35
static RunManager & Instance()
Static method to get a reference to the RunManager instance.
Definition: RunManager.cc:29
Class to handle G4Exception raised during PropagateOneStep()
Definition: ExtManager.cc:49
virtual bool Notify(const char *origin, const char *code, G4ExceptionSeverity, const char *description)
G4VExceptionHandler method called when an exception is raised.
Definition: ExtManager.cc:56
~StepExceptionHandler()
Destructor.
Definition: ExtManager.cc:54
StepExceptionHandler()
Constructor.
Definition: ExtManager.cc:52
Abstract base class for different kinds of events.