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 << 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