Geant4 Cross Reference |
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(®isterSubEvtWorkerMutex); 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(®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 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