Run

Basic concept of Run

In Geant4, Run is the largest unit of simulation. A run consists of a sequence of events. Within a run, the detector geometry, the set up of sensitive detectors, and the physics processes used in the simulation should be kept unchanged. A run is represented by a G4Run class object. A run starts with BeamOn() method of G4RunManager.

Representation of a run

G4Run represents a run. It has a run identification number, which should be set by the user, and the number of events simulated during the run. Please note that the run identification number is not used by the Geant4 kernel, and thus can be arbitrarily assigned at the user’s convenience.

G4Run has pointers to the tables G4VHitsCollection and G4VDigiCollection. These tables are associated in case sensitive detectors and digitizer modules are simulated, respectively. The usage of these tables will be mentioned in Hits and Digitization.

G4Run has two virtual methods, and thus you can extend G4Run class. In particular if you use Geant4 in multi-threaded mode and need to accumulate values, these two virtual method must be overwritten to specify how such values should be collected firstly for a worker thread, and then for the entire run. These virtual methods are the following.

virtual void RecordEvent(const G4Event*)

Method to be overwritten by the user for recording events in this (thread-local) run. At the end of the implementation, G4Run base-class method for must be invoked for recording data members in the base class.

void Merge(const G4Run*)

Method to be overwritten by the user for merging local Run object to the global Run object. At the end of the implementation, G4Run base-class method for must be invoked for merging data members in the base class.

Manage the run procedures

G4RunManager manages the procedures of a run. In the constructor of G4RunManager, all of the manager classes in Geant4 kernel, except for some static managers, are constructed. These managers are deleted in the destructor of G4RunManager. G4RunManager must be a singleton created in the user’s main() program; the pointer to this singleton object can be obtained by other code using the GetRunManager() static method.

As already mentioned in How to Define the main() Program, all of the user initialization classes defined by the user should be assigned to G4RunManager before starting initialization of the Geant4 kernel. The assignments of these user classes are done by SetUserInitialization() methods. All user classes defined by the Geant4 kernel will be summarized in User Actions.

G4RunManager has several public methods, which are listed below.

Initialize()

All initializations required by the Geant4 kernel are triggered by this method. Initializations are:

  • construction of the detector geometry and set up of sensitive detectors and/or digitizer modules,

  • construction of particles and physics processes,

  • calculation of cross-section tables.

This method is thus mandatory before proceeding to the first run. This method will be invoked automatically for the second and later runs in case some of the initialized quantities need to be updated.

BeamOn(G4int numberOfEvent)

This method triggers the actual simulation of a run, that is, an event loop. It takes an integer argument which represents the number of events to be simulated.

GetRunManager()

This static method returns the pointer to the G4RunManager singleton object.

GetCurrentEvent()

This method returns the pointer to the G4Event object which is currently being simulated. This method is available only when an event is being processed. At this moment, the application state of Geant4, which is explained in the following sub-section, is “EventProc”. When Geant4 is in a state other than “EventProc”, this method returns null. Please note that the return value of this method is const G4Event * and thus you cannot modify the contents of the object.

SetNumberOfEventsToBeStored(G4int nPrevious)

When simulating the “pile up” of more than one event, it is essential to access more than one event at the same moment. By invoking this method, G4RunManager keeps nPrevious G4Event objects. This method must be invoked before proceeding to BeamOn().

GetPreviousEvent(G4int i_thPrevious)

The pointer to the i_thPrevious G4Event object can be obtained through this method. A pointer to a const object is returned. It is inevitable that i_thPrevious events must have already been simulated in the same run for getting the i_thPrevious event. Otherwise, this method returns null.

AbortRun()

This method should be invoked whenever the processing of a run must be stopped. It is valid for GeomClosed and EventProc states. Run processing will be safely aborted even in the midst of processing an event. However, the last event of the aborted run will be incomplete and should not be used for further analysis.

Run manager classes for multi-threading mode

G4MTRunManager is the replacement of G4RunManager for multi-threading mode. At the very end of Initialize() method, G4MTRunManager creates and starts worker threads. The event each thread is tasked is in first-come-first-served basis, so that event numbers each thread has are not sequential.

G4WorkerRunManager is the local RunManager automatically instantiated by G4MTRunManager to take care of initialization and event handling of a thread. Both G4MTRunManager and G4WorkerRunManager are derived classes of G4RunManager base class.

The static method G4RunManager::GetRunManager() returns the following pointer.

  • It returns the pointer to the G4WorkerRunManager of the local thread when it is invoked from thread-local object.

  • It returns the pointer to the G4MTRunManager when it is invoked from shared object.

  • It returns the pointer to the base G4RunManager if it is used in the sequential mode.

G4RunManager has a method GetRunManagerType() that returns an enum named RMType to indicate what kind of RunManager it is. RMType is defined as { sequentialRM, masterRM, workerRM }. From the thread-local object, a static method G4MTRunManager::GetMasterRunManager() is available to access to G4MTRunManager. From a worker thread, the user may access to, for example, detector construction (it is a shared class) through this GetMasterRunManager() method.

