// Your (thread local) run global data: an instance of this object will be // automatically generated by the RunManager (for each worker thread) by calling // your RunAction::GenerateRun interface method. At the end of the Run, these // (thread local) Run global intances will be merged a global intance (the one // that belongs to the Master RunManager), according to your implementation of // the Merge interface method. // The appropriate (thread local) instance of this object will be available/ // obtainable in the appropriate (also thread local) EventAction Begin- and // End-OfEventAction interface methods where the (thread local) object will be // populated by data from at the end of each events. #ifndef YOURRUN_HH #define YOURRUN_HH #include "G4Run.hh" #include "Hist.hh" // forward declarations class YourDetectorConstruction; class YourPrimaryGeneratorAction; /** * @file YourRun.hh * @class YourRun * @author M. Novak * @date December 2019 * * Implementation of ``Geant4`` ``G4Run`` for this user application. * * The run of your application usually encapsulates all infomation that you would like to collect * during the simulation. Each thread will have their own object form this run class that is generated * before the simulation by the individual threads itself simply calling the ``G4RunAction::GenerateRun()`` * (i.e. YourRunAction::GenerateRun()) method of the ``G4RunAction`` (i.e. YourRunAction) object that * was constructed and registered for the given thread (in YourActionInitialization::Build() or YourActionInitialization::BuildForMaster() * methods for the workers or for the master respecively). * * While the run objects of the worker threads are used during the simulation to collect thread-local data, the run object generated by the master, * is not used during the simulation. This latter is used only at the end of the run and only to collect all thread-local run data into one gloabl * run object. This is done, by calling the Merge() method of this class that should contain the implementation how run data can be added/merged. * * @note for this application we will implement a simple histogram class. The only reason why we do this is to demonstrait the good practice regarding * the implementation of objects, that are used inside the run object, shoudl follow (e.g. easily `"mergable"`). */ class YourRun : public G4Run { // Method declaration: public: // CTR: YourRun(YourDetectorConstruction* det, YourPrimaryGeneratorAction* prim); ~YourRun() override; /** * Virtual method to be implemented to define the way of merging the underlying * (thread local) Run global data structures into one global instance. * * This method will be invoked by the master on its own run object (YourRun) * on each of the worker, i.e. thread local, run (YourRun) objects passing by their * pointer as the input argument. * * @param [in] run Pointer to a run (YourRun) obejct that needs to be merged to this run object. */ void Merge(const G4Run* run) override; // // Additional custom methods: // Method that we will call from the master run action at the end to compute final quantities using the // its run global Run object into which all thread local run global run object instance has already been merged // (when YourRunAction::EndOfRunAction() is invoked). void EndOfRunSummary(); // Public methods (will be used by the EventAction) to add energy deposit and // track length data after each events. void AddEnergyDepositPerEvent(const G4double edep) { fEdepInTarget += edep; fEdepInTarget2 += edep*edep; } void AddChTrackLengthPerEvent(const G4double length) { fChargedTrackLengthInTarget += length; fChargedTrackLengthInTarget2 += length*length; } // Public method (will be used by the EventAction) to fill the energy deposit // histogram after each event (in the EndOfEventAction) void FillEdepHistogram(const G4double edep) { if ( fIsActiveEdepHistogram ) { fEdepHistogram->Fill(edep); } } // Public method to set properties of the energy deposit histogram: this will // be invoked by the RunAction in its BeginOfRunAction method to set all // properties of the histogram before the simulation starts (only if the user // invoked the corresponding UI command i.e. /yourApp/runAction/edepHisto ). // A flag (fIsActiveEdepHisto) will also set to indicate that the user invoked // the UI command /yourApp/runAction/edepHisto ... that activates the energy // deposit histogram. The flag stays to be 'false' otherwise (as initialised). void SetEdepHisto(const G4String& filename, G4double emin, G4double emax, G4int numbins) { fIsActiveEdepHistogram = true; fEdepHistogram->ReSet(filename, emin, emax, numbins); } // Data member declarations: private: // data members to obtain some information needed at the end for the summary // Note: that the PrimaryGeneratorAction is not set to the master's RunAction // so it will be nullptr for the master's YourRun. We will set it in // the Merge. YourDetectorConstruction* fYourDetector; YourPrimaryGeneratorAction* fYourPrimary; // // Run global data members: // - sum of the energy deposit (charged track length) in the target per event // - and sum of the squared quantity per event for rms computation G4double fEdepInTarget; G4double fEdepInTarget2; G4double fChargedTrackLengthInTarget; G4double fChargedTrackLengthInTarget2; // Energy deposit per event (in the target) histogram and a flag to indicate // if this histogram was activated (requested) by the user invoking the // corresponding custum /yourApp/runAction/edepHisto UI command G4bool fIsActiveEdepHistogram; Hist* fEdepHistogram; }; #endif