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