Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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// Class G4GeometryWorkspace - implementation
27//
28// ----------------------------------------------------------------------
29
31
32#include "G4PVReplica.hh"
33#include "G4PVParameterised.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
45namespace
46{
47 G4Mutex solidclone = G4MUTEX_INITIALIZER;
49}
50
51// ----------------------------------------------------------------------
52//
54{
55 return &thePool;
56}
57
58// ----------------------------------------------------------------------
59//
61{
62 fpLogicalVolumeSIM=
64 fpPhysicalVolumeSIM=
66 fpReplicaSIM=
68 fpRegionSIM=
70
71 // Create a work area for Logical Volumes in this thread
72 // then capture its address
74
75 fLogicalVolumeOffset = fpLogicalVolumeSIM->GetOffset();
76
77 fPhysicalVolumeOffset = fpPhysicalVolumeSIM->GetOffset();
78
79 fReplicaOffset = fpReplicaSIM->GetOffset();
80
81 fRegionOffset = fpRegionSIM->GetOffset();
82}
83
84// ----------------------------------------------------------------------
85//
87{
88}
89
90// ----------------------------------------------------------------------
91//
92void
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
106 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolumeOffset);
107 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVolumeOffset);
108
109 fpReplicaSIM->UseWorkArea(fReplicaOffset);
110 fpRegionSIM->UseWorkArea(fRegionOffset);
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{
127 fpLogicalVolumeSIM->UseWorkArea(0);
128 fpPhysicalVolumeSIM->UseWorkArea(0);
129
130 fpReplicaSIM->UseWorkArea(0);
131 fpRegionSIM->UseWorkArea(0);
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 //
307 fpLogicalVolumeSIM->SlaveCopySubInstanceArray();
308 fpPhysicalVolumeSIM->SlaveCopySubInstanceArray();
309 fpReplicaSIM->SlaveCopySubInstanceArray();
310 fpRegionSIM->SlaveInitializeSubInstance();
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 }
353 fpLogicalVolumeSIM->FreeSlave();
354 fpPhysicalVolumeSIM->FreeSlave();
355 fpReplicaSIM->FreeSlave();
356 fpRegionSIM->FreeSlave();
357}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
std::mutex G4Mutex
Definition: G4Threading.hh:81
bool G4bool
Definition: G4Types.hh:86
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
void SlaveInitializeSubInstance()
void SlaveCopySubInstanceArray()
void UseWorkArea(T *newOffset)
G4bool CloneReplicaSolid(G4PVReplica *)
G4bool CloneParameterisedSolids(G4PVParameterised *paramVol)
static pool_type * GetPool()
G4VSolid * GetSolid() const
void TerminateWorker(G4LogicalVolume *ptrMasterObject)
static const G4LVManager & GetSubInstanceManager()
void InitialiseWorker(G4LogicalVolume *ptrMasterObject, G4VSolid *pSolid, G4VSensitiveDetector *pSDetector)
G4VSolid * GetMasterSolid() const
static const G4PVRManager & GetSubInstanceManager()
Definition: G4PVReplica.cc:327
void TerminateWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:383
virtual G4bool IsParameterised() const
Definition: G4PVReplica.cc:277
void InitialiseWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:338
static G4PhysicalVolumeStore * GetInstance()
static const G4RegionManager & GetSubInstanceManager()
Definition: G4Region.cc:55
G4LogicalVolume * GetLogicalVolume() const
static const G4PVManager & GetSubInstanceManager()
virtual G4VSolid * Clone() const
Definition: G4VSolid.cc:379
virtual G4GeometryType GetEntityType() const =0