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 10.6.p3)


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