Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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
30#include "G4AutoLock.hh"
31#include "G4MTRunManager.hh"
34#include "G4RNGHelper.hh"
35#include "G4Run.hh"
36#include "G4SDManager.hh"
37#include "G4ScoringManager.hh"
38#include "G4TaskRunManager.hh"
39#include "G4TiMemory.hh"
40#include "G4Timer.hh"
42#include "G4UImanager.hh"
43#include "G4UserRunAction.hh"
47#include "G4VScoringMesh.hh"
50#include "G4VUserPhysicsList.hh"
52#include "G4VVisManager.hh"
54#include "G4WorkerThread.hh"
55
56#include <fstream>
57#include <sstream>
58
59//============================================================================//
60
65
66//============================================================================//
67
72
73//============================================================================//
74
76{
77#ifdef G4MULTITHREADED
78 if (!visIsSetUp) {
80 if (pVVis != nullptr) {
81 pVVis->SetUpForAThread();
82 visIsSetUp = true;
83 }
84 }
85#endif
86 runIsSeeded = false;
87
88 if (!(kernel->RunInitialization(fakeRun))) return;
89
90 // Signal this thread can start event loop.
91 // Note this will return only when all threads reach this point
93 if (fakeRun) return;
94
97
99
100 delete currentRun;
101
102 currentRun = nullptr;
103
105
106 // Call a user hook: this is guaranteed all threads are "synchronized"
107 if (uwi != nullptr) uwi->WorkerRunStart();
108
110 if (currentRun == nullptr) currentRun = new G4Run();
111
116
119 if (fSDM != nullptr) {
121 }
122
123 if (G4VScoreNtupleWriter::Instance() != nullptr) {
124 auto hce = (fSDM != nullptr) ? fSDM->PrepareNewEvent() : nullptr;
126 delete hce;
127 }
128
129 std::ostringstream oss;
130 G4Random::saveFullState(oss);
133
134 for (G4int i_prev = 0; i_prev < n_perviousEventsToBeStored; ++i_prev)
135 previousEvents->push_back(nullptr);
136
137 if (printModulo > 0 || verboseLevel > 0) {
138 G4cout << "### Run " << currentRun->GetRunID() << " starts on worker thread "
139 << G4Threading::G4GetThreadId() << "." << G4endl;
140 }
141
143
144#if defined(GEANT4_USE_TIMEMORY)
145 workerRunProfiler.reset(new ProfilerConfig(currentRun));
146#endif
147
150 }
151
153 G4String fileN = "currentRun";
155 std::ostringstream os;
156 os << "run" << currentRun->GetRunID();
157 fileN = os.str();
158 }
159 StoreRNGStatus(fileN);
160 }
161
162 runAborted = false;
164}
165
166//============================================================================//
167
168void G4WorkerTaskRunManager::DoEventLoop(G4int n_event, const char* macroFile, G4int n_select)
169{
170 if (userPrimaryGeneratorAction == nullptr) {
171 G4Exception("G4RunManager::GenerateEvent()", "Run0032", FatalException,
172 "G4VUserPrimaryGeneratorAction is not defined!");
173 }
174
175 // This is the same as in the sequential case, just the for-loop indexes are
176 // different
177 InitializeEventLoop(n_event, macroFile, n_select);
178
179 // Reset random number seeds queue
180 while (!seedsQueue.empty())
181 seedsQueue.pop();
182 // for each run, worker should receive at least one set of random number
183 // seeds.
184 // runIsSeeded = false;
185
186 // Event loop
187 eventLoopOnGoing = true;
188 G4int i_event = -1;
189 nevModulo = -1;
190 currEvID = -1;
191
192 for (G4int evt = 0; evt < n_event; ++evt) {
193 ProcessOneEvent(i_event);
194 if (eventLoopOnGoing) {
196 if (runAborted) eventLoopOnGoing = false;
197 }
198 if (!eventLoopOnGoing) break;
199 }
200}
201
202//============================================================================//
203
205{
206 currentEvent = GenerateEvent(i_event);
207 if (eventLoopOnGoing) {
212 G4cout << "Applying command \"" << msgText << "\" @ " << __FUNCTION__ << ":" << __LINE__
213 << G4endl;
215 }
216 }
217}
218
219//============================================================================//
220
222{
223 auto anEvent = new G4Event(i_event);
224 G4long s1 = 0;
225 G4long s2 = 0;
226 G4long s3 = 0;
227 G4bool eventHasToBeSeeded = true;
228 if (G4MTRunManager::SeedOncePerCommunication() == 1 && runIsSeeded) eventHasToBeSeeded = false;
229
230 if (i_event < 0) {
232 if (nevM == 1) {
234 eventHasToBeSeeded);
235 runIsSeeded = true;
236 }
237 else {
238 if (nevModulo <= 0) {
240 eventHasToBeSeeded);
241 if (nevToDo == 0)
242 eventLoopOnGoing = false;
243 else {
244 currEvID = anEvent->GetEventID();
245 nevModulo = nevToDo - 1;
246 }
247 }
248 else {
249 if (G4MTRunManager::SeedOncePerCommunication() > 0) eventHasToBeSeeded = false;
250 anEvent->SetEventID(++currEvID);
251 nevModulo--;
252 }
253 if (eventLoopOnGoing && eventHasToBeSeeded) {
254 s1 = seedsQueue.front();
255 seedsQueue.pop();
256 s2 = seedsQueue.front();
257 seedsQueue.pop();
258 }
259 }
260
261 if (!eventLoopOnGoing) {
262 delete anEvent;
263 return nullptr;
264 }
265 }
266 else if (eventHasToBeSeeded) {
267 // Need to reseed random number generator
269 s1 = helper->GetSeed(i_event * 2);
270 s2 = helper->GetSeed(i_event * 2 + 1);
271 }
272
273 if (eventHasToBeSeeded) {
274 G4long seeds[3] = {s1, s2, 0};
275 G4Random::setTheSeeds(seeds, -1);
276 runIsSeeded = true;
277 }
278
279 // Read from file seed.
280 // Andrea Dotti 4 November 2015
281 // This is required for strong-reproducibility, in MT mode we have that each
282 // thread produces, for each event a status file, we want to do that.
283 // Search a random file with the format run{%d}evt{%d}.rndm
284
285 // This is the filename base constructed from run and event
286 const auto filename = [&] {
287 std::ostringstream os;
288 os << "run" << currentRun->GetRunID() << "evt" << anEvent->GetEventID();
289 return os.str();
290 };
291
292 G4bool RNGstatusReadFromFile = false;
293 if (readStatusFromFile) {
294 // Build full path of RNG status file for this event
295 std::ostringstream os;
296 os << filename() << ".rndm";
297 const G4String& randomStatusFile = os.str();
298 std::ifstream ifile(randomStatusFile.c_str());
299 if (ifile) {
300 // File valid and readable
301 RNGstatusReadFromFile = true;
302 G4Random::restoreEngineStatus(randomStatusFile.c_str());
303 }
304 }
305
307 std::ostringstream oss;
308 G4Random::saveFullState(oss);
310 anEvent->SetRandomNumberStatus(randomNumberStatusForThisEvent);
311 }
312
313 if (storeRandomNumberStatus && !RNGstatusReadFromFile) {
314 // If reading from file, avoid to rewrite the same
315 G4String fileN = "currentEvent";
316 if (rngStatusEventsFlag) fileN = filename();
317 StoreRNGStatus(fileN);
318 }
319
320 if (printModulo > 0 && anEvent->GetEventID() % printModulo == 0) {
321 G4cout << "--> Event " << anEvent->GetEventID() << " starts";
322 if (eventHasToBeSeeded) G4cout << " with initial seeds (" << s1 << "," << s2 << ")";
323 G4cout << "." << G4endl;
324 }
326 return anEvent;
327}
328
329//============================================================================//
330
332{
333 if (!fakeRun && (currentRun != nullptr)) {
334#if defined(GEANT4_USE_TIMEMORY)
335 workerRunProfiler.reset();
336#endif
338
339 // Call a user hook: note this is before the next barrier
340 // so threads execute this method asyncrhonouzly
341 //(TerminateRun allows for synch via G4RunAction::EndOfRun)
342 const G4UserWorkerInitialization* uwi =
344 if (uwi != nullptr) uwi->WorkerRunEnd();
345 }
346
347 if (currentRun != nullptr) {
349 }
350 // Signal this thread has finished envent-loop.
351 // Note this will return only whan all threads reach this point
353}
354
355//============================================================================//
356
358{
359 if (verboseLevel > 0 && !fakeRun) {
360 timer->Stop();
361 // prefix with thread # info due to how TBB calls this function
362 G4String prefix = "[thread " + std::to_string(workerContext->GetThreadId()) + "] ";
363 G4cout << prefix << "Thread-local run terminated." << G4endl;
364 G4cout << prefix << "Run Summary" << G4endl;
365 if (runAborted)
366 G4cout << prefix << " Run Aborted after " << numberOfEventProcessed << " events processed."
367 << G4endl;
368 else
369 G4cout << prefix << " Number of events processed : " << numberOfEventProcessed << G4endl;
370 G4cout << prefix << " " << *timer << G4endl;
371 }
372}
373
374//============================================================================//
375
376void G4WorkerTaskRunManager::SetupDefaultRNGEngine()
377{
378 const CLHEP::HepRandomEngine* mrnge =
380 assert(mrnge); // Master has created RNG
383 uwti->SetupRNGEngine(mrnge);
384}
385
386//============================================================================//
387
389{
390 std::ostringstream os;
391 os << randomNumberStatusDir << "G4Worker" << workerContext->GetThreadId() << "_" << fn << ".rndm";
392 G4Random::saveEngineStatus(os.str().c_str());
393}
394
395//============================================================================//
396
398{
400 if (mrm == nullptr) return;
401
402 //------------------------------------------------------------------------//
403 // Check UI commands not already processed
404 auto command_stack = mrm->GetCommandStack();
405 bool matching = (command_stack.size() == processedCommandStack.size());
406 if (matching) {
407 for (uintmax_t i = 0; i < command_stack.size(); ++i)
408 if (processedCommandStack.at(i) != command_stack.at(i)) {
409 matching = false;
410 break;
411 }
412 }
413
414 //------------------------------------------------------------------------//
415 // Execute UI commands stored in the master UI manager
416 if (!matching) {
417 for (const auto& itr : command_stack)
419 processedCommandStack = command_stack;
420 }
421}
422
423//============================================================================//
424
426{
428
429 delete currentRun;
430 currentRun = nullptr;
431}
432
433//============================================================================//
434
436{
438 G4bool newRun = false;
439 const G4Run* run = mrm->GetCurrentRun();
440 G4ThreadLocalStatic G4int runId = -1;
441 if ((run != nullptr) && run->GetRunID() != runId) {
442 runId = run->GetRunID();
443 newRun = true;
444 if (runId > 0) {
445 ProcessUI();
446 assert(workerContext != nullptr);
447 }
449 }
450
451 // Start this run
453 G4int numSelect = mrm->GetNumberOfSelectEvents();
454 G4String macroFile = mrm->GetSelectMacro();
455 G4bool empty_macro = (macroFile.empty() || macroFile == " ");
456
457 const char* macro = (empty_macro) ? nullptr : macroFile.c_str();
458 numSelect = (empty_macro) ? -1 : numSelect;
459
460 if (newRun) {
462 if (cond) {
465 }
466 }
467 DoEventLoop(nevts, macro, numSelect);
468}
469
470//============================================================================//
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
long G4long
Definition G4Types.hh:87
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
void ProcessOneEvent(G4Event *anEvent)
G4int GetEventID() const
Definition G4Event.hh:123
static G4int SeedOncePerCommunication()
virtual G4int SetUpNEvents(G4Event *, G4SeedsQueue *seedsQueue, G4bool reseedRequired=true)
const CLHEP::HepRandomEngine * getMasterRandomEngine() const
virtual void ThisWorkerReady()
G4int GetEventModulo() const
static G4MTRunManager * GetMasterRunManager()
std::vector< G4String > GetCommandStack()
virtual G4bool SetUpAnEvent(G4Event *, G4long &s1, G4long &s2, G4long &s3, G4bool reseedRequired=true)
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 numberOfEventProcessed
G4int GetNumberOfEventsToBeProcessed() const
virtual void InitializeEventLoop(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1)
G4RunManagerKernel * kernel
G4Run * currentRun
virtual G4bool ConfirmBeamOnCondition()
static G4RunManager * GetRunManager()
G4DCtable * DCtable
G4String randomNumberStatusForThisRun
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:108
G4int GetRunID() const
Definition G4Run.hh:86
void SetNumberOfEventToBeProcessed(G4int n_ev)
Definition G4Run.hh:107
void SetRunID(G4int id)
Definition G4Run.hh:106
void SetDCtable(G4DCtable *DCtbl)
Definition G4Run.hh:109
void SetRandomNumberStatus(G4String &st)
Definition G4Run.hh:110
G4HCofThisEvent * PrepareNewEvent()
static G4SDManager * GetSDMpointerIfExist()
G4HCtable * GetHCtable() const
static G4TaskRunManager * GetMasterRunManager()
static G4TemplateRNGHelper< T > * GetInstance()
virtual const T GetSeed(const G4int &sdId)
void Stop()
G4int ApplyCommand(const char *aCommand)
static G4UImanager * GetUIpointer()
virtual G4Run * GenerateRun()
virtual void BeginOfRunAction(const G4Run *)
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 MergePartialResults()
G4WorkerThread * workerContext
void ConstructScoringWorlds() override
void DoEventLoop(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1) override
G4Event * GenerateEvent(G4int i_event) override
void StoreRNGStatus(const G4String &filenamePrefix) override
G4ProfilerConfig< G4ProfileType::Run > ProfilerConfig
void ProcessOneEvent(G4int i_event) override
static G4WorkerTaskRunManagerKernel * GetWorkerRunManagerKernel()
static G4WorkerTaskRunManager * GetWorkerRunManager()
G4int GetThreadId() const
static void UpdateGeometryAndPhysicsVectorFromMaster()
G4int G4GetThreadId()
#define G4ThreadLocalStatic
Definition tls.hh:76