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