ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4GeometryWorkspace.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4GeometryWorkspace.cc
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 // Class G4GeometryWorkspace - implementation
27 //
28 // ----------------------------------------------------------------------
29 
30 #include "G4GeometryWorkspace.hh"
31 
32 #include "G4PVReplica.hh"
33 #include "G4PVParameterised.hh"
34 #include "G4VPVParameterisation.hh"
35 #include "G4PhysicalVolumeStore.hh"
36 #include "G4VSolid.hh"
37 
38 #include "G4LogicalVolume.hh"
39 #include "G4VPhysicalVolume.hh"
40 #include "G4PVReplica.hh"
41 #include "G4Region.hh"
42 
43 #include "G4AutoLock.hh"
44 
45 namespace
46 {
47  G4Mutex solidclone = G4MUTEX_INITIALIZER;
49 }
50 
51 // ----------------------------------------------------------------------
52 //
54 {
55  return &thePool;
56 }
57 
58 // ----------------------------------------------------------------------
59 //
61 {
70 
71  // Create a work area for Logical Volumes in this thread
72  // then capture its address
74 
76 
78 
80 
82 }
83 
84 // ----------------------------------------------------------------------
85 //
87 {
88 }
89 
90 // ----------------------------------------------------------------------
91 //
92 void
94 {
95  if( fVerbose )
96  {
97  G4cout << "G4GeometryWorkspace::UseWorkspace: Start " << G4endl;
98  }
99 
100  // Implementation originally in:
101  // G4WorkerThread::BuildGeometryAndPhysicsVector()
102  // and improved for G4PVParamaterised
103 
104  // Geometry related, split classes mechanism: instantiate sub-instance
105  // for this thread
108 
111 
112  // When recycling a workspace
113  // - it must be a lightweight operation, to reuse a valid work area
114  // - so it must NOT Initialise anything!
115  // Do not call InitialisePhysicalVolumes();
116 
117  if( fVerbose )
118  {
119  G4cout << "G4GeometryWorkspace::UseWorkspace: End " << G4endl;
120  }
121 }
122 
123 // ----------------------------------------------------------------------
124 //
126 {
129 
132 }
133 
134 // ----------------------------------------------------------------------
135 //
137 {
139  for (size_t ip=0; ip<physVolStore->size(); ++ip)
140  {
141  G4VPhysicalVolume* physVol = (*physVolStore)[ip];
142  G4LogicalVolume *logicalVol = physVol->GetLogicalVolume();
143 
144  // Use shadow pointer
145  //
146  G4VSolid* solid = logicalVol->GetMasterSolid();
147  G4PVReplica* g4PVReplica = nullptr;
148  g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
149  if (g4PVReplica == nullptr)
150  {
151  // Placement volume
152  logicalVol->InitialiseWorker(logicalVol,solid,0);
153  }
154  else
155  {
156  g4PVReplica->InitialiseWorker(g4PVReplica);
157  if( !g4PVReplica->IsParameterised() )
158  {
159  logicalVol->InitialiseWorker(logicalVol,solid,0);
160 
161  // If the replica's solid (in LV) is changed during navigation,
162  // it must be thread-private
163  //
164  CloneReplicaSolid( g4PVReplica );
165  }
166  else
167  {
168  G4PVParameterised *paramVol = dynamic_cast<G4PVParameterised*>(physVol);
169  if (paramVol == nullptr)
170  {
171  G4Exception("G4GeometryWorkspace::CreateAndUseWorkspace()",
172  "GeomVol0003", FatalException,
173  "Cannot find Parameterisation for parameterised volume.");
174  }
175  CloneParameterisedSolids( paramVol );
176  }
177  }
178  }
179  if( fVerbose )
180  {
181  G4cout << "G4GeometryWorkspace::InitialisePhysicalVolumes: "
182  << "Copying geometry - Done!" << G4endl;
183  }
184 }
185 
186 // ----------------------------------------------------------------------
187 // Create a clone of the solid for this replica in this thread
188 //
190 {
191  // The solid Ptr is in the Logical Volume
192  //
193  G4LogicalVolume* logicalV = replicaPV->GetLogicalVolume();
194  G4VSolid* solid = logicalV->GetSolid();
195 
196  G4AutoLock aLock(&solidclone);
197  G4VSolid* workerSolid = solid->Clone();
198  aLock.unlock();
199 
200  if( workerSolid != nullptr )
201  {
202  logicalV->InitialiseWorker(logicalV,workerSolid,0);
203  }
204  else
205  {
206  // In the case that not all solids support(ed) the Clone()
207  // method, we do similar thing here to dynamically cast
208  // and then get the clone method.
209  //
211  ed << "ERROR - Unable to initialise geometry for worker node." << "\n"
212  << "A solid lacks the Clone() method - or Clone() failed." << "\n"
213  << " Type of solid: " << solid->GetEntityType() << "\n"
214  << " Parameters: " << *solid;
215  G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()",
216  "GeomVol0003", FatalException, ed);
217  return false;
218  }
219  return true; // It Worked
220 }
221 
222 // ----------------------------------------------------------------------
223 // Each G4PVParameterised instance, has associated with it at least one
224 // solid for each worker thread.
225 // *Simple* Parameterisations have a single type of solid, and the
226 // pointer points to the same instance of a solid during the simulation.
227 // For this case, it is possible to adapt automatically to
228 // multi-threading, simply by cloning the solid - so long
229 // as all solids support the Clone() method.
230 //
233 {
234  // Check whether it is a simple parameterisation or not
235  //
236  // G4VPVParameterisation *param= paramVol->GetParameterisation();
237  // unsigned int numCopies= paramVol->GetMultiplicity();
238  // unsigned int numDifferent= 0;
239 
240  G4LogicalVolume* logicalV= paramVol->GetLogicalVolume();
241  G4VSolid* solid= logicalV->GetSolid();
242 
243  // for( unsigned int i=0; i< numCopies; ++i)
244  // {
245  // G4VSolid *solidChk= param->ComputeSolid(i, paramVol);
246  // if( solidChk != solid)
247  // {
248  // ++numDifferent;
249  // }
250  // }
251  // if( numDifferent>0 )
252  // {
253  // G4ExceptionDescription ed;
254  // ed << "ERROR - Parameterisation using several instances of Solids \n"
255  // << "potentially to support different types of solids. \n"
256  // << "Geant4-MT currently does not support this type of \n"
257  // << "parameterisation, sorry !";
258  // G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()",
259  // "GeomVol0001", FatalException, ed);
260  // }
261 
262  // Threads may attempt to clone a solids simultaneously.
263  // Those cloned solids will be registered into a shared solid
264  // store (C++ container). Need a lock to guarantee thread safety
265  //
266  G4AutoLock aLock(&solidclone);
267  G4VSolid *workerSolid = solid->Clone();
268  aLock.unlock();
269  if( workerSolid != nullptr )
270  {
271  logicalV->InitialiseWorker(logicalV,workerSolid,0);
272  }
273  else
274  {
275  // In the case that not all solids support(ed) the Clone()
276  // method, we do similar thing here to dynamically cast
277  // and then get the clone method
278  //
280  ed << "ERROR - Unable to initialise geometry for worker node. \n"
281  << "A solid lacks the Clone() method - or Clone() failed. \n"
282  << " Type of solid: " << solid->GetEntityType() << "\n"
283  << " Parameters: " << *solid;
284  G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()",
285  "GeomVol0003", FatalException, ed);
286  }
287  return true; // It Worked
288 }
289 
290 // ----------------------------------------------------------------------
291 //
293 {
294  if( fVerbose )
295  {
296  G4cout << "G4GeometryWorkspace::InitialiseWorkspace():"
297  << " Copying geometry - Start " << G4endl;
298  }
299 
300  // Implementation originally in:
301  // G4WorkerThread::BuildGeometryAndPhysicsVector()
302  // and improved for G4PVParamaterised
303 
304  // Geometry related, split classes mechanism:
305  // Do *NOT* instantiate sub-instance for this thread, just copy the contents!
306  //
311 
313 
314  if( fVerbose )
315  {
316  G4cout << "G4GeometryWorkspace::InitialiseWorkspace: "
317  << "Copying geometry - Done!" << G4endl;
318  }
319 }
320 
321 // ----------------------------------------------------------------------
322 //
324 {
326  for (size_t ip=0; ip<physVolStore->size(); ++ip)
327  {
328  G4VPhysicalVolume* physVol = (*physVolStore)[ip];
329  G4LogicalVolume* logicalVol = physVol->GetLogicalVolume();
330  G4PVReplica* g4PVReplica = nullptr;
331  g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
332  if (g4PVReplica != nullptr)
333  {
334  g4PVReplica->TerminateWorker(g4PVReplica);
335  G4PVParameterised* paramVol = nullptr;
336  paramVol = dynamic_cast<G4PVParameterised*>(physVol);
337  if (paramVol != nullptr)
338  {
339  // G4VSolid* solid = logicalVol->fSolid;
340  logicalVol->TerminateWorker(logicalVol);
341  // if( solid->IsClone() ) delete solid;
342  }
343  else
344  {
345  logicalVol->TerminateWorker(logicalVol);
346  }
347  }
348  else
349  {
350  logicalVol->TerminateWorker(logicalVol);
351  }
352  }
357 }