Belle II Software  release-08-01-10
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 
43 using namespace Belle2;
44 using namespace Belle2::Simulation;
45 
47 
49 class StepExceptionHandler: public G4VExceptionHandler {
50 public:
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 {
102  delete m_StepExceptionHandler;
103  if (m_Propagator) { delete m_Propagator; m_Propagator = NULL; }
104 }
105 
106 void ExtManager::InitTrackPropagation(G4ErrorMode mode)
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 
122 G4int 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 
136 void 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;
169  if (m_UncachedField) delete m_UncachedField;
170  if (m_MagneticField) delete m_MagneticField;
171  }
173  G4ErrorPropagatorData::GetErrorPropagatorData()->SetState(G4ErrorState_PreInit);
174 }
175 
176 void 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.