Geant4_10
G4WorkerThread.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 #include "G4WorkerThread.hh"
27 #include "G4WorkerRunManager.hh"
28 #include "G4MTRunManager.hh"
29 
31 {
32  threadId = tid;
33 }
34 
36 {
37  return threadId;
38 }
39 
41 {
42  numThreads = nw;
43 }
44 
46 {
47  return numThreads;
48 }
49 
50 //TODO: refactorize? Parts of these delegated to correct classes?
51 #include "G4LogicalVolume.hh"
52 #include "G4VPhysicalVolume.hh"
53 #include "G4PVReplica.hh"
54 #include "G4ParticleDefinition.hh"
55 #include "G4Region.hh"
56 #include "G4Material.hh"
57 #include "G4PhysicsVector.hh"
59 #include "G4PhysicalVolumeStore.hh"
60 #include "G4LogicalVolumeStore.hh"
61 #include "G4MaterialTable.hh"
62 #include "G4PolyconeSide.hh"
63 #include "G4PolyhedraSide.hh"
64 #include "G4PVParameterised.hh"
65 #include "G4Threading.hh"
66 #include "G4AutoLock.hh"
67 #include "G4VUserPhysicsList.hh"
68 #include "G4VPhysicsConstructor.hh"
69 #include "G4VModularPhysicsList.hh"
70 #include "G4GeometryWorkspace.hh"
72 #include "G4SolidsWorkspace.hh"
73 #include "G4SolidsWorkspacePool.hh"
74 
75 //namespace {
76 // G4Mutex solidclone = G4MUTEX_INITIALIZER;
77 //}
78 
80 {
81  // Initialise all split classes in the geometry with copy of data from master thread
84 
85  //Geometry related, split classes mechanism: instantiate sub-instance for this thread
86  //const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()).SlaveCopySubInstanceArray();
87  //const_cast<G4PVManager&>(G4VPhysicalVolume::GetSubInstanceManager()).SlaveCopySubInstanceArray();
88  //const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()).SlaveCopySubInstanceArray();
89  //const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()).SlaveInitializeSubInstance();
90  //G4Material::g4materialSubInstanceManager.SlaveCopySubInstanceArray(); //< Not anymore splitted class
91  //const_cast<G4PlSideManager&>(G4PolyconeSide::GetSubInstanceManager()).SlaveInitializeSubInstance();
92  //const_cast<G4PhSideManager&>(G4PolyhedraSide::GetSubInstanceManager()).SlaveInitializeSubInstance();
93  //Physics related
94  //const_cast<G4PVecManager&>(G4PhysicsVector::GetSubInstanceManager()).SlaveInitializeSubInstance();
96  const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager()).NewSubInstances();
97  const_cast<G4VUPLManager&>(G4VUserPhysicsList::GetSubInstanceManager()).NewSubInstances();
98  const_cast<G4VPCManager&>(G4VPhysicsConstructor::GetSubInstanceManager()).NewSubInstances();
99  const_cast<G4VMPLManager&>(G4VModularPhysicsList::GetSubInstanceManager()).SlaveCopySubInstanceArray();
100  /*
101  G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance();
102  for (size_t ip=0; ip<physVolStore->size(); ip++)
103  {
104  G4VPhysicalVolume* physVol = (*physVolStore)[ip];
105  G4LogicalVolume *g4LogicalVolume = physVol->GetLogicalVolume();
106  //use shadow pointer
107  G4VSolid *g4VSolid = g4LogicalVolume->GetMasterSolid();
108  G4PVReplica *g4PVReplica = 0;
109  g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
110  if (g4PVReplica)
111  {
112  //g4PVReplica->SlaveG4PVReplica(g4PVReplica);
113  g4PVReplica->InitialiseWorker(g4PVReplica);
114  G4PVParameterised *g4PVParameterised = 0;
115  g4PVParameterised = dynamic_cast<G4PVParameterised*>(physVol);
116  if (g4PVParameterised)
117  {
118  //01.25.2009 Xin Dong: For a G4PVParameterised instance, assoicated a
119  //cloned solid for each worker thread. If all solids support this clone
120  //method, we do not need to dynamically cast to solids that support this
121  //clone method. Before all solids support this clone method, we do similar
122  //thing here to dynamically cast and then get the clone method.
123 
124  //Threads may clone some solids simultaneously. Those cloned solids will be
125  //Registered into a shared solid store (C++ container). Need a lock to
126  //guarantee thread safety
127  G4AutoLock aLock(&solidclone);
128  G4VSolid *slaveg4VSolid = g4VSolid->Clone();
129  aLock.unlock();
130  //g4LogicalVolume->SlaveG4LogicalVolume(g4LogicalVolume, slaveg4VSolid, 0);
131  g4LogicalVolume->InitialiseWorker(g4LogicalVolume,slaveg4VSolid,0);
132  }
133  else
134  {
135  //g4LogicalVolume->SlaveG4LogicalVolume(g4LogicalVolume, g4VSolid, 0);
136  g4LogicalVolume->InitialiseWorker(g4LogicalVolume,g4VSolid,0);
137  }
138  }
139  else
140  {
141  //g4LogicalVolume->SlaveG4LogicalVolume(g4LogicalVolume, g4VSolid, 0);
142  g4LogicalVolume->InitialiseWorker(g4LogicalVolume,g4VSolid,0);
143  }
144  }
145  */
146 
147  //const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
148 
149  //size_t nmat = theMaterialTable->size();
150  //size_t i;
151  //for(i=0; i<nmat; i++) {
152  // ((*theMaterialTable)[i])->SlaveG4Material();
153  //}
154 }
155 
157 {
158 #if 0
159  // Manage Geometry Workspace explicitly
160  fGeometryWrk->ReleaseAndDestroyWorkspace();
161  delete fGeometryWrk;
162  fGeometryWrk=0;
163 #else
164  // Alternative:
165  // Initialise all split classes in the geometry with copy of data from master thread
166  // G4GeometryWorkspacePool::GetInstance()->ReleaseAndDestroyMyWorkspace();
169 #endif
170 //
171 //
172 // G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance();
173 // for (size_t ip=0; ip<physVolStore->size(); ip++)
174 // {
175 // G4VPhysicalVolume* physVol = (*physVolStore)[ip];
176 // G4LogicalVolume *g4LogicalVolume = physVol->GetLogicalVolume();
177 // // G4VSolid *g4VSolid = g4LogicalVolume->fSolid;
178 // G4PVReplica *g4PVReplica = 0;
179 // g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
180 // if (g4PVReplica)
181 // {
182 // //g4PVReplica->DestroySlaveG4PVReplica(g4PVReplica);
183 // g4PVReplica->TerminateWorker(g4PVReplica);
184 // G4PVParameterised *g4PVParameterised = 0;
185 // g4PVParameterised = dynamic_cast<G4PVParameterised*>(physVol);
186 // if (g4PVParameterised)
187 // {
188 // // G4VSolid *slaveg4VSolid = g4VSolid->Clone();
189 // //g4LogicalVolume->DestroySlaveG4LogicalVolume(g4LogicalVolume);
190 // g4LogicalVolume->TerminateWorker(g4LogicalVolume);
191 // // delete slaveg4VSolid;
192 // }
193 // else
194 // {
195 // //g4LogicalVolume->DestroySlaveG4LogicalVolume(g4LogicalVolume);
196 // g4LogicalVolume->TerminateWorker(g4LogicalVolume);
197 // }
198 // }
199 // else
200 // {
201 // //g4LogicalVolume->DestroySlaveG4LogicalVolume(g4LogicalVolume);
202 // g4LogicalVolume->TerminateWorker(g4LogicalVolume);
203 // }
204 // }
205 //
206 // //const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
207 //
208 // //size_t nmat = theMaterialTable->size();
209 // //size_t i;
210 // //for(i=0; i<nmat; i++) {
211 // // ((*theMaterialTable)[i])->DestroySlaveG4Material();
212 // //}
213 //
214 // const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()).FreeSlave();
215 // const_cast<G4PVManager&>(G4VPhysicalVolume::GetSubInstanceManager()).FreeSlave();
216 // const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()).FreeSlave();
217 // const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager()).FreeSlave();
218 // const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()).FreeSlave();
219 // //const_cast<G4PVecManager&>(G4PhysicsVector::GetSubInstanceManager()).FreeSlave();
221 // const_cast<G4PlSideManager&>(G4PolyconeSide::GetSubInstanceManager()).FreeSlave();
222 // const_cast<G4PhSideManager&>(G4PolyhedraSide::GetSubInstanceManager()).FreeSlave();
223  const_cast<G4VUPLManager&>(G4VUserPhysicsList::GetSubInstanceManager()).FreeSlave();
226 }
227 
228 #include "G4Region.hh"
229 #include "G4RegionStore.hh"
230 
232 {
233  //=================================================
234  //Step-0: keep sensitive detector and field manager
235  //=================================================
236  // First remember SD and Filed Associated with worker
237  // in order to re-use it
238  // (note that all the stuff after this will reset SD and Field
239  typedef std::map<G4LogicalVolume*,std::pair<G4VSensitiveDetector*,G4FieldManager*> > LV2SDFM;
240  LV2SDFM lvmap;
241  typedef std::map<G4LogicalVolume*,std::pair<G4Region*,G4bool> > LV2Region;
242  LV2Region lv2rmap;
243  typedef std::map<G4Region*,std::pair<G4FastSimulationManager*,G4UserSteppingAction*> > R2FSM;
244  R2FSM rgnmap;
246  for(size_t ip=0; ip<mLogVolStore->size(); ip++)
247  {
248  G4LogicalVolume *lv = (*mLogVolStore)[ip];
249  //The following needs an explanation.
250  //Consider the case in which the user adds one LogVolume between the runs. The problem is that the thread-local part
251  //(split class) of the G4LogicalVolume object is not initialized for workers because the initialization is done once when the
252  //thread starts (see G4MTRunManagerKernel::StartThread Step-2 that calls G4WorkerThread::BuildGeometryAndPhysicsVector in this class)
253  //The problem is that pointers of SD and FM for these newly added LV
254  //may be invalid pointers (because never initialized, we have seen this behavior in our testing). If now we remember
255  //them and re-use them in Step-4 below we set invalid pointers to LV for this thread.
256  //Thus we need a way to know if for a given LV we need to remember or not the SD and FM pointers.
257  //To solve this problem: We assume that the ConstructSDandField is called also by Master thread
258  //thus for newly added LV the shadow pointers of SD and Fields are correct.
259  // (LIMITATION: this assumption may be too stringent, a user to save memory could instantiate SD only
260  // for workers, but we require this not to happen!).
261  // Thus is a SD and FieldMgr are needed for this particular LV, and shadow are !=0 it means that user
262  // wants an SD and FM to be associated with LV, we get the values and we remember them.
263  G4VSensitiveDetector* sd = 0;
264  G4FieldManager* fmgr = 0;
265  if ( lv->GetMasterSensitiveDetector() != 0 ) sd = lv->GetSensitiveDetector();
266  if ( lv->GetMasterFieldManager() != 0 ) fmgr = lv->GetFieldManager();
267  if ( sd || fmgr ) lvmap[lv] = std::make_pair(sd,fmgr);
268  G4Region* rgn = lv->GetRegion();
269  G4bool isRoot = lv->IsRootRegion();
270  if ( rgn || isRoot ) lv2rmap[lv] = std::make_pair(rgn,isRoot);
271  }
273  for(size_t ir=0; ir<mRegStore->size(); ir++)
274  {
275  G4Region* reg = (*mRegStore)[ir];
278  if ( reg || usa ) rgnmap[reg] = std::make_pair(fsm,usa);
279  }
280 
281  //===========================
282  //Step-1: Clean the workspace
283  //===========================
285  geomWorkspace->DestroyWorkspace();
287  solidWorkspace->DestroyWorkspace();
288 
289  //===========================
290  //Step-2: Re-create and initialize workspace
291  //===========================
292  geomWorkspace->InitialiseWorkspace();
293  solidWorkspace->InitialiseWorkspace();
294 
295  // Alternative
296  //
297  // To wipe, release and get a new one ...
298  // G4GeometryWorkspacePool *fWorkspaceMgr= G4GeometryWorkspaceOutlet::GetInstance();
299  // fWorkspaceMgr->ReleaseAndDestroyMyWorkspace();
300  // Now re-create
301  // fWorkspaceMgr->CreateAndUseWorkspace();
302 
303 
304  //===================================================
305  //Step-4: Restore sensitive detector and field manaer
306  //===================================================
307  for ( LV2SDFM::const_iterator it = lvmap.begin() ; it != lvmap.end() ; ++it )
308  {
309  G4LogicalVolume* lv = it->first;
310  G4VSensitiveDetector* sd = (it->second).first;
311  G4FieldManager* fmgr = (it->second).second;
312  if(fmgr) lv->SetFieldManager(fmgr, false); //What should be the second parameter? We use always false for MT mode
313  if(sd) lv->SetSensitiveDetector(sd);
314  }
315  for ( LV2Region::const_iterator it2 = lv2rmap.begin() ; it2 != lv2rmap.end() ; it2++ )
316  {
317  G4LogicalVolume* lv2 = it2->first;
318  G4Region* rgn = (it2->second).first;
319  if(rgn) lv2->SetRegion(rgn);
320  G4bool isRoot = (it2->second).second;
321  lv2->SetRegionRootFlag(isRoot);
322  }
323  for ( R2FSM::const_iterator it3 = rgnmap.begin() ; it3 != rgnmap.end() ; it3++ )
324  {
325  G4Region* reg = it3->first;
326  G4FastSimulationManager* fsm = (it3->second).first;
327  if(fsm) reg->SetFastSimulationManager(fsm);
328  G4UserSteppingAction* usa = (it3->second).second;
329  if(usa) reg->SetRegionalSteppingAction(usa);
330  }
331 }
332 
G4SolidsWorkspace * GetWorkspace()
G4GeometryWorkspace * GetWorkspace()
void SetRegionRootFlag(G4bool rreg)
static void UpdateGeometryAndPhysicsVectorFromMaster()
static const G4VMPLManager & GetSubInstanceManager()
static void BuildGeometryAndPhysicsVector()
static G4SolidsWorkspacePool * GetInstance()
G4FieldManager * GetMasterFieldManager() const
G4Region * GetRegion() const
static const G4PDefManager & GetSubInstanceManager()
void SetThreadId(G4int threadId)
int G4int
Definition: G4Types.hh:78
void SetFieldManager(G4FieldManager *pFieldMgr, G4bool forceToAllDaughters)
static G4RegionStore * GetInstance()
void SetFastSimulationManager(G4FastSimulationManager *fsm)
void SetRegion(G4Region *reg)
G4FieldManager * GetFieldManager() const
G4VSensitiveDetector * GetMasterSensitiveDetector() const
G4int GetNumberThreads() const
bool G4bool
Definition: G4Types.hh:79
G4bool IsRootRegion() const
static G4LogicalVolumeStore * GetInstance()
G4int GetThreadId() const
G4int first
G4FastSimulationManager * GetFastSimulationManager() const
static void DestroyGeometryAndPhysicsVector()
static const G4VPCManager & GetSubInstanceManager()
static G4GeometryWorkspacePool * GetInstance()
static const G4VUPLManager & GetSubInstanceManager()
void SetRegionalSteppingAction(G4UserSteppingAction *rusa)
G4VSensitiveDetector * GetSensitiveDetector() const
void SetNumberThreads(G4int numnberThreads)
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)
G4UserSteppingAction * GetRegionalSteppingAction() const