G4UserRunAction

G4UserRunAction is one of the user action classes from which you can derive your own concrete class. This base class has three virtual methods as follows:

GenerateRun()

This method is invoked at the beginning of the BeamOn() method but after confirmation of the conditions of the Geant4 kernel. This method should be used to instantiate a user-specific run class object.

BeginOfRunAction()

This method is invoked at the beginning of the BeamOn() method but after confirmation of the conditions of the Geant4 kernel. Likely uses of this method include:

  • setting a run identification number,

  • booking histograms,

  • setting run specific conditions of the sensitive detectors and/or digitizer modules (e.g., dead channels).

EndOfRunAction()

This method is invoked at the very end of the BeamOn() method. Typical use cases of this method are

  • store/print histograms,

  • manipulate run summaries.

Geant4 as a state machine

Geant4 is designed as a state machine. Some methods in Geant4 are available for only a certain state(s). G4RunManager controls the state changes of the Geant4 application. States of Geant4 are represented by the enumeration G4ApplicationState. It has six states through the life cycle of a Geant4 application.

G4State_PreInit state

A Geant4 application starts with this state. The application needs to be initialized when it is in this state. The application occasionally comes back to this state if geometry, physics processes, and/or cut-off have been changed after processing a run.

G4State_Init state

The application is in this state while the Initialize() method of G4RunManager is being invoked. Methods defined in any user initialization classes are invoked during this state.

G4State_Idle state

The application is ready for starting a run.

G4State_GeomClosed state

When BeamOn() is invoked, the application proceeds to this state to process a run. Geometry, physics processes, and cut-off cannot be changed during run processing.

G4State_EventProc state

A Geant4 application is in this state when a particular event is being processed. GetCurrentEvent() and GetPreviousEvent() methods of G4RunManager are available only at this state.

G4State_Quit state

When the destructor of G4RunManager is invoked, the application comes to this “dead end” state. Managers of the Geant4 kernel are being deleted and thus the application cannot come back to any other state.

G4State_Abort state

When a G4Exception occurs, the application comes to this “dead end” state and causes a core dump. The user still has a hook to do some “safe” operations, e.g. storing histograms, by implementing a user concrete class of G4VStateDependent. The user also has a choice to suppress the occurrence of G4Exception by a UI command /control/suppressAbortion. When abortion is suppressed, you will still get error messages issued by G4Exception, and there is NO guarantee of a correct result after the G4Exception error message.

G4StateManager belongs to the intercoms category.

User’s hook for state change

In case the user wants to do something at the moment of state change of Geant4, the user can create a concrete class of the G4VStateDependent base class. For example, the user can store histograms when G4Exception occurs and Geant4 comes to the Abort state, but before the actual core dump.

The following is an example user code which stores histograms when Geant4 becomes to the Abort state. This class object should be made in, for example main(), by the user code. This object will be automatically registered to G4StateManager at its construction.

Listing 26 Header file of UserHookForAbortState
#ifndef UserHookForAbortState_H
#define UserHookForAbortState_H 1

#include "G4VStateDependent.hh"

class UserHookForAbortState : public G4VStateDependent
{
 public:
  UserHookForAbortState();   // constructor
  ~UserHookForAbortState();  // destructor

  virtual G4bool Notify(G4ApplicationState requiredState);
};
Listing 27 Source file of UserHookForAbortState
#include "UserHookForAbortState.hh"

UserHookForAbortState::UserHookForAbortState() {;}
UserHookForAbortState::~UserHookForAbortState() {;}

G4bool UserHookForAbortState::Notify(G4ApplicationState requiredState)
{
  if(requiredState!=Abort) return true;

  // Do book keeping here

  return true;
}

Customizing the Run Manager

Virtual Methods in the Run Manager

G4RunManager is a concrete class with a complete set of functionalities for managing the Geant4 kernel. It is the only manager class in the Geant4 kernel which must be constructed in the main() method of the user’s application. Thus, instead of constructing the G4RunManager provided by Geant4, you are free to construct your own RunManager. It is recommended, however, that your RunManager inherit G4RunManager. For this purpose, G4RunManager has various virtual methods which provide all the functionalities required to handle the Geant4 kernel. Hence, your customized run manager need only override the methods particular to your needs; the remaining methods in G4RunManager base class can still be used. A summary of the available methods is presented here:

public: virtual void Initialize();

main entry point of Geant4 kernel initialization

protected: virtual void InitializeGeometry();

geometry construction

protected: virtual void InitializePhysics();

physics processes construction

public: virtual void BeamOn(G4int n_event);

main entry point of the event loop

protected: virtual G4bool ConfirmBeamOnCondition();

check the kernel conditions for the event loop

protected: virtual void RunInitialization();

prepare a run

protected: virtual void DoEventLoop(G4int n_events);

manage an event loop

protected: virtual G4Event* GenerateEvent(G4int i_event);

generation of G4Event object

protected: virtual void AnalyzeEvent(G4Event* anEvent);

storage/analysis of an event

protected: virtual void RunTermination();

