Geant4  10.01.p02
G4GeometryWorkspace.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 // $Id: G4GeometryWorkspace.cc 79096 2014-02-14 16:07:39Z gcosmo $
28 //
29 //
30 // Class G4GeometryWorkspace - implementation
31 //
32 // ----------------------------------------------------------------------
33 
34 #include "G4GeometryWorkspace.hh"
35 
36 #include "G4PVReplica.hh"
37 #include "G4PVParameterised.hh"
38 #include "G4VPVParameterisation.hh"
39 #include "G4PhysicalVolumeStore.hh"
40 #include "G4VSolid.hh"
41 
42 #include "G4LogicalVolume.hh"
43 #include "G4VPhysicalVolume.hh"
44 #include "G4PVReplica.hh"
45 #include "G4Region.hh"
46 
47 #include "G4AutoLock.hh"
48 
49 namespace
50 {
51  G4Mutex solidclone = G4MUTEX_INITIALIZER;
52 }
53 
54 // ----------------------------------------------------------------------
55 //
57  : fVerbose(false)
58 {
67 
68  // Create a work area for Logical Volumes in this thread
69  // then capture its address
71 
73 
75 
77 
79 }
80 
81 // ----------------------------------------------------------------------
82 //
84 {
85 }
86 
87 // ----------------------------------------------------------------------
88 //
89 void
91 {
92  if( fVerbose )
93  {
94  G4cout << "G4GeometryWorkspace::UseWorkspace: Start " << G4endl;
95  }
96 
97  // Implementation originally in:
98  // G4WorkerThread::BuildGeometryAndPhysicsVector()
99  // and improved for G4PVParamaterised
100 
101  // Geometry related, split classes mechanism: instantiate sub-instance
102  // for this thread
105 
108 
109  // When recycling a workspace
110  // - it must be a lightweight operation, to reuse a valid work area
111  // - so it must NOT Initialise anything!
112  // Do not call InitialisePhysicalVolumes();
113 
114  if( fVerbose )
115  {
116  G4cout << "G4GeometryWorkspace::UseWorkspace: End " << G4endl;
117  }
118 }
119 
120 // ----------------------------------------------------------------------
121 //
123 {
126 
129 }
130 
131 // ----------------------------------------------------------------------
132 //
134 {
136  for (size_t ip=0; ip<physVolStore->size(); ip++)
137  {
138  G4VPhysicalVolume* physVol = (*physVolStore)[ip];
139  G4LogicalVolume *logicalVol = physVol->GetLogicalVolume();
140 
141  // Use shadow pointer
142  //
143  G4VSolid *solid = logicalVol->GetMasterSolid();
144  G4PVReplica *g4PVReplica = 0;
145  g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
146  if (!g4PVReplica)
147  {
148  // Placement volume
149  logicalVol->InitialiseWorker(logicalVol,solid,0);
150  }
151  else
152  {
153  g4PVReplica->InitialiseWorker(g4PVReplica);
154  if( ! g4PVReplica->IsParameterised() )
155  {
156  logicalVol->InitialiseWorker(logicalVol,solid,0);
157 
158  // If the replica's solid (in LV) is changed during navigation,
159  // it must be thread-private
160  //
161  CloneReplicaSolid( g4PVReplica );
162  }
163  else
164  {
165  G4PVParameterised *paramVol = dynamic_cast<G4PVParameterised*>(physVol);
166  if (!paramVol)
167  {
168  G4Exception("G4GeometryWorkspace::CreateAndUseWorkspace()",
169  "GeomVol0003", FatalException,
170  "Cannot find Parameterisation for parameterised volume.");
171  }
172  CloneParameterisedSolids( paramVol );
173  }
174  }
175  }
176  if( fVerbose )
177  {
178  G4cout << "G4GeometryWorkspace::InitialisePhysicalVolumes: "
179  << "Copying geometry - Done!" << G4endl;
180  }
181 }
182 
183 // ----------------------------------------------------------------------
184 // Create a clone of the solid for this replica in this thread
185 //
187 {
188  // The solid Ptr is in the Logical Volume
189  //
190  G4LogicalVolume *logicalV= replicaPV ->GetLogicalVolume();
191  G4VSolid *solid= logicalV->GetSolid();
192 
193  G4AutoLock aLock(&solidclone);
194  G4VSolid *workerSolid = solid->Clone();
195  aLock.unlock();
196 
197  if( workerSolid )
198  {
199  logicalV->InitialiseWorker(logicalV,workerSolid,0);
200  }
201  else
202  {
203  // In the case that not all solids support(ed) the Clone()
204  // method, we do similar thing here to dynamically cast
205  // and then get the clone method.
206  //
208  ed << "ERROR - Unable to initialise geometry for worker node." << "\n"
209  << "A solid lacks the Clone() method - or Clone() failed." << "\n"
210  << " Type of solid: " << solid->GetEntityType() << "\n"
211  << " Parameters: " << *solid;
212  G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()",
213  "GeomVol0003", FatalException, ed);
214  return false;
215  }
216  return true; // It Worked
217 }
218 
219 // ----------------------------------------------------------------------
220 // Each G4PVParameterised instance, has associated with it at least one
221 // solid for each worker thread.
222 // *Simple* Parameterisations have a single type of solid, and the
223 // pointer points to the same instance of a solid during the simulation.
224 // For this case, it is possible to adapt automatically to
225 // multi-threading, simply by cloning the solid - so long
226 // as all solids support the Clone() method.
227 //
230 {
231  // Check whether it is a simple parameterisation or not
232  //
233  G4VPVParameterisation *param= paramVol->GetParameterisation();
234  unsigned int numCopies= paramVol->GetMultiplicity();
235  unsigned int numDifferent= 0;
236 
237  G4LogicalVolume *logicalV= paramVol->GetLogicalVolume();
238  G4VSolid *solid= logicalV->GetSolid();
239 
240  for( unsigned int i=0; i< numCopies; i++)
241  {
242  G4VSolid *solidChk= param->ComputeSolid(i, paramVol);
243  if( solidChk != solid)
244  {
245  numDifferent++;
246  }
247  }
248  if( numDifferent>0 )
249  {
251  ed << "ERROR - Parameterisation using several instances of Solids \n"
252  << "potentially to support different types of solids. \n"
253  << "Geant4-MT currently does not support this type of \n"
254  << "parameterisation, sorry !";
255  G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()",
256  "GeomVol0001", FatalException, ed);
257  }
258 
259  // Threads may attempt to clone a solids simultaneously.
260  // Those cloned solids will be registered into a shared solid
261  // store (C++ container). Need a lock to guarantee thread safety
262  //
263  G4AutoLock aLock(&solidclone);
264  G4VSolid *workerSolid = solid->Clone();
265  aLock.unlock();
266  if( workerSolid )
267  {
268  logicalV->InitialiseWorker(logicalV,workerSolid,0);
269  }
270  else
271  {
272  // In the case that not all solids support(ed) the Clone()
273  // method, we do similar thing here to dynamically cast
274  // and then get the clone method
275  //
277  ed << "ERROR - Unable to initialise geometry for worker node. \n"
278  << "A solid lacks the Clone() method - or Clone() failed. \n"
279  << " Type of solid: " << solid->GetEntityType() << "\n"
280  << " Parameters: " << *solid;
281  G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()",
282  "GeomVol0003", FatalException, ed);
283  }
284  return true; // It Worked
285 }
286 
287 // ----------------------------------------------------------------------
288 //
290 {
291  if( fVerbose )
292  {
293  G4cout << "G4GeometryWorkspace::InitialiseWorkspace():"
294  << " Copying geometry - Start " << G4endl;
295  }
296 
297  // Implementation originally in:
298  // G4WorkerThread::BuildGeometryAndPhysicsVector()
299  // and improved for G4PVParamaterised
300 
301  // Geometry related, split classes mechanism:
302  // Do *NOT* instantiate sub-instance for this thread, just copy the contents!
303  //
308 
310 
311  if( fVerbose )
312  {
313  G4cout << "G4GeometryWorkspace::InitialiseWorkspace: "
314  << "Copying geometry - Done!" << G4endl;
315  }
316 }
317 
318 // ----------------------------------------------------------------------
319 //
321 {
323  for (size_t ip=0; ip<physVolStore->size(); ip++)
324  {
325  G4VPhysicalVolume* physVol = (*physVolStore)[ip];
326  G4LogicalVolume *logicalVol = physVol->GetLogicalVolume();
327  G4PVReplica *g4PVReplica = 0;
328  g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
329  if (g4PVReplica)
330  {
331  g4PVReplica->TerminateWorker(g4PVReplica);
332  G4PVParameterised *paramVol = 0;
333  paramVol = dynamic_cast<G4PVParameterised*>(physVol);
334  if (paramVol)
335  {
336  // G4VSolid *solid = logicalVol->fSolid;
337  logicalVol->TerminateWorker(logicalVol);
338  // if( solid->IsClone() ) delete solid;
339  }
340  else
341  {
342  logicalVol->TerminateWorker(logicalVol);
343  }
344  }
345  else
346  {
347  logicalVol->TerminateWorker(logicalVol);
348  }
349  }
354 }
G4LVManager * fpLogicalVolumeSIM
void TerminateWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:321
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
G4VSolid * GetMasterSolid() const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
static const G4LVManager & GetSubInstanceManager()
G4ReplicaData * fReplicaOffset
G4RegionData * fRegionOffset
virtual G4GeometryType GetEntityType() const =0
void InitialiseWorker(G4LogicalVolume *ptrMasterObject, G4VSolid *pSolid, G4VSensitiveDetector *pSDetector)
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
static const G4PVRManager & GetSubInstanceManager()
Definition: G4PVReplica.cc:265
static G4PhysicalVolumeStore * GetInstance()
virtual G4bool IsParameterised() const
Definition: G4PVReplica.cc:220
G4VPVParameterisation * GetParameterisation() const
G4GLOB_DLL std::ostream G4cout
static const G4PVManager & GetSubInstanceManager()
void InitialiseWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:276
bool G4bool
Definition: G4Types.hh:79
void SlaveCopySubInstanceArray()
G4bool CloneReplicaSolid(G4PVReplica *)
G4PVManager * fpPhysicalVolumeSIM
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4int G4Mutex
Definition: G4Threading.hh:173
void TerminateWorker(G4LogicalVolume *ptrMasterObject)
G4LogicalVolume * GetLogicalVolume() const
G4PVRManager * fpReplicaSIM
virtual G4int GetMultiplicity() const
Definition: G4PVReplica.cc:230
G4bool CloneParameterisedSolids(G4PVParameterised *paramVol)
#define G4endl
Definition: G4ios.hh:61
virtual G4VSolid * Clone() const
Definition: G4VSolid.cc:324
void UseWorkArea(T *newOffset)
G4RegionManager * fpRegionSIM
static const G4RegionManager & GetSubInstanceManager()
Definition: G4Region.cc:58
void SlaveInitializeSubInstance()
G4VSolid * GetSolid() const