Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 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(G4VUser 77 78 : G4TaskRunManager(task_queue, useTBB, grains 79 { 80 runManagerType = subEventMasterRM; 81 G4UImanager::GetUIpointer()->SetAlias("RunMo 82 } 83 84 //============================================ 85 86 G4SubEvtRunManager::G4SubEvtRunManager(G4bool 87 : G4SubEvtRunManager(nullptr, useTBB, 0) 88 { runManagerType = subEventMasterRM; } 89 90 //============================================ 91 92 G4SubEvtRunManager::~G4SubEvtRunManager() 93 { 94 // relying all the necessary deletion upon t 95 // G4TaskRunManager::~G4TaskRunManager() 96 } 97 98 //============================================ 99 100 void G4SubEvtRunManager::Initialize() 101 { 102 SetSeedOncePerCommunication(1); 103 G4bool firstTime = (threadPool == nullptr); 104 if (firstTime) G4TaskRunManager::InitializeT 105 106 G4RunManager::Initialize(); 107 108 // make sure all worker threads are set up. 109 G4RunManager::BeamOn(0); 110 if (firstTime) G4RunManager::SetRunIDCounter 111 // G4UImanager::GetUIpointer()->SetIgnoreCmd 112 } 113 114 //============================================ 115 116 void G4SubEvtRunManager::RunInitialization() 117 { 118 G4RunManager::RunInitialization(); 119 if(!fakeRun) 120 { if(CheckSubEvtTypes()) runInProgress = tru 121 } 122 123 //============================================ 124 125 void G4SubEvtRunManager::ProcessOneEvent(G4int 126 { 127 currentEvent = GenerateEvent(i_event); 128 eventManager->ProcessOneEvent(currentEvent); 129 130 // Following two lines should not be execute 131 // be still being processed. These methods a 132 // to this event are processed and scores of 133 // corresponding master event. 134 //AnalyzeEvent(currentEvent); 135 //UpdateScoring(); 136 137 if (i_event < n_select_msg) G4UImanager::Get 138 } 139 140 //============================================ 141 142 void G4SubEvtRunManager::TerminateOneEvent() 143 { 144 // We must serialize access here because wor 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(G4 155 { 156 if(n_perviousEventsToBeStored>0) { 157 G4ExceptionDescription ed; 158 ed << "G4RunManager::SetNumberOfEventsToBe 159 << "User may still keep events bu G4Eve 160 G4Exception("G4SubEvtRunManager::StackPrev 161 return; 162 } 163 164 if(anEvent->GetNumberOfRemainingSubEvents()> 165 // sub-events are still under processing. Ev 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) userEventAc 177 auto pVisManager = G4VVisManager::GetCon 178 if (pVisManager) pVisManager->EventReady 179 UpdateScoring(anEvent); 180 if(anEvent->ToBeKept() || anEvent->GetNu 181 { // we keep this event for post-process 182 currentRun->StoreEvent(anEvent); 183 } 184 else 185 { 186 ReportEventDeletion(anEvent); 187 delete anEvent; 188 } 189 } else { 190 G4Exception("G4SubEvtRunManager::StackPr 191 } 192 } 193 194 CleanUpUnnecessaryEvents(0); 195 } 196 197 //============================================ 198 199 void G4SubEvtRunManager::CleanUpUnnecessaryEve 200 { 201 // Delete events that are no longer necessar 202 // processing such as visualization. 203 // N.B. If ToBeKept() is true, the pointer o 204 // kept in G4Run, and deleted along with the 205 206 if(keepNEvents>0) { 207 G4ExceptionDescription ed; 208 ed << "G4RunManager::SetNumberOfEventsToBe 209 << "User may still keep events bu G4Eve 210 G4Exception("G4SubEvtRunManager::CleanUpUn 211 return; 212 } 213 214 assert(currentRun!=nullptr); 215 216 auto eventVector = currentRun->GetEventVecto 217 if(eventVector==nullptr || eventVector->empt 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() 227 { // This event has been completed sin 228 ev->EventCompleted(); 229 if(userEventAction!=nullptr) userEve 230 auto pVisManager = G4VVisManager::Ge 231 if (pVisManager) pVisManager->EventR 232 UpdateScoring(ev); 233 if(ev->ToBeKept() || ev->GetNumberOf 234 { // we keep this event for post-pro 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->GetNumberO 250 { // we still need this event 251 eItr++; 252 } 253 else 254 { // post-processing done. we no longer 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 o 275 // Instead of pthread based workers, create 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([cm 285 for (auto& itr : cmds) 286 G4UImanager::GetUIpointer()->Apply 287 G4WorkerTaskRunManager::GetWorkerRun 288 }); 289 } 290 } 291 else { 292 std::stringstream msg; 293 msg << "--> G4SubEvtRunManager::CreateAn 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" << ms 300 301 G4TaskRunManagerKernel::InitCommandStack 302 threadPool->execute_on_all_threads([]() 303 } 304 initializeStarted = true; 305 } 306 else { 307 auto initCmdStack = GetCommandStack(); 308 if (!initCmdStack.empty()) { 309 threadPool->execute_on_all_threads([cmds 310 for (auto& itr : cmds) 311 G4UImanager::GetUIpointer()->ApplyCo 312 }); 313 } 314 315 // cleans up a previous run and events in 316 // does not execute any tasks 317 threadPool->execute_on_all_threads([]() { 318 319 { 320 std::stringstream msg; 321 msg << "--> G4SubEvtRunManager::CreateAn 322 << "Creating " << numberOfTasks << " 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" << ms 329 } 330 331 /* TODO (PHASE-II): Better calculation of 332 Currently, number of tasks is equal to 333 and each task has a loop that endlessly 334 until no additional sub-event is availa 335 This is not ideal. We should make each 336 number of sub-events, and create as man 337 on the fly during the event loop of the 338 G4int remaining = numberOfEventToBeProcess 339 for (G4int nt = 0; nt < numberOfTasks + 1; 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 354 workTaskGroup->exec([]() { G4TaskRunManagerK 355 } 356 357 //============================================ 358 359 void G4SubEvtRunManager::RefillSeeds() 360 { 361 G4RNGHelper* helper = G4RNGHelper::GetInstan 362 G4int nFill = 0; 363 switch (SeedOncePerCommunication()) { 364 case 0: 365 nFill = numberOfEventToBeProcessed - nSe 366 break; 367 case 1: 368 nFill = numberOfTasks - nSeedsFilled; 369 break; 370 case 2: 371 default: 372 nFill = (numberOfEventToBeProcessed - nS 373 } 374 // Generates up to nSeedsMax seed pairs only 375 if (nFill > nSeedsMax) nFill = nSeedsMax; 376 masterRNGEngine->flatArray(nSeedsPerEvent * 377 helper->Refill(randDbl, nFill); 378 nSeedsFilled += nFill; 379 } 380 381 //============================================ 382 383 void G4SubEvtRunManager::InitializeEventLoop(G 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_e 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 InitializeSee 412 // use default: nSeedsPerEvent seeds per e 413 414 if (n_event > 0) { 415 G4bool _overload = InitializeSeeds(n_eve 416 G4bool _functor = false; 417 if (!_overload) _functor = initSeedsCall 418 if (!_overload && !_functor) { 419 G4RNGHelper* helper = G4RNGHelper::Get 420 switch (SeedOncePerCommunication()) { 421 case 1: 422 nSeedsFilled = nworkers; 423 break; 424 default: 425 G4ExceptionDescription msgd; 426 msgd << "Parameter value <" << See 427 << "> of seedOncePerCommunica 428 "to 1."; 429 G4Exception("G4SubEvtRunManager::I 430 SetSeedOncePerCommunication(1); 431 nSeedsFilled = nworkers; 432 } 433 434 // Generates up to nSeedsMax seed pair 435 if (nSeedsFilled > nSeedsMax) nSeedsFi 436 masterRNGEngine->flatArray(nSeedsPerEv 437 helper->Fill(randDbl, nSeedsFilled, n_ 438 } 439 } 440 } 441 442 // Now initialize workers. Check if user def 443 if (userWorkerThreadInitialization == nullpt 444 userWorkerThreadInitialization = new G4Use 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 finis 458 // i.e. wait for them to return from RunTerm 459 // This guarantee that userrunaction for wor 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- 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->GetEventVec 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 485 { notReady++; } 486 } 487 if(notReady>0) 488 { 489 if(verboseLevel>2) 490 { 491 G4cout << "G4SubEvtRunManager::Run 492 << " events are still incom 493 } 494 G4THREADSLEEP(1); 495 } 496 } 497 } 498 CleanUpUnnecessaryEvents(0); 499 } 500 } 501 502 //============================================ 503 504 void G4SubEvtRunManager::ConstructScoringWorld 505 { 506 masterScM = G4ScoringManager::GetScoringMana 507 // Call base class stuff... 508 G4RunManager::ConstructScoringWorlds(); 509 510 GetMasterWorlds().clear(); 511 auto nWorlds = (G4int)G4TransportationManage 512 auto itrW = G4TransportationManager::GetTran 513 for (G4int iWorld = 0; iWorld < nWorlds; ++i 514 addWorld(iWorld, *itrW); 515 ++itrW; 516 } 517 } 518 519 //============================================ 520 521 void G4SubEvtRunManager::MergeScores(const G4S 522 { 523 G4AutoLock l(&scorerMergerMutex); 524 if (masterScM != nullptr) masterScM->Merge(l 525 } 526 527 const G4SubEvent* G4SubEvtRunManager::GetSubEv 528 G4long& s1, G4long& s2, G4long& 529 { 530 G4AutoLock l(&accessSubEventMutex); 531 532 // This method is invoked from the worker, the 533 // remains to the master, i.e. will be deleted 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->GetEventVecto 544 // RACE HERE: against: 545 // 1 G4Run::StoreEvent(G4Event*) G4Run.cc:80 546 // 2 G4RunManager::StackPreviousEvent(G4Even 547 for(auto& ev : *eventVector) 548 { 549 // looping over stored events 550 // RACE HERE: against: 551 // 1 G4Run::StoreEvent(G4Event*) G4Run.cc: 552 // 2 G4RunManager::StackPreviousEvent(G4Ev 553 auto se = const_cast<G4Event*>(ev)->PopSub 554 if(se!=nullptr) 555 { 556 // Sub-event is found in an event that is 557 notReady = false; 558 if(reseedRequired) SetUpSeedsForSubEvent 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 st 567 notReady = false; 568 if(reseedRequired) SetUpSeedsForSubEvent(s 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 576 notReady = true; 577 } 578 else 579 { 580 // Run is over. No more sub-event to come 581 notReady = false; 582 } 583 return nullptr; 584 } 585 } 586 587 void G4SubEvtRunManager::SetUpSeedsForSubEvent 588 { 589 //TODO (PHASE-II): Seeding scheme for sub-ev 590 G4RNGHelper* helper = G4RNGHelper::GetInstan 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->GetSee 595 ++nSeedsUsed; 596 if (nSeedsUsed == nSeedsFilled) RefillSeeds( 597 } 598 599 600 //============================================ 601 // 602 //G4bool G4SubEvtRunManager::SetUpAnEvent(G4Ev 603 // G4bool 604 //{ 605 // G4AutoLock l(&setUpEventMutex); 606 // if (numberOfEventProcessed < numberOfEvent 607 // evt->SetEventID(numberOfEventProcessed); 608 // if (reseedRequired) { 609 // G4RNGHelper* helper = G4RNGHelper::Get 610 // G4int idx_rndm = nSeedsPerEvent * nSee 611 // s1 = helper->GetSeed(idx_rndm); 612 // s2 = helper->GetSeed(idx_rndm + 1); 613 // if (nSeedsPerEvent == 3) s3 = helper-> 614 // ++nSeedsUsed; 615 // if (nSeedsUsed == nSeedsFilled) Refill 616 // } 617 // numberOfEventProcessed++; 618 // return true; 619 // } 620 // return false; 621 //} 622 623 //============================================ 624 // 625 //G4int G4SubEvtRunManager::SetUpNEvents(G4Eve 626 //{ 627 // G4AutoLock l(&setUpEventMutex); 628 // if (numberOfEventProcessed < numberOfEvent 629 // G4int nevt = numberOfEventsPerTask; 630 // G4int nmod = eventModulo; 631 // if (numberOfEventProcessed + nevt > numb 632 // nevt = numberOfEventToBeProcessed - nu 633 // nmod = numberOfEventToBeProcessed - nu 634 // } 635 // evt->SetEventID(numberOfEventProcessed); 636 // 637 // if (reseedRequired) { 638 // G4RNGHelper* helper = G4RNGHelper::Get 639 // G4int nevRnd = nmod; 640 // if (SeedOncePerCommunication() > 0) ne 641 // for (G4int i = 0; i < nevRnd; ++i) { 642 // seedsQueue->push(helper->GetSeed(nSe 643 // seedsQueue->push(helper->GetSeed(nSe 644 // if (nSeedsPerEvent == 3) seedsQueue- 645 // nSeedsUsed++; 646 // if (nSeedsUsed == nSeedsFilled) Refi 647 // } 648 // } 649 // numberOfEventProcessed += nevt; 650 // return nevt; 651 // } 652 // return 0; 653 //} 654 655 //============================================ 656 657 void G4SubEvtRunManager::SubEventFinished(cons 658 { 659 G4AutoLock l(&accessSubEventMutex); 660 auto masterEvt = se->GetEvent(); 661 if(masterEvt==nullptr) { 662 G4Exception("G4SubEvtRunManager::SubEventF 663 FatalException,"Pointer of master event 664 return; // NOLINT: required to help Coveri 665 } 666 667 if(userEventAction) { 668 userEventAction->MergeSubEvent(masterEvt,e 669 } 670 if(trajectoriesToBeMerged) MergeTrajectories 671 UpdateScoringForSubEvent(se,evt); 672 evt->ScoresRecorded(); 673 eventManager->TerminateSubEvent(se,evt); 674 } 675 676 //============================================ 677 678 void G4SubEvtRunManager::MergeTrajectories(con 679 { 680 auto masterEvt = se->GetEvent(); 681 auto* trajVector = evt->GetTrajectoryContain 682 auto* masterTrajContainer = masterEvt->GetTr 683 if(masterTrajContainer==nullptr) 684 { 685 masterTrajContainer = new G4TrajectoryCont 686 masterEvt->SetTrajectoryContainer(masterTr 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::UpdateScoringForSubEv 700 { 701 auto masterEvt = se->GetEvent(); 702 703 G4ScoringManager* ScM = G4ScoringManager::Ge 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 bel 710 << " --- sub-event has " << evt->Ge 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->GetH 717 if (masterHCE == nullptr || (G4int)masterHCE 718 { 719 G4Exception("G4SubEvtRunManager::UpdateSco 720 FatalException,"Number of hits colleacti 721 return; 722 } 723 for (G4int i = 0; i < nColl; ++i) { 724 auto* HC = dynamic_cast<G4THitsMap<G4doubl 725 auto* masterHC = dynamic_cast<G4THitsMap<G 726 if (HC != nullptr && masterHC != nullptr) 727 { *masterHC += *HC; } 728 else 729 { 730 G4Exception("G4SubEvtRunManager::Update 731 FatalException,"HitsCollection is not 732 return; 733 } 734 } 735 736 } 737 738 //============================================ 739 740 void G4SubEvtRunManager::CleanUpPreviousEvents 741 { 742 // Delete all events carried over from previ 743 // This method is invoked at the beginning o 744 // or from the destructor of G4RunManager at 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 G 753 if(currentRun!=nullptr) 754 { 755 auto eventVector = currentRun->GetEven 756 auto eItr = std::find(eventVector->cbe 757 if(eItr != eventVector->cend()) eventV 758 } 759 delete evt; 760 } 761 evItr = previousEvents->erase(evItr); 762 } 763 if(currentRun!=nullptr) 764 { 765 auto eventVector = currentRun->GetEventVec 766 if(eventVector==nullptr || eventVector->em 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 786 RequestWorkersProcessCommandsStack(); 787 788 if (workTaskGroup != nullptr) { 789 workTaskGroup->join(); 790 if (!fakeRun) 791 threadPool->execute_on_all_threads([]() 792 } 793 } 794 795 //============================================ 796 797 void G4SubEvtRunManager::AbortRun(G4bool softA 798 { 799 // This method is valid only for GeomClosed 800 G4ApplicationState currentState = G4StateMan 801 if (currentState == G4State_GeomClosed || cu 802 runAborted = true; 803 MTkernel->BroadcastAbortRun(softAbort); 804 } 805 else { 806 G4cerr << "Run is not in progress. AbortRu 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::WaitForEndEventLoopWo 820 { 821 if (workTaskGroup != nullptr) { 822 workTaskGroup->join(); 823 if (!fakeRun) 824 threadPool->execute_on_all_threads( 825 []() { G4TaskRunManagerKernel::Termina 826 } 827 } 828 829 //============================================ 830 831 void G4SubEvtRunManager::RequestWorkersProcess 832 { 833 PrepareCommandsStack(); 834 835 auto process_commands_stack = []() { 836 G4MTRunManager* mrm = G4MTRunManager::GetM 837 if (mrm != nullptr) { 838 auto cmds = mrm->GetCommandStack(); 839 for (const auto& itr : cmds) 840 G4UImanager::GetUIpointer()->ApplyComm 841 mrm->ThisWorkerProcessCommandsStackDone( 842 } 843 }; 844 845 if (threadPool != nullptr) threadPool->execu 846 } 847 848 //============================================ 849 850 void G4SubEvtRunManager::ThisWorkerProcessComm 851 852 //============================================ 853 854 void G4SubEvtRunManager::RegisterSubEventType( 855 { 856 G4AutoLock l(®isterSubEvtWorkerMutex); 857 fSubEvtTypeMap[ty] = maxEnt; 858 eventManager->UseSubEventParallelism(); 859 eventManager->GetStackManager()->RegisterSub 860 } 861 862 void G4SubEvtRunManager::RegisterSubEvtWorker( 863 { 864 G4AutoLock l(®isterSubEvtWorkerMutex); 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 883 << " registered. There must be at lea 884 G4Exception("G4SubEvtRunManager::CheckSu 885 "SubEvtRM1210",FatalException,ed); 886 return false; 887 } 888 } 889 return true; 890 } 891 892 void G4SubEvtRunManager::SetUserInitialization 893 { 894 userWorkerInitialization = userInit; 895 } 896 897 // ------------------------------------------- 898 void G4SubEvtRunManager::SetUserInitialization 899 { 900 userWorkerThreadInitialization = userInit; 901 } 902 903 // ------------------------------------------- 904 void G4SubEvtRunManager::SetUserInitialization 905 { 906 userActionInitialization = userInit; 907 userActionInitialization->BuildForMaster(); 908 } 909 910 // ------------------------------------------- 911 void G4SubEvtRunManager::SetUserInitialization 912 { 913 G4RunManager::SetUserInitialization(userDC); 914 } 915 916 // ------------------------------------------- 917 void G4SubEvtRunManager::SetUserInitialization 918 { 919 pl->InitializeWorker(); 920 G4RunManager::SetUserInitialization(pl); 921 } 922 923 // ------------------------------------------- 924 void G4SubEvtRunManager::SetUserAction(G4UserR 925 { 926 G4RunManager::SetUserAction(userAction); 927 if (userAction != nullptr) userAction->SetMa 928 } 929 930 // ------------------------------------------- 931 void G4SubEvtRunManager::SetUserAction(G4UserE 932 { 933 G4RunManager::SetUserAction(ua); 934 } 935 936 // ------------------------------------------- 937 void G4SubEvtRunManager::SetUserAction(G4VUser 938 { 939 G4RunManager::SetUserAction(ua); 940 } 941 942 // ------------------------------------------- 943 void G4SubEvtRunManager::SetUserAction(G4UserS 944 { 945 G4RunManager::SetUserAction(ua); 946 } 947 948 // ------------------------------------------- 949 void G4SubEvtRunManager::SetUserAction(G4UserT 950 { 951 G4RunManager::SetUserAction(ua); 952 } 953 954 // ------------------------------------------- 955 void G4SubEvtRunManager::SetUserAction(G4UserS 956 { 957 G4RunManager::SetUserAction(ua); 958 } 959 960 961