terminate a run

public: virtual void DefineWorldVolume(G4VPhysicalVolume * worldVol);

set the world volume to G4Navigator

public: virtual void AbortRun();

abort the run

Customizing the Event Loop

In G4RunManager the event loop is handled by the virtual method DoEventLoop(). This method is implemented by a for loop consisting of the following steps:

  1. construct a G4Event object and assign to it primary vertex(es) and primary particles. This is done by the virtual GeneratePrimaryEvent() method.

  2. send the G4Event object to G4EventManager for the detector simulation. Hits and trajectories will be associated with the G4Event object as a consequence.

  3. perform bookkeeping for the current G4Event object. This is done by the virtual AnalyzeEvent() method.

DoEventLoop() performs the entire simulation of an event. However, it is often useful to split the above three steps into isolated application programs. If, for example, you wish to examine the effects of changing discriminator thresholds, ADC gate widths and/or trigger conditions on simulated events, much time can be saved by performing steps 1 and 2 in one program and step 3 in another. The first program need only generate the hit/trajectory information once and store it, perhaps in a database. The second program could then retrieve the stored G4Event objects and perform the digitization (analysis) using the above threshold, gate and trigger settings. These settings could then be changed and the digitization program re-run without re-generating the G4Events.

Changing the Detector Geometry

The detector geometry defined in your G4VUserDetectorConstruction concrete class can be changed during a run break (between two runs). Two different cases are considered.

The first is the case in which you want to delete the entire structure of your old geometry and build up a completely new set of volumes. For this case, you need to delete them by yourself, and let RunManager invokes Construct() and ConstructSDandField() methods of your detector construction once again when RunManager starts the next run.

G4RunManager* runManager = G4RunManager::GetRunManager();
runManager->ReinitializeGeometry();

If this ReinitializeGeometry() is invoked, GeometryHasBeenModified() (discussed next) is automatically invoked. Presumably this case is rather rare. The second case is more frequent for the user.

The second case is the following. Suppose you want to move and/or rotate a particular piece of your detector component. This case can easily happen for a beam test of your detector. It is obvious for this case that you need not change the world volume. Rather, it should be said that your world volume (experimental hall for your beam test) should be big enough for moving/rotating your test detector. For this case, you can still use all of your detector geometries, and just use a Set method of a particular physical volume to update the transformation vector as you want. Thus, you don’t need to re-set your world volume pointer to RunManager.

If you want to change your geometry for every run, you can implement it in the BeginOfRunAction() method of G4UserRunAction class, which will be invoked at the beginning of each run, or, derive the RunInitialization() method. Please note that, for both of the above mentioned cases, you need to let RunManager know “the geometry needs to be closed again”. Thus, you need to invoke

runManager->GeometryHasBeenModified();

before proceeding to the next run. An example of changing geometry is given in a Geant4 tutorial in Geant4 Training kit #2.

Switch physics processes

In the InitializePhysics() method, G4VUserPhysicsList::Construct is invoked in order to define particles and physics processes in your application. Basically, you can not add nor remove any particles during execution, because particles are static objects in Geant4 (see How to Specify Particles and Particles for details). In addition, it is very difficult to add and/or remove physics processes during execution, because registration procedures are very complex, except for experts (see How to Specify Physics Processes and Physics Processes). This is why the initializePhysics() method is assumed to be invoked at once in Geant4 kernel initialization.

However, you can switch on/off physics processes defined in your G4VUserPhysicsList concrete class and also change parameters in physics processes during the run break.

You can use ActivateProcess() and InActivateProcess() methods of G4ProcessManager anywhere outside the event loop to switch on/off some process. You should be very careful to switch on/off processes inside the event loop, though it is not prohibited to use these methods even in the EventProc state.

It is a likely case to change cut-off values in a run. You can change defaultCutValue in G4VUserPhysicsList during the Idle state. In this case, all cross section tables need to be recalculated before the event loop. You should use the CutOffHasBeenModified() method when you change cut-off values so that the SetCuts method of your PhysicsList concrete class will be invoked.

Managing worker thread

G4UserWorkerInitialization is an additional user initialization class to be used only for the multi-threaded mode. The object of this class can be set to G4MTRunManager, but not to G4RunManager. G4UserWorkerInitialization class has five virtual methods as the user hooks which are invoked at several occasions of the life cycle of each thread.

virtual void WorkerInitialize() const

This method is called after the tread is created but before the G4WorkerRunManager is instantiated.

virtual void WorkerStart() const

This method is called once at the beginning of simulation job when kernel classes and user action classes have already instantiated but geometry and physics have not been yet initialized. This situation is identical to “PreInit” state in the sequential mode.

virtual void WorkerStartRun() const

This method is called before an event loop. Geometry and physics have already been set up for the thread. All threads are synchronized and ready to start the local event loop. This situation is identical to “Idle” state in the sequential mode.

virtual void WorkerRunEnd() const

This method is called for each thread when the local event loop is done, but before the synchronization over all worker threads.

virtual void WorkerStop() const

This method is called once at the end of simulation job.