Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/run/src/G4SubEvtRunManager.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 
 28 #include "G4SubEvtRunManager.hh"
 29 
 30 #include "G4AutoLock.hh"
 31 #include "G4EnvironmentUtils.hh"
 32 #include "G4ProductionCutsTable.hh"
 33 #include "G4Run.hh"
 34 #include "G4ScoringManager.hh"
 35 #include "G4THitsMap.hh"
 36 #include "G4StateManager.hh"
 37 #include "G4Task.hh"
 38 #include "G4TaskGroup.hh"
 39 #include "G4TaskManager.hh"
 40 #include "G4TaskRunManagerKernel.hh"
 41 #include "G4ThreadLocalSingleton.hh"
 42 #include "G4ThreadPool.hh"
 43 #include "G4Threading.hh"
 44 #include "G4Timer.hh"
 45 #include "G4TransportationManager.hh"
 46 #include "G4UImanager.hh"
 47 #include "G4UserRunAction.hh"
 48 #include "G4UserTaskInitialization.hh"
 49 #include "G4UserTaskQueue.hh"
 50 #include "G4UserSubEvtThreadInitialization.hh"
 51 #include "G4VUserActionInitialization.hh"
 52 #include "G4VUserPhysicsList.hh"
 53 #include "G4UserEventAction.hh"
 54 #include "G4VScoreNtupleWriter.hh"
 55 #include "G4WorkerSubEvtRunManager.hh"
 56 #include "G4WorkerThread.hh"
 57 #include "G4VVisManager.hh"
 58 #include "G4Trajectory.hh"
 59 
 60 #include <cstdlib>
 61 #include <cstring>
 62 #include <iterator>
 63 #include <algorithm>
 64 
 65 //============================================================================//
 66 
 67 namespace
 68 {
 69 G4Mutex scorerMergerMutex;
 70 G4Mutex accessSubEventMutex;
 71 G4Mutex registerSubEvtWorkerMutex;
 72 }  // namespace
 73 
 74 //============================================================================//
 75 
 76 G4SubEvtRunManager::G4SubEvtRunManager(G4VUserTaskQueue* task_queue, 
 77                                                G4bool useTBB, G4int grainsize)
 78  : G4TaskRunManager(task_queue, useTBB, grainsize)
 79 {
 80   runManagerType = subEventMasterRM;
 81   G4UImanager::GetUIpointer()->SetAlias("RunMode subEventParallel");
 82 }
 83 
 84 //============================================================================//
 85 
 86 G4SubEvtRunManager::G4SubEvtRunManager(G4bool useTBB)
 87  : G4SubEvtRunManager(nullptr, useTBB, 0)
 88 { runManagerType = subEventMasterRM; }
 89 
 90 //============================================================================//
 91 
 92 G4SubEvtRunManager::~G4SubEvtRunManager()
 93 {
 94   // relying all the necessary deletion upon the base class
 95   // G4TaskRunManager::~G4TaskRunManager()
 96 }
 97 
 98 //============================================================================//
 99 
