Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/run/src/G4WorkerRunManager.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /run/src/G4WorkerRunManager.cc (Version 11.3.0) and /run/src/G4WorkerRunManager.cc (Version 9.5.p2)


  1 //                                                  1 
  2 // *******************************************    
  3 // * License and Disclaimer                       
  4 // *                                              
  5 // * The  Geant4 software  is  copyright of th    
  6 // * the Geant4 Collaboration.  It is provided    
  7 // * conditions of the Geant4 Software License    
  8 // * LICENSE and available at  http://cern.ch/    
  9 // * include a list of copyright holders.         
 10 // *                                              
 11 // * Neither the authors of this software syst    
 12 // * institutes,nor the agencies providing fin    
 13 // * work  make  any representation or  warran    
 14 // * regarding  this  software system or assum    
 15 // * use.  Please see the license in the file     
 16 // * for the full disclaimer and the limitatio    
 17 // *                                              
 18 // * This  code  implementation is the result     
 19 // * technical work of the GEANT4 collaboratio    
 20 // * By using,  copying,  modifying or  distri    
 21 // * any work based  on the software)  you  ag    
 22 // * use  in  resulting  scientific  publicati    
 23 // * acceptance of all terms of the Geant4 Sof    
 24 // *******************************************    
 25 //                                                
 26 // G4WorkerRunManager implementation              
 27 //                                                
 28 // Original authors: X.Dong, A.Dotti - 2013       
 29 // -------------------------------------------    
 30                                                   
 31 #include "G4WorkerRunManager.hh"                  
 32                                                   
 33 #include "G4AutoLock.hh"                          
 34 #include "G4CopyRandomState.hh"                   
 35 #include "G4MTRunManager.hh"                      
 36 #include "G4ParallelWorldProcess.hh"              
 37 #include "G4ParallelWorldProcessStore.hh"         
 38 #include "G4RNGHelper.hh"                         
 39 #include "G4Run.hh"                               
 40 #include "G4SDManager.hh"                         
 41 #include "G4ScoringManager.hh"                    
 42 #include "G4Timer.hh"                             
 43 #include "G4TransportationManager.hh"             
 44 #include "G4UImanager.hh"                         
 45 #include "G4UserRunAction.hh"                     
 46 #include "G4UserWorkerInitialization.hh"          
 47 #include "G4UserWorkerThreadInitialization.hh"    
 48 #include "G4VScoreNtupleWriter.hh"                
 49 #include "G4VScoringMesh.hh"                      
 50 #include "G4VUserActionInitialization.hh"         
 51 #include "G4VUserDetectorConstruction.hh"         
 52 #include "G4VUserPhysicsList.hh"                  
 53 #include "G4VUserPrimaryGeneratorAction.hh"       
 54 #include "G4VVisManager.hh"                       
 55 #include "G4WorkerRunManagerKernel.hh"            
 56 #include "G4WorkerThread.hh"                      
 57                                                   
 58 #include "G4GeometryManager.hh"   // For paral    
 59                                                   
 60 #include <fstream>                                
 61 #include <sstream>                                
 62                                                   
 63 // -------------------------------------------    
 64 G4WorkerRunManager* G4WorkerRunManager::GetWor    
 65 {                                                 
 66   return static_cast<G4WorkerRunManager*>(G4Ru    
 67 }                                                 
 68                                                   
 69 // -------------------------------------------    
 70 G4WorkerRunManagerKernel* G4WorkerRunManager::    
 71 {                                                 
 72   return static_cast<G4WorkerRunManagerKernel*    
 73 }                                                 
 74                                                   
 75 // -------------------------------------------    
 76 G4WorkerRunManager::G4WorkerRunManager() : G4R    
 77 {                                                 
 78   // This constructor should never be called i    
 79                                                   
 80 #ifndef G4MULTITHREADED                           
 81   G4ExceptionDescription msg;                     
 82   msg << "Geant4 code is compiled without mult    
 83          "(-DG4MULTITHREADED "                    
 84          "is set to off).";                       
 85   msg << " This type of RunManager can only be    
 86          "applications.";                         
 87   G4Exception("G4WorkerRunManager::G4WorkerRun    
 88 #endif                                            
 89   // G4ParticleTable::GetParticleTable()->Work    
 90      // WorkerG4ParticleTable() would be perfo    
 91      // as it is called already from G4Particl    
 92      // which is called beforehand by other Ge    
 93   G4ScoringManager* masterScM = G4MTRunManager    
 94   if (masterScM != nullptr) G4ScoringManager::    
 95                                                   
 96   // Properly initialise luxury level for Ranl    
 97   //                                              
 98   if (dynamic_cast<const CLHEP::Ranlux64Engine    
 99     const auto theEngine = dynamic_cast<const     
100     luxury = theEngine->getLuxury();              
101   }                                               
102   else if (dynamic_cast<const CLHEP::RanluxEng    
103     const auto theEngine = dynamic_cast<const     
104     luxury = theEngine->getLuxury();              
105   }                                               
106                                                   
107   G4UImanager::GetUIpointer()->SetIgnoreCmdNot    
108                                                   
109 #ifdef G4MULTITHREADED                            
110   G4VVisManager* pVVis = G4VVisManager::GetCon    
111   if (pVVis != nullptr) {                         
112     pVVis->SetUpForAThread();                     
113     visIsSetUp = true;                            
114   }                                               
115 #endif                                            
116 }                                                 
117                                                   
118 // -------------------------------------------    
119 G4WorkerRunManager::~G4WorkerRunManager()         
120 {                                                 
121   CleanUpPreviousEvents();                        
122   // Put these pointers to zero: owned by mast    
123   // If not to zero, the base class destructor    
124   // delete them                                  
125   userDetector = nullptr;                         
126   userWorkerInitialization = nullptr;             
127   userWorkerThreadInitialization = nullptr;       
128   userActionInitialization = nullptr;             
129   physicsList->TerminateWorker();                 
130   physicsList = nullptr;                          
131   if (verboseLevel > 1) G4cout << "Destroying     
132 }                                                 
133                                                   
134 // -------------------------------------------    
135 void G4WorkerRunManager::InitializeGeometry()     
136 {                                                 
137   if (userDetector == nullptr) {                  
138     G4Exception("G4RunManager::InitializeGeome    
139                 "G4VUserDetectorConstruction i    
140     return;                                       
141   }                                               
142                                                   
143   if (fGeometryHasBeenDestroyed) {                
144     G4TransportationManager::GetTransportation    
145   }                                               
146                                                   
147   // Step 0: Contribute to the voxelisation of    
148   G4GeometryManager* geomManager = G4GeometryM    
149   if( geomManager->IsParallelOptimisationConfi    
150     G4cout << "G4RunManager::InitializeGeometr    
151            << G4endl;  // TODO - suppress / de    
152     geomManager->UndertakeOptimisation();         
153   }                                               
154   //  A barrier must ensure that all that all     
155   //  Currently we rely on the (later) barrier    
156                                                   
157   // Step1: Get pointer to the physiWorld (not    
158   // pointer, i.e. the one shared by all threa    
159   G4RunManagerKernel* masterKernel = G4MTRunMa    
160   G4VPhysicalVolume* worldVol = masterKernel->    
161   // Step2:, Call a new "WorkerDefineWorldVolu    
162   kernel->WorkerDefineWorldVolume(worldVol, fa    
163   kernel->SetNumberOfParallelWorld(masterKerne    
164   // Step3: Call user's ConstructSDandField()     
165   userDetector->ConstructSDandField();            
166   userDetector->ConstructParallelSD();            
167   geometryInitialized = true;                     
168 }                                                 
169                                                   
170 // -------------------------------------------    
171 void G4WorkerRunManager::RunInitialization()      
172 {                                                 
173 #ifdef G4MULTITHREADED                            
174   if (!visIsSetUp) {                              
175     G4VVisManager* pVVis = G4VVisManager::GetC    
176     if (pVVis != nullptr) {                       
177       pVVis->SetUpForAThread();                   
178       visIsSetUp = true;                          
179     }                                             
180   }                                               
181 #endif                                            
182                                                   
183   if (!(kernel->RunInitialization(fakeRun))) r    
184                                                   
185   // Signal this thread can start event loop.     
186   // Note this will return only when all threa    
187   G4MTRunManager::GetMasterRunManager()->ThisW    
188   if (fakeRun) return;                            
189                                                   
190   const G4UserWorkerInitialization* uwi =         
191     G4MTRunManager::GetMasterRunManager()->Get    
192   CleanUpPreviousEvents();                        
193   delete currentRun;                              
194   currentRun = nullptr;                           
195                                                   
196   if (fGeometryHasBeenDestroyed) G4ParallelWor    
197   // Call a user hook: this is guaranteed all     
198   if (uwi != nullptr) uwi->WorkerRunStart();      
199                                                   
200   if (userRunAction != nullptr) currentRun = u    
201   if (currentRun == nullptr) currentRun = new     
202                                                   
203   currentRun->SetRunID(runIDCounter);             
204   currentRun->SetNumberOfEventToBeProcessed(nu    
205                                                   
206   currentRun->SetDCtable(DCtable);                
207   G4SDManager* fSDM = G4SDManager::GetSDMpoint    
208   if (fSDM != nullptr) {                          
209     currentRun->SetHCtable(fSDM->GetHCtable())    
210   }                                               
211                                                   
212   if (G4VScoreNtupleWriter::Instance() != null    
213     auto hce = (fSDM != nullptr) ? fSDM->Prepa    
214     isScoreNtupleWriter = G4VScoreNtupleWriter    
215     delete hce;                                   
216   }                                               
217                                                   
218   std::ostringstream oss;                         
219   G4Random::saveFullState(oss);                   
220   randomNumberStatusForThisRun = oss.str();       
221   currentRun->SetRandomNumberStatus(randomNumb    
222                                                   
223   for (G4int i_prev = 0; i_prev < n_perviousEv    
224     previousEvents->push_back(nullptr);           
225   }                                               
226                                                   
227   if (printModulo > 0 || verboseLevel > 0) {      
228     G4cout << "### Run " << currentRun->GetRun    
229            << G4Threading::G4GetThreadId() <<     
230   }                                               
231   if (userRunAction != nullptr) userRunAction-    
232                                                   
233   if (isScoreNtupleWriter) {                      
234     G4VScoreNtupleWriter::Instance()->OpenFile    
235   }                                               
236                                                   
237   if (storeRandomNumberStatus) {                  
238     G4String fileN = "currentRun";                
239     if (rngStatusEventsFlag) {                    
240       std::ostringstream os;                      
241       os << "run" << currentRun->GetRunID();      
242       fileN = os.str();                           
243     }                                             
244     StoreRNGStatus(fileN);                        
245   }                                               
246                                                   
247   runAborted = false;                             
248   numberOfEventProcessed = 0;                     
249 }                                                 
250                                                   
251 // -------------------------------------------    
252 void G4WorkerRunManager::DoEventLoop(G4int n_e    
253 {                                                 
254   if (userPrimaryGeneratorAction == nullptr) {    
255     G4Exception("G4RunManager::GenerateEvent()    
256                 "G4VUserPrimaryGeneratorAction    
257   }                                               
258                                                   
259   // This is the same as in the sequential cas    
260   // different                                    
261   InitializeEventLoop(n_event, macroFile, n_se    
262                                                   
263   // Reset random number seeds queue              
264   while (!seedsQueue.empty()) {                   
265     seedsQueue.pop();                             
266   }                                               
267   // for each run, worker should receive at le    
268   // seeds.                                       
269   runIsSeeded = false;                            
270                                                   
271   // Event loop                                   
272   eventLoopOnGoing = true;                        
273   ///////    G4int i_event = workerContext->Ge    
274   G4int i_event = -1;                             
275   nevModulo = -1;                                 
276   currEvID = -1;                                  
277                                                   
278   while (eventLoopOnGoing) {                      
279     ProcessOneEvent(i_event);                     
280     if (eventLoopOnGoing) {                       
281       TerminateOneEvent();                        
282       if (runAborted) {                           
283         eventLoopOnGoing = false;                 
284       }                                           
285     }                                             
286   }                                               
287                                                   
288   TerminateEventLoop();                           
289 }                                                 
290                                                   
291 // -------------------------------------------    
292 void G4WorkerRunManager::ProcessOneEvent(G4int    
293 {                                                 
294   currentEvent = GenerateEvent(i_event);          
295   if (eventLoopOnGoing) {                         
296     eventManager->ProcessOneEvent(currentEvent    
297     AnalyzeEvent(currentEvent);                   
298     UpdateScoring();                              
299     if (currentEvent->GetEventID() < n_select_    
300       G4UImanager::GetUIpointer()->ApplyComman    
301   }                                               
302 }                                                 
303                                                   
304 // -------------------------------------------    
305 G4Event* G4WorkerRunManager::GenerateEvent(G4i    
306 {                                                 
307   auto anEvent = new G4Event(i_event);            
308   G4long s1 = 0;                                  
309   G4long s2 = 0;                                  
310   G4long s3 = 0;                                  
311   G4bool eventHasToBeSeeded = true;               
312   if (G4MTRunManager::SeedOncePerCommunication    
313     eventHasToBeSeeded = false;                   
314   }                                               
315                                                   
316   if (i_event < 0) {                              
317     G4int nevM = G4MTRunManager::GetMasterRunM    
318     if (nevM == 1) {                              
319       eventLoopOnGoing = G4MTRunManager::GetMa    
320                                                   
321       runIsSeeded = true;                         
322     }                                             
323     else {                                        
324       if (nevModulo <= 0) {                       
325         G4int nevToDo = G4MTRunManager::GetMas    
326                                                   
327         if (nevToDo == 0) {                       
328           eventLoopOnGoing = false;               
329         }                                         
330         else {                                    
331           currEvID = anEvent->GetEventID();       
332           nevModulo = nevToDo - 1;                
333         }                                         
334       }                                           
335       else {                                      
336         if (G4MTRunManager::SeedOncePerCommuni    
337         anEvent->SetEventID(++currEvID);          
338         --nevModulo;                              
339       }                                           
340       if (eventLoopOnGoing && eventHasToBeSeed    
341         s1 = seedsQueue.front();                  
342         seedsQueue.pop();                         
343         s2 = seedsQueue.front();                  
344         seedsQueue.pop();                         
345       }                                           
346     }                                             
347                                                   
348     if (!eventLoopOnGoing) {                      
349       delete anEvent;                             
350       return nullptr;                             
351     }                                             
352   }                                               
353   else if (eventHasToBeSeeded) {                  
354     // Need to reseed random number generator     
355     G4RNGHelper* helper = G4RNGHelper::GetInst    
356     s1 = helper->GetSeed(i_event * 2);            
357     s2 = helper->GetSeed(i_event * 2 + 1);        
358   }                                               
359                                                   
360   if (eventHasToBeSeeded) {                       
361     G4long seeds[3] = {s1, s2, 0};                
362     G4Random::setTheSeeds(seeds, luxury);         
363     runIsSeeded = true;                           
364   }                                               
365                                                   
366   // Read from file seed.                         
367   // Andrea Dotti 4 November 2015                 
368   // This is required for strong-reproducibili    
369   // thread produces, for each event a status     
370   // Search a random file with the format run{    
371                                                   
372   // This is the filename base constructed fro    
373   const auto filename = [&] {                     
374     std::ostringstream os;                        
375     os << "run" << currentRun->GetRunID() << "    
376     return os.str();                              
377   };                                              
378                                                   
379   G4bool RNGstatusReadFromFile = false;           
380   if (readStatusFromFile) {                       
381     // Build full path of RNG status file for     
382     std::ostringstream os;                        
383     os << filename() << ".rndm";                  
384     const G4String& randomStatusFile = os.str(    
385     std::ifstream ifile(randomStatusFile.c_str    
386     if (ifile) {  // File valid and readable      
387       RNGstatusReadFromFile = true;               
388       G4Random::restoreEngineStatus(randomStat    
389     }                                             
390   }                                               
391                                                   
392   if (storeRandomNumberStatusToG4Event == 1 ||    
393     std::ostringstream oss;                       
394     G4Random::saveFullState(oss);                 
395     randomNumberStatusForThisEvent = oss.str()    
396     anEvent->SetRandomNumberStatus(randomNumbe    
397   }                                               
398                                                   
399   if (storeRandomNumberStatus && !RNGstatusRea    
400   {  // If reading from file, avoid to rewrite    
401     G4String fileN = "currentEvent";              
402     if (rngStatusEventsFlag) {                    
403       fileN = filename();                         
404     }                                             
405     StoreRNGStatus(fileN);                        
406   }                                               
407                                                   
408   if (printModulo > 0 && anEvent->GetEventID()    
409     G4cout << "--> Event " << anEvent->GetEven    
410     if (eventHasToBeSeeded) {                     
411       G4cout << " with initial seeds (" << s1     
412     }                                             
413     G4cout << "." << G4endl;                      
414   }                                               
415   userPrimaryGeneratorAction->GeneratePrimarie    
416   return anEvent;                                 
417 }                                                 
418                                                   
419 // -------------------------------------------    
420 void G4WorkerRunManager::MergePartialResults(G    
421 {                                                 
422   // Merge partial results into global run        
423   G4MTRunManager* mtRM = G4MTRunManager::GetMa    
424   G4ScoringManager* ScM = G4ScoringManager::Ge    
425   if (ScM != nullptr) mtRM->MergeScores(ScM);     
426 #ifdef G4VERBOSE                                  
427   if(mergeEvents && verboseLevel>3) {             
428     auto eventVector = currentRun->GetEventVec    
429     if(eventVector!=nullptr || !(eventVector->    
430       G4cout<<"G4WorkerRunManager::MergePartia    
431             <<eventVector->size()<<" events."<    
432     }                                             
433   }                                               
434 #endif                                            
435   if(mergeEvents) mtRM->MergeRun(currentRun);     
436 }                                                 
437                                                   
438 // -------------------------------------------    
439 void G4WorkerRunManager::RunTermination()         
440 {                                                 
441   if (!fakeRun) {                                 
442     MergePartialResults();                        
443                                                   
444     // Call a user hook: note this is before t    
445     // so threads execute this method asyncrho    
446     //(TerminateRun allows for synch via G4Run    
447     const G4UserWorkerInitialization* uwi =       
448       G4MTRunManager::GetMasterRunManager()->G    
449     if (uwi != nullptr) uwi->WorkerRunEnd();      
450   }                                               
451                                                   
452   G4RunManager::RunTermination();                 
453   // Signal this thread has finished envent-lo    
454   // Note this will return only whan all threa    
455   G4MTRunManager::GetMasterRunManager()->ThisW    
456 }                                                 
457                                                   
458 // -------------------------------------------    
459 void G4WorkerRunManager::TerminateEventLoop()     
460 {                                                 
461   if (verboseLevel > 0 && !fakeRun) {             
462     timer->Stop();                                
463     G4cout << "Thread-local run terminated." <    
464     G4cout << "Run Summary" << G4endl;            
465     if (runAborted) {                             
466       G4cout << "  Run Aborted after " << numb    
467     }                                             
468     else {                                        
469       G4cout << "  Number of events processed     
470     }                                             
471     G4cout << "  " << *timer << G4endl;           
472   }                                               
473 }                                                 
474                                                   
475 // -------------------------------------------    
476 namespace                                         
477 {                                                 
478 G4Mutex ConstructScoringWorldsMutex = G4MUTEX_    
479 }                                                 
480                                                   
481 // -------------------------------------------    
482 void G4WorkerRunManager::ConstructScoringWorld    
483 {                                                 
484   using MeshShape = G4VScoringMesh::MeshShape;    
485                                                   
486   // Return if unnecessary                        
487   G4ScoringManager* ScM = G4ScoringManager::Ge    
488   if (ScM == nullptr) return;                     
489   auto nPar = (G4int)ScM->GetNumberOfMesh();      
490   if (nPar < 1) return;                           
491                                                   
492   // Update thread-local G4TransportationManag    
493   kernel->WorkerUpdateWorldVolume();              
494                                                   
495   G4ScoringManager* masterScM = G4MTRunManager    
496                                                   
497   auto particleIterator = G4ParticleTable::Get    
498                                                   
499   for (G4int iw = 0; iw < nPar; ++iw) {           
500     G4VScoringMesh* mesh = ScM->GetMesh(iw);      
501     if (fGeometryHasBeenDestroyed) mesh->Geome    
502     G4VPhysicalVolume* pWorld = nullptr;          
503     if (mesh->GetShape() != MeshShape::realWor    
504       pWorld =                                    
505         G4TransportationManager::GetTransporta    
506       if (pWorld == nullptr) {                    
507         G4ExceptionDescription ed;                
508         ed << "Mesh name <" << ScM->GetWorldNa    
509         G4Exception("G4WorkerRunManager::Const    
510       }                                           
511     }                                             
512     if ((mesh->GetMeshElementLogical()) == nul    
513       G4AutoLock l(&ConstructScoringWorldsMute    
514       G4VScoringMesh* masterMesh = masterScM->    
515       mesh->SetMeshElementLogical(masterMesh->    
516       l.unlock();                                 
517                                                   
518       if (mesh->GetShape() != MeshShape::realW    
519         G4ParallelWorldProcess* theParallelWor    
520         if (theParallelWorldProcess != nullptr    
521           theParallelWorldProcess->SetParallel    
522         }                                         
523         else {                                    
524           theParallelWorldProcess = new G4Para    
525           mesh->SetParallelWorldProcess(thePar    
526           theParallelWorldProcess->SetParallel    
527                                                   
528           particleIterator->reset();              
529           while ((*particleIterator)()) {         
530             G4ParticleDefinition* particle = p    
531             G4ProcessManager* pmanager = parti    
532             if (pmanager != nullptr) {            
533               pmanager->AddProcess(theParallel    
534               if (theParallelWorldProcess->IsA    
535                 pmanager->SetProcessOrdering(t    
536               }                                   
537               pmanager->SetProcessOrderingToSe    
538               pmanager->SetProcessOrdering(the    
539             }  // if(pmanager)                    
540           }  // while                             
541         }                                         
542         theParallelWorldProcess->SetLayeredMat    
543       }                                           
544     }                                             
545     mesh->WorkerConstruct(pWorld);                
546   }                                               
547 }                                                 
548                                                   
549 // -------------------------------------------    
550 void G4WorkerRunManager::SetUserInitialization    
551 {                                                 
552   G4Exception("G4RunManager::SetUserInitializa    
553               FatalException, "This method sho    
554 }                                                 
555                                                   
556 // -------------------------------------------    
557 void G4WorkerRunManager::SetUserInitialization    
558 {                                                 
559   G4Exception("G4RunManager::SetUserInitializa    
560               FatalException, "This method sho    
561 }                                                 
562                                                   
563 // -------------------------------------------    
564 void G4WorkerRunManager::SetUserInitialization    
565 {                                                 
566   G4Exception("G4RunManager::SetUserInitializa    
567               FatalException, "This method sho    
568 }                                                 
569                                                   
570 // -------------------------------------------    
571 void G4WorkerRunManager::SetUserInitialization    
572 {                                                 
573   G4Exception("G4RunManager::SetUserInitializa    
574               FatalException, "This method sho    
575 }                                                 
576                                                   
577 // -------------------------------------------    
578 void G4WorkerRunManager::SetUserInitialization    
579 {                                                 
580   pl->InitializeWorker();                         
581   G4RunManager::SetUserInitialization(pl);        
582 }                                                 
583                                                   
584 // -------------------------------------------    
585 void G4WorkerRunManager::SetUserAction(G4UserR    
586 {                                                 
587   G4RunManager::SetUserAction(userAction);        
588   if (userAction != nullptr) userAction->SetMa    
589 }                                                 
590                                                   
591 // -------------------------------------------    
592 void G4WorkerRunManager::SetupDefaultRNGEngine    
593 {                                                 
594   const CLHEP::HepRandomEngine* mrnge =           
595     G4MTRunManager::GetMasterRunManager()->get    
596   const G4UserWorkerThreadInitialization* uwti    
597     G4MTRunManager::GetMasterRunManager()->Get    
598   uwti->SetupRNGEngine(mrnge);                    
599 }                                                 
600                                                   
601 // Forward calls (avoid GCC compilation warnin    
602                                                   
603 // -------------------------------------------    
604 void G4WorkerRunManager::SetUserAction(G4UserE    
605 {                                                 
606   G4RunManager::SetUserAction(ua);                
607 }                                                 
608                                                   
609 // -------------------------------------------    
610 void G4WorkerRunManager::SetUserAction(G4VUser    
611 {                                                 
612   G4RunManager::SetUserAction(ua);                
613 }                                                 
614                                                   
615 // -------------------------------------------    
616 void G4WorkerRunManager::SetUserAction(G4UserS    
617 {                                                 
618   G4RunManager::SetUserAction(ua);                
619 }                                                 
620                                                   
621 // -------------------------------------------    
622 void G4WorkerRunManager::SetUserAction(G4UserT    
623 {                                                 
624   G4RunManager::SetUserAction(ua);                
625 }                                                 
626                                                   
627 // -------------------------------------------    
628 void G4WorkerRunManager::SetUserAction(G4UserS    
629 {                                                 
630   G4RunManager::SetUserAction(ua);                
631 }                                                 
632                                                   
633 // -------------------------------------------    
634 void G4WorkerRunManager::StoreRNGStatus(const     
635 {                                                 
636   std::ostringstream os;                          
637   os << randomNumberStatusDir << "G4Worker" <<    
638   G4Random::saveEngineStatus(os.str().c_str())    
639 }                                                 
640                                                   
641 // -------------------------------------------    
642 void G4WorkerRunManager::rndmSaveThisRun()        
643 {                                                 
644   G4int runNumber = 0;                            
645   if (currentRun != nullptr) runNumber = curre    
646   if (!storeRandomNumberStatus) {                 
647     G4cerr << "Warning from G4RunManager::rndm    
648            << " Random number status was not s    
649            << "/random/setSavingFlag command m    
650            << "Command ignored." << G4endl;       
651     return;                                       
652   }                                               
653                                                   
654   std::ostringstream oos;                         
655   oos << "G4Worker" << workerContext->GetThrea    
656       << "currentRun.rndm"                        
657       << "\0";                                    
658   G4fs::path fileIn = randomNumberStatusDir +     
659                                                   
660   std::ostringstream os;                          
661   os << "run" << runNumber << ".rndm" << '\0';    
662   G4fs::path fileOut = randomNumberStatusDir +    
663                                                   
664   if (G4CopyRandomState(fileIn, fileOut, "G4Wo    
665       && verboseLevel > 0)                        
666   {                                               
667     G4cout << fileIn << " is copied to " << fi    
668   }                                               
669 }                                                 
670                                                   
671 // -------------------------------------------    
672 void G4WorkerRunManager::rndmSaveThisEvent()      
673 {                                                 
674   if (currentEvent == nullptr) {                  
675     G4cerr << "Warning from G4RunManager::rndm    
676            << " there is no currentEvent avail    
677     return;                                       
678   }                                               
679                                                   
680   if (!storeRandomNumberStatus) {                 
681     G4cerr << "Warning from G4RunManager::rndm    
682            << " Random number engine status is    
683            << "/random/setSavingFlag command m    
684            << "prior to the start of the run.     
685     return;                                       
686   }                                               
687                                                   
688   std::ostringstream oos;                         
689   oos << "G4Worker" << workerContext->GetThrea    
690       << "currentEvent.rndm"                      
691       << "\0";                                    
692   G4fs::path fileIn = randomNumberStatusDir +     
693                                                   
694   std::ostringstream os;                          
695   os << "run" << currentRun->GetRunID() << "ev    
696   G4fs::path fileOut = randomNumberStatusDir +    
697                                                   
698   if (G4CopyRandomState(fileIn, fileOut, "G4Wo    
699       && verboseLevel > 0)                        
700   {                                               
701     G4cout << fileIn << " is copied to " << fi    
702   }                                               
703 }                                                 
704                                                   
705 // -------------------------------------------    
706 void G4WorkerRunManager::DoWork()                 
707 {                                                 
708   G4MTRunManager* mrm = G4MTRunManager::GetMas    
709   G4MTRunManager::WorkerActionRequest nextActi    
710   while (nextAction != G4MTRunManager::WorkerA    
711     if (nextAction == G4MTRunManager::WorkerAc    
712                                                   
713     {                                             
714       // The following code deals with changin    
715       static G4ThreadLocal G4bool skipInitiali    
716       if (skipInitialization) {                   
717         // re-initialization is not necessary     
718         skipInitialization = false;               
719       }                                           
720       else {                                      
721         //        ReinitializeGeometry();         
722         workerContext->UpdateGeometryAndPhysic    
723       }                                           
724                                                   
725       // Execute UI commands stored in the mas    
726       std::vector<G4String> cmds = mrm->GetCom    
727       G4UImanager* uimgr = G4UImanager::GetUIp    
728       for (const auto& cmd : cmds) {              
729         uimgr->ApplyCommand(cmd);                 
730       }                                           
731       // Start this run                           
732       G4int numevents = mrm->GetNumberOfEvents    
733       G4String macroFile = mrm->GetSelectMacro    
734       G4int numSelect = mrm->GetNumberOfSelect    
735       if (macroFile.empty() || macroFile == "     
736         this->BeamOn(numevents);                  
737       }                                           
738       else {                                      
739         this->BeamOn(numevents, macroFile, num    
740       }                                           
741     }                                             
742     else if (nextAction == G4MTRunManager::Wor    
743       std::vector<G4String> cmds = mrm->GetCom    
744       G4UImanager* uimgr = G4UImanager::GetUIp    
745       for (const auto& cmd : cmds) {              
746         uimgr->ApplyCommand(cmd);                 
747       }                                           
748       mrm->ThisWorkerProcessCommandsStackDone(    
749     }                                             
750     else {                                        
751       G4ExceptionDescription d;                   
752       d << "Cannot continue, this worker has b    
753         << static_cast<std::underlying_type<G4    
754       G4Exception("G4WorkerRunManager::DoWork"    
755     }                                             
756                                                   
757     // Now wait for master thread to signal ne    
758     nextAction = mrm->ThisWorkerWaitForNextAct    
759   }  // No more actions to perform                
760                                                   
761   return;                                         
762 }                                                 
763