Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/run/src/G4MTRunManagerKernel.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 // G4MTRunManagerKernel implementation
 27 //
 28 // Author: M.Asai - July 2013
 29 // --------------------------------------------------------------------
 30 #include "G4MTRunManagerKernel.hh"
 31 
 32 #include "G4AutoLock.hh"
 33 #include "G4DecayTable.hh"
 34 #include "G4LogicalVolume.hh"
 35 #include "G4Material.hh"
 36 #include "G4MaterialTable.hh"
 37 #include "G4PVParameterised.hh"
 38 #include "G4PVReplica.hh"
 39 #include "G4ParticleDefinition.hh"
 40 #include "G4ParticleTable.hh"
 41 #include "G4ParticleTableIterator.hh"
 42 #include "G4PhysicalVolumeStore.hh"
 43 #include "G4PhysicsVector.hh"
 44 #include "G4PolyconeSide.hh"
 45 #include "G4PolyhedraSide.hh"
 46 #include "G4Region.hh"
 47 #include "G4RegionStore.hh"
 48 #include "G4StateManager.hh"
 49 #include "G4UImanager.hh"
 50 #include "G4UserWorkerInitialization.hh"
 51 #include "G4UserWorkerThreadInitialization.hh"
 52 #include "G4VDecayChannel.hh"
 53 #include "G4VModularPhysicsList.hh"
 54 #include "G4VPhysicalVolume.hh"
 55 #include "G4VPhysicsConstructor.hh"
 56 #include "G4VUserActionInitialization.hh"
 57 #include "G4VUserPhysicsList.hh"
 58 #include "G4WorkerRunManager.hh"
 59 #include "G4WorkerThread.hh"
 60 
 61 std::vector<G4WorkerRunManager*>* G4MTRunManagerKernel::workerRMvector = nullptr;
 62 
 63 G4ThreadLocal G4WorkerThread* G4MTRunManagerKernel::wThreadContext = nullptr;
 64 
 65 // --------------------------------------------------------------------
 66 namespace
 67 {
 68 G4Mutex workerRMMutex = G4MUTEX_INITIALIZER;
 69 }
 70 
 71 // --------------------------------------------------------------------
 72 G4MTRunManagerKernel::G4MTRunManagerKernel() : G4RunManagerKernel(masterRMK)
 73 {
 74   // This version of the constructor should never be called in sequential mode!
 75 #ifndef G4MULTITHREADED
 76   G4ExceptionDescription msg;
 77   msg << "Geant4 code is compiled without multi-threading support "
 78          "(-DG4MULTITHREADED "
 79          "is set to off).";
 80   msg << " This type of RunManager can only be used in mult-threaded "
 81          "applications.";
 82   G4Exception("G4RunManagerKernel::G4RunManagerKernel()", "Run0109", FatalException, msg);
 83 #endif
 84   G4AutoLock l(&workerRMMutex);
 85   if (workerRMvector == nullptr) workerRMvector = new std::vector<G4WorkerRunManager*>;
 86   l.unlock();
 87   // Set flag that a MT-type kernel has been instantiated
 88   G4Threading::SetMultithreadedApplication(true);
 89 }
 90 
 91 // --------------------------------------------------------------------
 92 G4MTRunManagerKernel::~G4MTRunManagerKernel()
 93 {
 94   G4AutoLock l(&workerRMMutex);
 95   if (workerRMvector != nullptr) {
 96     if (!workerRMvector->empty()) {
 97       G4ExceptionDescription msg;
 98       msg << "G4MTRunManagerKernel is to be deleted while " << workerRMvector->size()
 99           << " G4WorkerRunManager are still alive.";
100       G4Exception("G4RunManagerKernel::~G4RunManagerKernel()", "Run10035", FatalException, msg);
101     }
102     delete workerRMvector;
103     workerRMvector = nullptr;
104   }
105 }
106 
107 // --------------------------------------------------------------------
108 void G4MTRunManagerKernel::SetupShadowProcess() const
109 {
110   // Behavior is the same as base class (sequential mode)
111   // ShadowProcess pointer == process poitner
112   G4RunManagerKernel::SetupShadowProcess();
113 }
114 
115 // --------------------------------------------------------------------
116 G4WorkerThread* G4MTRunManagerKernel::GetWorkerThread()
117 {
118   return wThreadContext;
119 }
120 
121 // --------------------------------------------------------------------
122 void G4MTRunManagerKernel::StartThread(G4WorkerThread* context)
123 {
124   //!!!!!!!!!!!!!!!!!!!!!!!!!!
125   //!!!!!! IMPORTANT !!!!!!!!!
126   //!!!!!!!!!!!!!!!!!!!!!!!!!!
127   // Here is not sequential anymore and G4UserWorkerThreadInitialization is
128   // a shared user initialization class.
129   // This means this method cannot use data members of G4RunManagerKernel
130   // unless they are invariant ("read-only") and can be safely shared.
131   // All the rest that is not invariant should be incapsulated into
132   // the context (or, as for wThreadContext be G4ThreadLocal)
133   //!!!!!!!!!!!!!!!!!!!!!!!!!!
134   // #ifdef G4MULTITHREADED
135   //     turnontpmalloc();
136   // #endif
137   G4Threading::WorkerThreadJoinsPool();
138   wThreadContext = context;
139   G4MTRunManager* masterRM = G4MTRunManager::GetMasterRunManager();
140 
141   //============================
142   // Step-0: Thread ID
143   //============================
144   // Initialise per-thread stream-output
145   // The following line is needed before we actually do IO initialisation
146   // because the constructor of UI manager resets the IO destination.
147   G4int thisID = wThreadContext->GetThreadId();
148   G4Threading::G4SetThreadId(thisID);
149   G4UImanager::GetUIpointer()->SetUpForAThread(thisID);
150 
151   //============================
152   // Optimization: optional
153   //============================
154   // Enforce thread affinity if requested
155   wThreadContext->SetPinAffinity(masterRM->GetPinAffinity());
156 
157   //============================
158   // Step-1: Random number engine
159   //============================
160   // RNG Engine needs to be initialised by "cloning" the master one.
161   const CLHEP::HepRandomEngine* masterEngine = masterRM->getMasterRandomEngine();
162   masterRM->GetUserWorkerThreadInitialization()->SetupRNGEngine(masterEngine);
163 
164   //============================
165   // Step-2: Initialise worker thread
166   //============================
167   if (masterRM->GetUserWorkerInitialization() != nullptr) {
168     masterRM->GetUserWorkerInitialization()->WorkerInitialize();
169   }
170   if (masterRM->GetUserActionInitialization() != nullptr) {
171     G4VSteppingVerbose* sv = masterRM->GetUserActionInitialization()->InitializeSteppingVerbose();
172     if (sv != nullptr) {
173       G4VSteppingVerbose::SetInstance(sv);
174     }
175   }
176   // Now initialise worker part of shared objects (geometry/physics)
177   G4WorkerThread::BuildGeometryAndPhysicsVector();
178   G4WorkerRunManager* wrm = masterRM->GetUserWorkerThreadInitialization()->CreateWorkerRunManager();
179   wrm->SetWorkerThread(wThreadContext);
180   G4AutoLock wrmm(&workerRMMutex);
181   workerRMvector->push_back(wrm);
182   wrmm.unlock();
183 
184   //================================
185   // Step-3: Setup worker run manager
186   //================================
187   // Set the detector and physics list to the worker thread. Share with master
188   const G4VUserDetectorConstruction* detector = masterRM->GetUserDetectorConstruction();
189   wrm->G4RunManager::SetUserInitialization(const_cast<G4VUserDetectorConstruction*>(detector));
190   const G4VUserPhysicsList* physicslist = masterRM->GetUserPhysicsList();
191   wrm->SetUserInitialization(const_cast<G4VUserPhysicsList*>(physicslist));
192 
193   //================================
194   // Step-4: Initialise worker run manager
195   //================================
196   if (masterRM->GetUserActionInitialization() != nullptr) {
197     masterRM->GetNonConstUserActionInitialization()->Build();
198   }
199   if (masterRM->GetUserWorkerInitialization() != nullptr) {
200     masterRM->GetUserWorkerInitialization()->WorkerStart();
201   }
202   wrm->Initialize();
203 
204   //================================
205   // Step5: Loop over requests from the master thread
206   //================================
207   // This function should enter a loop processing new runs and actions
208   // requests from master. It should block until thread is ready
209   // to terminate
210   wrm->DoWork();
211 
212   //===============================
213   // Step-6: Terminate worker thread
214   //===============================
215   if (masterRM->GetUserWorkerInitialization() != nullptr) {
216     masterRM->GetUserWorkerInitialization()->WorkerStop();
217   }
218 
219   wrmm.lock();
220   for (auto itrWrm = workerRMvector->cbegin(); itrWrm != workerRMvector->cend(); ++itrWrm) {
221     if ((*itrWrm) == wrm) {
222       workerRMvector->erase(itrWrm);
223       break;
224     }
225   }
226   wrmm.unlock();
227   delete wrm;
228 
229   //===============================
230   // Step-7: Cleanup split classes
231   //===============================
232   G4WorkerThread::DestroyGeometryAndPhysicsVector();
233   wThreadContext = nullptr;
234 
235   G4Threading::WorkerThreadLeavesPool();
236 }
237 
238 // --------------------------------------------------------------------
239 void G4MTRunManagerKernel::SetUpDecayChannels()
240 {
241   auto pItr = G4ParticleTable::GetParticleTable()->GetIterator();
242   pItr->reset();
243   while ((*pItr)()) {
244     G4DecayTable* dt = pItr->value()->GetDecayTable();
245     if (dt != nullptr) {
246       G4int nCh = dt->entries();
247       for (G4int i = 0; i < nCh; ++i) {
248         dt->GetDecayChannel(i)->GetDaughter(0);
249       }
250     }
251   }
252 }
253 
254 // --------------------------------------------------------------------
255 void G4MTRunManagerKernel::BroadcastAbortRun(G4bool softAbort)
256 {
257   G4AutoLock wrmm(&workerRMMutex);
258 
259   for (const auto& itr : *workerRMvector) {
260     itr->AbortRun(softAbort);
261   }
262 }
263