100 void G4SubEvtRunManager::Initialize()
101 {
102   SetSeedOncePerCommunication(1);
103   G4bool firstTime = (threadPool == nullptr);
104   if (firstTime) G4TaskRunManager::InitializeThreadPool();
105 
106   G4RunManager::Initialize();
107 
108   // make sure all worker threads are set up.
109   G4RunManager::BeamOn(0);
110   if (firstTime) G4RunManager::SetRunIDCounter(0);
111   // G4UImanager::GetUIpointer()->SetIgnoreCmdNotFound(true);
112 }
113 
114 //============================================================================//
115 
116 void G4SubEvtRunManager::RunInitialization()
117 {
118   G4RunManager::RunInitialization();
119   if(!fakeRun) 
120   { if(CheckSubEvtTypes()) runInProgress = true; }
121 }
122 
123 //============================================================================//
124 
125 void G4SubEvtRunManager::ProcessOneEvent(G4int i_event)
126 {
127   currentEvent = GenerateEvent(i_event);
128   eventManager->ProcessOneEvent(currentEvent);
129   
130   // Following two lines should not be executed here, as spawned sub-events may 
131   // be still being processed. These methods are invoked when all sub-events belongings
132   // to this event are processed and scores of these sub-events are marged to the
133   // corresponding master event.
134   //AnalyzeEvent(currentEvent);
135   //UpdateScoring();
136 
137   if (i_event < n_select_msg) G4UImanager::GetUIpointer()->ApplyCommand(msgText);
138 }
139 
140 //============================================================================//
141 
142 void G4SubEvtRunManager::TerminateOneEvent()
143 {
144   // We must serialize access here because workers may access Run/Event vectors
145   // and we can't override StackPreviousEvent
146   G4AutoLock l(&accessSubEventMutex);
147   StackPreviousEvent(currentEvent);
148   currentEvent = nullptr;
149   ++numberOfEventProcessed;
150 }
151 
152 //============================================================================//
153 
154 void G4SubEvtRunManager::StackPreviousEvent(G4Event* anEvent)
155 {
156   if(n_perviousEventsToBeStored>0) {
157     G4ExceptionDescription ed;
158     ed << "G4RunManager::SetNumberOfEventsToBeStored() is not supported in sub-event parallel mode.\n"
159        << "User may still keep events bu G4EventManager::KeepTheCurrentEvent()";
160     G4Exception("G4SubEvtRunManager::StackPreviousEvent","SubEvtRM1200",FatalException,ed);
161     return;
162   }
163 
164   if(anEvent->GetNumberOfRemainingSubEvents()>0)
165   // sub-events are still under processing. Event is not yet fully completed.
166   {
167     currentRun->StoreEvent(anEvent);
168   }
169   else
170   // Event is already completed.
171   { 
172     // making sure this is the first path
173     if(!(anEvent->IsEventCompleted()))
174     {
175       anEvent->EventCompleted();
176       if(userEventAction!=nullptr) userEventAction->EndOfEventAction(anEvent);
177       auto pVisManager = G4VVisManager::GetConcreteInstance();
178       if (pVisManager) pVisManager->EventReadyForVis(anEvent);
179       UpdateScoring(anEvent);
180       if(anEvent->ToBeKept() || anEvent->GetNumberOfGrips()>0) 
181       { // we keep this event for post-processing (i.e. for vis)
182         currentRun->StoreEvent(anEvent);
183       }
184       else
185       { 
186         ReportEventDeletion(anEvent);
187         delete anEvent;
188       }
189     } else {
190       G4Exception("G4SubEvtRunManager::StackPreviousEvent","SubEvtRM1209",FatalException,"We should not be here!!");
191     }
192   }
193 
194   CleanUpUnnecessaryEvents(0);
195 }
196 
197 //============================================================================//
198 
199 void G4SubEvtRunManager::CleanUpUnnecessaryEvents(G4int keepNEvents)
200 {
201   // Delete events that are no longer necessary for post
202   // processing such as visualization.
203   // N.B. If ToBeKept() is true, the pointer of this event is
204   // kept in G4Run, and deleted along with the deletion of G4Run.
205 
206   if(keepNEvents>0) {
207     G4ExceptionDescription ed;
208     ed << "G4RunManager::SetNumberOfEventsToBeStored() is not supported in sub-event parallel mode.\n"
209        << "User may still keep events bu G4EventManager::KeepTheCurrentEvent()";
210     G4Exception("G4SubEvtRunManager::CleanUpUnnecessaryEvents","SubEvtRM1201",FatalException,ed);
211     return;
212   }
213 
214   assert(currentRun!=nullptr);
215 
216   auto eventVector = currentRun->GetEventVector();
217   if(eventVector==nullptr || eventVector->empty()) return;
218   auto eItr = eventVector->cbegin();
219   while(eItr != eventVector->cend())
220   {
221     const G4Event* ev = *eItr;
222     if(ev!=nullptr)
223     {
224       if(!(ev->IsEventCompleted()))
225       {
226         if(ev->GetNumberOfRemainingSubEvents()==0)
227         { // This event has been completed since last time we were here
228           ev->EventCompleted();
229           if(userEventAction!=nullptr) userEventAction->EndOfEventAction(ev);
230           auto pVisManager = G4VVisManager::GetConcreteInstance();
231           if (pVisManager) pVisManager->EventReadyForVis(ev);
232           UpdateScoring(ev);
233           if(ev->ToBeKept() || ev->GetNumberOfGrips()>0) 
234           { // we keep this event for post-processing (i.e. for vis)
235             eItr++;
236           }
237           else
238           { // this event is no longer needed
239             ReportEventDeletion(ev);
240             delete ev;
241             eItr = eventVector->erase(eItr);
242           }
243         }
244         else
245         { // this event is still incomplete
246           eItr++;
247         }
248       }
249       else if(ev->ToBeKept() || ev->GetNumberOfGrips()>0) 
250       { // we still need this event
251         eItr++;
252       }
253       else
254       { // post-processing done. we no longer need this event
255         ReportEventDeletion(ev);
256         delete ev;
257         eItr = eventVector->erase(eItr);
258       } 
259     }
260     else
261     { // ev is a null pointer 
262       eItr = eventVector->erase(eItr);
263     }
264   }   
265 }
266 
267 //============================================================================//
268 
269 void G4SubEvtRunManager::CreateAndStartWorkers()
270 {
271   // Now loop on requested number of workers
272   // This will also start the workers
273   // Currently we do not allow to change the
274   // number of threads: threads area created once
275   // Instead of pthread based workers, create tbbTask
276   static G4bool initializeStarted = false;
277 
278   ComputeNumberOfTasks();
279 
280   if (fakeRun) {
281     if (initializeStarted) {
282       auto initCmdStack = GetCommandStack();
283       if (!initCmdStack.empty()) {
284         threadPool->execute_on_all_threads([cmds = std::move(initCmdStack)]() {
285           for (auto& itr : cmds)
286             G4UImanager::GetUIpointer()->ApplyCommand(itr);
287           G4WorkerTaskRunManager::GetWorkerRunManager()->DoWork();
288         });
289       }
290     }
291     else {
292       std::stringstream msg;
293       msg << "--> G4SubEvtRunManager::CreateAndStartWorkers() --> "
294           << "Initializing workers...";
295 
296       std::stringstream ss;
297       ss.fill('=');
298       ss << std::setw((G4int)msg.str().length()) << "";
299       G4cout << "\n" << ss.str() << "\n" << msg.str() << "\n" << ss.str() << "\n" << G4endl;
300 
301       G4TaskRunManagerKernel::InitCommandStack() = GetCommandStack();
302       threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::InitializeWorker(); });
303     }
304     initializeStarted = true;
305   }
306   else {
307     auto initCmdStack = GetCommandStack();
308     if (!initCmdStack.empty()) {
309       threadPool->execute_on_all_threads([cmds = std::move(initCmdStack)]() {
310         for (auto& itr : cmds)
311           G4UImanager::GetUIpointer()->ApplyCommand(itr);
312       });
313     }
314 
315     // cleans up a previous run and events in case a thread
316     // does not execute any tasks
317     threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::ExecuteWorkerInit(); });
318 
319     {
320       std::stringstream msg;
321       msg << "--> G4SubEvtRunManager::CreateAndStartWorkers() --> "
322           << "Creating " << numberOfTasks << " tasks with " << numberOfEventsPerTask
323           << " events/task...";
324 
325       std::stringstream ss;
326       ss.fill('=');
327       ss << std::setw((G4int)msg.str().length()) << "";
328       G4cout << "\n" << ss.str() << "\n" << msg.str() << "\n" << ss.str() << "\n" << G4endl;
329     }
330 
331     /* TODO (PHASE-II): Better calculation of task/event/subevents
332        Currently, number of tasks is equal to number of threads
333        and each task has a loop that endlessly asks for next sub-event
334        until no additional sub-event is available in the master.
335        This is not ideal. We should make each task work only for some limited 
336        number of sub-events, and create as many number of tasks as needed
337        on the fly during the event loop of the master thread., e.g.
338     G4int remaining = numberOfEventToBeProcessed;
339     for (G4int nt = 0; nt < numberOfTasks + 1; ++nt) {
340       if (remaining > 0) AddEventTask(nt);
341       remaining -= numberOfEventsPerTask;
342     }
343     */
344     for(G4int nt = 0; nt < numberOfTasks; ++nt)
345     { AddEventTask(nt); }
346   }
347 }
348 
349 //============================================================================//
350 
351 void G4SubEvtRunManager::AddEventTask(G4int nt)
352 {
353   if (verboseLevel > 3) G4cout << "Adding task " << nt << " to task-group..." << G4endl;
354   workTaskGroup->exec([]() { G4TaskRunManagerKernel::ExecuteWorkerTask(); });
355 }
356 
357 //============================================================================//
358 
359 void G4SubEvtRunManager::RefillSeeds()
360 {
361   G4RNGHelper* helper = G4RNGHelper::GetInstance();
362   G4int nFill = 0;
363   switch (SeedOncePerCommunication()) {
364     case 0:
365       nFill = numberOfEventToBeProcessed - nSeedsFilled;
366       break;
367     case 1:
368       nFill = numberOfTasks - nSeedsFilled;
369       break;
370     case 2:
371     default:
372       nFill = (numberOfEventToBeProcessed - nSeedsFilled * eventModulo) / eventModulo + 1;
373   }
374   // Generates up to nSeedsMax seed pairs only.
375   if (nFill > nSeedsMax) nFill = nSeedsMax;
376   masterRNGEngine->flatArray(nSeedsPerEvent * nFill, randDbl);
377   helper->Refill(randDbl, nFill);
378   nSeedsFilled += nFill;
379 }
380 
381 //============================================================================//
382 
383 void G4SubEvtRunManager::InitializeEventLoop(G4int n_event, const char* macroFile, G4int n_select)
384 {
385   MTkernel->SetUpDecayChannels();
386   numberOfEventToBeProcessed = n_event;
387   numberOfEventProcessed = 0;
388 
389   if (!fakeRun) {
390     nSeedsUsed = 0;
391     nSeedsFilled = 0;
392 
393     if (verboseLevel > 0) timer->Start();
394 
395     n_select_msg = n_select;
396     if (macroFile != nullptr) {
397       if (n_select_msg < 0) n_select_msg = n_event;
398 
399       msgText = "/control/execute ";
400       msgText += macroFile;
401       selectMacro = macroFile;
402     }
403     else {
404       n_select_msg = -1;
405       selectMacro = "";
406     }
407 
408     ComputeNumberOfTasks();
409 
410     // initialize seeds
411     // If user did not implement InitializeSeeds,
412     // use default: nSeedsPerEvent seeds per event
413 
414     if (n_event > 0) {
415       G4bool _overload = InitializeSeeds(n_event);
416       G4bool _functor = false;
417       if (!_overload) _functor = initSeedsCallback(n_event, nSeedsPerEvent, nSeedsFilled);
418       if (!_overload && !_functor) {
419         G4RNGHelper* helper = G4RNGHelper::GetInstance();
420         switch (SeedOncePerCommunication()) {
421           case 1:
422             nSeedsFilled = nworkers;
423             break;
424           default:
425             G4ExceptionDescription msgd;
426             msgd << "Parameter value <" << SeedOncePerCommunication()
427                  << "> of seedOncePerCommunication is invalid. It is reset "
428                     "to 1.";
429             G4Exception("G4SubEvtRunManager::InitializeEventLoop()", "Run10036", JustWarning, msgd);
430             SetSeedOncePerCommunication(1);
431             nSeedsFilled = nworkers;
432         }
433 
434         // Generates up to nSeedsMax seed pairs only.
435         if (nSeedsFilled > nSeedsMax) nSeedsFilled = nSeedsMax;
436         masterRNGEngine->flatArray(nSeedsPerEvent * nSeedsFilled, randDbl);
437         helper->Fill(randDbl, nSeedsFilled, n_event, nSeedsPerEvent);
438       }
439     }
440   }
441 
442   // Now initialize workers. Check if user defined a WorkerThreadInitialization
443   if (userWorkerThreadInitialization == nullptr)
444     userWorkerThreadInitialization = new G4UserSubEvtThreadInitialization();
445 
446   // Prepare UI commands for threads
447   PrepareCommandsStack();
448 
449   // Start worker threads
450   CreateAndStartWorkers();
451 }
452 
453 //============================================================================//
454 
455 void G4SubEvtRunManager::RunTermination()
456 {
457   // Wait for all worker threads to have finished the run
458   // i.e. wait for them to return from RunTermination()
459   // This guarantee that userrunaction for workers has been called
460 
461   runInProgress = false;
462 
463   //TODO (PHASE-II): do we need this???
464   workTaskGroup->wait();
465 
466   // Wait now for all threads to finish event-loop
467   WaitForEndEventLoopWorkers();
468 
469   // Now call base-class method
470   G4RunManager::TerminateEventLoop();
471   G4RunManager::RunTermination();
472 
473   if(currentRun!=nullptr) 
474   {
475     auto eventVector = currentRun->GetEventVector();
476     if(eventVector!=nullptr)
477     {
478       G4int notReady = 1;
479       while(notReady>0)
480       {
481         notReady = 0;
482         for(auto ev:*eventVector)
483         {
484           if(ev->GetNumberOfRemainingSubEvents()>0 || ev->GetNumberOfGrips()>0 )
485           { notReady++; }
486         }
487         if(notReady>0)
488         {
489           if(verboseLevel>2)
490           {
491             G4cout << "G4SubEvtRunManager::RunTermination - " << notReady
492                    << " events are still incomplete. Waiting for them." << G4endl;
493           }
494           G4THREADSLEEP(1);
495         }
496       }
497     }
498     CleanUpUnnecessaryEvents(0);
499   }
500 }
501 
502 //============================================================================//
503 
504 void G4SubEvtRunManager::ConstructScoringWorlds()
505 {
506   masterScM = G4ScoringManager::GetScoringManagerIfExist();
507   // Call base class stuff...
508   G4RunManager::ConstructScoringWorlds();
509 
510   GetMasterWorlds().clear();
511   auto nWorlds = (G4int)G4TransportationManager::GetTransportationManager()->GetNoWorlds();
512   auto itrW = G4TransportationManager::GetTransportationManager()->GetWorldsIterator();
513   for (G4int iWorld = 0; iWorld < nWorlds; ++iWorld) {
514     addWorld(iWorld, *itrW);
515     ++itrW;
516   }
517 }
518 
519 //============================================================================//
520 
521 void G4SubEvtRunManager::MergeScores(const G4ScoringManager* localScoringManager)
522 {
523   G4AutoLock l(&scorerMergerMutex);
524   if (masterScM != nullptr) masterScM->Merge(localScoringManager);
525 }
526 
527 const G4SubEvent* G4SubEvtRunManager::GetSubEvent(G4int ty, G4bool& notReady,
528               G4long& s1, G4long& s2, G4long& s3, G4bool reseedRequired)
529 {
530   G4AutoLock l(&accessSubEventMutex);
531 
532 // This method is invoked from the worker, the ownership of G4SubEvent object
533 // remains to the master, i.e. will be deleted by the master thread through
534 // TerminateSubEvent() method.
535 
536   if(currentRun==nullptr)
537   {
538   // Run has not yet started.
539     notReady = true;
540     return nullptr;
541   }
542 
543   auto eventVector = currentRun->GetEventVector();
544   // RACE HERE: against:
545   // 1 G4Run::StoreEvent(G4Event*) G4Run.cc:80
546   // 2 G4RunManager::StackPreviousEvent(G4Event*) G4RunManager.cc:572
547   for(auto& ev : *eventVector)
548   {
549   // looping over stored events
550     // RACE HERE: against:
551     // 1 G4Run::StoreEvent(G4Event*) G4Run.cc:80 
552     // 2 G4RunManager::StackPreviousEvent(G4Event*) G4RunManager.cc:572 
553     auto se = const_cast<G4Event*>(ev)->PopSubEvent(ty);
554     if(se!=nullptr)
555     {
556     // Sub-event is found in an event that is already finished its event-loop
557       notReady = false;
558       if(reseedRequired) SetUpSeedsForSubEvent(s1,s2,s3);
559       return se;
560     }
561   }
562 
563   auto sep = eventManager->PopSubEvent(ty);
564   if(sep!=nullptr)
565   {
566   // Sub-event is found in an event that is still in the event loop
567     notReady = false;
568     if(reseedRequired) SetUpSeedsForSubEvent(s1,s2,s3);
569     return sep;
570   } else {
571   // No sub-event available
572     // RACE HERE vs line 345
573     if(runInProgress)
574     {
575     // Run is still in progress. Worker should wait until a sub-event is ready
576       notReady = true;
577     }
578     else
579     {
580     // Run is over. No more sub-event to come unless new run starts.
581       notReady = false;
582     }
583     return nullptr;
584   }
585 }
586 
587 void G4SubEvtRunManager::SetUpSeedsForSubEvent(G4long& s1, G4long& s2, G4long& s3)
588 {
589   //TODO (PHASE-II): Seeding scheme for sub-event has to be revisited
590   G4RNGHelper* helper = G4RNGHelper::GetInstance();
591   G4int idx_rndm = nSeedsPerEvent * nSeedsUsed;
592   s1 = helper->GetSeed(idx_rndm);
593   s2 = helper->GetSeed(idx_rndm + 1);
594   if (nSeedsPerEvent == 3) s3 = helper->GetSeed(idx_rndm + 2);
595   ++nSeedsUsed;
596   if (nSeedsUsed == nSeedsFilled) RefillSeeds();
597 }
598 
599 
600 //============================================================================//
601 //
602 //G4bool G4SubEvtRunManager::SetUpAnEvent(G4Event* evt, G4long& s1, G4long& s2, G4long& s3,
603 //                                      G4bool reseedRequired)
604 //{
605 //  G4AutoLock l(&setUpEventMutex);
606 //  if (numberOfEventProcessed < numberOfEventToBeProcessed) {
607 //    evt->SetEventID(numberOfEventProcessed);
608 //    if (reseedRequired) {
609 //      G4RNGHelper* helper = G4RNGHelper::GetInstance();
610 //      G4int idx_rndm = nSeedsPerEvent * nSeedsUsed;
611 //      s1 = helper->GetSeed(idx_rndm);
612 //      s2 = helper->GetSeed(idx_rndm + 1);
613 //      if (nSeedsPerEvent == 3) s3 = helper->GetSeed(idx_rndm + 2);
614 //      ++nSeedsUsed;
615 //      if (nSeedsUsed == nSeedsFilled) RefillSeeds();
616 //    }
617 //    numberOfEventProcessed++;
618 //    return true;
619 //  }
620 //  return false;
621 //}
622 
623 //============================================================================//
624 //
625 //G4int G4SubEvtRunManager::SetUpNEvents(G4Event* evt, G4SeedsQueue* seedsQueue, G4bool reseedRequired)
626 //{
627 //  G4AutoLock l(&setUpEventMutex);
628 //  if (numberOfEventProcessed < numberOfEventToBeProcessed && !runAborted) {
629 //    G4int nevt = numberOfEventsPerTask;
630 //    G4int nmod = eventModulo;
631 //    if (numberOfEventProcessed + nevt > numberOfEventToBeProcessed) {
632 //      nevt = numberOfEventToBeProcessed - numberOfEventProcessed;
633 //      nmod = numberOfEventToBeProcessed - numberOfEventProcessed;
634 //    }
635 //    evt->SetEventID(numberOfEventProcessed);
636 //
637 //    if (reseedRequired) {
638 //      G4RNGHelper* helper = G4RNGHelper::GetInstance();
639 //      G4int nevRnd = nmod;
640 //      if (SeedOncePerCommunication() > 0) nevRnd = 1;
641 //      for (G4int i = 0; i < nevRnd; ++i) {
642 //        seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed));
643 //        seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 1));
644 //        if (nSeedsPerEvent == 3) seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 2));
645 //        nSeedsUsed++;
646 //        if (nSeedsUsed == nSeedsFilled) RefillSeeds();
647 //      }
648 //    }
649 //    numberOfEventProcessed += nevt;
650 //    return nevt;
651 //  }
652 //  return 0;
653 //}
654 
655 //============================================================================//
656 
657 void G4SubEvtRunManager::SubEventFinished(const G4SubEvent* se,const G4Event* evt)
658 {
659   G4AutoLock l(&accessSubEventMutex);
660   auto masterEvt = se->GetEvent();
661   if(masterEvt==nullptr) {
662     G4Exception("G4SubEvtRunManager::SubEventFinished()","SERM0001",
663       FatalException,"Pointer of master event is null. PANIC!");
664     return; // NOLINT: required to help Coverity recognise FatalException as exit point
665   }
666 
667   if(userEventAction) {
668     userEventAction->MergeSubEvent(masterEvt,evt);
669   }
670   if(trajectoriesToBeMerged) MergeTrajectories(se,evt);
671   UpdateScoringForSubEvent(se,evt);
672   evt->ScoresRecorded();
673   eventManager->TerminateSubEvent(se,evt);
674 }
675 
676 //============================================================================//
677 
678 void G4SubEvtRunManager::MergeTrajectories(const G4SubEvent* se,const G4Event* evt)
679 {
680   auto masterEvt = se->GetEvent();
681   auto* trajVector = evt->GetTrajectoryContainer()->GetVector();
682   auto* masterTrajContainer = masterEvt->GetTrajectoryContainer();
683   if(masterTrajContainer==nullptr) 
684   {
685     masterTrajContainer = new G4TrajectoryContainer;
686     masterEvt->SetTrajectoryContainer(masterTrajContainer);
687   }
688   for(auto& traj : *trajVector)
689   {
690     if(traj!=nullptr) {
691       auto* cloned = traj->CloneForMaster();
692       masterTrajContainer->push_back(cloned);
693     }
694   }
695 }
696 
697 //============================================================================//
698 
699 void G4SubEvtRunManager::UpdateScoringForSubEvent(const G4SubEvent* se,const G4Event* evt)
700 {
701   auto masterEvt = se->GetEvent();
702 
703   G4ScoringManager* ScM = G4ScoringManager::GetScoringManagerIfExist();
704   if (ScM == nullptr) return;
705   auto nPar = (G4int)ScM->GetNumberOfMesh();
706   if (nPar < 1) return;
707 
708   if(verboseLevel>3) {
709     G4cout << "merging scores of sub-event belonging to event id #" << masterEvt->GetEventID()
710            << " --- sub-event has " << evt->GetHCofThisEvent()->GetCapacity()
711            << " hits collections" << G4endl;
712   }
713   G4HCofThisEvent* HCE = evt->GetHCofThisEvent();
714   if (HCE == nullptr) return;
715   auto nColl = (G4int)HCE->GetCapacity();
716   G4HCofThisEvent* masterHCE = masterEvt->GetHCofThisEvent();
717   if (masterHCE == nullptr || (G4int)masterHCE->GetCapacity() != nColl) 
718   {
719     G4Exception("G4SubEvtRunManager::UpdateScoringForSubEvent()","SERM0002",
720       FatalException,"Number of hits colleactions for scrorers mismatch!! PANIC!!");
721     return;
722   }
723   for (G4int i = 0; i < nColl; ++i) {
724     auto* HC = dynamic_cast<G4THitsMap<G4double>*>(HCE->GetHC(i));
725     auto* masterHC = dynamic_cast<G4THitsMap<G4double>*>(masterHCE->GetHC(i));
726     if (HC != nullptr && masterHC != nullptr)
727     { *masterHC += *HC; }
728     else
729     {
730        G4Exception("G4SubEvtRunManager::UpdateScoringForSubEvent()","SERM0003",
731          FatalException,"HitsCollection is not type of G4THitsMap<G4double>. PANIC!!");
732        return;
733     }
734   }
735   
736 }
737 
738 //============================================================================//
739 
740 void G4SubEvtRunManager::CleanUpPreviousEvents()
741 {
742   // Delete all events carried over from previous run.
743   // This method is invoked at the beginning of the next run
744   // or from the destructor of G4RunManager at the very end of
745   // the program.
746   auto evItr = previousEvents->cbegin();
747   while (evItr != previousEvents->cend()) {
748     G4Event* evt = *evItr;
749     if (evt != nullptr)
750     {
751       ReportEventDeletion(evt);
752       // remove evt from the event vector of G4Run as well
753       if(currentRun!=nullptr)
754       {
755         auto eventVector = currentRun->GetEventVector();
756         auto eItr = std::find(eventVector->cbegin(),eventVector->cend(),evt);
757         if(eItr != eventVector->cend()) eventVector->erase(eItr);
758       }
759       delete evt;
760     }
761     evItr = previousEvents->erase(evItr);
762   }
763   if(currentRun!=nullptr)
764   {
765     auto eventVector = currentRun->GetEventVector();
766     if(eventVector==nullptr || eventVector->empty()) return;
767     auto eItr = eventVector->cbegin();
768     while(eItr != eventVector->cend())
769     {
770       const G4Event* ev = *eItr;
771       if(ev!=nullptr)
772       {
773         ReportEventDeletion(ev);
774         delete ev;
775       }
776       eItr = eventVector->erase(eItr);
777     }
778   }
779 }
780 
781 //============================================================================//
782 
783 void G4SubEvtRunManager::TerminateWorkers()
784 {
785   // Force workers to execute (if any) all UI commands left in the stack
786   RequestWorkersProcessCommandsStack();
787 
788   if (workTaskGroup != nullptr) {
789     workTaskGroup->join();
790     if (!fakeRun)
791       threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::TerminateWorker(); });
792   }
793 }
794 
795 //============================================================================//
796 
797 void G4SubEvtRunManager::AbortRun(G4bool softAbort)
798 {
799   // This method is valid only for GeomClosed or EventProc state
800   G4ApplicationState currentState = G4StateManager::GetStateManager()->GetCurrentState();
801   if (currentState == G4State_GeomClosed || currentState == G4State_EventProc) {
802     runAborted = true;
803     MTkernel->BroadcastAbortRun(softAbort);
804   }
805   else {
806     G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
807   }
808 }
809 
810 //============================================================================//
811 
812 void G4SubEvtRunManager::AbortEvent()
813 {
814   // nothing to do in the master thread
815 }
816 
817 //============================================================================//
818 
819 void G4SubEvtRunManager::WaitForEndEventLoopWorkers()
820 {
821   if (workTaskGroup != nullptr) {
822     workTaskGroup->join();
823     if (!fakeRun)
824       threadPool->execute_on_all_threads(
825         []() { G4TaskRunManagerKernel::TerminateWorkerRunEventLoop(); });
826   }
827 }
828 
829 //============================================================================//
830 
831 void G4SubEvtRunManager::RequestWorkersProcessCommandsStack()
832 {
833   PrepareCommandsStack();
834 
835   auto process_commands_stack = []() {
836     G4MTRunManager* mrm = G4MTRunManager::GetMasterRunManager();
837     if (mrm != nullptr) {
838       auto cmds = mrm->GetCommandStack();
839       for (const auto& itr : cmds)
840         G4UImanager::GetUIpointer()->ApplyCommand(itr);  // TLS instance
841       mrm->ThisWorkerProcessCommandsStackDone();
842     }
843   };
844 
845   if (threadPool != nullptr) threadPool->execute_on_all_threads(process_commands_stack);
846 }
847 
848 //============================================================================//
849 
850 void G4SubEvtRunManager::ThisWorkerProcessCommandsStackDone() {}
851 
852 //============================================================================//
853 
854 void G4SubEvtRunManager::RegisterSubEventType(G4int ty, G4int maxEnt) 
855 {
856   G4AutoLock l(&registerSubEvtWorkerMutex);
857   fSubEvtTypeMap[ty] = maxEnt;
858   eventManager->UseSubEventParallelism();
859   eventManager->GetStackManager()->RegisterSubEventType(ty,maxEnt);
860 }
861 
862 void G4SubEvtRunManager::RegisterSubEvtWorker(G4WorkerSubEvtRunManager*wrm,G4int typ)
863 {
864   G4AutoLock l(&registerSubEvtWorkerMutex);
865   fWorkerMap[wrm] = typ;
866 }
867 
868 G4bool G4SubEvtRunManager::CheckSubEvtTypes()
869 {
870   for(auto& seT : fSubEvtTypeMap)
871   {
872     G4int ty = seT.first;
873     G4int seTyp = -1;
874     for(auto& worker : fWorkerMap)
875     {
876       if(worker.second==ty)
877       { seTyp = ty; break; }
878     }
879     if(seTyp==-1)
880     {
881       G4ExceptionDescription ed;
882       ed << "There is no worker with sub-event type " << ty
883          << " registered. There must be at least one worker who is responsible.";
884       G4Exception("G4SubEvtRunManager::CheckSubEvtTypes",
885          "SubEvtRM1210",FatalException,ed);
886       return false;
887     }
888   }
889   return true;
890 }
891 
892 void G4SubEvtRunManager::SetUserInitialization(G4UserWorkerInitialization* userInit)
893 {
894   userWorkerInitialization = userInit;
895 }
896 
897 // --------------------------------------------------------------------
898 void G4SubEvtRunManager::SetUserInitialization(G4UserWorkerThreadInitialization* userInit)
899 {
900   userWorkerThreadInitialization = userInit;
901 }
902 
903 // --------------------------------------------------------------------
904 void G4SubEvtRunManager::SetUserInitialization(G4VUserActionInitialization* userInit)
905 {
906   userActionInitialization = userInit;
907   userActionInitialization->BuildForMaster();
908 }
909 
910 // --------------------------------------------------------------------
911 void G4SubEvtRunManager::SetUserInitialization(G4VUserDetectorConstruction* userDC)
912 {
913   G4RunManager::SetUserInitialization(userDC);
914 }
915 
916 // --------------------------------------------------------------------
917 void G4SubEvtRunManager::SetUserInitialization(G4VUserPhysicsList* pl)
918 {
919   pl->InitializeWorker();
920   G4RunManager::SetUserInitialization(pl);
921 }
922 
923 // --------------------------------------------------------------------
924 void G4SubEvtRunManager::SetUserAction(G4UserRunAction* userAction)
925 {
926   G4RunManager::SetUserAction(userAction);
927   if (userAction != nullptr) userAction->SetMaster(true);
928 }
929 
930 // --------------------------------------------------------------------
931 void G4SubEvtRunManager::SetUserAction(G4UserEventAction* ua)
932 {
933   G4RunManager::SetUserAction(ua);
934 }
935 
936 // --------------------------------------------------------------------
937 void G4SubEvtRunManager::SetUserAction(G4VUserPrimaryGeneratorAction* ua)
938 {
939   G4RunManager::SetUserAction(ua);
940 }
941 
942 // --------------------------------------------------------------------
943 void G4SubEvtRunManager::SetUserAction(G4UserStackingAction* ua)
944 {
945   G4RunManager::SetUserAction(ua);
946 }
947 
948 // --------------------------------------------------------------------
949 void G4SubEvtRunManager::SetUserAction(G4UserTrackingAction* ua)
950 {
951   G4RunManager::SetUserAction(ua);
952 }
953 
954 // --------------------------------------------------------------------
955 void G4SubEvtRunManager::SetUserAction(G4UserSteppingAction* ua)
956 {
957   G4RunManager::SetUserAction(ua);
958 }
959 
960 
961