Geant4_10
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 #include "G4GeometryWorkspace.hh"
28 
29 #include "G4PVReplica.hh"
30 #include "G4PVParameterised.hh"
31 #include "G4VPVParameterisation.hh"
32 #include "G4PhysicalVolumeStore.hh"
33 #include "G4VSolid.hh"
34 
35 #include "G4LogicalVolume.hh"
36 #include "G4VPhysicalVolume.hh"
37 #include "G4PVReplica.hh"
38 #include "G4Region.hh"
39 
40 #include "G4AutoLock.hh"
41 
42 
44  : fVerbose(false)
45 {
46  fpLogicalVolumeSIM=
48  fpPhysicalVolumeSIM=
50  fpReplicaSIM=
52  fpRegionSIM=
54 
55  // Create a work area for Logical Volumes in this thread - then capture its address
57 
58  fLogicalVolumeOffset= fpLogicalVolumeSIM->GetOffset();
59 
60  fPhysicalVolumeOffset= fpPhysicalVolumeSIM->GetOffset();
61 
62  fReplicaOffset= fpReplicaSIM->GetOffset();
63 
64  fRegionOffset= fpRegionSIM->GetOffset();
65 }
66 
68 {
69 
70 }
71 
72 // Static methods
73 // For with current (original) G4WorkerThread -- which uses static methods
74 
75 void
77 {
78  if( fVerbose )
79  G4cout << "G4GeometryWorkspace::UseWorkspace: Start " << G4endl;
80 
81  // Implementation copied from G4WorkerThread::BuildGeometryAndPhysicsVector()
82  // and improved for G4PVParamaterised
83  // John Apostolakis, May 30, 2013
84 
85  //Geometry related, split classes mechanism: instantiate sub-instance for this thread
86  fpLogicalVolumeSIM->UseWorkArea(fLogicalVolumeOffset);
87  fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVolumeOffset);
88 
89  fpReplicaSIM->UseWorkArea(fReplicaOffset);
90  fpRegionSIM->UseWorkArea(fRegionOffset);
91 
92  // When recycling a workspace
93  // - it must be a lightweight operation, to reuse a valid work area
94  // - so it must NOT Initialise anything!
95  // Do not call InitialisePhysicalVolumes();
96 
97  if( fVerbose )
98  G4cout << "G4GeometryWorkspace::UseWorkspace: End " << G4endl;
99 }
100 
101 
103 // The opposite of Use Workspace - let go of it.
104 {
105  fpLogicalVolumeSIM->UseWorkArea(0);
106  fpPhysicalVolumeSIM->UseWorkArea(0);
107 
108  fpReplicaSIM->UseWorkArea(0);
109  fpRegionSIM->UseWorkArea(0);
110 }
111 
112 namespace {
113  G4Mutex solidclone= G4MUTEX_INITIALIZER;
114 }
116  {
118  for (size_t ip=0; ip<physVolStore->size(); ip++)
119  {
120  G4VPhysicalVolume* physVol = (*physVolStore)[ip];
121  G4LogicalVolume *logicalVol = physVol->GetLogicalVolume();
122  //use shadow pointer
123  G4VSolid *solid = logicalVol->GetMasterSolid();
124  G4PVReplica *g4PVReplica = 0;
125  g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
126  if (!g4PVReplica)
127  {
128  // Placement volume
129  logicalVol->InitialiseWorker(logicalVol,solid,0);
130  }
131  else
132  {
133  //g4PVReplica->SlaveG4PVReplica(g4PVReplica);
134  g4PVReplica->InitialiseWorker(g4PVReplica);
135  if( ! g4PVReplica->IsParameterised() )
136  {
137  logicalVol->InitialiseWorker(logicalVol,solid,0);
138  // If the replica's solid (in LV) is changed during navigation, it must be thread-private
139  CloneReplicaSolid( g4PVReplica );
140  }
141  else
142  {
143  G4PVParameterised *paramVol
144  = dynamic_cast<G4PVParameterised*>(physVol);
145  if (!paramVol)
146  {
147  G4Exception("G4GeometryWorkspace::CreateAndUseWorkspace", "Runtime Error PV01",
149  "Cannot find Parameterisation for G4PVParameterised object.");
150  }
151  CloneParameterisedSolids( paramVol );
152  }
153  }
154  }
155  if( fVerbose )
156  G4cout << "G4GeometryWorkspace::InitialisePhysicalVolumes: "
157  << "Copying geometry - Done!" << G4endl;
158 }
159 
160 
162 {
163  // Create a clone of the solid for this replica in this thread
164 
165  // Check that it is not a parameterisation ?
166 
167  // The solid Ptr is in the Logical Volume
168  G4LogicalVolume *logicalV= replicaPV ->GetLogicalVolume();
169  G4VSolid *solid= logicalV->GetSolid();
170 
171  G4AutoLock aLock(&solidclone);
172  G4VSolid *workerSolid = solid->Clone();
173  aLock.unlock();
174 
175  if( workerSolid )
176  {
177  logicalV->InitialiseWorker(logicalV,workerSolid,0);
178  }else{
179  // In the case that not all solids support(ed) the Clone()
180  // method, we do similar thing here to dynamically cast
181  // and then get the clone method.
183  ed << " ERROR: Unable to initialise geometry for worker node." << G4endl;
184  ed << " A solid lacks the Clone() method - or Clone() failed." << G4endl;
185  ed << " Type of solid: " << solid->GetEntityType() << G4endl;
186  ed << " Parameters: " << *solid << G4endl;
187  G4Exception(" G4GeometryWorkspace::CloneParameterisedVolume", "MT-BuildGeometry001",
188  FatalException, ed);
189  return false;
190  }
191  return true; // It Worked
192 }
193 
195 {
196  // Each G4PVParameterised instance, has associated with it at least one
197  // solid for each worker thread.
198  // *Simple* Parameterisations have a single type of solid, and the
199  // pointer points to the same instance of a solid during the simulation.
200  // For this case, it is possible to adapt automatically to
201  // multi-threading, simply by cloning the solid - so long
202  // as all solids support the Clone() method.
203 
204  // Check whether it is a simple parameterisation or not
205  G4VPVParameterisation *param= paramVol->GetParameterisation();
206  unsigned int numCopies= paramVol->GetMultiplicity();
207  unsigned int numDifferent= 0;
208 
209  G4LogicalVolume *logicalV= paramVol->GetLogicalVolume();
210  // assert( logicalV != 0);
211  G4VSolid *solid= logicalV->GetSolid();
212 
213  for( unsigned int i=0; i< numCopies; i++)
214  {
215  G4VSolid *solidChk= param->ComputeSolid(i, paramVol);
216  if( solidChk != solid)
217  {
218  numDifferent++;
219  }
220  }
221  if( numDifferent>0 )
222  {
224 
225  ed << " Parameterisation is implemented using several instances of Solids "
226  << " - potentially to support different types of solids. " << G4endl;
227  ed << " The current implementation of Geant4-MT does not support "
228  << " this type of Parameterisation" << G4endl;
229  G4Exception("G4GeometryWorkspace::CloneParameterisedVolume", "GeometryNotSupportedInMT-01",
230  FatalException, ed);
231  }
232 
233  // Threads may attempt to clone a solids simultaneously. Those cloned solids will be
234  // registered into a shared solid store (C++ container). Need a lock to
235  // guarantee thread safety
236  G4AutoLock aLock(&solidclone);
237  G4VSolid *workerSolid = solid->Clone();
238  aLock.unlock();
239  if( workerSolid )
240  {
241  logicalV->InitialiseWorker(logicalV,workerSolid,0);
242  }else{
243  // In the case that not all solids support(ed) the Clone()
244  // method, we do similar thing here to dynamically cast
245  // and then get the clone method.
247  ed << " ERROR: Unable to initialise geometry for worker node." << G4endl;
248  ed << " A solid lacks the Clone() method - or Clone() failed." << G4endl;
249  ed << " Type of solid: " << solid->GetEntityType() << G4endl;
250  ed << " Parameters: " << *solid << G4endl;
251  G4Exception(" G4GeometryWorkspace::CloneParameterisedVolume", "MT-BuildGeometry001",
252  FatalException, ed);
253  }
254  return true; // It Worked
255 }
256 
257 
258 void
260 {
261  if( fVerbose )
262  G4cout << "G4GeometryWorkspace::InitialiseWorkspace: Copying geometry - Start " << G4endl;
263 
264  // Implementation copied from G4WorkerThread::BuildGeometryAndPhysicsVector()
265  // and improved for G4PVParamaterised
266  // John Apostolakis, May 30, 2013
267 
268  //Geometry related, split classes mechanism:
269  // Do *NOT* instantiate sub-instance for this thread,
270  // just copy the contents !!
271  fpLogicalVolumeSIM->SlaveCopySubInstanceArray();
272  fpPhysicalVolumeSIM->SlaveCopySubInstanceArray();
273  fpReplicaSIM->SlaveCopySubInstanceArray();
274  fpRegionSIM->SlaveInitializeSubInstance();
275 
277 
278  if( fVerbose )
279  G4cout << "G4GeometryWorkspace::InitialiseWorkspace: "
280  << "Copying geometry - Done!" << G4endl;
281 }
282 
284 {
286  for (size_t ip=0; ip<physVolStore->size(); ip++)
287  {
288  G4VPhysicalVolume* physVol = (*physVolStore)[ip];
289  G4LogicalVolume *logicalVol = physVol->GetLogicalVolume();
290  G4PVReplica *g4PVReplica = 0;
291  g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
292  if (g4PVReplica)
293  {
294  g4PVReplica->TerminateWorker(g4PVReplica);
295  G4PVParameterised *paramVol = 0;
296  paramVol = dynamic_cast<G4PVParameterised*>(physVol);
297  if (paramVol)
298  {
299  // G4VSolid *solid = logicalVol->fSolid;
300  logicalVol->TerminateWorker(logicalVol);
301  // if( solid->IsClone() ) delete solid;
302  }
303  else
304  {
305  logicalVol->TerminateWorker(logicalVol);
306  }
307  }
308  else
309  {
310  logicalVol->TerminateWorker(logicalVol);
311  }
312  }
313 
314  fpLogicalVolumeSIM->FreeSlave();
315  fpPhysicalVolumeSIM->FreeSlave();
316  fpReplicaSIM->FreeSlave();
317  fpRegionSIM->FreeSlave();
318 }
void TerminateWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:300
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
G4VSolid * GetMasterSolid() const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
static const G4LVManager & GetSubInstanceManager()
virtual G4GeometryType GetEntityType() const =0
void InitialiseWorker(G4LogicalVolume *ptrMasterObject, G4VSolid *pSolid, G4VSensitiveDetector *pSDetector)
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:158
static const G4PVRManager & GetSubInstanceManager()
Definition: G4PVReplica.cc:275
static G4PhysicalVolumeStore * GetInstance()
virtual G4bool IsParameterised() const
Definition: G4PVReplica.cc:219
G4VPVParameterisation * GetParameterisation() const
G4GLOB_DLL std::ostream G4cout
static const G4PVManager & GetSubInstanceManager()
void InitialiseWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:287
bool G4bool
Definition: G4Types.hh:79
void SlaveCopySubInstanceArray()
G4bool CloneReplicaSolid(G4PVReplica *)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4int G4Mutex
Definition: G4Threading.hh:156
void TerminateWorker(G4LogicalVolume *ptrMasterObject)
G4LogicalVolume * GetLogicalVolume() const
virtual G4int GetMultiplicity() const
Definition: G4PVReplica.cc:229
G4bool CloneParameterisedSolids(G4PVParameterised *paramVol)
#define G4endl
Definition: G4ios.hh:61
virtual G4VSolid * Clone() const
Definition: G4VSolid.cc:324
void UseWorkArea(T *newOffset)
static const G4RegionManager & GetSubInstanceManager()
Definition: G4Region.cc:58
void SlaveInitializeSubInstance()
G4VSolid * GetSolid() const