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