Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4WorkerTaskRunManager.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27
29#include "G4MTRunManager.hh"
31#include "G4RNGHelper.hh"
32#include "G4Run.hh"
33#include "G4SDManager.hh"
34#include "G4ScoringManager.hh"
35#include "G4TiMemory.hh"
36#include "G4Timer.hh"
38#include "G4UImanager.hh"
39#include "G4UserRunAction.hh"
43#include "G4VScoringMesh.hh"
46#include "G4VUserPhysicsList.hh"
48#include "G4VVisManager.hh"
50#include "G4WorkerThread.hh"
51#include "G4AutoLock.hh"
53#include "G4TaskRunManager.hh"
54
55#include <fstream>
56#include <sstream>
57
58// namespace
59// {
60// G4Mutex ConstructScoringWorldsMutex;
61// }
62
63//============================================================================//
64
66{
68}
69
70//============================================================================//
71
74{
75 return static_cast<G4WorkerTaskRunManagerKernel*>(
77}
78
79//============================================================================//
80
83{}
84
85//============================================================================//
86
88{
89#ifdef G4MULTITHREADED
90 if(!visIsSetUp)
91 {
93 if(pVVis)
94 {
95 pVVis->SetUpForAThread();
96 visIsSetUp = true;
97 }
98 }
99#endif
100 runIsSeeded = false;
101
103 return;
104
105 // Signal this thread can start event loop.
106 // Note this will return only when all threads reach this point
108 if(fakeRun)
109 return;
110
111 const G4UserWorkerInitialization* uwi =
113
115 if(currentRun)
116 delete currentRun;
117
118 currentRun = nullptr;
119
122
123 // Call a user hook: this is guaranteed all threads are "synchronized"
124 if(uwi)
125 uwi->WorkerRunStart();
126
127 if(userRunAction)
129 if(!currentRun)
130 currentRun = new G4Run();
131
136
139 if(fSDM != nullptr)
140 {
142 }
143
145 {
146 auto hce = (fSDM != nullptr) ? fSDM->PrepareNewEvent() : nullptr;
148 delete hce;
149 }
150
151 std::ostringstream oss;
152 G4Random::saveFullState(oss);
155
156 for(G4int i_prev = 0; i_prev < n_perviousEventsToBeStored; ++i_prev)
157 previousEvents->push_back(nullptr);
158
159 if(printModulo > 0 || verboseLevel > 0)
160 {
161 G4cout << "### Run " << currentRun->GetRunID()
162 << " starts on worker thread " << G4Threading::G4GetThreadId() << "."
163 << G4endl;
164 }
165
166 if(userRunAction)
168
169#if defined(GEANT4_USE_TIMEMORY)
170 workerRunProfiler.reset(new ProfilerConfig(currentRun));
171#endif
172
174 {
176 }
177
179 {
180 G4String fileN = "currentRun";
182 {
183 std::ostringstream os;
184 os << "run" << currentRun->GetRunID();
185 fileN = os.str();
186 }
187 StoreRNGStatus(fileN);
188 }
189
190 runAborted = false;
192}
193
194//============================================================================//
195
196void G4WorkerTaskRunManager::DoEventLoop(G4int n_event, const char* macroFile,
197 G4int n_select)
198{
200 {
201 G4Exception("G4RunManager::GenerateEvent()", "Run0032", FatalException,
202 "G4VUserPrimaryGeneratorAction is not defined!");
203 }
204
205 // This is the same as in the sequential case, just the for-loop indexes are
206 // different
207 InitializeEventLoop(n_event, macroFile, n_select);
208
209 // Reset random number seeds queue
210 while(seedsQueue.size() > 0)
211 seedsQueue.pop();
212 // for each run, worker should receive at least one set of random number
213 // seeds.
214 // runIsSeeded = false;
215
216 // Event loop
217 eventLoopOnGoing = true;
218 G4int i_event = -1;
219 nevModulo = -1;
220 currEvID = -1;
221
222 for(G4int evt = 0; evt < n_event; ++evt)
223 {
224 ProcessOneEvent(i_event);
226 {
228 if(runAborted)
229 eventLoopOnGoing = false;
230 }
232 break;
233 }
234
235 // TerminateEventLoop();
236}
237
238//============================================================================//
239
241{
242 currentEvent = GenerateEvent(i_event);
244 {
249 {
250 G4cout << "Applying command \"" << msgText << "\" @ " << __FUNCTION__
251 << ":" << __LINE__ << G4endl;
253 }
254 }
255}
256
257//============================================================================//
258
260{
261 G4Event* anEvent = new G4Event(i_event);
262 long s1 = 0;
263 long s2 = 0;
264 long s3 = 0;
265 G4bool eventHasToBeSeeded = true;
267 eventHasToBeSeeded = false;
268
269 if(i_event < 0)
270 {
272 if(nevM == 1)
273 {
275 anEvent, s1, s2, s3, eventHasToBeSeeded);
276 runIsSeeded = true;
277 }
278 else
279 {
280 if(nevModulo <= 0)
281 {
283 anEvent, &seedsQueue, eventHasToBeSeeded);
284 if(nevToDo == 0)
285 eventLoopOnGoing = false;
286 else
287 {
288 currEvID = anEvent->GetEventID();
289 nevModulo = nevToDo - 1;
290 }
291 }
292 else
293 {
295 eventHasToBeSeeded = false;
296 anEvent->SetEventID(++currEvID);
297 nevModulo--;
298 }
299 if(eventLoopOnGoing && eventHasToBeSeeded)
300 {
301 s1 = seedsQueue.front();
302 seedsQueue.pop();
303 s2 = seedsQueue.front();
304 seedsQueue.pop();
305 }
306 }
307
309 {
310 delete anEvent;
311 return nullptr;
312 }
313 }
314 else if(eventHasToBeSeeded)
315 {
316 // Need to reseed random number generator
318 s1 = helper->GetSeed(i_event * 2);
319 s2 = helper->GetSeed(i_event * 2 + 1);
320 }
321
322 if(eventHasToBeSeeded)
323 {
324 long seeds[3] = { s1, s2, 0 };
325 G4Random::setTheSeeds(seeds, -1);
326 runIsSeeded = true;
327 ////G4cout<<"Event "<<currEvID<<" is seeded with { "<<s1<<", "<<s2<<"
328 ///}"<<G4endl;
329 }
330
331 // Read from file seed.
332 // Andrea Dotti 4 November 2015
333 // This is required for strong-reproducibility, in MT mode we have that each
334 // thread produces, for each event a status file, we want to do that.
335 // Search a random file with the format run{%d}evt{%d}.rndm
336
337 // This is the filename base constructed from run and event
338 const auto filename = [&] {
339 std::ostringstream os;
340 os << "run" << currentRun->GetRunID() << "evt" << anEvent->GetEventID();
341 return os.str();
342 };
343
344 G4bool RNGstatusReadFromFile = false;
346 {
347 // Build full path of RNG status file for this event
348 std::ostringstream os;
349 os << filename() << ".rndm";
350 const G4String& randomStatusFile = os.str();
351 std::ifstream ifile(randomStatusFile.c_str());
352 if(ifile)
353 {
354 // File valid and readable
355 RNGstatusReadFromFile = true;
356 G4Random::restoreEngineStatus(randomStatusFile.c_str());
357 }
358 }
359
362 {
363 std::ostringstream oss;
364 G4Random::saveFullState(oss);
367 }
368
369 if(storeRandomNumberStatus && !RNGstatusReadFromFile)
370 {
371 // If reading from file, avoid to rewrite the same
372 G4String fileN = "currentEvent";
374 fileN = filename();
375 StoreRNGStatus(fileN);
376 }
377
378 if(printModulo > 0 && anEvent->GetEventID() % printModulo == 0)
379 {
380 G4cout << "--> Event " << anEvent->GetEventID() << " starts";
381 if(eventHasToBeSeeded)
382 G4cout << " with initial seeds (" << s1 << "," << s2 << ")";
383 G4cout << "." << G4endl;
384 }
386 return anEvent;
387}
388
389//============================================================================//
390
392{
393 if(!fakeRun && currentRun)
394 {
395#if defined(GEANT4_USE_TIMEMORY)
396 workerRunProfiler.reset();
397#endif
399
400 // Call a user hook: note this is before the next barrier
401 // so threads execute this method asyncrhonouzly
402 //(TerminateRun allows for synch via G4RunAction::EndOfRun)
403 const G4UserWorkerInitialization* uwi =
405 if(uwi)
406 uwi->WorkerRunEnd();
407 }
408
409 if(currentRun)
410 {
412 }
413 // Signal this thread has finished envent-loop.
414 // Note this will return only whan all threads reach this point
416}
417
418//============================================================================//
419
421{
422 if(verboseLevel > 0 && !fakeRun)
423 {
424 timer->Stop();
425 // prefix with thread # info due to how TBB calls this function
427 "[thread " + std::to_string(workerContext->GetThreadId()) + "] ";
428 G4cout << prefix << "Thread-local run terminated." << G4endl;
429 G4cout << prefix << "Run Summary" << G4endl;
430 if(runAborted)
431 G4cout << prefix << " Run Aborted after " << numberOfEventProcessed
432 << " events processed." << G4endl;
433 else
434 G4cout << prefix
435 << " Number of events processed : " << numberOfEventProcessed
436 << G4endl;
437 G4cout << prefix << " " << *timer << G4endl;
438 }
439}
440
441//============================================================================//
442
443void G4WorkerTaskRunManager::SetupDefaultRNGEngine()
444{
445 const CLHEP::HepRandomEngine* mrnge =
447 assert(mrnge); // Master has created RNG
450 uwti->SetupRNGEngine(mrnge);
451}
452
453//============================================================================//
454
456{
457 std::ostringstream os;
458 os << randomNumberStatusDir << "G4Worker" << workerContext->GetThreadId()
459 << "_" << fn << ".rndm";
460 G4Random::saveEngineStatus(os.str().c_str());
461}
462
463//============================================================================//
464
466{
468 if(!mrm)
469 return;
470
471 //------------------------------------------------------------------------//
472 // Check UI commands not already processed
473 auto command_stack = mrm->GetCommandStack();
474 bool matching = (command_stack.size() == processedCommandStack.size());
475 if(matching)
476 {
477 for(uintmax_t i = 0; i < command_stack.size(); ++i)
478 if(processedCommandStack.at(i) != command_stack.at(i))
479 {
480 matching = false;
481 break;
482 }
483 }
484
485 //------------------------------------------------------------------------//
486 // Execute UI commands stored in the master UI manager
487 if(!matching)
488 {
489 for(const auto& itr : command_stack)
491 processedCommandStack = command_stack;
492 }
493}
494
495//============================================================================//
496
498{
500 if(currentRun)
501 delete currentRun;
502 currentRun = nullptr;
503}
504
505//============================================================================//
506
508{
510 G4bool newRun = false;
511 const G4Run* run = mrm->GetCurrentRun();
512 G4ThreadLocalStatic G4int runId = -1;
513 if(run && run->GetRunID() != runId)
514 {
515 runId = run->GetRunID();
516 newRun = true;
517 if(runId > 0)
518 {
519 ProcessUI();
520 assert(workerContext != nullptr);
521 }
523 }
524
525 // Start this run
527 G4int numSelect = mrm->GetNumberOfSelectEvents();
528 G4String macroFile = mrm->GetSelectMacro();
529 bool empty_macro = (macroFile == "" || macroFile == " ");
530
531 const char* macro = (empty_macro) ? nullptr : macroFile.c_str();
532 numSelect = (empty_macro) ? -1 : numSelect;
533
534 if(newRun)
535 {
537 if(cond)
538 {
541 }
542 }
543 DoEventLoop(nevts, macro, numSelect);
544}
545
546//============================================================================//
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
void ProcessOneEvent(G4Event *anEvent)
void SetRandomNumberStatus(G4String &st)
Definition: G4Event.hh:90
G4int GetEventID() const
Definition: G4Event.hh:118
void SetEventID(G4int i)
Definition: G4Event.hh:80
static G4int SeedOncePerCommunication()
virtual G4int SetUpNEvents(G4Event *, G4SeedsQueue *seedsQueue, G4bool reseedRequired=true)
virtual G4bool SetUpAnEvent(G4Event *, long &s1, long &s2, long &s3, G4bool reseedRequired=true)
const CLHEP::HepRandomEngine * getMasterRandomEngine() const
virtual void ThisWorkerReady()
G4int GetEventModulo() const
static G4MTRunManager * GetMasterRunManager()
std::vector< G4String > GetCommandStack()
virtual void ThisWorkerEndEventLoop()
static G4ParallelWorldProcessStore * GetInstance()
G4bool RunInitialization(G4bool fakeRun=false)
G4bool isScoreNtupleWriter
void CleanUpPreviousEvents()
G4int storeRandomNumberStatusToG4Event
const G4UserWorkerInitialization * GetUserWorkerInitialization() const
std::list< G4Event * > * previousEvents
G4Timer * timer
G4int n_select_msg
G4int numberOfEventProcessed
G4int GetNumberOfEventsToBeProcessed() const
virtual void InitializeEventLoop(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1)
G4int runIDCounter
G4RunManagerKernel * kernel
G4int verboseLevel
G4Run * currentRun
virtual G4bool ConfirmBeamOnCondition()
static G4RunManager * GetRunManager()
G4DCtable * DCtable
G4String randomNumberStatusForThisRun
G4bool runAborted
G4String msgText
static G4bool IfGeometryHasBeenDestroyed()
G4UserRunAction * userRunAction
G4bool rngStatusEventsFlag
virtual void RunTermination()
const G4String & GetSelectMacro() const
G4VUserPrimaryGeneratorAction * userPrimaryGeneratorAction
const G4Run * GetCurrentRun() const
G4int numberOfEventToBeProcessed
G4String randomNumberStatusDir
G4String randomNumberStatusForThisEvent
const G4UserWorkerThreadInitialization * GetUserWorkerThreadInitialization() const
G4int n_perviousEventsToBeStored
G4bool storeRandomNumberStatus
G4EventManager * eventManager
virtual void TerminateOneEvent()
G4int GetNumberOfSelectEvents() const
virtual void AnalyzeEvent(G4Event *anEvent)
void UpdateScoring()
G4Event * currentEvent
Definition: G4Run.hh:49
void SetHCtable(G4HCtable *HCtbl)
Definition: G4Run.hh:107
G4int GetRunID() const
Definition: G4Run.hh:78
void SetNumberOfEventToBeProcessed(G4int n_ev)
Definition: G4Run.hh:103
void SetRunID(G4int id)
Definition: G4Run.hh:102
void SetDCtable(G4DCtable *DCtbl)
Definition: G4Run.hh:108
void SetRandomNumberStatus(G4String &st)
Definition: G4Run.hh:109
G4HCofThisEvent * PrepareNewEvent()
Definition: G4SDManager.cc:113
static G4SDManager * GetSDMpointerIfExist()
Definition: G4SDManager.cc:47
G4HCtable * GetHCtable() const
Definition: G4SDManager.hh:101
static G4TaskRunManager * GetMasterRunManager()
static G4TemplateRNGHelper< T > * GetInstance()
Definition: G4RNGHelper.cc:42
virtual const T GetSeed(const G4int &sdId)
Definition: G4RNGHelper.hh:64
void Stop()
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:495
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:77
virtual void BeginOfRunAction(const G4Run *aRun)
virtual G4Run * GenerateRun()
virtual void SetupRNGEngine(const CLHEP::HepRandomEngine *aRNGEngine) const
virtual G4bool Book(G4HCofThisEvent *hce)=0
static G4VScoreNtupleWriter * Instance()
virtual void OpenFile()=0
virtual void GeneratePrimaries(G4Event *anEvent)=0
static G4VVisManager * GetConcreteInstance()
virtual void ConstructScoringWorlds()
virtual void MergePartialResults()
G4WorkerThread * workerContext
virtual void DoEventLoop(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1) override
virtual G4Event * GenerateEvent(G4int i_event) override
virtual void StoreRNGStatus(const G4String &filenamePrefix) override
virtual void RunTermination() override
virtual void TerminateEventLoop() override
virtual void DoWork() override
G4ProfilerConfig< G4ProfileType::Run > ProfilerConfig
virtual void ProcessOneEvent(G4int i_event) override
static G4WorkerTaskRunManagerKernel * GetWorkerRunManagerKernel()
virtual void RunInitialization() override
static G4WorkerTaskRunManager * GetWorkerRunManager()
G4int GetThreadId() const
static void UpdateGeometryAndPhysicsVectorFromMaster()
G4int G4GetThreadId()
Definition: G4Threading.cc:122
#define G4ThreadLocalStatic
Definition: tls.hh:76