Import Geant4 11.3.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2024-06-28 13:08:51 +02:00
parent f7b23877ed
commit e58e650b32
5232 changed files with 239416 additions and 244360 deletions
+33 -4
View File
@@ -6,7 +6,36 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-12-13 Ben Morgan (run-V11-01-11)
## 2024-06-14 I. Hrivnacova (run-V11-02-08)
- G4RunManager::ReinitializeGeometry: added call to G4FieldBuilder::Reinitialize
## 2024-06-04 John Apostolakis (run-V11-02-07)
- Add call in G4WorkerRunManager to use parallel initialisation of voxels
(Requires geommng-V11-02-02.)
## 2024-06-01 Makoto Asaim (run-V11-02-06)
- Initial implementation of creation/processing of SubEvents
- Co-working with event-V11-02-04, track-V11-02-03
## 2024-05-09 Ben Morgan (run-V11-02-05)
- Remove use of no longer supported TiMemory.
## 2024-05-07 Makoto Asai (run-V11-02-04)
- G4RunManager : add SetDefaultClassification methods to enable to set the
default classification for the track newly arriving to a stack.
## 2024-04-11 Gabriele Cosmo (run-V11-02-03)
- Fixed compilation warnings for implicit type conversions on macOS/XCode
on G4MSSteppingAction. Use consistently G4 types.
## 2024-04-04 Shogo Okada (run-V11-02-02)
- G4PhysicsListHelper: added `DNATripleIoni` and `DNAQuadrupleIoni` for the
implementation of multiple-ionisation processes in Geant4-DNA.
## 2024-04-03 Alvaro Tolosa-Delgado (run-V11-02-01)
- Material Scan output extended.
## 2023-12-13 Ben Morgan (run-V11-02-00)
- Fix Issue #86: report number of threads from G4TaskRunManager correctly.
## 2023-11-17 I. Hrivnacova (run-V11-01-10)
@@ -83,7 +112,7 @@ It must **not** be used as a substitute for writing good git commit messages!
call to `geant4_add_category` to define library build from source modules.
- Make DLL export symbol a CMake module-level compile definition to aid
future modularization
## 2022-01-18 Jonas Hahnfeld (run-V11-00-02)
- Prefer pointer to `const G4Material` if possible
@@ -125,12 +154,12 @@ July 01, 2021 Vladimir Ivanchenko (run-V10-07-07)
May 20, 2021 Vladimir Ivanchenko (run-V10-07-06)
- G4VPhysicsConstructor - fix initialisation of hadronic parameters
avoiding uncontrolled override of the verbosityLevel
avoiding uncontrolled override of the verbosityLevel
May 17, 2021 Jonathan Madsen (run-V10-07-05)
- Removed calling physicsList->TerminateWorker() in G4WorkerRunManager
as this appears to cause errors at termination
April 25, 2021 Hoang Tran (run-V10-07-04)
- Added new G4DNAStaticMoleculeReactionProcess in PhysicsListHelper for DNA processs
+76
View File
@@ -36,9 +36,13 @@
#include "G4UserSteppingAction.hh"
#include "globals.hh"
#include "G4ThreeVector.hh"
#include <vector>
class G4Region;
class G4MSSteppingAction : public G4UserSteppingAction
{
public:
@@ -52,12 +56,84 @@ class G4MSSteppingAction : public G4UserSteppingAction
inline G4double GetX0() const { return x0; }
inline G4double GetLambda0() const { return lambda; }
/// Print material properties verbosely for each step of geantino
/// This function is useful for single shot scans.
void PrintEachMaterialVerbose(std::ostream & oss);
/// Print list of {material name, thickness, x0, lambda}, integrated by material name
/// This function is useful for global scans.
void PrintIntegratedMaterialVerbose(std::ostream & oss);
private:
G4bool regionSensitive = false;
G4Region* theRegion = nullptr;
G4double length = 0.0;
G4double x0 = 0.0;
G4double lambda = 0.0;
struct shape_mat_info_t
{
/// Calculated average atomic number
G4double aveZ = 0.0;
/// Calculated average mass number
G4double aveA = 0.0;
/// Density of material given by user
G4double density = 0.0;
/// Material radiation length
G4double radiation_length = 0.0;
/// Material interaction length
G4double interaction_length = 0.0;
/// Step of the geantino
G4double thickness = 0.0;
/// Integrated path of the geantino
G4double integrated_thickness = 0.0;
/// Calculated x0 = thickness/radiation_length
G4double x0 = 0.0;
/// Calculated lambda = thickness/interaction_length
G4double lambda = 0.0;
/// Integrated x0
G4double integrated_x0 = 0.0;
/// Integrated lambda
G4double integrated_lambda = 0.0;
/// Entry point of the geantino into the solid
G4ThreeVector entry_point = { };
/// Exit point of the geantino out of the solid
G4ThreeVector exit_point = { };
/// Material name. Composition is not checked.
/// That is, if there are two identical materials
/// except for the name, they are treated as different
G4String material_name = { };
/// Getter that returns the full material name
G4String GetName(){return material_name;};
/// Getter that returns the material name, splitted in blocks of length 'column_width'
G4String GetName(G4int column_width)
{
G4int input_name_length = (G4int)material_name.length();
if( input_name_length < column_width) return material_name;
G4String formated_name;
for (size_t i = 0; i < material_name.length(); i += column_width)
{
// for each block of characters of length 'column_width', append '\n'
formated_name += material_name.substr(i, column_width);
if (i + column_width < material_name.length())
{
formated_name += '\n';
}
// append spaces for last block of characters so its length corresponds to column_width
else
{
formated_name+=G4String( column_width-(input_name_length%column_width),' ');
}
}
return formated_name;
};
};
std::vector<shape_mat_info_t> shape_mat_info_v;
};
#endif
+3 -8
View File
@@ -39,7 +39,6 @@
#define G4MTRunManager_hh 1
#include "G4MTBarrier.hh"
#include "G4Profiler.hh"
#include "G4RNGHelper.hh"
#include "G4RunManager.hh"
#include "G4Threading.hh"
@@ -60,10 +59,6 @@ class G4MTRunManager : public G4RunManager
friend class G4RunManagerFactory;
public:
// The profiler aliases are only used when compiled with
// GEANT4_USE_TIMEMORY.
using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
// Map of defined worlds.
using masterWorlds_t = std::map<G4int, G4VPhysicalVolume*>;
@@ -157,8 +152,8 @@ class G4MTRunManager : public G4RunManager
void SetUserAction(G4UserSteppingAction* userAction) override;
// To be invoked solely from G4WorkerRunManager to merge the results
void MergeScores(const G4ScoringManager* localScoringManager);
void MergeRun(const G4Run* localRun);
virtual void MergeScores(const G4ScoringManager* localScoringManager);
virtual void MergeRun(const G4Run* localRun);
// Handling of more than one run per thread
enum class WorkerActionRequest
@@ -274,7 +269,7 @@ class G4MTRunManager : public G4RunManager
G4MTBarrier nextActionRequestBarrier;
G4MTBarrier processUIBarrier;
private:
protected:
// List of workers (i.e. thread)
using G4ThreadsList = std::list<G4Thread*>;
+7
View File
@@ -77,6 +77,7 @@ class G4MaterialScanner
inline G4bool GetRegionSensitive() const { return regionSensitive; }
G4bool SetRegionName(const G4String& val);
inline const G4String& GetRegionName() const { return regionName; }
inline void SetVerbosity(G4int v) { verbosity = v; };
private:
void DoScan();
@@ -115,6 +116,12 @@ class G4MaterialScanner
G4bool regionSensitive = false;
G4String regionName = "notDefined";
G4Region* theRegion = nullptr;
/// Configure degree of verbosity of Material Scan
/// verbosity 0: default
/// verbosity 1: call PrintIntegratedMaterialVerbose
/// verbosity 2: call PrintEachMaterialVerbose
G4int verbosity = 0;
};
#endif
+2 -4
View File
@@ -36,7 +36,6 @@
#ifndef G4Run_hh
#define G4Run_hh 1
#include "G4Profiler.hh"
#include "globals.hh"
#include <vector>
@@ -47,9 +46,6 @@ class G4DCtable;
class G4Run
{
public:
using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
public:
G4Run();
virtual ~G4Run();
@@ -102,6 +98,8 @@ class G4Run
// Returns the event vector.
inline std::vector<const G4Event*>* GetEventVector() const { return eventVector; }
inline G4int GetEventVectorSize() const
{ return (eventVector!=nullptr) ? (G4int)(eventVector->size()) : 0; }
inline void SetRunID(G4int id) { runID = id; }
inline void SetNumberOfEventToBeProcessed(G4int n_ev) { numberOfEventToBeProcessed = n_ev; }
+63 -19
View File
@@ -103,7 +103,6 @@
#include "G4Event.hh"
#include "G4EventManager.hh"
#include "G4Profiler.hh"
#include "G4RunManagerKernel.hh"
#include "globals.hh"
@@ -139,11 +138,6 @@ class G4RunManager
{
friend class G4RunManagerFactory;
public:
// the profiler aliases are only used when compiled with the
// GEANT4_USE_TIMEMORY flag enabled.
using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
public:
// Static method which returns the singleton pointer of G4RunManager
// or its derived class.
@@ -253,12 +247,6 @@ class G4RunManager
virtual G4Event* GenerateEvent(G4int i_event);
virtual void AnalyzeEvent(G4Event* anEvent);
// This method configures the global fallback query and label generators.
virtual void ConfigureProfilers(const std::vector<std::string>& args = {});
// Calls the above virtual method.
void ConfigureProfilers(G4int argc, char** argv);
// Dummy methods to dispatch generic inheritance calls from G4RunManager
// base class.
virtual void SetNumberOfThreads(G4int) {}
@@ -404,6 +392,20 @@ class G4RunManager
eventManager->GetStackManager()->SetNumberOfAdditionalWaitingStacks(iAdd);
}
// Define the default classification for a newly arriving track.
// Default can be alternated by the UserStackingAction.
// G4ExceptionSeverity can be set to warn the user if the classification is changed
// by the UserStackingAction.
inline void SetDefaultClassification(G4TrackStatus ts,
G4ClassificationOfNewTrack val,
G4ExceptionSeverity es = G4ExceptionSeverity::IgnoreTheIssue)
{ eventManager->GetStackManager()->SetDefaultClassification(ts,val,es); }
inline void SetDefaultClassification(const G4ParticleDefinition* pd,
G4ClassificationOfNewTrack val,
G4ExceptionSeverity es = G4ExceptionSeverity::IgnoreTheIssue)
{ eventManager->GetStackManager()->SetDefaultClassification(pd,val,es); }
inline const G4String& GetVersionString() const { return kernel->GetVersionString(); }
inline void SetPrimaryTransformer(G4PrimaryTransformer* pt)
@@ -519,22 +521,66 @@ class G4RunManager
{
sequentialRM,
masterRM,
workerRM
workerRM,
subEventMasterRM,
subEventWorkerRM
};
inline RMType GetRunManagerType() const { return runManagerType; }
// Following methods are used only for sub-event parallel mode.
// Actual explanations of these methods are found in G4SubEvtRunManager class
virtual void RegisterSubEventType(G4int, G4int)
{
G4Exception("G4RunManager::RegisterSubEventType","RunSE1000",FatalException,
"Base class method is invoked for a RunManager that is not sub-event paralle mode");
}
virtual void UpdateScoringForSubEvent(const G4SubEvent*,const G4Event*)
{
G4Exception("G4RunManager::UpdateScoringForSubEvent","RunSE1001",FatalException,
"Base class method is invoked for a RunManager that is not sub-event paralle mode");
}
virtual const G4SubEvent* GetSubEvent(G4int, G4bool&,
G4long&, G4long&, G4long&, G4bool)
{
G4Exception("G4RunManager::GetSubEvent","RunSE1002",FatalException,
"Base class method is invoked for a RunManager that is not sub-event paralle mode");
return nullptr;
}
virtual void SubEventFinished(const G4SubEvent*,const G4Event*)
{
G4Exception("G4RunManager::SubEventFinished","RunSE1003",FatalException,
"Base class method is invoked for a RunManager that is not sub-event paralle mode");
}
virtual G4int GetSubEventType() const
{
G4Exception("G4RunManager::GetSubEventType","RunSE1010",FatalException,
"Base class method is invoked for RunManager that is not a worker in sub-event paralle mode");
return -1;
}
virtual std::size_t GetMaxNTrack() const
{ return 0; }
virtual void ReportEventDeletion(const G4Event* evt);
protected:
// This constructor is called in case of multi-threaded build.
G4RunManager(RMType rmType);
void CleanUpPreviousEvents();
void CleanUpUnnecessaryEvents(G4int keepNEvents);
void StackPreviousEvent(G4Event* anEvent);
// This method is invoked at the end of processing each event
virtual void StackPreviousEvent(G4Event* anEvent);
// This method is invoked at the beginning of next run or when the
// program is quiting. So, we delete all the kept G4Event objects.
virtual void CleanUpPreviousEvents();
// This method is invoked at the end of processing each event
// to delete any G4Event objects that are no longer needed.
virtual void CleanUpUnnecessaryEvents(G4int keepNEvents);
virtual void StoreRNGStatus(const G4String& filenamePrefix);
void UpdateScoring();
void UpdateScoring(const G4Event* evt = nullptr);
// Called by destructor to delete user detector. Note: the user detector
// is shared among threads, thus this should be re-implemented in derived
@@ -605,8 +651,6 @@ class G4RunManager
static G4ThreadLocal G4RunManager* fRunManager;
G4RunMessenger* runMessenger = nullptr;
std::unique_ptr<ProfilerConfig> masterRunProfiler;
};
#endif
+201
View File
@@ -0,0 +1,201 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4SubEvtRunManager
//
// Class description:
//
// This is a class for run control in sub-event parallel mode.
// It extends G4TaskRunManager re-implementing multi-threaded behavior in
// key methods (see documentation for G4MTRunManager).
//
// N.B. G4TaskRunManagerKernel is still used by this G4SubEvtRunManager
// without any modification. -- future work for phase-II developments
//
// Original author: M. Asai (JLAB) - 2024
// --------------------------------------------------------------------
#ifndef G4SubEvtRunManager_hh
#define G4SubEvtRunManager_hh 1
#include "G4TaskRunManager.hh"
#include <atomic>
class G4SubEvtRunManager : public G4TaskRunManager
{
friend class G4RunManagerFactory;
public:
static G4SubEvtRunManager* GetMasterRunManager()
{
auto* _rm = G4MTRunManager::GetMasterRunManager();
return dynamic_cast<G4SubEvtRunManager*>(_rm);
}
G4SubEvtRunManager(G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false));
G4SubEvtRunManager(G4VUserTaskQueue* taskQueue,
G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false), G4int evtGrainsize = 0);
~G4SubEvtRunManager() override;
// Inherited methods to re-implement for MT case
void Initialize() override;
void Initialize(uint64_t nthreads) override { PTL::TaskRunManager::Initialize(nthreads); }
void RunInitialization() override;
void InitializeEventLoop(G4int n_event, const char* macroFile = nullptr,
G4int n_select = -1) override;
void TerminateOneEvent() override;
void ProcessOneEvent(G4int i_event) override;
void ConstructScoringWorlds() override;
void RunTermination() override;
void CleanUpPreviousEvents() override;
// The following two methods are not used in sub-event parallel mode.
G4bool SetUpAnEvent(G4Event*, G4long&, G4long&, G4long&, G4bool = true) override
{ return false; }
G4int SetUpNEvents(G4Event*, G4SeedsQueue*, G4bool = true) override
{ return -1; }
void RegisterSubEventType(G4int ty, G4int maxEnt) override
{
eventManager->UseSubEventParallelism();
eventManager->GetStackManager()->RegisterSubEventType(ty,maxEnt);
}
// The following method should be invoked by G4WorkerSubEvtRunManager for each
// sub-event. This method returns a sub-event. This sub-event object must not
// be deleted by the worker thread.
// Null pointer is returned if
// - run is in progress but no sub-event is available yet (notReady=true), or
// - run is over and no more sub-event is available unless new run starts (notReady=false)
// If a worker runs with its own random number sequence, the Boolean flag 'reseedRequired'
// should be set to false. This is *NOT* allowed for the first event.
// G4Event object should be instantiated by G4WorkerSubEvtRunManager based on the
// input provided in G4SubEvent.
const G4SubEvent* GetSubEvent(G4int ty, G4bool& notReady,
G4long& s1, G4long& s2, G4long& s3, G4bool reseedRequired = true) override;
// Notify the master thread that processing of sub-event "se" is over.
// Outcome of processed sub-event must be kept in "evt".
// "se" is deleted by the master thread, while "evt" must be deleted by the worker thread
// after invoking this method.
void SubEventFinished(const G4SubEvent* se,const G4Event* evt) override;
// Merge local scores to the master
void MergeScores(const G4ScoringManager* localScoringManager) override;
// Nothing to do for merging run
void MergeRun(const G4Run*) override
{}
// Returns number of currently active threads.
// This number may be different from the number of threads currently
// in running state, e.g. the number returned by:
// G4Threading::GetNumberOfActiveWorkerThreads() method.
std::size_t GetNumberActiveThreads() const override
{ return threads.size(); }
// Worker threads barrier: this method should be called by each
// worker when ready to start thread event-loop.
// This method will return only when all workers are ready.
// void ThisWorkerReady() override;
// Worker threads barrier: this method should be called by each
// worker when worker event loop is terminated.
// void ThisWorkerEndEventLoop() override;
void SetUserInitialization(G4VUserPhysicsList* userPL) override;
void SetUserInitialization(G4VUserDetectorConstruction* userDC) override;
void SetUserInitialization(G4UserWorkerInitialization* userInit) override;
void SetUserInitialization(G4UserWorkerThreadInitialization* userInit) override;
void SetUserInitialization(G4VUserActionInitialization* userInit) override;
void SetUserAction(G4UserRunAction* userAction) override;
void SetUserAction(G4VUserPrimaryGeneratorAction* userAction) override;
void SetUserAction(G4UserEventAction* userAction) override;
void SetUserAction(G4UserStackingAction* userAction) override;
void SetUserAction(G4UserTrackingAction* userAction) override;
void SetUserAction(G4UserSteppingAction* userAction) override;
// Called to force workers to request and process the UI commands stack
// This will block untill all workers have processed UI commands
void RequestWorkersProcessCommandsStack() override;
// Called by workers to signal to master it has completed processing of
// UI commands
void ThisWorkerProcessCommandsStackDone() override;
// Worker thread barrier: this method should be used by workers' run
// manager to wait, after an event loop for the next action to be
// performed (for example execute a new run).
void WaitForReadyWorkers() override {}
void WaitForEndEventLoopWorkers() override;
// This returns the action to be performed.
WorkerActionRequest ThisWorkerWaitForNextAction() override
{
return WorkerActionRequest::UNDEFINED;
}
void AbortRun(G4bool softAbort = false) override;
void AbortEvent() override;
protected:
void ComputeNumberOfTasks() override
{
// This method is not used for sub-event parallel mode
numberOfTasks = (G4int)threadPool->size();
numberOfEventsPerTask = -1;
eventModulo = -1;
}
// Initialize the seeds list, if derived class does not implement this
// method, a default generation will be used (nevents*2 random seeds).
// Return true if initialization is done.
// Adds one seed to the list of seeds.
G4bool InitializeSeeds(G4int /*nevts*/) override { return false; };
// Adds one seed to the list of seeds
void RefillSeeds() override;
//void PrepareCommandsStack() override;
// Creates worker threads and signal to start
void CreateAndStartWorkers() override;
void TerminateWorkers() override;
void NewActionRequest(WorkerActionRequest) override {}
void AddEventTask(G4int) override;
void SetUpSeedsForSubEvent(G4long& s1, G4long& s2, G4long& s3);
void UpdateScoringForSubEvent(const G4SubEvent* se,const G4Event* evt) override;
void CleanUpUnnecessaryEvents(G4int keepNEvents) override;
void StackPreviousEvent(G4Event* anEvent) override;
protected:
std::atomic<G4bool> runInProgress = false;
};
#endif // G4SubEvtRunManager_hh
+3 -6
View File
@@ -38,7 +38,6 @@
#include "G4EnvironmentUtils.hh"
#include "G4MTBarrier.hh"
#include "G4MTRunManager.hh"
#include "G4Profiler.hh"
#include "G4RNGHelper.hh"
#include "G4RunManager.hh"
#include "G4TBBTaskGroup.hh"
@@ -68,8 +67,6 @@ class G4TaskRunManager : public G4MTRunManager, public PTL::TaskRunManager
friend class G4RunManagerFactory;
public:
// the profiler aliases are only used when compiled with GEANT4_USE_TIMEMORY
using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
using InitializeSeedsCallback = std::function<G4bool(G4int, G4int&, G4int&)>;
using RunTaskGroup = G4TaskGroup<void>;
@@ -141,8 +138,8 @@ class G4TaskRunManager : public G4MTRunManager, public PTL::TaskRunManager
G4int SetUpNEvents(G4Event*, G4SeedsQueue* seedsQueue, G4bool reseedRequired = true) override;
// To be invoked solely from G4WorkerTaskRunManager to merge the results
void MergeScores(const G4ScoringManager* localScoringManager);
void MergeRun(const G4Run* localRun);
void MergeScores(const G4ScoringManager* localScoringManager) override;
void MergeRun(const G4Run* localRun) override;
// Called to force workers to request and process the UI commands stack
// This will block untill all workers have processed UI commands
@@ -206,7 +203,7 @@ class G4TaskRunManager : public G4MTRunManager, public PTL::TaskRunManager
return false;
};
private:
protected:
// grainsize
G4bool workersStarted = false;
G4int eventGrainsize = 0;
@@ -0,0 +1,63 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Author: Makoto Asai (JLAB)
//
// class description:
//
// This class is used for multi-threaded Geant4.
// It encapsulates the mechanism of starting/stopping threads.
#ifndef G4UserSubEvtThreadInitialization_hh
#define G4UserSubEvtThreadInitialization_hh
class G4VUserPrimaryGeneratorAction;
class G4UserRunAction;
class G4UserEventAction;
class G4UserStackingAction;
class G4UserTrackingAction;
class G4UserSteppingAction;
class G4WorkerThread;
class G4WorkerTaskRunManager;
#include "G4Threading.hh"
#include "G4UserTaskThreadInitialization.hh"
#include "Randomize.hh"
class G4UserSubEvtThreadInitialization : public G4UserTaskThreadInitialization
{
public: // with description
G4UserSubEvtThreadInitialization() = default;
~G4UserSubEvtThreadInitialization() override = default;
// Called by StartThread function to create a run-manager implementing worker
// behvior. User should re-implemtn this function in derived class to
// instantiate his/her user-defined WorkerRunManager. By default this method
// instantiates G4WorkerTaskRunManager object.
G4WorkerRunManager* CreateWorkerRunManager() const override;
};
#endif // G4UserSubEvtThreadInitialization_hh
+3 -9
View File
@@ -47,9 +47,6 @@ class G4WorkerRunManagerKernel;
class G4WorkerRunManager : public G4RunManager
{
public:
using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
public:
static G4WorkerRunManager* GetWorkerRunManager();
static G4WorkerRunManagerKernel* GetWorkerRunManagerKernel();
@@ -95,7 +92,7 @@ class G4WorkerRunManager : public G4RunManager
// This method will merge (reduce) the results
// of this run into the global run
virtual void MergePartialResults();
virtual void MergePartialResults(G4bool mergeEvents = true);
protected:
G4WorkerThread* workerContext = nullptr;
@@ -111,11 +108,8 @@ class G4WorkerRunManager : public G4RunManager
G4SeedsQueue seedsQueue;
G4bool readStatusFromFile = false;
private:
void SetupDefaultRNGEngine();
private:
std::unique_ptr<ProfilerConfig> workerRunProfiler;
protected:
virtual void SetupDefaultRNGEngine();
};
#endif // G4WorkerRunManager_hh
@@ -0,0 +1,96 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Author: Makoto Asai (JLAB) - 2024
//
// class description:
//
// This is a class for run control in GEANT4 for multi-threaded runs
// of worker thread running in sub-event parallel mode.
// It extends G4RunManager re-implementing multi-threaded behavior in
// key methods. See documentation for G4RunManager. User should never
// initialize instances of this class, that are usually handled by
// G4MTRunManager. There exists one instance of this class for each
// worker in a MT application.
#ifndef G4WorkerSubEvtRunManager_h
#define G4WorkerSubEvtRunManager_h 1
#include "G4WorkerTaskRunManager.hh"
class G4WorkerThread;
class G4WorkerTaskRunManagerKernel;
// N.B. G4WorkerTaskRunManagerKernel is still used by this G4WorkerSubEvtRunManager
// without any modification. -- future work for phase-II developments
using G4WorkerSubEvtRunManagerKernel = G4WorkerTaskRunManagerKernel;
class G4WorkerSubEvtRunManager : public G4WorkerTaskRunManager
{
public:
static G4WorkerSubEvtRunManager* GetWorkerRunManager();
static G4WorkerSubEvtRunManagerKernel* GetWorkerRunManagerKernel();
G4WorkerSubEvtRunManager(G4int subEventType = 1);
//G4WorkerSubEvtRunManager() = delete;
// Modified for worker behavior
void RunInitialization() override;
void DoEventLoop(G4int n_event, const char* macroFile = nullptr, G4int n_select = -1) override;
void ProcessOneEvent(G4int i_event) override;
G4Event* GenerateEvent(G4int i_event) override;
void RunTermination() override;
void TerminateEventLoop() override;
void DoWork() override;
void RestoreRndmEachEvent(G4bool flag) override { readStatusFromFile = flag; }
void DoCleanup() override;
void ProcessUI() override;
void SetUserInitialization(G4VUserPhysicsList* userPL) override;
void SetUserInitialization(G4VUserDetectorConstruction* userDC) override;
void SetUserInitialization(G4UserWorkerInitialization* userInit) override;
void SetUserInitialization(G4UserWorkerThreadInitialization* userInit) override;
void SetUserInitialization(G4VUserActionInitialization* userInit) override;
void SetUserAction(G4UserRunAction* userAction) override;
void SetUserAction(G4VUserPrimaryGeneratorAction* userAction) override;
void SetUserAction(G4UserEventAction* userAction) override;
void SetUserAction(G4UserStackingAction* userAction) override;
void SetUserAction(G4UserTrackingAction* userAction) override;
void SetUserAction(G4UserSteppingAction* userAction) override;
protected:
void StoreRNGStatus(const G4String& filenamePrefix) override;
void SetupDefaultRNGEngine() override;
private:
G4int fSubEventType = -1;
public:
G4int GetSubEventType() const override
{ return fSubEventType; }
};
#endif // G4WorkerSubEvtRunManager_h
+3 -5
View File
@@ -48,7 +48,6 @@ class G4WorkerTaskRunManagerKernel;
class G4WorkerTaskRunManager : public G4WorkerRunManager
{
public:
using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
using G4StrVector = std::vector<G4String>;
public:
@@ -74,12 +73,11 @@ class G4WorkerTaskRunManager : public G4WorkerRunManager
protected:
void StoreRNGStatus(const G4String& filenamePrefix) override;
private:
void SetupDefaultRNGEngine();
protected:
void SetupDefaultRNGEngine() override;
private:
protected:
G4StrVector processedCommandStack;
std::unique_ptr<ProfilerConfig> workerRunProfiler;
};
#endif // G4WorkerTaskRunManager_h
@@ -44,6 +44,7 @@ class G4UIcmdWith3VectorAndUnit;
class G4UIcmdWithABool;
class G4UIcmdWithAString;
class G4MaterialScanner;
class G4UIcmdWithAnInteger;
class G4MatScanMessenger : public G4UImessenger
{
@@ -66,6 +67,7 @@ class G4MatScanMessenger : public G4UImessenger
G4UIcmdWithABool* regSenseCmd = nullptr;
G4UIcmdWithAString* regionCmd = nullptr;
G4UIcmdWith3VectorAndUnit* eyePosCmd = nullptr;
G4UIcmdWithAnInteger * verboseCmd = nullptr;
};
#endif
+6
View File
@@ -20,9 +20,11 @@ geant4_add_module(G4run
G4RunManagerFactory.hh
G4RunManager.hh
G4RunManagerKernel.hh
G4SubEvtRunManager.hh
G4TaskRunManager.hh
G4TaskRunManagerKernel.hh
G4UserRunAction.hh
G4UserSubEvtThreadInitialization.hh
G4UserTaskInitialization.hh
G4UserTaskThreadInitialization.hh
G4UserWorkerInitialization.hh
@@ -38,6 +40,7 @@ geant4_add_module(G4run
G4VUserPrimaryGeneratorAction.hh
G4WorkerRunManager.hh
G4WorkerRunManagerKernel.hh
G4WorkerSubEvtRunManager.hh
G4WorkerTaskRunManager.hh
G4WorkerTaskRunManagerKernel.hh
G4WorkerThread.hh
@@ -67,10 +70,12 @@ geant4_add_module(G4run
G4RunManagerFactory.cc
G4RunManagerKernel.cc
G4RunMessenger.cc
G4SubEvtRunManager.cc
G4TaskRunManager.cc
G4TaskRunManagerKernel.cc
G4UserPhysicsListMessenger.cc
G4UserRunAction.cc
G4UserSubEvtThreadInitialization.cc
G4UserTaskThreadInitialization.cc
G4UserWorkerThreadInitialization.cc
G4VModularPhysicsList.cc
@@ -83,6 +88,7 @@ geant4_add_module(G4run
G4VUserPrimaryGeneratorAction.cc
G4WorkerRunManager.cc
G4WorkerRunManagerKernel.cc
G4WorkerSubEvtRunManager.cc
G4WorkerTaskRunManager.cc
G4WorkerTaskRunManagerKernel.cc
G4WorkerThread.cc)
+101
View File
@@ -36,6 +36,8 @@
#include "G4Step.hh"
#include "G4VPhysicalVolume.hh"
#include <map>
// --------------------------------------------------------------------
void G4MSSteppingAction::Initialize(G4bool rSens, G4Region* reg)
{
@@ -44,6 +46,7 @@ void G4MSSteppingAction::Initialize(G4bool rSens, G4Region* reg)
length = 0.;
x0 = 0.;
lambda = 0.;
shape_mat_info_v.clear();
}
// --------------------------------------------------------------------
@@ -59,4 +62,102 @@ void G4MSSteppingAction::UserSteppingAction(const G4Step* aStep)
length += stlen;
x0 += stlen / (material->GetRadlen());
lambda += stlen / (material->GetNuclearInterLength());
// store information per step (1 geantino step = 1 solid)
{
shape_mat_info_v.push_back({});
shape_mat_info_t & thisMaterialInfo = shape_mat_info_v.back();
// calculate average mass number and atomic number
{
const std::vector<const G4Element*> * ElementVector_ptr = material->GetElementVector();
for( auto & element : *ElementVector_ptr)
{
thisMaterialInfo.aveA += element->GetA();
thisMaterialInfo.aveZ += element->GetZ();
}
thisMaterialInfo.aveA /= ElementVector_ptr->size();
thisMaterialInfo.aveZ /= ElementVector_ptr->size();
}
thisMaterialInfo.density = material->GetDensity();
thisMaterialInfo.radiation_length = material->GetRadlen();
thisMaterialInfo.interaction_length = material->GetNuclearInterLength();
thisMaterialInfo.thickness = aStep->GetStepLength();
thisMaterialInfo.integrated_thickness = length;
thisMaterialInfo.lambda = stlen / (material->GetNuclearInterLength());
thisMaterialInfo.x0 = stlen / (material->GetRadlen());
thisMaterialInfo.integrated_lambda = lambda;
thisMaterialInfo.integrated_x0 = x0;
thisMaterialInfo.entry_point = preStepPoint->GetPosition();
thisMaterialInfo.exit_point = aStep->GetPostStepPoint()->GetPosition();
thisMaterialInfo.material_name = material->GetName();
}
}
void G4MSSteppingAction::PrintEachMaterialVerbose(std::ostream & oss)
{
G4int colwidth = 11;
G4int matname_colwidth = 15;
oss << G4endl<< G4endl;
oss << " Material Atomic properties (averaged) Radiation Interaction Integr. Lambda X0 Entry point Exit point\n name Mass Z density length length Thickness Thickness (cm) (cm)\n (g/mole) (g/cm3) (cm) (cm) (cm) (cm) \n";
oss << G4endl;
for( auto & matInfo : shape_mat_info_v)
{
oss << std::setw(matname_colwidth) << std::left << matInfo.GetName(matname_colwidth) << " ";
oss << std::setw(colwidth) << std::fixed << std::setprecision(2) << matInfo.aveA / (CLHEP::g/CLHEP::mole);
oss << std::setw(colwidth) << std::fixed << std::setprecision(2) << matInfo.aveZ;
oss << std::setw(colwidth) << std::scientific << std::setprecision(2) << matInfo.density / (CLHEP::g/CLHEP::cm3);
oss << std::setw(colwidth) << std::scientific << matInfo.radiation_length / CLHEP::cm;
oss << std::setw(colwidth) << std::scientific << matInfo.interaction_length / CLHEP::cm;
oss << std::setw(colwidth) << std::scientific << matInfo.thickness/CLHEP::cm;
oss << std::setw(colwidth) << std::scientific << matInfo.integrated_thickness/CLHEP::cm;
oss << std::setw(colwidth) << std::scientific << matInfo.lambda;
oss << std::setw(colwidth) << std::scientific << matInfo.x0;
oss << std::setw(colwidth) << " ";
oss << std::scientific << std::right << "(";
oss << std::scientific << std::left << matInfo.entry_point.x()/CLHEP::cm;
oss << ", " << matInfo.entry_point.y()/CLHEP::cm;
oss << ", " << matInfo.entry_point.z()/CLHEP::cm << ")";
oss << std::setw(colwidth) << " ";
oss << std::scientific << std::right << "(";
oss << std::scientific << std::left << matInfo.exit_point.x()/CLHEP::cm;
oss << ", " << matInfo.exit_point.y()/CLHEP::cm;
oss << ", " << matInfo.exit_point.z()/CLHEP::cm << ")";
oss << G4endl;
oss << G4endl;
}
}
void G4MSSteppingAction::PrintIntegratedMaterialVerbose(std::ostream& oss)
{
// create database (db) of material name (key) and information
std::map<G4String, shape_mat_info_t> mat_db;
// accumulate information for each material name into mat_db
for( auto & matInfo : shape_mat_info_v)
{
G4String key = matInfo.material_name;
if( 0 == mat_db.count( key ) )
{
mat_db[key] = shape_mat_info_t{};
}
mat_db[key].x0 += matInfo.x0;
mat_db[key].thickness += matInfo.thickness;
mat_db[key].lambda += matInfo.lambda;
}
oss << std::scientific << std::setprecision(2) << '\t';
for(auto & [key,mat] : mat_db)
oss << '\t' << key
<< '\t'<< mat.thickness/CLHEP::mm
<< '\t'<< mat.x0
<< '\t'<< mat.lambda;
return;
}
-3
View File
@@ -37,7 +37,6 @@
#include "G4Run.hh"
#include "G4ScoringManager.hh"
#include "G4StateManager.hh"
#include "G4TiMemory.hh"
#include "G4Timer.hh"
#include "G4TransportationManager.hh"
#include "G4UImanager.hh"
@@ -625,8 +624,6 @@ void G4MTRunManager::TerminateWorkers()
RequestWorkersProcessCommandsStack();
// Ask workers to exit
NewActionRequest(WorkerActionRequest::ENDWORKER);
// finalize profiler before shutting down the threads
G4Profiler::Finalize();
// Now join threads.
#ifdef G4MULTITHREADED // protect here to prevent warning in compilation
while (!threads.empty()) {
+13
View File
@@ -39,6 +39,7 @@
#include "G4UIcmdWithABool.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcommand.hh"
#include "G4UIdirectory.hh"
#include "G4UIparameter.hh"
@@ -137,6 +138,14 @@ G4MatScanMessenger::G4MatScanMessenger(G4MaterialScanner* p1)
regionCmd->SetGuidance("set to TRUE with this command.");
regionCmd->SetParameterName("region", true);
regionCmd->SetDefaultValue("DefaultRegionForTheWorld");
verboseCmd = new G4UIcmdWithAnInteger("/control/matScan/verbose", this);
verboseCmd->SetGuidance("Set verbose level of material scan");
verboseCmd->SetGuidance("0: default, properties integrated over the scan");
verboseCmd->SetGuidance("1: integrated properties per material");
verboseCmd->SetGuidance("2: detailed properties per material crossed");
verboseCmd->SetParameterName("verbose_level", false);
verboseCmd->SetDefaultValue(0);
}
// --------------------------------------------------------------------
@@ -222,6 +231,10 @@ void G4MatScanMessenger::SetNewValue(G4UIcommand* command, G4String newValue)
else if (command == regionCmd) {
if (theScanner->SetRegionName(newValue)) theScanner->SetRegionSensitive(true);
}
else if(command == verboseCmd)
{
theScanner->SetVerbosity(StoI(newValue));
}
else if (command == singleCmd || command == single2Cmd) {
G4int ntheta = theScanner->GetNTheta();
G4double thetaMin = theScanner->GetThetaMin();
+10 -1
View File
@@ -166,7 +166,16 @@ void G4MaterialScanner::DoScan()
G4cout << " " << std::setw(11) << theta / deg << " " << std::setw(11) << phi / deg
<< " " << std::setw(11) << length / mm << " " << std::setw(11) << x0 << " "
<< std::setw(11) << lambda << G4endl;
<< std::setw(11) << lambda;
if(1 == verbosity)
{
theMatScannerSteppingAction->PrintIntegratedMaterialVerbose(G4cout);
}
else if(2 == verbosity)
{
theMatScannerSteppingAction->PrintEachMaterialVerbose(G4cout);
}
G4cout << G4endl;
aveLength += length / mm;
aveX0 += x0;
aveLambda += lambda;
+20
View File
@@ -975,6 +975,26 @@ void G4PhysicsListHelper::ReadInDefaultOrderingParameter()
theTable->push_back(tmp);
sizeOfTable += 1;
tmp.processTypeName = "DNATripleIoni";
tmp.processType = fElectromagnetic;
tmp.processSubType = fLowEnergyTripleIonisation;
tmp.ordering[0] = -1;
tmp.ordering[1] = -1;
tmp.ordering[2] = 1000;
tmp.isDuplicable = false;
theTable->push_back(tmp);
sizeOfTable += 1;
tmp.processTypeName = "DNAQuadrupleIoni";
tmp.processType = fElectromagnetic;
tmp.processSubType = fLowEnergyQuadrupleIonisation;
tmp.ordering[0] = -1;
tmp.ordering[1] = -1;
tmp.ordering[2] = 1000;
tmp.isDuplicable = false;
theTable->push_back(tmp);
sizeOfTable += 1;
tmp.processTypeName = "HadElastic";
tmp.processType = fHadronic;
tmp.processSubType = fHadronElastic;
+14 -5
View File
@@ -44,13 +44,22 @@ G4Run::G4Run()
// --------------------------------------------------------------------
G4Run::~G4Run()
{
// Objects made by local thread should not be deleted by the master thread
G4RunManager::RMType rmType =
G4RunManager::GetRunManager()->GetRunManagerType();
if(rmType != G4RunManager::masterRM)
if(G4RunManager::GetRunManager()->GetRunManagerType()!=G4RunManager::masterRM)
{
for(auto& itr : *eventVector)
{ delete itr; }
{
// if(itr->ToBeKept()) {
// G4ExceptionDescription ede;
// ede << "Deleting G4Event (id:" << itr->GetEventID()
// << ") that has ToBeKept() flag on.\n"
// << " KeepEventFlag : " << itr->KeepTheEventFlag()
// << " NoOfGrip : " << itr->GetNumberOfGrips()
// << " NoOfSubEvt : " << itr->GetNumberOfRemainingSubEvents();
// G4Exception("G4Run::~G4Run()","Run0002",JustWarning,ede);
// }
// G4RunManager::GetRunManager()->ReportEventDeletion(itr);
delete itr;
}
}
delete eventVector;
}
+68 -184
View File
@@ -47,7 +47,6 @@
#include "G4ProcessManager.hh"
#include "G4ProcessTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Profiler.hh"
#include "G4RegionStore.hh"
#include "G4Run.hh"
#include "G4RunManagerKernel.hh"
@@ -60,9 +59,9 @@
#include "G4SmartVoxelStat.hh"
#include "G4SolidStore.hh"
#include "G4StateManager.hh"
#include "G4TiMemory.hh"
#include "G4Timer.hh"
#include "G4TransportationManager.hh"
#include "G4FieldBuilder.hh"
#include "G4UImanager.hh"
#include "G4UnitsTable.hh"
#include "G4UserRunAction.hh"
@@ -180,14 +179,11 @@ G4RunManager::G4RunManager(RMType rmType)
G4Random::saveFullState(oss);
randomNumberStatusForThisRun = oss.str();
randomNumberStatusForThisEvent = oss.str();
ConfigureProfilers();
}
// --------------------------------------------------------------------
G4RunManager::~G4RunManager()
{
// finalise profiler before shutting down the threads
G4Profiler::Finalize();
G4StateManager* pStateManager = G4StateManager::GetStateManager();
// set the application state to the quite state
if (pStateManager->GetCurrentState() != G4State_Quit) {
@@ -196,6 +192,14 @@ G4RunManager::~G4RunManager()
}
CleanUpPreviousEvents();
if (verboseLevel > 1 && currentRun!=nullptr) {
G4cout << "Deleting G4Run (id:" << currentRun->GetRunID() << ") ";
if(currentRun->GetEventVectorSize()>0) {
G4cout << " that has " << currentRun->GetEventVectorSize()
<< " events kept in eventVector";
}
G4cout << G4endl;
}
delete currentRun;
delete timer;
delete runMessenger;
@@ -227,25 +231,25 @@ G4RunManager::~G4RunManager()
// --------------------------------------------------------------------
void G4RunManager::DeleteUserInitializations()
{
if (verboseLevel > 1) G4cout << "UserDetectorConstruction deleted " << userDetector << G4endl;
delete userDetector;
userDetector = nullptr;
if (verboseLevel > 1) G4cout << "UserDetectorConstruction deleted." << G4endl;
if (verboseLevel > 1) G4cout << "UserPhysicsList deleted " << physicsList << G4endl;
delete physicsList;
physicsList = nullptr;
if (verboseLevel > 1) G4cout << "UserPhysicsList deleted." << G4endl;
if (verboseLevel > 1) G4cout << "UserActionInitialization deleted " << userActionInitialization << G4endl;
delete userActionInitialization;
userActionInitialization = nullptr;
if (verboseLevel > 1) G4cout << "UserActionInitialization deleted." << G4endl;
if (verboseLevel > 1) G4cout << "UserWorkerInitialization deleted " << userWorkerInitialization << G4endl;
delete userWorkerInitialization;
userWorkerInitialization = nullptr;
if (verboseLevel > 1) G4cout << "UserWorkerInitialization deleted." << G4endl;
if (verboseLevel > 1) G4cout << "UserWorkerThreadInitialization deleted " << userWorkerThreadInitialization << G4endl;
delete userWorkerThreadInitialization;
userWorkerThreadInitialization = nullptr;
if (verboseLevel > 1) G4cout << "UserWorkerThreadInitialization deleted." << G4endl;
}
// --------------------------------------------------------------------
@@ -302,6 +306,14 @@ void G4RunManager::RunInitialization()
numberOfEventProcessed = 0;
CleanUpPreviousEvents();
if (verboseLevel > 2 && currentRun!=nullptr) {
G4cout << "Deleting G4Run (id:" << currentRun->GetRunID() << ") ";
if(currentRun->GetEventVectorSize()>0) {
G4cout << " that has " << currentRun->GetEventVectorSize()
<< " events kept in eventVector";
}
G4cout << G4endl;
}
delete currentRun;
currentRun = nullptr;
@@ -341,10 +353,6 @@ void G4RunManager::RunInitialization()
}
if (userRunAction != nullptr) userRunAction->BeginOfRunAction(currentRun);
#if defined(GEANT4_USE_TIMEMORY)
masterRunProfiler.reset(new ProfilerConfig(currentRun));
#endif
if (isScoreNtupleWriter) {
G4VScoreNtupleWriter::Instance()->OpenFile();
}
@@ -487,10 +495,12 @@ void G4RunManager::AnalyzeEvent(G4Event* anEvent)
void G4RunManager::RunTermination()
{
if (!fakeRun) {
#if defined(GEANT4_USE_TIMEMORY)
masterRunProfiler.reset();
#endif
CleanUpUnnecessaryEvents(0);
// if(G4int(previousEvents->size())>0) {
// G4ExceptionDescription ed;
// ed << "Run still has " << previousEvents->size() << " unfinished events!!";
// G4Exception("G4RunManager::RunTermination()","RM09009",FatalException,ed);
// }
// tasking occasionally will call this function even
// if there was not a current run
if (currentRun != nullptr) {
@@ -522,9 +532,13 @@ void G4RunManager::CleanUpPreviousEvents()
auto evItr = previousEvents->cbegin();
while (evItr != previousEvents->cend()) {
G4Event* evt = *evItr;
if (evt != nullptr && !(evt->ToBeKept())) delete evt;
if (evt != nullptr && !(evt->ToBeKept())) {
ReportEventDeletion(evt);
delete evt;
}
evItr = previousEvents->erase(evItr);
}
}
// --------------------------------------------------------------------
@@ -543,7 +557,10 @@ void G4RunManager::CleanUpUnnecessaryEvents(G4int keepNEvents)
G4Event* evt = *evItr;
if (evt != nullptr) {
if (evt->GetNumberOfGrips() == 0) {
if (!(evt->ToBeKept())) delete evt;
if (!(evt->ToBeKept())) {
ReportEventDeletion(evt);
delete evt;
}
evItr = previousEvents->erase(evItr);
}
else {
@@ -569,9 +586,21 @@ void G4RunManager::StackPreviousEvent(G4Event* anEvent)
previousEvents->push_back(anEvent);
}
}
CleanUpUnnecessaryEvents(n_perviousEventsToBeStored);
}
// --------------------------------------------------------------------
void G4RunManager::ReportEventDeletion(const G4Event* evt)
{
if(verboseLevel > 2) {
G4cout << "deleting G4Event(" << evt << ") eventID = " << evt->GetEventID();
if(evt->GetNumberOfCompletedSubEvent()>0) {
G4cout << " -- contains " << evt->GetNumberOfCompletedSubEvent() << " completed sub-events";
}
G4cout << G4endl;
}
}
// --------------------------------------------------------------------
void G4RunManager::Initialize()
{
@@ -821,19 +850,31 @@ void G4RunManager::ConstructScoringWorlds()
}
// --------------------------------------------------------------------
void G4RunManager::UpdateScoring()
void G4RunManager::UpdateScoring(const G4Event* evt)
{
if(evt==nullptr) evt = currentEvent;
//MAMAMAMA need revisiting
if(evt->ScoresAlreadyRecorded()) return;
//MAMAMAMA need revisiting
if (isScoreNtupleWriter) {
G4VScoreNtupleWriter::Instance()->Fill(currentEvent->GetHCofThisEvent(),
currentEvent->GetEventID());
G4VScoreNtupleWriter::Instance()->Fill(evt->GetHCofThisEvent(), evt->GetEventID());
}
if(evt->ScoresAlreadyRecorded()) {
G4Exception("G4RunManager::UpdateScoring()","RMSubEvt001",FatalException,
"Double-counting!!!");
}
evt->ScoresRecorded();
G4ScoringManager* ScM = G4ScoringManager::GetScoringManagerIfExist();
if (ScM == nullptr) return;
auto nPar = (G4int)ScM->GetNumberOfMesh();
if (nPar < 1) return;
G4HCofThisEvent* HCE = currentEvent->GetHCofThisEvent();
G4HCofThisEvent* HCE = evt->GetHCofThisEvent();
if (HCE == nullptr) return;
auto nColl = (G4int)HCE->GetCapacity();
for (G4int i = 0; i < nColl; ++i) {
@@ -1002,168 +1043,11 @@ void G4RunManager::ReinitializeGeometry(G4bool destroyFirst, G4bool prop)
G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
if (pVVisManager != nullptr) pVVisManager->GeometryHasChanged();
}
// Reinitialize field builder
if (G4FieldBuilder::IsInstance()) {
G4FieldBuilder::Instance()->Reinitialize();
}
}
}
// --------------------------------------------------------------------
void G4RunManager::ConfigureProfilers(G4int argc, char** argv)
{
std::vector<std::string> _args;
for (G4int i = 0; i < argc; ++i)
_args.emplace_back(argv[i]);
ConfigureProfilers(_args);
}
// --------------------------------------------------------------------
void G4RunManager::ConfigureProfilers(const std::vector<std::string>& args)
{
#ifdef GEANT4_USE_TIMEMORY
// parse command line if arguments were passed
G4Profiler::Configure(args);
#else
G4ConsumeParameters(args);
#endif
}
// --------------------------------------------------------------------
#if !defined(GEANT4_USE_TIMEMORY)
# define TIMEMORY_WEAK_PREFIX
# define TIMEMORY_WEAK_POSTFIX
#endif
// --------------------------------------------------------------------
extern "C"
{
// this allows the default setup to be overridden by linking
// in an custom extern C function into the application
TIMEMORY_WEAK_PREFIX
void G4RunProfilerInit(void) TIMEMORY_WEAK_POSTFIX;
extern void G4ProfilerInit(void);
// this gets executed when the library gets loaded
void G4RunProfilerInit(void)
{
#ifdef GEANT4_USE_TIMEMORY
G4ProfilerInit();
// guard against re-initialization
static G4bool _once = false;
if (_once) return;
_once = true;
puts(">>> G4RunProfilerInit <<<");
using RunProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
using EventProfilerConfig = G4ProfilerConfig<G4ProfileType::Event>;
using TrackProfilerConfig = G4ProfilerConfig<G4ProfileType::Track>;
using StepProfilerConfig = G4ProfilerConfig<G4ProfileType::Step>;
using UserProfilerConfig = G4ProfilerConfig<G4ProfileType::User>;
//
// these are the default functions for evaluating whether
// to start profiling
//
RunProfilerConfig::GetFallbackQueryFunctor() = [](const G4Run* _run) {
return G4Profiler::GetEnabled(G4ProfileType::Run) && _run;
};
EventProfilerConfig::GetFallbackQueryFunctor() = [](const G4Event* _event) {
return G4Profiler::GetEnabled(G4ProfileType::Event) && _event;
};
TrackProfilerConfig::GetFallbackQueryFunctor() = [](const G4Track* _track) {
return G4Profiler::GetEnabled(G4ProfileType::Track) && _track && _track->GetDynamicParticle();
};
StepProfilerConfig::GetFallbackQueryFunctor() = [](const G4Step* _step) {
return G4Profiler::GetEnabled(G4ProfileType::Step) && _step && _step->GetTrack();
};
UserProfilerConfig::GetFallbackQueryFunctor() = [](const std::string& _user) {
return G4Profiler::GetEnabled(G4ProfileType::User) && !_user.empty();
};
//
// these are the default functions which encode the profiling label.
// Will not be called unless the query returned true
//
RunProfilerConfig::GetFallbackLabelFunctor() = [](const G4Run* _run) {
return TIMEMORY_JOIN('/', "G4Run", _run->GetRunID());
};
EventProfilerConfig::GetFallbackLabelFunctor() = [](const G4Event* _event) -> std::string {
if (G4Profiler::GetPerEvent())
return TIMEMORY_JOIN('/', "G4Event", _event->GetEventID());
else
return "G4Event";
};
TrackProfilerConfig::GetFallbackLabelFunctor() = [](const G4Track* _track) {
auto pdef = _track->GetDynamicParticle()->GetParticleDefinition();
return TIMEMORY_JOIN('/', "G4Track", pdef->GetParticleName());
};
StepProfilerConfig::GetFallbackLabelFunctor() = [](const G4Step* _step) {
auto pdef = _step->GetTrack()->GetParticleDefinition();
return TIMEMORY_JOIN('/', "G4Step", pdef->GetParticleName());
};
UserProfilerConfig::GetFallbackLabelFunctor() = [](const std::string& _user) {
return _user;
};
using RunTool = typename RunProfilerConfig::type;
using EventTool = typename EventProfilerConfig::type;
using TrackTool = typename TrackProfilerConfig::type;
using StepTool = typename StepProfilerConfig::type;
using UserTool = typename UserProfilerConfig::type;
RunProfilerConfig::GetFallbackToolFunctor() = [](const std::string& _label) {
return new RunTool{_label};
};
EventProfilerConfig::GetFallbackToolFunctor() = [](const std::string& _label) {
return new EventTool{_label};
};
TrackProfilerConfig::GetFallbackToolFunctor() = [](const std::string& _label) {
return new TrackTool(_label, tim::scope::config(tim::scope::flat{}));
};
StepProfilerConfig::GetFallbackToolFunctor() = [](const std::string& _label) {
return new StepTool(_label, tim::scope::config(tim::scope::flat{}));
};
UserProfilerConfig::GetFallbackToolFunctor() = [](const std::string& _label) {
return new UserTool(_label);
};
auto comps = "wall_clock, cpu_clock, cpu_util, peak_rss";
auto run_env_comps = tim::get_env<std::string>("G4PROFILE_RUN_COMPONENTS", comps);
auto event_env_comps = tim::get_env<std::string>("G4PROFILE_EVENT_COMPONENTS", comps);
auto track_env_comps = tim::get_env<std::string>("G4PROFILE_TRACK_COMPONENTS", comps);
auto step_env_comps = tim::get_env<std::string>("G4PROFILE_STEP_COMPONENTS", comps);
auto user_env_comps = tim::get_env<std::string>("G4PROFILE_USER_COMPONENTS", comps);
tim::configure<G4RunProfiler>(run_env_comps);
tim::configure<G4EventProfiler>(event_env_comps);
tim::configure<G4TrackProfiler>(track_env_comps);
tim::configure<G4StepProfiler>(step_env_comps);
tim::configure<G4UserProfiler>(user_env_comps);
#endif
}
} // extern "C"
// --------------------------------------------------------------------
#ifdef GEANT4_USE_TIMEMORY
namespace
{
static G4bool profiler_is_initialized = (G4RunProfilerInit(), true);
}
#endif
// --------------------------------------------------------------------
+6 -1
View File
@@ -59,7 +59,6 @@
#include "G4SDManager.hh"
#include "G4ScoreSplittingProcess.hh"
#include "G4StateManager.hh"
#include "G4TiMemory.hh"
#include "G4TransportationManager.hh"
#include "G4UImanager.hh"
#include "G4UnitsTable.hh"
@@ -683,6 +682,12 @@ void G4RunManagerKernel::RunTermination()
void G4RunManagerKernel::ResetNavigator()
{
if (runManagerKernelType == workerRMK) {
// To ensure that it is called when using G4TaskRunManagerKernel
if( G4GeometryManager::IsParallelOptimisationConfigured() &&
!G4GeometryManager::IsParallelOptimisationFinished() )
{
G4GeometryManager::GetInstance()->UndertakeOptimisation();
}
geometryNeedsToBeClosed = false;
return;
}
+2 -1
View File
@@ -89,9 +89,10 @@ G4RunMessenger::G4RunMessenger(G4RunManager* runMgr) : runManager(runMgr)
verboseCmd->SetGuidance(" 0 : Silent (default)");
verboseCmd->SetGuidance(" 1 : Display main topics");
verboseCmd->SetGuidance(" 2 : Display main topics and run summary");
verboseCmd->SetGuidance(" 3 : Display some additional information");
verboseCmd->SetParameterName("level", true);
verboseCmd->SetDefaultValue(0);
verboseCmd->SetRange("level >=0 && level <=2");
verboseCmd->SetRange("level >=0 && level <=3");
printProgCmd = new G4UIcmdWithAnInteger("/run/printProgress", this);
printProgCmd->SetGuidance("Display begin_of_event information at given frequency.");
+852
View File
@@ -0,0 +1,852 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
#include "G4SubEvtRunManager.hh"
#include "G4AutoLock.hh"
#include "G4EnvironmentUtils.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Run.hh"
#include "G4ScoringManager.hh"
#include "G4StateManager.hh"
#include "G4Task.hh"
#include "G4TaskGroup.hh"
#include "G4TaskManager.hh"
#include "G4TaskRunManagerKernel.hh"
#include "G4ThreadLocalSingleton.hh"
#include "G4ThreadPool.hh"
#include "G4Threading.hh"
#include "G4Timer.hh"
#include "G4TransportationManager.hh"
#include "G4UImanager.hh"
#include "G4UserRunAction.hh"
#include "G4UserTaskInitialization.hh"
#include "G4UserTaskQueue.hh"
#include "G4UserSubEvtThreadInitialization.hh"
#include "G4VUserActionInitialization.hh"
#include "G4VUserPhysicsList.hh"
#include "G4UserEventAction.hh"
#include "G4VScoreNtupleWriter.hh"
#include "G4WorkerSubEvtRunManager.hh"
#include "G4WorkerThread.hh"
#include "G4VVisManager.hh"
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <algorithm>
//============================================================================//
namespace
{
G4Mutex scorerMergerMutex;
G4Mutex accessSubEventMutex;
} // namespace
//============================================================================//
G4SubEvtRunManager::G4SubEvtRunManager(G4VUserTaskQueue* task_queue, G4bool useTBB, G4int grainsize)
: G4TaskRunManager(task_queue, useTBB, grainsize)
{ runManagerType = subEventMasterRM; }
//============================================================================//
G4SubEvtRunManager::G4SubEvtRunManager(G4bool useTBB)
: G4SubEvtRunManager(nullptr, useTBB, 0)
{ runManagerType = subEventMasterRM; }
//============================================================================//
G4SubEvtRunManager::~G4SubEvtRunManager()
{
// relying all the necessary deletion upon the base class
// G4TaskRunManager::~G4TaskRunManager()
}
//============================================================================//
void G4SubEvtRunManager::Initialize()
{
G4bool firstTime = (threadPool == nullptr);
if (firstTime) G4TaskRunManager::InitializeThreadPool();
G4RunManager::Initialize();
// make sure all worker threads are set up.
G4RunManager::BeamOn(0);
if (firstTime) G4RunManager::SetRunIDCounter(0);
// G4UImanager::GetUIpointer()->SetIgnoreCmdNotFound(true);
}
//============================================================================//
void G4SubEvtRunManager::RunInitialization()
{
G4RunManager::RunInitialization();
if(!fakeRun) runInProgress = true;
}
//============================================================================//
void G4SubEvtRunManager::ProcessOneEvent(G4int i_event)
{
currentEvent = GenerateEvent(i_event);
eventManager->ProcessOneEventForSERM(currentEvent);
// Following two lines should not be executed here, as spawned sub-events may
// be still being processed. These methods are invoked when all sub-events belongings
// to this event are processed and scores of these sub-events are marged to the
// corresponding master event.
//AnalyzeEvent(currentEvent);
//UpdateScoring();
if (i_event < n_select_msg) G4UImanager::GetUIpointer()->ApplyCommand(msgText);
}
//============================================================================//
void G4SubEvtRunManager::TerminateOneEvent()
{
// We must serialize access here because workers may access Run/Event vectors
// and we can't override StackPreviousEvent
G4AutoLock l(&accessSubEventMutex);
StackPreviousEvent(currentEvent);
currentEvent = nullptr;
++numberOfEventProcessed;
}
//============================================================================//
void G4SubEvtRunManager::StackPreviousEvent(G4Event* anEvent)
{
if(n_perviousEventsToBeStored>0) {
G4ExceptionDescription ed;
ed << "G4RunManager::SetNumberOfEventsToBeStored() is not supported in sub-event parallel mode.\n"
<< "User may still keep events bu G4EventManager::KeepTheCurrentEvent()";
G4Exception("G4SubEvtRunManager::StackPreviousEvent","SubEvtRM1200",FatalException,ed);
return;
}
if(anEvent->GetNumberOfRemainingSubEvents()>0)
// sub-events are still under processing. Event is not yet fully completed.
{
currentRun->StoreEvent(anEvent);
}
else
// Event is already completed.
{
// making sure this is the first path
if(!(anEvent->IsEventCompleted()))
{
anEvent->EventCompleted();
if(userEventAction!=nullptr) userEventAction->EndOfEventAction(anEvent);
auto pVisManager = G4VVisManager::GetConcreteInstance();
if (pVisManager) pVisManager->EventReadyForVis(anEvent);
UpdateScoring(anEvent);
if(!(anEvent->ToBeKept()))
{
ReportEventDeletion(anEvent);
delete anEvent;
}
else
{ // we keep this event for post-processing (i.e. for vis)
currentRun->StoreEvent(anEvent);
}
} else {
G4Exception("G4SubEvtRunManager::StackPreviousEvent","SubEvtRM1209",FatalException,"We should not be here!!");
}
}
CleanUpUnnecessaryEvents(0);
}
//============================================================================//
void G4SubEvtRunManager::CleanUpUnnecessaryEvents(G4int keepNEvents)
{
// Delete events that are no longer necessary for post
// processing such as visualization.
// N.B. If ToBeKept() is true, the pointer of this event is
// kept in G4Run, and deleted along with the deletion of G4Run.
if(keepNEvents>0) {
G4ExceptionDescription ed;
ed << "G4RunManager::SetNumberOfEventsToBeStored() is not supported in sub-event parallel mode.\n"
<< "User may still keep events bu G4EventManager::KeepTheCurrentEvent()";
G4Exception("G4SubEvtRunManager::CleanUpUnnecessaryEvents","SubEvtRM1201",FatalException,ed);
return;
}
assert(currentRun!=nullptr);
auto eventVector = currentRun->GetEventVector();
if(eventVector==nullptr || eventVector->empty()) return;
auto eItr = eventVector->cbegin();
while(eItr != eventVector->cend())
{
const G4Event* ev = *eItr;
if(ev!=nullptr)
{
if(!(ev->IsEventCompleted()) && ev->GetNumberOfRemainingSubEvents()==0)
{ // This event has been completed since last time we were here
ev->EventCompleted();
if(userEventAction!=nullptr) userEventAction->EndOfEventAction(ev);
auto pVisManager = G4VVisManager::GetConcreteInstance();
if (pVisManager) pVisManager->EventReadyForVis(ev);
UpdateScoring(ev);
if(!(ev->ToBeKept()))
{
ReportEventDeletion(ev);
delete ev;
eItr = eventVector->erase(eItr);
}
else
{ // we keep this event for post-processing (i.e. for vis)
eItr++;
}
}
else if(!(ev->ToBeKept()))
{ // post-processing done. we no longer need this event
ReportEventDeletion(ev);
delete ev;
eItr = eventVector->erase(eItr);
}
else
{ // we still need this event
eItr++;
}
}
else
{ // ev is a null pointer
eItr = eventVector->erase(eItr);
}
}
}
//============================================================================//
void G4SubEvtRunManager::CreateAndStartWorkers()
{
// Now loop on requested number of workers
// This will also start the workers
// Currently we do not allow to change the
// number of threads: threads area created once
// Instead of pthread based workers, create tbbTask
static G4bool initializeStarted = false;
ComputeNumberOfTasks();
if (fakeRun) {
if (initializeStarted) {
auto initCmdStack = GetCommandStack();
if (!initCmdStack.empty()) {
threadPool->execute_on_all_threads([initCmdStack]() {
for (auto& itr : initCmdStack)
G4UImanager::GetUIpointer()->ApplyCommand(itr);
G4WorkerTaskRunManager::GetWorkerRunManager()->DoWork();
});
}
}
else {
std::stringstream msg;
msg << "--> G4SubEvtRunManager::CreateAndStartWorkers() --> "
<< "Initializing workers...";
std::stringstream ss;
ss.fill('=');
ss << std::setw((G4int)msg.str().length()) << "";
G4cout << "\n" << ss.str() << "\n" << msg.str() << "\n" << ss.str() << "\n" << G4endl;
G4TaskRunManagerKernel::InitCommandStack() = GetCommandStack();
threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::InitializeWorker(); });
}
initializeStarted = true;
}
else {
auto initCmdStack = GetCommandStack();
if (!initCmdStack.empty()) {
threadPool->execute_on_all_threads([initCmdStack]() {
for (auto& itr : initCmdStack)
G4UImanager::GetUIpointer()->ApplyCommand(itr);
});
}
// cleans up a previous run and events in case a thread
// does not execute any tasks
threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::ExecuteWorkerInit(); });
{
std::stringstream msg;
msg << "--> G4SubEvtRunManager::CreateAndStartWorkers() --> "
<< "Creating " << numberOfTasks << " tasks with " << numberOfEventsPerTask
<< " events/task...";
std::stringstream ss;
ss.fill('=');
ss << std::setw((G4int)msg.str().length()) << "";
G4cout << "\n" << ss.str() << "\n" << msg.str() << "\n" << ss.str() << "\n" << G4endl;
}
/* TODO (PHASE-II): Better calculation of task/event/subevents
Currently, number of tasks is equal to number of threads
and each task has a loop that endlessly asks for next sub-event
until no additional sub-event is available in the master.
This is not ideal. We should make each task work only for some limited
number of sub-events, and create as many number of tasks as needed
on the fly during the event loop of the master thread., e.g.
G4int remaining = numberOfEventToBeProcessed;
for (G4int nt = 0; nt < numberOfTasks + 1; ++nt) {
if (remaining > 0) AddEventTask(nt);
remaining -= numberOfEventsPerTask;
}
*/
for(G4int nt = 0; nt < numberOfTasks; ++nt)
{ AddEventTask(nt); }
}
}
//============================================================================//
void G4SubEvtRunManager::AddEventTask(G4int nt)
{
if (verboseLevel > 1) G4cout << "Adding task " << nt << " to task-group..." << G4endl;
workTaskGroup->exec([]() { G4TaskRunManagerKernel::ExecuteWorkerTask(); });
}
//============================================================================//
void G4SubEvtRunManager::RefillSeeds()
{
G4RNGHelper* helper = G4RNGHelper::GetInstance();
G4int nFill = 0;
switch (SeedOncePerCommunication()) {
case 0:
nFill = numberOfEventToBeProcessed - nSeedsFilled;
break;
case 1:
nFill = numberOfTasks - nSeedsFilled;
break;
case 2:
default:
nFill = (numberOfEventToBeProcessed - nSeedsFilled * eventModulo) / eventModulo + 1;
}
// Generates up to nSeedsMax seed pairs only.
if (nFill > nSeedsMax) nFill = nSeedsMax;
masterRNGEngine->flatArray(nSeedsPerEvent * nFill, randDbl);
helper->Refill(randDbl, nFill);
nSeedsFilled += nFill;
}
//============================================================================//
void G4SubEvtRunManager::InitializeEventLoop(G4int n_event, const char* macroFile, G4int n_select)
{
MTkernel->SetUpDecayChannels();
numberOfEventToBeProcessed = n_event;
numberOfEventProcessed = 0;
if (!fakeRun) {
nSeedsUsed = 0;
nSeedsFilled = 0;
if (verboseLevel > 0) timer->Start();
n_select_msg = n_select;
if (macroFile != nullptr) {
if (n_select_msg < 0) n_select_msg = n_event;
msgText = "/control/execute ";
msgText += macroFile;
selectMacro = macroFile;
}
else {
n_select_msg = -1;
selectMacro = "";
}
ComputeNumberOfTasks();
// initialize seeds
// If user did not implement InitializeSeeds,
// use default: nSeedsPerEvent seeds per event
if (n_event > 0) {
G4bool _overload = InitializeSeeds(n_event);
G4bool _functor = false;
if (!_overload) _functor = initSeedsCallback(n_event, nSeedsPerEvent, nSeedsFilled);
if (!_overload && !_functor) {
G4RNGHelper* helper = G4RNGHelper::GetInstance();
switch (SeedOncePerCommunication()) {
case 0:
nSeedsFilled = n_event;
break;
case 1:
nSeedsFilled = numberOfTasks;
break;
case 2:
nSeedsFilled = n_event / eventModulo + 1;
break;
default:
G4ExceptionDescription msgd;
msgd << "Parameter value <" << SeedOncePerCommunication()
<< "> of seedOncePerCommunication is invalid. It is reset "
"to 0.";
G4Exception("G4SubEvtRunManager::InitializeEventLoop()", "Run10036", JustWarning, msgd);
SetSeedOncePerCommunication(0);
nSeedsFilled = n_event;
}
// Generates up to nSeedsMax seed pairs only.
if (nSeedsFilled > nSeedsMax) nSeedsFilled = nSeedsMax;
masterRNGEngine->flatArray(nSeedsPerEvent * nSeedsFilled, randDbl);
helper->Fill(randDbl, nSeedsFilled, n_event, nSeedsPerEvent);
}
}
}
// Now initialize workers. Check if user defined a WorkerThreadInitialization
if (userWorkerThreadInitialization == nullptr)
userWorkerThreadInitialization = new G4UserSubEvtThreadInitialization();
// Prepare UI commands for threads
PrepareCommandsStack();
// Start worker threads
CreateAndStartWorkers();
}
//============================================================================//
void G4SubEvtRunManager::RunTermination()
{
// Wait for all worker threads to have finished the run
// i.e. wait for them to return from RunTermination()
// This guarantee that userrunaction for workers has been called
runInProgress = false;
//TODO (PHASE-II): do we need this???
workTaskGroup->wait();
// Wait now for all threads to finish event-loop
WaitForEndEventLoopWorkers();
if(currentRun!=nullptr) CleanUpUnnecessaryEvents(0);
// Now call base-class method
G4RunManager::TerminateEventLoop();
G4RunManager::RunTermination();
}
//============================================================================//
void G4SubEvtRunManager::ConstructScoringWorlds()
{
masterScM = G4ScoringManager::GetScoringManagerIfExist();
// Call base class stuff...
G4RunManager::ConstructScoringWorlds();
masterWorlds.clear();
auto nWorlds = (G4int)G4TransportationManager::GetTransportationManager()->GetNoWorlds();
auto itrW = G4TransportationManager::GetTransportationManager()->GetWorldsIterator();
for (G4int iWorld = 0; iWorld < nWorlds; ++iWorld) {
addWorld(iWorld, *itrW);
++itrW;
}
}
//============================================================================//
void G4SubEvtRunManager::MergeScores(const G4ScoringManager* localScoringManager)
{
G4AutoLock l(&scorerMergerMutex);
if (masterScM != nullptr) masterScM->Merge(localScoringManager);
}
const G4SubEvent* G4SubEvtRunManager::GetSubEvent(G4int ty, G4bool& notReady,
G4long& s1, G4long& s2, G4long& s3, G4bool reseedRequired)
{
G4AutoLock l(&accessSubEventMutex);
// This method is invoked from the worker, the ownership of G4SubEvent object
// remains to the master, i.e. will be deleted by the master thread through
// TerminateSubEvent() method.
if(currentRun==nullptr)
{
// Run has not yet started.
notReady = true;
return nullptr;
}
auto eventVector = currentRun->GetEventVector();
// RACE HERE: against:
// 1 G4Run::StoreEvent(G4Event*) G4Run.cc:80
// 2 G4RunManager::StackPreviousEvent(G4Event*) G4RunManager.cc:572
for(auto& ev : *eventVector)
{
// looping over stored events
// RACE HERE: against:
// 1 G4Run::StoreEvent(G4Event*) G4Run.cc:80
// 2 G4RunManager::StackPreviousEvent(G4Event*) G4RunManager.cc:572
auto se = const_cast<G4Event*>(ev)->PopSubEvent(ty);
if(se!=nullptr)
{
// Sub-event is found in an event that is already finished its event-loop
notReady = false;
if(reseedRequired) SetUpSeedsForSubEvent(s1,s2,s3);
return se;
}
}
auto sep = eventManager->PopSubEvent(ty);
if(sep!=nullptr)
{
// Sub-event is found in an event that is still in the event loop
notReady = false;
if(reseedRequired) SetUpSeedsForSubEvent(s1,s2,s3);
return sep;
} else {
// No sub-event available
// RACE HERE vs line 345
if(runInProgress)
{
// Run is still in progress. Worker should wait until a sub-event is ready
notReady = true;
}
else
{
// Run is over. No more sub-event to come unless new run starts.
notReady = false;
}
return nullptr;
}
}
void G4SubEvtRunManager::SetUpSeedsForSubEvent(G4long& s1, G4long& s2, G4long& s3)
{
//TODO (PHASE-II): Seeding scheme for sub-event has to be revisited
G4RNGHelper* helper = G4RNGHelper::GetInstance();
G4int idx_rndm = nSeedsPerEvent * nSeedsUsed;
s1 = helper->GetSeed(idx_rndm);
s2 = helper->GetSeed(idx_rndm + 1);
if (nSeedsPerEvent == 3) s3 = helper->GetSeed(idx_rndm + 2);
++nSeedsUsed;
if (nSeedsUsed == nSeedsFilled) RefillSeeds();
}
//============================================================================//
//
//G4bool G4SubEvtRunManager::SetUpAnEvent(G4Event* evt, G4long& s1, G4long& s2, G4long& s3,
// G4bool reseedRequired)
//{
// G4AutoLock l(&setUpEventMutex);
// if (numberOfEventProcessed < numberOfEventToBeProcessed) {
// evt->SetEventID(numberOfEventProcessed);
// if (reseedRequired) {
// G4RNGHelper* helper = G4RNGHelper::GetInstance();
// G4int idx_rndm = nSeedsPerEvent * nSeedsUsed;
// s1 = helper->GetSeed(idx_rndm);
// s2 = helper->GetSeed(idx_rndm + 1);
// if (nSeedsPerEvent == 3) s3 = helper->GetSeed(idx_rndm + 2);
// ++nSeedsUsed;
// if (nSeedsUsed == nSeedsFilled) RefillSeeds();
// }
// numberOfEventProcessed++;
// return true;
// }
// return false;
//}
//============================================================================//
//
//G4int G4SubEvtRunManager::SetUpNEvents(G4Event* evt, G4SeedsQueue* seedsQueue, G4bool reseedRequired)
//{
// G4AutoLock l(&setUpEventMutex);
// if (numberOfEventProcessed < numberOfEventToBeProcessed && !runAborted) {
// G4int nevt = numberOfEventsPerTask;
// G4int nmod = eventModulo;
// if (numberOfEventProcessed + nevt > numberOfEventToBeProcessed) {
// nevt = numberOfEventToBeProcessed - numberOfEventProcessed;
// nmod = numberOfEventToBeProcessed - numberOfEventProcessed;
// }
// evt->SetEventID(numberOfEventProcessed);
//
// if (reseedRequired) {
// G4RNGHelper* helper = G4RNGHelper::GetInstance();
// G4int nevRnd = nmod;
// if (SeedOncePerCommunication() > 0) nevRnd = 1;
// for (G4int i = 0; i < nevRnd; ++i) {
// seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed));
// seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 1));
// if (nSeedsPerEvent == 3) seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 2));
// nSeedsUsed++;
// if (nSeedsUsed == nSeedsFilled) RefillSeeds();
// }
// }
// numberOfEventProcessed += nevt;
// return nevt;
// }
// return 0;
//}
//============================================================================//
void G4SubEvtRunManager::SubEventFinished(const G4SubEvent* se,const G4Event* evt)
{
G4AutoLock l(&accessSubEventMutex);
UpdateScoringForSubEvent(se,evt);
eventManager->TerminateSubEvent(se,evt);
}
//============================================================================//
void G4SubEvtRunManager::UpdateScoringForSubEvent(const G4SubEvent* se,const G4Event* evt)
{
auto masterEvt = se->GetEvent();
if(masterEvt==nullptr) {
G4Exception("G4SubEvtRunManager::UpdateScoringForSubEvent()","SERM0001",
FatalException,"Pointer of master event is null. PANIC!");
}
if(userEventAction) {
userEventAction->MergeSubEvent(masterEvt,evt);
}
//if (isScoreNtupleWriter) {
// G4VScoreNtupleWriter::Instance()->Fill(evt->GetHCofThisEvent(),
// se->GetEvent()->GetEventID());
//}
evt->ScoresRecorded();
G4ScoringManager* ScM = G4ScoringManager::GetScoringManagerIfExist();
if (ScM == nullptr) return;
auto nPar = (G4int)ScM->GetNumberOfMesh();
if (nPar < 1) return;
if(verboseLevel>2) {
G4cout << "merging scores of sub-event belonging to event id #" << masterEvt->GetEventID()
<< " --- sub-event has " << evt->GetHCofThisEvent()->GetCapacity()
<< " hits collections" << G4endl;
}
G4HCofThisEvent* HCE = evt->GetHCofThisEvent();
if (HCE == nullptr) return;
auto nColl = (G4int)HCE->GetCapacity();
for (G4int i = 0; i < nColl; ++i) {
G4VHitsCollection* HC = HCE->GetHC(i);
if (HC != nullptr) ScM->Accumulate(HC);
}
}
//============================================================================//
void G4SubEvtRunManager::CleanUpPreviousEvents()
{
// Delete all events carried over from previous run.
// This method is invoked at the beginning of the next run
// or from the destructor of G4RunManager at the very end of
// the program.
auto evItr = previousEvents->cbegin();
while (evItr != previousEvents->cend()) {
G4Event* evt = *evItr;
if (evt != nullptr)
{
ReportEventDeletion(evt);
// remove evt from the event vector of G4Run as well
if(currentRun!=nullptr)
{
auto eventVector = currentRun->GetEventVector();
auto eItr = std::find(eventVector->cbegin(),eventVector->cend(),evt);
if(eItr != eventVector->cend()) eventVector->erase(eItr);
}
delete evt;
}
evItr = previousEvents->erase(evItr);
}
if(currentRun!=nullptr)
{
auto eventVector = currentRun->GetEventVector();
if(eventVector==nullptr || eventVector->empty()) return;
auto eItr = eventVector->cbegin();
while(eItr != eventVector->cend())
{
const G4Event* ev = *eItr;
if(ev!=nullptr)
{
ReportEventDeletion(ev);
delete ev;
}
eItr = eventVector->erase(eItr);
}
}
}
//============================================================================//
void G4SubEvtRunManager::TerminateWorkers()
{
// Force workers to execute (if any) all UI commands left in the stack
RequestWorkersProcessCommandsStack();
if (workTaskGroup != nullptr) {
workTaskGroup->join();
if (!fakeRun)
threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::TerminateWorker(); });
}
}
//============================================================================//
void G4SubEvtRunManager::AbortRun(G4bool softAbort)
{
// This method is valid only for GeomClosed or EventProc state
G4ApplicationState currentState = G4StateManager::GetStateManager()->GetCurrentState();
if (currentState == G4State_GeomClosed || currentState == G4State_EventProc) {
runAborted = true;
MTkernel->BroadcastAbortRun(softAbort);
}
else {
G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
}
}
//============================================================================//
void G4SubEvtRunManager::AbortEvent()
{
// nothing to do in the master thread
}
//============================================================================//
void G4SubEvtRunManager::WaitForEndEventLoopWorkers()
{
if (workTaskGroup != nullptr) {
workTaskGroup->join();
if (!fakeRun)
threadPool->execute_on_all_threads(
[]() { G4TaskRunManagerKernel::TerminateWorkerRunEventLoop(); });
}
}
//============================================================================//
void G4SubEvtRunManager::RequestWorkersProcessCommandsStack()
{
PrepareCommandsStack();
auto process_commands_stack = []() {
G4MTRunManager* mrm = G4MTRunManager::GetMasterRunManager();
if (mrm != nullptr) {
auto cmds = mrm->GetCommandStack();
for (const auto& itr : cmds)
G4UImanager::GetUIpointer()->ApplyCommand(itr); // TLS instance
mrm->ThisWorkerProcessCommandsStackDone();
}
};
if (threadPool != nullptr) threadPool->execute_on_all_threads(process_commands_stack);
}
//============================================================================//
void G4SubEvtRunManager::ThisWorkerProcessCommandsStackDone() {}
//============================================================================//
void G4SubEvtRunManager::SetUserInitialization(G4UserWorkerInitialization* userInit)
{
userWorkerInitialization = userInit;
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserInitialization(G4UserWorkerThreadInitialization* userInit)
{
userWorkerThreadInitialization = userInit;
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserInitialization(G4VUserActionInitialization* userInit)
{
userActionInitialization = userInit;
userActionInitialization->BuildForMaster();
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserInitialization(G4VUserDetectorConstruction* userDC)
{
G4RunManager::SetUserInitialization(userDC);
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserInitialization(G4VUserPhysicsList* pl)
{
pl->InitializeWorker();
G4RunManager::SetUserInitialization(pl);
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserAction(G4UserRunAction* userAction)
{
G4RunManager::SetUserAction(userAction);
if (userAction != nullptr) userAction->SetMaster(true);
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserAction(G4UserEventAction* ua)
{
G4RunManager::SetUserAction(ua);
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserAction(G4VUserPrimaryGeneratorAction* ua)
{
G4RunManager::SetUserAction(ua);
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserAction(G4UserStackingAction* ua)
{
G4RunManager::SetUserAction(ua);
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserAction(G4UserTrackingAction* ua)
{
G4RunManager::SetUserAction(ua);
}
// --------------------------------------------------------------------
void G4SubEvtRunManager::SetUserAction(G4UserSteppingAction* ua)
{
G4RunManager::SetUserAction(ua);
}
-4
View File
@@ -40,7 +40,6 @@
#include "G4ThreadLocalSingleton.hh"
#include "G4ThreadPool.hh"
#include "G4Threading.hh"
#include "G4TiMemory.hh"
#include "G4Timer.hh"
#include "G4TransportationManager.hh"
#include "G4UImanager.hh"
@@ -148,9 +147,6 @@ G4TaskRunManager::G4TaskRunManager(G4bool useTBB) : G4TaskRunManager(nullptr, us
G4TaskRunManager::~G4TaskRunManager()
{
// finalize profiler before shutting down the threads
G4Profiler::Finalize();
// terminate all the workers
G4TaskRunManager::TerminateWorkers();
-1
View File
@@ -45,7 +45,6 @@
#include "G4Run.hh"
#include "G4StateManager.hh"
#include "G4TaskManager.hh"
#include "G4TiMemory.hh"
#include "G4UImanager.hh"
#include "G4UserWorkerInitialization.hh"
#include "G4UserWorkerThreadInitialization.hh"
@@ -0,0 +1,37 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "G4UserSubEvtThreadInitialization.hh"
#include "G4WorkerSubEvtRunManager.hh"
//============================================================================//
G4WorkerRunManager* G4UserSubEvtThreadInitialization::CreateWorkerRunManager() const
{
return new G4WorkerSubEvtRunManager();
}
//============================================================================//
+46 -10
View File
@@ -39,7 +39,6 @@
#include "G4Run.hh"
#include "G4SDManager.hh"
#include "G4ScoringManager.hh"
#include "G4TiMemory.hh"
#include "G4Timer.hh"
#include "G4TransportationManager.hh"
#include "G4UImanager.hh"
@@ -56,6 +55,8 @@
#include "G4WorkerRunManagerKernel.hh"
#include "G4WorkerThread.hh"
#include "G4GeometryManager.hh" // For parallel geometry initialisation
#include <fstream>
#include <sstream>
@@ -137,10 +138,20 @@ void G4WorkerRunManager::InitializeGeometry()
"G4VUserDetectorConstruction is not defined!");
return;
}
if (fGeometryHasBeenDestroyed) {
G4TransportationManager::GetTransportationManager()->ClearParallelWorlds();
}
// Step 0: Contribute to the voxelisation of the geometry
if( G4GeometryManager::IsParallelOptimisationConfigured() ) {
G4cout << "G4RunManager::InitializeGeometry calling GeometryManager's UndertakeOptimisation"
<< G4endl; // TODO - suppress / delete this in final version
G4GeometryManager::GetInstance()->UndertakeOptimisation();
}
// A barrier must ensure that all that all threads have finished this work.
// Currently we rely on the (later) barrier at the end of initialisation.
// Step1: Get pointer to the physiWorld (note: needs to get the "super
// pointer, i.e. the one shared by all threads"
G4RunManagerKernel* masterKernel = G4MTRunManager::GetMasterRunManagerKernel();
@@ -217,10 +228,6 @@ void G4WorkerRunManager::RunInitialization()
}
if (userRunAction != nullptr) userRunAction->BeginOfRunAction(currentRun);
#if defined(GEANT4_USE_TIMEMORY)
workerRunProfiler.reset(new ProfilerConfig(currentRun));
#endif
if (isScoreNtupleWriter) {
G4VScoreNtupleWriter::Instance()->OpenFile();
}
@@ -408,22 +415,51 @@ G4Event* G4WorkerRunManager::GenerateEvent(G4int i_event)
}
// --------------------------------------------------------------------
void G4WorkerRunManager::MergePartialResults()
void G4WorkerRunManager::MergePartialResults(G4bool mergeEvents)
{
// Merge partial results into global run
G4MTRunManager* mtRM = G4MTRunManager::GetMasterRunManager();
G4ScoringManager* ScM = G4ScoringManager::GetScoringManagerIfExist();
if (ScM != nullptr) mtRM->MergeScores(ScM);
mtRM->MergeRun(currentRun);
/************************** MAMAMAMAMA
if(mergeEvents) {
G4int ctr = 0;
G4int ctrD = 0;
G4int ctrK = 0;
G4int ctrG = 0;
auto eventVector = currentRun->GetEventVector();
if(eventVector!=nullptr || !(eventVector->empty())) {
auto eItr = eventVector->cbegin();
while(eItr != eventVector->cend())
{
ctr++;
const G4Event* ev = *eItr;
if(ev->ToBeKept()) { ctrD++; }
if(ev->KeepTheEventFlag()) { ctrK++; }
if(ev->GetNumberOfGrips()>0) { ctrG++; }
eItr++;
}
// if(!(ev->ToBeKept()))
// {
// ReportEventDeletion(ev);
// delete ev;
// eItr = eventVector->erase(eItr);
// ctrD++;
// }
// else
// { eItr++; }
// }
}
G4cout<<"MAMAMAMAMA ctr="<<ctr<<" - ctrD="<<ctrD<<" - ctrK="<<ctrK<<" - ctrG="<<ctrG<<G4endl;
}
********************************/
if(mergeEvents) mtRM->MergeRun(currentRun);
}
// --------------------------------------------------------------------
void G4WorkerRunManager::RunTermination()
{
if (!fakeRun) {
#if defined(GEANT4_USE_TIMEMORY)
workerRunProfiler.reset();
#endif
MergePartialResults();
// Call a user hook: note this is before the next barrier
+621
View File
@@ -0,0 +1,621 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
#include "G4WorkerSubEvtRunManager.hh"
#include "G4AutoLock.hh"
#include "G4MTRunManager.hh"
#include "G4ParallelWorldProcess.hh"
#include "G4ParallelWorldProcessStore.hh"
#include "G4RNGHelper.hh"
#include "G4Run.hh"
#include "G4SDManager.hh"
#include "G4ScoringManager.hh"
#include "G4SubEvtRunManager.hh"
#include "G4Timer.hh"
#include "G4TransportationManager.hh"
#include "G4UImanager.hh"
#include "G4UserRunAction.hh"
#include "G4UserWorkerInitialization.hh"
#include "G4UserWorkerThreadInitialization.hh"
#include "G4VScoreNtupleWriter.hh"
#include "G4VScoringMesh.hh"
#include "G4VUserActionInitialization.hh"
#include "G4VUserDetectorConstruction.hh"
#include "G4VUserPhysicsList.hh"
#include "G4VUserPrimaryGeneratorAction.hh"
#include "G4VVisManager.hh"
#include "G4WorkerTaskRunManagerKernel.hh"
#include "G4WorkerThread.hh"
#include <fstream>
#include <sstream>
//============================================================================//
G4WorkerSubEvtRunManager* G4WorkerSubEvtRunManager::GetWorkerRunManager()
{
return static_cast<G4WorkerSubEvtRunManager*>(G4RunManager::GetRunManager());
}
//============================================================================//
G4WorkerSubEvtRunManagerKernel* G4WorkerSubEvtRunManager::GetWorkerRunManagerKernel()
{
return static_cast<G4WorkerSubEvtRunManagerKernel*>(GetWorkerRunManager()->kernel);
}
//============================================================================//
G4WorkerSubEvtRunManager::G4WorkerSubEvtRunManager(G4int seType)
: fSubEventType(seType)
{ runManagerType = subEventWorkerRM; }
void G4WorkerSubEvtRunManager::RunInitialization()
{
#ifdef G4MULTITHREADED
if (!visIsSetUp) {
G4VVisManager* pVVis = G4VVisManager::GetConcreteInstance();
if (pVVis != nullptr) {
pVVis->SetUpForAThread();
visIsSetUp = true;
}
}
#endif
runIsSeeded = false;
if (!(kernel->RunInitialization(fakeRun))) return;
// Signal this thread can start event loop.
// Note this will return only when all threads reach this point
G4MTRunManager::GetMasterRunManager()->ThisWorkerReady();
if (fakeRun) return;
const G4UserWorkerInitialization* uwi =
G4MTRunManager::GetMasterRunManager()->GetUserWorkerInitialization();
CleanUpPreviousEvents();
delete currentRun;
currentRun = nullptr;
if (IfGeometryHasBeenDestroyed()) G4ParallelWorldProcessStore::GetInstance()->UpdateWorlds();
// Call a user hook: this is guaranteed all threads are "synchronized"
if (uwi != nullptr) uwi->WorkerRunStart();
if (userRunAction != nullptr) currentRun = userRunAction->GenerateRun();
if (currentRun == nullptr) currentRun = new G4Run();
currentRun->SetRunID(runIDCounter);
G4TaskRunManager* mrm = G4TaskRunManager::GetMasterRunManager();
numberOfEventToBeProcessed = mrm->GetNumberOfEventsToBeProcessed();
currentRun->SetNumberOfEventToBeProcessed(numberOfEventToBeProcessed);
currentRun->SetDCtable(DCtable);
G4SDManager* fSDM = G4SDManager::GetSDMpointerIfExist();
if (fSDM != nullptr) {
currentRun->SetHCtable(fSDM->GetHCtable());
}
if (G4VScoreNtupleWriter::Instance() != nullptr) {
auto hce = (fSDM != nullptr) ? fSDM->PrepareNewEvent() : nullptr;
isScoreNtupleWriter = G4VScoreNtupleWriter::Instance()->Book(hce);
delete hce;
}
std::ostringstream oss;
G4Random::saveFullState(oss);
randomNumberStatusForThisRun = oss.str();
currentRun->SetRandomNumberStatus(randomNumberStatusForThisRun);
for (G4int i_prev = 0; i_prev < n_perviousEventsToBeStored; ++i_prev)
previousEvents->push_back(nullptr);
if (printModulo > 0 || verboseLevel > 0) {
G4cout << "### Run " << currentRun->GetRunID() << " starts on worker thread "
<< G4Threading::G4GetThreadId() << "." << G4endl;
}
if (userRunAction != nullptr) userRunAction->BeginOfRunAction(currentRun);
if (isScoreNtupleWriter) {
G4VScoreNtupleWriter::Instance()->OpenFile();
}
if (storeRandomNumberStatus) {
G4String fileN = "currentRun";
if (rngStatusEventsFlag) {
std::ostringstream os;
os << "run" << currentRun->GetRunID();
fileN = os.str();
}
StoreRNGStatus(fileN);
}
runAborted = false;
numberOfEventProcessed = 0;
}
//============================================================================//
void G4WorkerSubEvtRunManager::DoEventLoop(G4int n_event, const char* macroFile, G4int n_select)
{
//MAMAMAMA
G4Exception("G4WorkerSubEvtRunManager::DoEventLoop()","SuvEvtXXX001",FatalException,"We should not be here!");
//MAMAMAMA
if (userPrimaryGeneratorAction == nullptr) {
G4Exception("G4RunManager::GenerateEvent()", "Run0032", FatalException,
"G4VUserPrimaryGeneratorAction is not defined!");
}
// This is the same as in the sequential case, just the for-loop indexes are
// different
InitializeEventLoop(n_event, macroFile, n_select);
// Reset random number seeds queue
while (!seedsQueue.empty())
seedsQueue.pop();
// for each run, worker should receive at least one set of random number
// seeds.
// runIsSeeded = false;
// Event loop
eventLoopOnGoing = true;
G4int i_event = -1;
nevModulo = -1;
currEvID = -1;
for (G4int evt = 0; evt < n_event; ++evt) {
ProcessOneEvent(i_event);
if (eventLoopOnGoing) {
TerminateOneEvent();
if (runAborted) eventLoopOnGoing = false;
}
if (!eventLoopOnGoing) break;
}
}
//============================================================================//
void G4WorkerSubEvtRunManager::ProcessOneEvent(G4int i_event)
{
//MAMAMAMA
G4Exception("G4WorkerSubEvtRunManager::ProcessOneEvent()","SuvEvtXXX002",FatalException,"We should not be here!");
//MAMAMAMA
currentEvent = GenerateEvent(i_event);
if (eventLoopOnGoing) {
eventManager->ProcessOneEvent(currentEvent);
AnalyzeEvent(currentEvent);
UpdateScoring();
if (currentEvent->GetEventID() < n_select_msg) {
G4cout << "Applying command \"" << msgText << "\" @ " << __FUNCTION__ << ":" << __LINE__
<< G4endl;
G4UImanager::GetUIpointer()->ApplyCommand(msgText);
}
}
}
//============================================================================//
G4Event* G4WorkerSubEvtRunManager::GenerateEvent(G4int i_event)
{
//MAMAMAMA
G4Exception("G4WorkerSubEvtRunManager::GenerateEvent()","SuvEvtXXX003",FatalException,"We should not be here!");
//MAMAMAMA
auto anEvent = new G4Event(i_event);
G4long s1 = 0;
G4long s2 = 0;
G4long s3 = 0;
G4bool eventHasToBeSeeded = true;
if (G4MTRunManager::SeedOncePerCommunication() == 1 && runIsSeeded) eventHasToBeSeeded = false;
if (i_event < 0) {
G4int nevM = G4MTRunManager::GetMasterRunManager()->GetEventModulo();
if (nevM == 1) {
eventLoopOnGoing = G4MTRunManager::GetMasterRunManager()->SetUpAnEvent(anEvent, s1, s2, s3,
eventHasToBeSeeded);
runIsSeeded = true;
}
else {
if (nevModulo <= 0) {
G4int nevToDo = G4MTRunManager::GetMasterRunManager()->SetUpNEvents(anEvent, &seedsQueue,
eventHasToBeSeeded);
if (nevToDo == 0)
eventLoopOnGoing = false;
else {
currEvID = anEvent->GetEventID();
nevModulo = nevToDo - 1;
}
}
else {
if (G4MTRunManager::SeedOncePerCommunication() > 0) eventHasToBeSeeded = false;
anEvent->SetEventID(++currEvID);
nevModulo--;
}
if (eventLoopOnGoing && eventHasToBeSeeded) {
s1 = seedsQueue.front();
seedsQueue.pop();
s2 = seedsQueue.front();
seedsQueue.pop();
}
}
if (!eventLoopOnGoing) {
delete anEvent;
return nullptr;
}
}
else if (eventHasToBeSeeded) {
// Need to reseed random number generator
G4RNGHelper* helper = G4RNGHelper::GetInstance();
s1 = helper->GetSeed(i_event * 2);
s2 = helper->GetSeed(i_event * 2 + 1);
}
if (eventHasToBeSeeded) {
G4long seeds[3] = {s1, s2, 0};
G4Random::setTheSeeds(seeds, -1);
runIsSeeded = true;
}
// Read from file seed.
// Andrea Dotti 4 November 2015
// This is required for strong-reproducibility, in MT mode we have that each
// thread produces, for each event a status file, we want to do that.
// Search a random file with the format run{%d}evt{%d}.rndm
// This is the filename base constructed from run and event
const auto filename = [&] {
std::ostringstream os;
os << "run" << currentRun->GetRunID() << "evt" << anEvent->GetEventID();
return os.str();
};
G4bool RNGstatusReadFromFile = false;
if (readStatusFromFile) {
// Build full path of RNG status file for this event
std::ostringstream os;
os << filename() << ".rndm";
const G4String& randomStatusFile = os.str();
std::ifstream ifile(randomStatusFile.c_str());
if (ifile) {
// File valid and readable
RNGstatusReadFromFile = true;
G4Random::restoreEngineStatus(randomStatusFile.c_str());
}
}
if (storeRandomNumberStatusToG4Event == 1 || storeRandomNumberStatusToG4Event == 3) {
std::ostringstream oss;
G4Random::saveFullState(oss);
randomNumberStatusForThisEvent = oss.str();
anEvent->SetRandomNumberStatus(randomNumberStatusForThisEvent);
}
if (storeRandomNumberStatus && !RNGstatusReadFromFile) {
// If reading from file, avoid to rewrite the same
G4String fileN = "currentEvent";
if (rngStatusEventsFlag) fileN = filename();
StoreRNGStatus(fileN);
}
if (printModulo > 0 && anEvent->GetEventID() % printModulo == 0) {
G4cout << "--> Event " << anEvent->GetEventID() << " starts";
if (eventHasToBeSeeded) G4cout << " with initial seeds (" << s1 << "," << s2 << ")";
G4cout << "." << G4endl;
}
userPrimaryGeneratorAction->GeneratePrimaries(anEvent);
return anEvent;
}
//============================================================================//
void G4WorkerSubEvtRunManager::RunTermination()
{
if (!fakeRun && (currentRun != nullptr)) {
MergePartialResults(true);
// Call a user hook: note this is before the next barrier
// so threads execute this method asyncrhonouzly
//(TerminateRun allows for synch via G4RunAction::EndOfRun)
const G4UserWorkerInitialization* uwi =
G4MTRunManager::GetMasterRunManager()->GetUserWorkerInitialization();
if (uwi != nullptr) uwi->WorkerRunEnd();
}
if (currentRun != nullptr) {
G4RunManager::RunTermination();
}
// Signal this thread has finished envent-loop.
// Note this will return only whan all threads reach this point
G4MTRunManager::GetMasterRunManager()->ThisWorkerEndEventLoop();
}
//============================================================================//
void G4WorkerSubEvtRunManager::TerminateEventLoop()
{
if (verboseLevel > 0 && !fakeRun) {
timer->Stop();
// prefix with thread # info due to how TBB calls this function
G4String prefix = "[thread " + std::to_string(workerContext->GetThreadId()) + "] ";
G4cout << prefix << "Thread-local run terminated." << G4endl;
G4cout << prefix << "Run Summary" << G4endl;
if (runAborted)
G4cout << prefix << " Run Aborted after " << numberOfEventProcessed << " events processed."
<< G4endl;
else
G4cout << prefix << " Number of events processed : " << numberOfEventProcessed << G4endl;
G4cout << prefix << " " << *timer << G4endl;
}
}
//============================================================================//
void G4WorkerSubEvtRunManager::SetupDefaultRNGEngine()
{
const CLHEP::HepRandomEngine* mrnge =
G4MTRunManager::GetMasterRunManager()->getMasterRandomEngine();
assert(mrnge); // Master has created RNG
const G4UserWorkerThreadInitialization* uwti =
G4MTRunManager::GetMasterRunManager()->GetUserWorkerThreadInitialization();
uwti->SetupRNGEngine(mrnge);
}
//============================================================================//
void G4WorkerSubEvtRunManager::StoreRNGStatus(const G4String& fn)
{
std::ostringstream os;
os << randomNumberStatusDir << "G4Worker" << workerContext->GetThreadId() << "_" << fn << ".rndm";
G4Random::saveEngineStatus(os.str().c_str());
}
//============================================================================//
void G4WorkerSubEvtRunManager::ProcessUI()
{
G4TaskRunManager* mrm = G4TaskRunManager::GetMasterRunManager();
if (mrm == nullptr) return;
//------------------------------------------------------------------------//
// Check UI commands not already processed
auto command_stack = mrm->GetCommandStack();
bool matching = (command_stack.size() == processedCommandStack.size());
if (matching) {
for (uintmax_t i = 0; i < command_stack.size(); ++i)
if (processedCommandStack.at(i) != command_stack.at(i)) {
matching = false;
break;
}
}
//------------------------------------------------------------------------//
// Execute UI commands stored in the master UI manager
if (!matching) {
for (const auto& itr : command_stack)
G4UImanager::GetUIpointer()->ApplyCommand(itr);
processedCommandStack = command_stack;
}
}
//============================================================================//
void G4WorkerSubEvtRunManager::DoCleanup()
{
// Nothing to do for a run
//CleanUpPreviousEvents();
//
//delete currentRun;
//currentRun = nullptr;
}
//============================================================================//
void G4WorkerSubEvtRunManager::DoWork()
{
if(verboseLevel>1) {
G4cout << "G4WorkerSubEvtRunManager::DoWork() starts.........." << G4endl;
}
//G4TaskRunManager* mrm = G4TaskRunManager::GetMasterRunManager();
G4SubEvtRunManager* mrm = G4SubEvtRunManager::GetMasterRunManager();
G4bool newRun = false;
const G4Run* run = mrm->GetCurrentRun();
G4ThreadLocalStatic G4int runId = -1;
if ((run != nullptr) && run->GetRunID() != runId) {
runId = run->GetRunID();
newRun = true;
if (runId > 0) { ProcessUI(); }
}
G4bool reseedRequired = false;
if (newRun) {
G4bool cond = ConfirmBeamOnCondition();
if (cond) {
ConstructScoringWorlds();
RunInitialization();
}
reseedRequired = true;
}
assert(workerContext != nullptr);
workerContext->UpdateGeometryAndPhysicsVectorFromMaster();
eventManager->UseSubEventParallelism(true);
G4bool needMoreWork = true;
while(needMoreWork)
{
G4bool notReady = false;
G4long s1, s2, s3;
auto subEv = mrm->GetSubEvent(fSubEventType, notReady, s1, s2, s3, reseedRequired);
if(subEv==nullptr && notReady)
{
// Master is not yet ready for tasking a sub-event.
// Wait 1 second and retry.
G4THREADSLEEP(1);
}
else if(subEv==nullptr)
{
// No more sub-event to process
needMoreWork = false;
}
else
{
// Let's work for this sub-event.
if(reseedRequired)
{
G4long seeds[3] = {s1, s2, s3};
G4Random::setTheSeeds(seeds, -1);
reseedRequired = false;
}
// create a G4Event object for this sub-event. This G4Event object will contain output
// to be merged into the master event.
auto masterEvent = subEv->GetEvent();
G4Event* ev = new G4Event(masterEvent->GetEventID());
ev->FlagAsSubEvent(masterEvent,fSubEventType);
// Create a G4TrackVector as the input
G4TrackVector* tv = new G4TrackVector();
for(auto& stackedTrack : *subEv)
{
// tracks (and trajectories) stored in G4SubEvent object belong to the master thread
// and thus they must not be deleted by the worker thread. They must be cloned.
G4Track* tr = new G4Track();
tr->CopyTrackInfo(*(stackedTrack.GetTrack()),false);
//MAMAMAMAMA cloning of trajectory object is not yet implemented.
tv->push_back(tr);
}
// Process this sub-event
currentEvent = ev;
eventManager->ProcessOneEvent(tv,ev);
// We don't need following two lines, as they are taken care by the master
//////AnalyzeEvent(ev);
//////UpdateScoring();
// Report the results to the master
mrm->SubEventFinished(subEv,ev);
// clean up
delete tv;
delete ev;
}
}
if(verboseLevel>1) {
G4cout << "G4WorkerSubEvtRunManager::DoWork() completed.........." << G4endl;
}
}
//============================================================================//
void G4WorkerSubEvtRunManager::SetUserInitialization(G4UserWorkerInitialization*)
{
G4Exception("G4WorkerSubEvtRunManager::SetUserInitialization(G4UserWorkerInitialization*)", "RunSE0118",
FatalException, "This method should be used only with an instance of the master thread");
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserInitialization(G4UserWorkerThreadInitialization*)
{
G4Exception("G4WorkerSubEvtRunManager::SetUserInitialization(G4UserWorkerThreadInitialization*)", "RunSE0119",
FatalException, "This method should be used only with an instance of the master thread");
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserInitialization(G4VUserActionInitialization*)
{
G4Exception("G4WorkerSubEvtRunManager::SetUserInitialization(G4VUserActionInitialization*)", "RunSE0120",
FatalException, "This method should be used only with an instance of the master thread");
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserInitialization(G4VUserDetectorConstruction*)
{
G4Exception("G4WorkerSubEvtRunManager::SetUserInitialization(G4VUserDetectorConstruction*)", "RunSE0121",
FatalException, "This method should be used only with an instance of the master thread");
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserInitialization(G4VUserPhysicsList* pl)
{
pl->InitializeWorker();
G4RunManager::SetUserInitialization(pl);
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserAction(G4UserRunAction*)
{
G4Exception("G4WorkerSubEvtRunManager::SetUserAction(G4UserRunAction*)", "RunSE0221",
FatalException, "This method should be used only with an instance of the master thread");
}
// Forward calls (avoid GCC compilation warnings)
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserAction(G4UserEventAction* ua)
{
G4RunManager::SetUserAction(ua);
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserAction(G4VUserPrimaryGeneratorAction*)
{
G4Exception("G4WorkerSubEvtRunManager::SetUserAction(G4VUserPrimaryGeneratorAction*)", "RunSE0223",
FatalException, "This method should be used only with an instance of the master thread");
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserAction(G4UserStackingAction* ua)
{
G4RunManager::SetUserAction(ua);
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserAction(G4UserTrackingAction* ua)
{
G4RunManager::SetUserAction(ua);
}
// --------------------------------------------------------------------
void G4WorkerSubEvtRunManager::SetUserAction(G4UserSteppingAction* ua)
{
G4RunManager::SetUserAction(ua);
}
+1 -8
View File
@@ -36,7 +36,6 @@
#include "G4SDManager.hh"
#include "G4ScoringManager.hh"
#include "G4TaskRunManager.hh"
#include "G4TiMemory.hh"
#include "G4Timer.hh"
#include "G4TransportationManager.hh"
#include "G4UImanager.hh"
@@ -141,10 +140,6 @@ void G4WorkerTaskRunManager::RunInitialization()
if (userRunAction != nullptr) userRunAction->BeginOfRunAction(currentRun);
#if defined(GEANT4_USE_TIMEMORY)
workerRunProfiler.reset(new ProfilerConfig(currentRun));
#endif
if (isScoreNtupleWriter) {
G4VScoreNtupleWriter::Instance()->OpenFile();
}
@@ -259,6 +254,7 @@ G4Event* G4WorkerTaskRunManager::GenerateEvent(G4int i_event)
}
if (!eventLoopOnGoing) {
anEvent->ScoresRecorded();
delete anEvent;
return nullptr;
}
@@ -331,9 +327,6 @@ G4Event* G4WorkerTaskRunManager::GenerateEvent(G4int i_event)
void G4WorkerTaskRunManager::RunTermination()
{
if (!fakeRun && (currentRun != nullptr)) {
#if defined(GEANT4_USE_TIMEMORY)
workerRunProfiler.reset();
#endif
MergePartialResults();
// Call a user hook: note this is before the next barrier