Import Geant4 11.3.0.beta source tree
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user