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),
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:28
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.
void EventTermination(G4ErrorMode)
Terminate an event and set state to G4ErrorState_Init.
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.
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.
G4int PropagateOneStep(G4ErrorTrajState *currentTS, G4ErrorMode mode=G4ErrorMode_PropForwards)
Propagate a track by one step.
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.
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.