Geant4  10.00.p01
G4WorkerRunManager.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 
28 #include "G4WorkerRunManager.hh"
30 #include "G4UImanager.hh"
32 #include "G4MTRunManager.hh"
33 #include "G4ScoringManager.hh"
36 #include "G4WorkerThread.hh"
37 #include "G4VUserPhysicsList.hh"
41 #include "G4UserRunAction.hh"
42 #include "G4RNGHelper.hh"
43 #include "G4Run.hh"
45 #include "G4VVisManager.hh"
46 #include "G4SDManager.hh"
47 #include "G4VScoringMesh.hh"
48 #include <sstream>
49 
51 { return static_cast<G4WorkerRunManager*>(G4RunManager::GetRunManager()); }
52 
54 { return static_cast<G4WorkerRunManagerKernel*>(GetWorkerRunManager()->kernel); }
55 
57  //This constructor should never be called in non-multithreaded mode
58 #ifndef G4MULTITHREADED
60  msg<<"Geant4 code is compiled without multi-threading support (-DG4MULTITHREADED is set to off).";
61  msg<<" This type of RunManager can only be used in mult-threaded applications.";
62  G4Exception("G4WorkerRunManager::G4WorkerRunManager()","Run0035",FatalException,msg);
63 #endif
66  if(masterScM) G4ScoringManager::GetScoringManager(); //TLS instance for a worker
67 
68  eventLoopOnGoing = false;
69  nevModulo = -1;
70  currEvID = -1;
71 
73 
74 #ifdef G4MULTITHREADED
76  if(pVVis)
77  {
78  pVVis->SetUpForAThread();
79  visIsSetUp = true;
80  }
81  else
82  { visIsSetUp = false; }
83 #endif
84 }
85 
86 #include "G4MTRunManager.hh"
87 
89  // Delete thread-local process manager objects
91 
92  //Put these pointers to zero: owned by master thread
93  //If not to zero, the base class destructor will attempt to
94  //delete them
95  userDetector = 0;
99  physicsList = 0;
100  if(verboseLevel>0) G4cout<<"Destroying WorkerRunManager ("<<this<<")"<<G4endl;
101 }
102 
103 
105  if(!userDetector)
106  {
107  G4Exception("G4RunManager::InitializeGeometry", "Run0033",
108  FatalException, "G4VUserDetectorConstruction is not defined!");
109  return;
110  }
111  //Step1: Get pointer to the physiWorld (note: needs to get the "super pointer, i.e. the one shared by all threads"
113  G4VPhysicalVolume* worldVol = masterKernel->GetCurrentWorld();
114  //Step2:, Call a new "WorkerDefineWorldVolume( pointer from 2-, false);
115  kernel->WorkerDefineWorldVolume(worldVol,false);
117  //Step3: Call user's ConstructSDandField()
120  geometryInitialized = true;
121 }
122 
124 {
125 #ifdef G4MULTITHREADED
126  if(!visIsSetUp)
127  {
129  if(pVVis)
130  {
131  pVVis->SetUpForAThread();
132  visIsSetUp = true;
133  }
134  }
135 #endif
136 
137  if(!(kernel->RunInitialization(fakeRun))) return;
138 
139  //Signal this thread can start event loop.
140  //Note this will return only when all threads reach this point
142  if(fakeRun) return;
143 
144  const G4UserWorkerInitialization* uwi
146  if(currentRun) delete currentRun;
147  currentRun = 0;
148 
149  //Call a user hook: this is guaranteed all threads are "synchronized"
150  if(uwi) uwi->WorkerRunStart();
151 
153  if(!currentRun) currentRun = new G4Run();
154 
157 
160  if(fSDM)
161  { currentRun->SetHCtable(fSDM->GetHCtable()); }
162 
163  std::ostringstream oss;
164  G4Random::saveFullState(oss);
165  randomNumberStatusForThisRun = oss.str();
167 
168  previousEvents->clear();
169  for(G4int i_prev=0;i_prev<n_perviousEventsToBeStored;i_prev++)
170  { previousEvents->push_back((G4Event*)0); }
171 
172  if(printModulo>0 || verboseLevel>0)
173  {
174  G4cout << "### Run " << currentRun->GetRunID() << " starts on worker thread "
175  << G4Threading::G4GetThreadId() << "." << G4endl;
176  }
178 
180  G4String fileN = "currentRun";
181  if ( rngStatusEventsFlag ) {
182  std::ostringstream os;
183  os << "run" << currentRun->GetRunID();
184  fileN = os.str();
185  }
186  StoreRNGStatus(fileN);
187  }
188 
189  runAborted = false;
191 }
192 
193 void G4WorkerRunManager::DoEventLoop(G4int n_event, const char* macroFile , G4int n_select)
194 {
196  {
197  G4Exception("G4RunManager::GenerateEvent()", "Run0032", FatalException,
198  "G4VUserPrimaryGeneratorAction is not defined!");
199  }
200 
201  //This is the same as in the sequential case, just the for-loop indexes are
202  //different
203  InitializeEventLoop(n_event,macroFile,n_select);
204 
205  // Reset random number seeds queue
206  while(seedsQueue.size()>0)
207  { seedsQueue.pop(); }
208 
209  // Event loop
210  eventLoopOnGoing = true;
212  G4int i_event = -1;
213  nevModulo = -1;
214  currEvID = -1;
215 
216  while(eventLoopOnGoing)
217  {
218  ProcessOneEvent(i_event);
219  if(eventLoopOnGoing)
220  {
222  if(runAborted)
223  { eventLoopOnGoing = false; }
229  }
230  }
231 
233 }
234 
236 {
237  currentEvent = GenerateEvent(i_event);
238  if(eventLoopOnGoing)
239  {
242  UpdateScoring();
244  }
245 }
246 
248 {
249  G4Event* anEvent = new G4Event(i_event);
250  long s1, s2;
251  long s3 = 0;
252 
253  if(i_event<0)
254  {
256  if(nevM==1)
257  {
259  ->SetUpAnEvent(anEvent,s1,s2,s3);
260  }
261  else
262  {
263  if(nevModulo<=0)
264  {
266  ->SetUpNEvents(anEvent,&seedsQueue);
267  if(nevToDo==0)
268  { eventLoopOnGoing = false; }
269  else
270  {
271  currEvID = anEvent->GetEventID();
272  nevModulo = nevToDo - 1;
273  }
274  }
275  else
276  {
277  anEvent->SetEventID(++currEvID);
278  nevModulo--;
279  }
280  if(eventLoopOnGoing)
281  {
282  s1 = seedsQueue.front(); seedsQueue.pop();
283  s2 = seedsQueue.front(); seedsQueue.pop();
284  }
285  }
286 
287  if(!eventLoopOnGoing)
288  {
289  delete anEvent;
290  return 0;
291  }
292  }
293  else
294  {
295  //Need to reseed random number generator
297  s1 = helper->GetSeed(i_event*2);
298  s2 = helper->GetSeed(i_event*2+1);
299  }
300 
301  long seeds[3] = { s1, s2, 0 };
302  G4Random::setTheSeeds(seeds,-1);
303 
305  {
306  std::ostringstream oss;
307  G4Random::saveFullState(oss);
308  randomNumberStatusForThisEvent = oss.str();
310  }
311 
313  G4String fileN = "currentEvent";
314  if ( rngStatusEventsFlag ) {
315  std::ostringstream os;
316  os << "run" << currentRun->GetRunID() << "evt" << anEvent->GetEventID();
317  fileN = os.str();
318  }
319  StoreRNGStatus(fileN);
320  }
321 
322  if(printModulo > 0 && anEvent->GetEventID()%printModulo == 0 )
323  {
324  G4cout << "--> Event " << anEvent->GetEventID() << " starts with initial seeds ("
325  << s1 << "," << s2 << ")." << G4endl;
326  }
328  return anEvent;
329 }
330 
332 {
333  //Merge partial results into global run
336  if(ScM) mtRM->MergeScores(ScM);
337  mtRM->MergeRun(currentRun);
338 }
339 
341 {
342  if(!fakeRun)
343  {
345 
346  //Call a user hook: note this is before the next barrier
347  //so threads execute this method asyncrhonouzly
348  //(TerminateRun allows for synch via G4RunAction::EndOfRun)
349  const G4UserWorkerInitialization* uwi
351  if(uwi) uwi->WorkerRunEnd();
352  }
353 
355  //Signal this thread has finished envent-loop.
356  //Note this will return only whan all threads reach this point
358 
359 }
360 
361 /****************************
362 void G4WorkerRunManager::BeamOn(G4int n_event,const char* macroFile,G4int n_select)
363 {
364  if(n_event>0)
365  { G4RunManager::BeamOn(n_event,macroFile,n_select); }
366  else
367  {
368  // fake BeamOn.
369  G4MTRunManager::GetMasterRunManager()->ThisWorkerReady();
370  G4MTRunManager::GetMasterRunManager()->ThisWorkerEndEventLoop();
371  }
372 }
373 ******************************/
374 
375 #include "G4AutoLock.hh"
376 namespace { G4Mutex ConstructScoringWorldsMutex = G4MUTEX_INITIALIZER; }
378 {
379  // Return if unnecessary
381  if(!ScM) return;
382  G4int nPar = ScM->GetNumberOfMesh();
383  if(nPar<1) return;
384 
385  // Update thread-local G4TransportationManager of all the world volumes
387 
389  assert( masterScM != NULL );
390 
393 
394  for(G4int iw=0;iw<nPar;iw++)
395  {
396  G4VScoringMesh* mesh = ScM->GetMesh(iw);
397  G4VPhysicalVolume* pWorld
399  ->IsWorldExisting(ScM->GetWorldName(iw));
400  if(!pWorld)
401  {
403  ed<<"Mesh name <"<<ScM->GetWorldName(iw)<<"> is not found in the masther thread.";
404  G4Exception("G4WorkerRunManager::ConstructScoringWorlds()","RUN79001",
405  FatalException,ed);
406  }
407  if(!(mesh->GetMeshElementLogical()))
408  {
409  G4AutoLock l(&ConstructScoringWorldsMutex);
410  G4VScoringMesh* masterMesh = masterScM->GetMesh(iw);
411  mesh->SetMeshElementLogical(masterMesh->GetMeshElementLogical());
412  l.unlock();
413 
414  G4ParallelWorldProcess* theParallelWorldProcess
415  = new G4ParallelWorldProcess(ScM->GetWorldName(iw));
416  theParallelWorldProcess->SetParallelWorld(ScM->GetWorldName(iw));
417 
418  particleIterator->reset();
419  while( (*particleIterator)() ){
420  G4ParticleDefinition* particle = particleIterator->value();
421  G4ProcessManager* pmanager = particle->GetProcessManager();
422  if(pmanager)
423  {
424  pmanager->AddProcess(theParallelWorldProcess);
425  if(theParallelWorldProcess->IsAtRestRequired(particle))
426  { pmanager->SetProcessOrdering(theParallelWorldProcess, idxAtRest, 9999); }
427  pmanager->SetProcessOrderingToSecond(theParallelWorldProcess, idxAlongStep);
428  pmanager->SetProcessOrdering(theParallelWorldProcess, idxPostStep, 9999);
429  } //if(pmanager)
430  }//while
431  }
432  mesh->WorkerConstruct(pWorld);
433  }
434 }
435 
437 {
438  G4Exception("G4RunManager::SetUserInitialization(G4UserWorkerInitialization*)", "Run3021",
439  FatalException, "This method should be used only with an instance of G4MTRunManager");
440 }
441 
443 {
444  G4Exception("G4RunManager::SetUserInitialization(G4UserWorkerThreadInitialization*)", "Run3021",
445  FatalException, "This method should be used only with an instance of G4MTRunManager");
446 }
447 
449 {
450  G4Exception("G4RunManager::SetUserInitialization(G4VUserActionInitialization*)", "Run3021",
451  FatalException, "This method should be used only with an instance of G4MTRunManager");
452 }
453 
455 {
456  G4Exception("G4RunManager::SetUserInitialization(G4VUserDetectorConstruction*)", "Run3021",
457  FatalException, "This method should be used only with an instance of G4MTRunManager");
458 }
459 
461 {
462  pl->InitializeWorker();
464 }
465 
467 {
468  G4RunManager::SetUserAction(userAction);
469  userAction->SetMaster(false);
470 }
471 
473 {
474  const CLHEP::HepRandomEngine* mrnge = G4MTRunManager::GetMasterRunManager()->getMasterRandomEngine();
475  assert(mrnge);//Master has created RNG
478  uwti->SetupRNGEngine(mrnge);
479 }
480 
481 
482 //Forward calls (avoid GCC compilation warnings)
484 {
486 }
487 
489 {
491 }
492 
494 {
496 }
497 
499 {
501 }
502 
504 {
506 }
507 
509 {
510  std::ostringstream os;
511  os << randomNumberStatusDir << "G4Worker"<<workerContext->GetThreadId()<<"_"<<fn <<".rndm";
512  G4Random::saveEngineStatus(os.str().c_str());
513 }
void SetNumberOfEventToBeProcessed(G4int n_ev)
Definition: G4Run.hh:97
G4VPhysicalVolume * IsWorldExisting(const G4String &worldName)
void SetMaster(G4bool val=true)
void WorkerG4ParticleTable()
G4int numberOfEventToBeProcessed
static G4TemplateRNGHelper * GetInstance()
Definition: G4RNGHelper.hh:52
virtual void TerminateEventLoop()
void SetDCtable(G4DCtable *DCtbl)
Definition: G4Run.hh:101
G4int GetNumberOfParallelWorld() const
virtual void SetUserInitialization(G4VUserDetectorConstruction *userInit)
G4int n_select_msg
virtual G4bool SetUpAnEvent(G4Event *, long &s1, long &s2, long &s3)
G4int numberOfEventProcessed
G4String GetWorldName(G4int i) const
G4String randomNumberStatusForThisRun
virtual void RunTermination()
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
virtual void ThisWorkerEndEventLoop()
virtual void SetupRNGEngine(const CLHEP::HepRandomEngine *aRNGEngine) const
G4VUserPhysicsList * physicsList
virtual void InitializeGeometry()
G4String randomNumberStatusForThisEvent
G4WorkerThread * workerContext
static G4VVisManager * GetConcreteInstance()
void SetIgnoreCmdNotFound(G4bool val)
Definition: G4UImanager.hh:269
void SetNumberOfParallelWorld(G4int i)
void SetProcessOrderingToSecond(G4VProcess *aProcess, G4ProcessVectorDoItIndex idDoIt)
G4VUserActionInitialization * userActionInitialization
void SetMeshElementLogical(G4LogicalVolume *val)
virtual void ConstructScoringWorlds()
static G4WorkerRunManager * GetWorkerRunManager()
G4bool storeRandomNumberStatus
G4bool IsAtRestRequired(G4ParticleDefinition *)
#define assert(x)
Definition: mymalloc.cc:1309
G4UserWorkerThreadInitialization * userWorkerThreadInitialization
virtual void DoEventLoop(G4int n_event, const char *macroFile=0, G4int n_select=-1)
virtual void RunInitialization()
virtual const T GetSeed(const G4int &sdId)
Definition: G4RNGHelper.hh:77
const G4UserWorkerInitialization * GetUserWorkerInitialization() const
virtual void WorkerConstruct(G4VPhysicalVolume *fWorldPhys)
virtual void SetUserInitialization(G4VUserPhysicsList *userInit)
G4ProcessManager * GetProcessManager() const
G4String msgText
int G4int
Definition: G4Types.hh:78
G4bool runAborted
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:158
G4bool RunInitialization(G4bool fakeRun=false)
void WorkerDefineWorldVolume(G4VPhysicalVolume *worldVol, G4bool topologyIsChanged=true)
G4Event * currentEvent
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:58
G4int GetEventID() const
Definition: G4Event.hh:140
G4bool geometryInitialized
G4HCtable * GetHCtable() const
Definition: G4SDManager.hh:101
G4VUserPrimaryGeneratorAction * userPrimaryGeneratorAction
void SetParallelWorld(G4String parallelWorldName)
static G4RunManagerKernel * GetMasterRunManagerKernel()
G4GLOB_DLL std::ostream G4cout
void MergeRun(const G4Run *localRun)
void reset(G4bool ifSkipIon=true)
static G4ScoringManager * GetScoringManagerIfExist()
G4UserWorkerInitialization * userWorkerInitialization
G4String randomNumberStatusDir
G4bool rngStatusEventsFlag
virtual void AnalyzeEvent(G4Event *anEvent)
virtual G4int SetUpNEvents(G4Event *, G4SeedsQueue *seedsQueue)
static G4MTRunManager * GetMasterRunManager()
G4int AddProcess(G4VProcess *aProcess, G4int ordAtRestDoIt=ordInActive, G4int ordAlongSteptDoIt=ordInActive, G4int ordPostStepDoIt=ordInActive)
G4int storeRandomNumberStatusToG4Event
G4int GetRunID() const
Definition: G4Run.hh:76
Definition: G4Run.hh:46
G4int GetThreadId() const
void SetProcessOrdering(G4VProcess *aProcess, G4ProcessVectorDoItIndex idDoIt, G4int ordDoIt=ordDefault)
G4UserRunAction * userRunAction
virtual void RunTermination()
virtual void ProcessOneEvent(G4int i_event)
void SetHCtable(G4HCtable *HCtbl)
Definition: G4Run.hh:99
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
void SetRandomNumberStatus(G4String &st)
Definition: G4Event.hh:124
static G4TransportationManager * GetTransportationManager()
const G4UserWorkerThreadInitialization * GetUserWorkerThreadInitialization() const
static G4RunManager * GetRunManager()
Definition: G4RunManager.cc:74
G4int runIDCounter
G4int G4Mutex
Definition: G4Threading.hh:156
static G4ScoringManager * GetMasterScoringManager()
virtual void GeneratePrimaries(G4Event *anEvent)=0
virtual void ThisWorkerReady()
static G4ParticleTable * GetParticleTable()
virtual G4Event * GenerateEvent(G4int i_event)
virtual void InitializeEventLoop(G4int n_event, const char *macroFile=0, G4int n_select=-1)
const CLHEP::HepRandomEngine * getMasterRandomEngine() const
G4int GetEventModulo() const
virtual void BeginOfRunAction(const G4Run *aRun)
G4LogicalVolume * GetMeshElementLogical() const
std::vector< G4InuclElementaryParticle >::iterator particleIterator
Definition: G4BigBanger.cc:64
G4Run * currentRun
#define G4endl
Definition: G4ios.hh:61
void ProcessOneEvent(G4Event *anEvent)
G4RunManagerKernel * kernel
static G4ScoringManager * GetScoringManager()
size_t GetNumberOfMesh() const
G4EventManager * eventManager
virtual void TerminateOneEvent()
void SetRunID(G4int id)
Definition: G4Run.hh:95
G4VUserDetectorConstruction * userDetector
G4VScoringMesh * GetMesh(G4int i) const
virtual void SetUserAction(G4UserRunAction *userAction)
void SetRandomNumberStatus(G4String &st)
Definition: G4Run.hh:103
virtual G4Run * GenerateRun()
void MergeScores(const G4ScoringManager *localScoringManager)
std::vector< G4Event * > * previousEvents
void SetEventID(G4int i)
Definition: G4Event.hh:114
G4PTblDicIterator * GetIterator() const
void UpdateScoring()
G4DCtable * DCtable
G4int n_perviousEventsToBeStored
G4VPhysicalVolume * GetCurrentWorld() const
G4int G4GetThreadId()
Definition: G4Threading.cc:103
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:419
G4int verboseLevel
virtual void SetUserAction(G4UserRunAction *userAction)
static G4SDManager * GetSDMpointerIfExist()
Definition: G4SDManager.cc:49
static G4WorkerRunManagerKernel * GetWorkerRunManagerKernel()
virtual void MergePartialResults()
virtual void StoreRNGStatus(const G4String &filenamePrefix)