Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4SubEvtRunManager.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
28#include "G4SubEvtRunManager.hh"
29
30#include "G4AutoLock.hh"
31#include "G4EnvironmentUtils.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"
42#include "G4ThreadPool.hh"
43#include "G4Threading.hh"
44#include "G4Timer.hh"
46#include "G4UImanager.hh"
47#include "G4UserRunAction.hh"
49#include "G4UserTaskQueue.hh"
52#include "G4VUserPhysicsList.hh"
53#include "G4UserEventAction.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
67namespace
68{
69G4Mutex scorerMergerMutex;
70G4Mutex accessSubEventMutex;
71G4Mutex registerSubEvtWorkerMutex;
72} // namespace
73
74//============================================================================//
75
77 G4bool useTBB, G4int grainsize)
78 : G4TaskRunManager(task_queue, useTBB, grainsize)
79{
81 G4UImanager::GetUIpointer()->SetAlias("RunMode subEventParallel");
82}
83
84//============================================================================//
85
89
90//============================================================================//
91
93{
94 // relying all the necessary deletion upon the base class
95 // G4TaskRunManager::~G4TaskRunManager()
96}
97
98//============================================================================//
99
101{
103 G4bool firstTime = (threadPool == nullptr);
105
107
108 // make sure all worker threads are set up.
110 if (firstTime) G4RunManager::SetRunIDCounter(0);
111 // G4UImanager::GetUIpointer()->SetIgnoreCmdNotFound(true);
112}
113
114//============================================================================//
115
117{
119 if(!fakeRun)
120 { if(CheckSubEvtTypes()) runInProgress = true; }
121}
122
123//============================================================================//
124
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
138}
139
140//============================================================================//
141
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);
148 currentEvent = nullptr;
150}
151
152//============================================================================//
153
155{
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
195}
196
197//============================================================================//
198
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) {
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 {
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
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
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
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
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)
288 });
289 }
290 }
291 else {
292 if (verboseLevel > 0) {
293 std::stringstream msg;
294 msg << "--> G4SubEvtRunManager::CreateAndStartWorkers() --> "
295 << "Initializing workers...";
296
297 std::stringstream ss;
298 ss.fill('=');
299 ss << std::setw((G4int)msg.str().length()) << "";
300 G4cout << "\n" << ss.str() << "\n" << msg.str() << "\n" << ss.str() << "\n" << G4endl;
301 }
302
304 threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::InitializeWorker(); });
305 }
306 initializeStarted = true;
307 }
308 else {
309 auto initCmdStack = GetCommandStack();
310 if (!initCmdStack.empty()) {
311 threadPool->execute_on_all_threads([cmds = std::move(initCmdStack)]() {
312 for (auto& itr : cmds)
314 });
315 }
316
317 // cleans up a previous run and events in case a thread
318 // does not execute any tasks
319 threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::ExecuteWorkerInit(); });
320
321 if (verboseLevel > 0) {
322 std::stringstream msg;
323 msg << "--> G4SubEvtRunManager::CreateAndStartWorkers() --> "
324 << "Creating " << numberOfTasks << " tasks with " << numberOfEventsPerTask
325 << " events/task...";
326
327 std::stringstream ss;
328 ss.fill('=');
329 ss << std::setw((G4int)msg.str().length()) << "";
330 G4cout << "\n" << ss.str() << "\n" << msg.str() << "\n" << ss.str() << "\n" << G4endl;
331 }
332
333 /* TODO (PHASE-II): Better calculation of task/event/subevents
334 Currently, number of tasks is equal to number of threads
335 and each task has a loop that endlessly asks for next sub-event
336 until no additional sub-event is available in the master.
337 This is not ideal. We should make each task work only for some limited
338 number of sub-events, and create as many number of tasks as needed
339 on the fly during the event loop of the master thread., e.g.
340 G4int remaining = numberOfEventToBeProcessed;
341 for (G4int nt = 0; nt < numberOfTasks + 1; ++nt) {
342 if (remaining > 0) AddEventTask(nt);
343 remaining -= numberOfEventsPerTask;
344 }
345 */
346 for(G4int nt = 0; nt < numberOfTasks; ++nt)
347 { AddEventTask(nt); }
348 }
349}
350
351//============================================================================//
352
354{
355 if (verboseLevel > 3) G4cout << "Adding task " << nt << " to task-group..." << G4endl;
357}
358
359//============================================================================//
360
362{
364 G4int nFill = 0;
365 switch (SeedOncePerCommunication()) {
366 case 0:
368 break;
369 case 1:
370 nFill = numberOfTasks - nSeedsFilled;
371 break;
372 case 2:
373 default:
375 }
376 // Generates up to nSeedsMax seed pairs only.
377 if (nFill > nSeedsMax) nFill = nSeedsMax;
378 masterRNGEngine->flatArray(nSeedsPerEvent * nFill, randDbl);
379 helper->Refill(randDbl, nFill);
380 nSeedsFilled += nFill;
381}
382
383//============================================================================//
384
385void G4SubEvtRunManager::InitializeEventLoop(G4int n_event, const char* macroFile, G4int n_select)
386{
387 MTkernel->SetUpDecayChannels();
390
391 if (!fakeRun) {
392 nSeedsUsed = 0;
393 nSeedsFilled = 0;
394
395 if (verboseLevel > 0) timer->Start();
396
397 n_select_msg = n_select;
398 if (macroFile != nullptr) {
399 if (n_select_msg < 0) n_select_msg = n_event;
400
401 msgText = "/control/execute ";
402 msgText += macroFile;
403 selectMacro = macroFile;
404 }
405 else {
406 n_select_msg = -1;
407 selectMacro = "";
408 }
409
411
412 // initialize seeds
413 // If user did not implement InitializeSeeds,
414 // use default: nSeedsPerEvent seeds per event
415
416 if (n_event > 0) {
417 G4bool _overload = InitializeSeeds(n_event);
418 G4bool _functor = false;
419 if (!_overload) _functor = initSeedsCallback(n_event, nSeedsPerEvent, nSeedsFilled);
420 if (!_overload && !_functor) {
422 switch (SeedOncePerCommunication()) {
423 case 1:
425 break;
426 default:
428 msgd << "Parameter value <" << SeedOncePerCommunication()
429 << "> of seedOncePerCommunication is invalid. It is reset "
430 "to 1.";
431 G4Exception("G4SubEvtRunManager::InitializeEventLoop()", "Run10036", JustWarning, msgd);
434 }
435
436 // Generates up to nSeedsMax seed pairs only.
439 helper->Fill(randDbl, nSeedsFilled, n_event, nSeedsPerEvent);
440 }
441 }
442 }
443
444 // Now initialize workers. Check if user defined a WorkerThreadInitialization
445 if (userWorkerThreadInitialization == nullptr)
447
448 // Prepare UI commands for threads
450
451 // Start worker threads
453}
454
455//============================================================================//
456
458{
459 // Wait for all worker threads to have finished the run
460 // i.e. wait for them to return from RunTermination()
461 // This guarantee that userrunaction for workers has been called
462
463 runInProgress = false;
464
465 //TODO (PHASE-II): do we need this???
466 workTaskGroup->wait();
467
468 // Wait now for all threads to finish event-loop
470
471 // Now call base-class method
474
475 if(currentRun!=nullptr)
476 {
477 auto eventVector = currentRun->GetEventVector();
478 if(eventVector!=nullptr)
479 {
480 G4int notReady = 1;
481 while(notReady>0)
482 {
483 notReady = 0;
484 for(auto ev:*eventVector)
485 {
486 if(ev->GetNumberOfRemainingSubEvents()>0 || ev->GetNumberOfGrips()>0 )
487 { notReady++; }
488 }
489 if(notReady>0)
490 {
491 if(verboseLevel>2)
492 {
493 G4cout << "G4SubEvtRunManager::RunTermination - " << notReady
494 << " events are still incomplete. Waiting for them." << G4endl;
495 }
496 G4THREADSLEEP(1);
497 }
498 }
499 }
501 }
502}
503
504//============================================================================//
505
507{
509 // Call base class stuff...
511
512 GetMasterWorlds().clear();
513 auto nWorlds = (G4int)G4TransportationManager::GetTransportationManager()->GetNoWorlds();
515 for (G4int iWorld = 0; iWorld < nWorlds; ++iWorld) {
516 addWorld(iWorld, *itrW);
517 ++itrW;
518 }
519}
520
521//============================================================================//
522
523void G4SubEvtRunManager::MergeScores(const G4ScoringManager* localScoringManager)
524{
525 G4AutoLock l(&scorerMergerMutex);
526 if (masterScM != nullptr) masterScM->Merge(localScoringManager);
527}
528
530 G4long& s1, G4long& s2, G4long& s3, G4bool reseedRequired)
531{
532 G4AutoLock l(&accessSubEventMutex);
533
534// This method is invoked from the worker, the ownership of G4SubEvent object
535// remains to the master, i.e. will be deleted by the master thread through
536// TerminateSubEvent() method.
537
538 if(currentRun==nullptr)
539 {
540 // Run has not yet started.
541 notReady = true;
542 return nullptr;
543 }
544
545 auto eventVector = currentRun->GetEventVector();
546 // RACE HERE: against:
547 // 1 G4Run::StoreEvent(G4Event*) G4Run.cc:80
548 // 2 G4RunManager::StackPreviousEvent(G4Event*) G4RunManager.cc:572
549 for(auto& ev : *eventVector)
550 {
551 // looping over stored events
552 // RACE HERE: against:
553 // 1 G4Run::StoreEvent(G4Event*) G4Run.cc:80
554 // 2 G4RunManager::StackPreviousEvent(G4Event*) G4RunManager.cc:572
555 auto se = const_cast<G4Event*>(ev)->PopSubEvent(ty);
556 if(se!=nullptr)
557 {
558 // Sub-event is found in an event that is already finished its event-loop
559 notReady = false;
560 if(reseedRequired) SetUpSeedsForSubEvent(s1,s2,s3);
561 return se;
562 }
563 }
564
565 auto sep = eventManager->PopSubEvent(ty);
566 if(sep!=nullptr)
567 {
568 // Sub-event is found in an event that is still in the event loop
569 notReady = false;
570 if(reseedRequired) SetUpSeedsForSubEvent(s1,s2,s3);
571 return sep;
572 } else {
573 // No sub-event available
574 // RACE HERE vs line 345
575 if(runInProgress)
576 {
577 // Run is still in progress. Worker should wait until a sub-event is ready
578 notReady = true;
579 }
580 else
581 {
582 // Run is over. No more sub-event to come unless new run starts.
583 notReady = false;
584 }
585 return nullptr;
586 }
587}
588
590{
591 //TODO (PHASE-II): Seeding scheme for sub-event has to be revisited
593 G4int idx_rndm = nSeedsPerEvent * nSeedsUsed;
594 s1 = helper->GetSeed(idx_rndm);
595 s2 = helper->GetSeed(idx_rndm + 1);
596 if (nSeedsPerEvent == 3) s3 = helper->GetSeed(idx_rndm + 2);
597 ++nSeedsUsed;
599}
600
601
602//============================================================================//
603//
604//G4bool G4SubEvtRunManager::SetUpAnEvent(G4Event* evt, G4long& s1, G4long& s2, G4long& s3,
605// G4bool reseedRequired)
606//{
607// G4AutoLock l(&setUpEventMutex);
608// if (numberOfEventProcessed < numberOfEventToBeProcessed) {
609// evt->SetEventID(numberOfEventProcessed);
610// if (reseedRequired) {
611// G4RNGHelper* helper = G4RNGHelper::GetInstance();
612// G4int idx_rndm = nSeedsPerEvent * nSeedsUsed;
613// s1 = helper->GetSeed(idx_rndm);
614// s2 = helper->GetSeed(idx_rndm + 1);
615// if (nSeedsPerEvent == 3) s3 = helper->GetSeed(idx_rndm + 2);
616// ++nSeedsUsed;
617// if (nSeedsUsed == nSeedsFilled) RefillSeeds();
618// }
619// numberOfEventProcessed++;
620// return true;
621// }
622// return false;
623//}
624
625//============================================================================//
626//
627//G4int G4SubEvtRunManager::SetUpNEvents(G4Event* evt, G4SeedsQueue* seedsQueue, G4bool reseedRequired)
628//{
629// G4AutoLock l(&setUpEventMutex);
630// if (numberOfEventProcessed < numberOfEventToBeProcessed && !runAborted) {
631// G4int nevt = numberOfEventsPerTask;
632// G4int nmod = eventModulo;
633// if (numberOfEventProcessed + nevt > numberOfEventToBeProcessed) {
634// nevt = numberOfEventToBeProcessed - numberOfEventProcessed;
635// nmod = numberOfEventToBeProcessed - numberOfEventProcessed;
636// }
637// evt->SetEventID(numberOfEventProcessed);
638//
639// if (reseedRequired) {
640// G4RNGHelper* helper = G4RNGHelper::GetInstance();
641// G4int nevRnd = nmod;
642// if (SeedOncePerCommunication() > 0) nevRnd = 1;
643// for (G4int i = 0; i < nevRnd; ++i) {
644// seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed));
645// seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 1));
646// if (nSeedsPerEvent == 3) seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 2));
647// nSeedsUsed++;
648// if (nSeedsUsed == nSeedsFilled) RefillSeeds();
649// }
650// }
651// numberOfEventProcessed += nevt;
652// return nevt;
653// }
654// return 0;
655//}
656
657//============================================================================//
658
660{
661 G4AutoLock l(&accessSubEventMutex);
662 auto masterEvt = se->GetEvent();
663 if(masterEvt==nullptr) {
664 G4Exception("G4SubEvtRunManager::SubEventFinished()","SERM0001",
665 FatalException,"Pointer of master event is null. PANIC!");
666 return; // NOLINT: required to help Coverity recognise FatalException as exit point
667 }
668
669 if(userEventAction) {
670 userEventAction->MergeSubEvent(masterEvt,evt);
671 }
672 if(trajectoriesToBeMerged) MergeTrajectories(se,evt);
674 evt->ScoresRecorded();
675 eventManager->TerminateSubEvent(se,evt);
676}
677
678//============================================================================//
679
681{
682 auto masterEvt = se->GetEvent();
683 auto* trajVector = evt->GetTrajectoryContainer()->GetVector();
684 auto* masterTrajContainer = masterEvt->GetTrajectoryContainer();
685 if(masterTrajContainer==nullptr)
686 {
687 masterTrajContainer = new G4TrajectoryContainer;
688 masterEvt->SetTrajectoryContainer(masterTrajContainer);
689 }
690 for(auto& traj : *trajVector)
691 {
692 if(traj!=nullptr) {
693 auto* cloned = traj->CloneForMaster();
694 masterTrajContainer->push_back(cloned);
695 }
696 }
697}
698
699//============================================================================//
700
702{
703 auto masterEvt = se->GetEvent();
704
706 if (ScM == nullptr) return;
707 auto nPar = (G4int)ScM->GetNumberOfMesh();
708 if (nPar < 1) return;
709
710 if(verboseLevel>3) {
711 G4cout << "merging scores of sub-event belonging to event id #" << masterEvt->GetEventID()
712 << " --- sub-event has " << evt->GetHCofThisEvent()->GetCapacity()
713 << " hits collections" << G4endl;
714 }
715 G4HCofThisEvent* HCE = evt->GetHCofThisEvent();
716 if (HCE == nullptr) return;
717 auto nColl = (G4int)HCE->GetCapacity();
718 G4HCofThisEvent* masterHCE = masterEvt->GetHCofThisEvent();
719 if (masterHCE == nullptr || (G4int)masterHCE->GetCapacity() != nColl)
720 {
721 G4Exception("G4SubEvtRunManager::UpdateScoringForSubEvent()","SERM0002",
722 FatalException,"Number of hits colleactions for scrorers mismatch!! PANIC!!");
723 return;
724 }
725 for (G4int i = 0; i < nColl; ++i) {
726 auto* HC = dynamic_cast<G4THitsMap<G4double>*>(HCE->GetHC(i));
727 auto* masterHC = dynamic_cast<G4THitsMap<G4double>*>(masterHCE->GetHC(i));
728 if (HC != nullptr && masterHC != nullptr)
729 { *masterHC += *HC; }
730 else
731 {
732 G4Exception("G4SubEvtRunManager::UpdateScoringForSubEvent()","SERM0003",
733 FatalException,"HitsCollection is not type of G4THitsMap<G4double>. PANIC!!");
734 return;
735 }
736 }
737
738}
739
740//============================================================================//
741
743{
744 // Delete all events carried over from previous run.
745 // This method is invoked at the beginning of the next run
746 // or from the destructor of G4RunManager at the very end of
747 // the program.
748 auto evItr = previousEvents->cbegin();
749 while (evItr != previousEvents->cend()) {
750 G4Event* evt = *evItr;
751 if (evt != nullptr)
752 {
754 // remove evt from the event vector of G4Run as well
755 if(currentRun!=nullptr)
756 {
757 auto eventVector = currentRun->GetEventVector();
758 auto eItr = std::find(eventVector->cbegin(),eventVector->cend(),evt);
759 if(eItr != eventVector->cend()) eventVector->erase(eItr);
760 }
761 delete evt;
762 }
763 evItr = previousEvents->erase(evItr);
764 }
765 if(currentRun!=nullptr)
766 {
767 auto eventVector = currentRun->GetEventVector();
768 if(eventVector==nullptr || eventVector->empty()) return;
769 auto eItr = eventVector->cbegin();
770 while(eItr != eventVector->cend())
771 {
772 const G4Event* ev = *eItr;
773 if(ev!=nullptr)
774 {
776 delete ev;
777 }
778 eItr = eventVector->erase(eItr);
779 }
780 }
781}
782
783//============================================================================//
784
786{
787 // Force workers to execute (if any) all UI commands left in the stack
789
790 if (workTaskGroup != nullptr) {
791 workTaskGroup->join();
792 if (!fakeRun)
793 threadPool->execute_on_all_threads([]() { G4TaskRunManagerKernel::TerminateWorker(); });
794 }
795}
796
797//============================================================================//
798
800{
801 // This method is valid only for GeomClosed or EventProc state
803 if (currentState == G4State_GeomClosed || currentState == G4State_EventProc) {
804 runAborted = true;
805 MTkernel->BroadcastAbortRun(softAbort);
806 }
807 else {
808 G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
809 }
810}
811
812//============================================================================//
813
815{
816 // nothing to do in the master thread
817}
818
819//============================================================================//
820
822{
823 if (workTaskGroup != nullptr) {
824 workTaskGroup->join();
825 if (!fakeRun)
826 threadPool->execute_on_all_threads(
828 }
829}
830
831//============================================================================//
832
834{
836
837 auto process_commands_stack = []() {
839 if (mrm != nullptr) {
840 auto cmds = mrm->GetCommandStack();
841 for (const auto& itr : cmds)
842 G4UImanager::GetUIpointer()->ApplyCommand(itr); // TLS instance
844 }
845 };
846
847 if (threadPool != nullptr) threadPool->execute_on_all_threads(process_commands_stack);
848}
849
850//============================================================================//
851
853
854//============================================================================//
855
857{
858 G4AutoLock l(&registerSubEvtWorkerMutex);
859 fSubEvtTypeMap[ty] = maxEnt;
860 eventManager->UseSubEventParallelism();
861 eventManager->GetStackManager()->RegisterSubEventType(ty,maxEnt);
862}
863
865{
866 G4AutoLock l(&registerSubEvtWorkerMutex);
867 fWorkerMap[wrm] = typ;
868}
869
870G4bool G4SubEvtRunManager::CheckSubEvtTypes()
871{
872 for(auto& seT : fSubEvtTypeMap)
873 {
874 G4int ty = seT.first;
875 G4int seTyp = -1;
876 for(auto& worker : fWorkerMap)
877 {
878 if(worker.second==ty)
879 { seTyp = ty; break; }
880 }
881 if(seTyp==-1)
882 {
884 ed << "There is no worker with sub-event type " << ty
885 << " registered. There must be at least one worker who is responsible.";
886 G4Exception("G4SubEvtRunManager::CheckSubEvtTypes",
887 "SubEvtRM1210",FatalException,ed);
888 return false;
889 }
890 }
891 return true;
892}
893
898
899// --------------------------------------------------------------------
904
905// --------------------------------------------------------------------
911
912// --------------------------------------------------------------------
917
918// --------------------------------------------------------------------
924
925// --------------------------------------------------------------------
927{
928 G4RunManager::SetUserAction(userAction);
929 if (userAction != nullptr) userAction->SetMaster(true);
930}
931
932// --------------------------------------------------------------------
937
938// --------------------------------------------------------------------
943
944// --------------------------------------------------------------------
949
950// --------------------------------------------------------------------
955
956// --------------------------------------------------------------------
961
962
G4ApplicationState
@ G4State_EventProc
@ G4State_GeomClosed
G4TemplateAutoLock< G4Mutex > G4AutoLock
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4TemplateRNGHelper< G4long > G4RNGHelper
#define G4THREADSLEEP(tick)
std::mutex G4Mutex
long G4long
Definition G4Types.hh:87
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
PTL::VUserTaskQueue G4VUserTaskQueue
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
G4bool ToBeKept() const
Definition G4Event.hh:105
G4int GetNumberOfGrips() const
Definition G4Event.hh:123
G4TrajectoryContainer * GetTrajectoryContainer() const
Definition G4Event.hh:168
G4HCofThisEvent * GetHCofThisEvent() const
Definition G4Event.hh:164
G4bool IsEventCompleted() const
Definition G4Event.hh:308
void ScoresRecorded() const
Definition G4Event.hh:305
void EventCompleted() const
Definition G4Event.hh:307
G4int GetNumberOfRemainingSubEvents() const
Definition G4Event.cc:277
std::size_t GetCapacity()
G4VHitsCollection * GetHC(G4int i)
static G4int SeedOncePerCommunication()
static void SetSeedOncePerCommunication(G4int val)
G4int numberOfEventToBeProcessed
virtual void ThisWorkerProcessCommandsStackDone()
static void addWorld(G4int counter, G4VPhysicalVolume *w)
virtual void PrepareCommandsStack()
static G4MTRUN_DLL G4ScoringManager * masterScM
static G4MTRunManager * GetMasterRunManager()
static masterWorlds_t & GetMasterWorlds()
std::vector< G4String > GetCommandStack()
G4UserWorkerInitialization * userWorkerInitialization
virtual void Initialize()
virtual void ReportEventDeletion(const G4Event *evt)
std::list< G4Event * > * previousEvents
G4Timer * timer
void SetRunIDCounter(G4int i)
G4UserWorkerThreadInitialization * userWorkerThreadInitialization
G4int numberOfEventProcessed
G4UserEventAction * userEventAction
G4Run * currentRun
G4String msgText
virtual void BeamOn(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1)
G4String selectMacro
virtual void RunTermination()
G4VUserActionInitialization * userActionInitialization
void UpdateScoring(const G4Event *evt=nullptr)
virtual void TerminateEventLoop()
virtual void SetUserAction(G4UserRunAction *userAction)
RMType runManagerType
G4int n_perviousEventsToBeStored
virtual void SetUserInitialization(G4VUserDetectorConstruction *userInit)
virtual G4Event * GenerateEvent(G4int i_event)
G4EventManager * eventManager
virtual void RunInitialization()
G4Event * currentEvent
virtual void ConstructScoringWorlds()
std::size_t GetNumberOfMesh() const
static G4ScoringManager * GetScoringManagerIfExist()
const G4ApplicationState & GetCurrentState() const
static G4StateManager * GetStateManager()
G4Event * GetEvent() const
Definition G4SubEvent.hh:76
void RunTermination() override
void RegisterSubEvtWorker(G4WorkerSubEvtRunManager *, G4int)
void ConstructScoringWorlds() override
void AbortEvent() override
void CleanUpUnnecessaryEvents(G4int keepNEvents) override
void CleanUpPreviousEvents() override
void AbortRun(G4bool softAbort=false) override
G4SubEvtRunManager(G4bool useTBB=G4GetEnv< G4bool >("G4USE_TBB", false))
void ComputeNumberOfTasks() override
void ProcessOneEvent(G4int i_event) override
void UpdateScoringForSubEvent(const G4SubEvent *se, const G4Event *evt) override
void RunInitialization() override
void StackPreviousEvent(G4Event *anEvent) override
std::atomic< G4bool > runInProgress
void AddEventTask(G4int) override
void TerminateOneEvent() override
void SetUserInitialization(G4VUserPhysicsList *userPL) override
void MergeTrajectories(const G4SubEvent *se, const G4Event *evt) override
void InitializeEventLoop(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1) override
void SubEventFinished(const G4SubEvent *se, const G4Event *evt) override
void WaitForEndEventLoopWorkers() override
void SetUpSeedsForSubEvent(G4long &s1, G4long &s2, G4long &s3)
void MergeScores(const G4ScoringManager *localScoringManager) override
void TerminateWorkers() override
void Initialize() override
void CreateAndStartWorkers() override
void ThisWorkerProcessCommandsStackDone() override
void RequestWorkersProcessCommandsStack() override
void RegisterSubEventType(G4int ty, G4int maxEnt) override
void RefillSeeds() override
G4bool InitializeSeeds(G4int) override
const G4SubEvent * GetSubEvent(G4int ty, G4bool &notReady, G4long &s1, G4long &s2, G4long &s3, G4bool reseedRequired=true) override
void SetUserAction(G4UserRunAction *userAction) override
static std::vector< G4String > & InitCommandStack()
void InitializeThreadPool() override
InitializeSeedsCallback initSeedsCallback
RunTaskGroup * workTaskGroup
CLHEP::HepRandomEngine * masterRNGEngine
G4TaskRunManagerKernel * MTkernel
G4ThreadPool *& threadPool
G4TaskRunManager(G4bool useTBB=G4GetEnv< G4bool >("G4USE_TBB", false))
static G4TemplateRNGHelper< G4long > * GetInstance()
virtual const T GetSeed(const G4int &sdId)
void Fill(G4double *dbl, G4int nev, G4int nev_tot, G4int nrpe)
void Refill(G4double *dbl, G4int nev)
TrajectoryVector * GetVector() const
static G4TransportationManager * GetTransportationManager()
std::vector< G4VPhysicalVolume * >::iterator GetWorldsIterator()
G4int ApplyCommand(const char *aCommand)
void SetAlias(const char *aliasLine)
static G4UImanager * GetUIpointer()
virtual void SetMaster(G4bool val=true)
virtual void InitializeWorker()
static G4VVisManager * GetConcreteInstance()
static G4WorkerTaskRunManager * GetWorkerRunManager()