Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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// G4GeometryWorkspace - implementation
27//
28// Authors: John Apostolakis (CERN), Andrea Dotti (SLAC), July 2013
29// --------------------------------------------------------------------
30
33#include "G4AutoLock.hh"
34
35namespace
36{
37 G4Mutex mutex_init = G4MUTEX_INITIALIZER;
39}
40
41// ----------------------------------------------------------------------
42//
44{
45 return &thePool;
46}
47
48// ----------------------------------------------------------------------
49//
51{
52 fpLogicalVolumeSIM=
54 fpPhysicalVolumeSIM=
56 fpReplicaSIM=
58 fpRegionSIM=
60
61 // Create a work area for Logical Volumes in this thread
62 // then capture its address
63 //
65
66 fLogicalVolumeOffset = fpLogicalVolumeSIM->GetOffset();
67
68 fPhysicalVolumeOffset = fpPhysicalVolumeSIM->GetOffset();
69
70 fReplicaOffset = fpReplicaSIM->GetOffset();
71
72 fRegionOffset = fpRegionSIM->GetOffset();
73}
74
75// ----------------------------------------------------------------------
76//
78{
79}
80
81// ----------------------------------------------------------------------
82//
83void
85{
86 // Geometry related, split classes mechanism: instantiate sub-instance
87 // for this thread
88 //
89 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolumeOffset);
90 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVolumeOffset);
91
92 fpReplicaSIM->UseWorkArea(fReplicaOffset);
93 fpRegionSIM->UseWorkArea(fRegionOffset);
94
95 // When recycling a workspace
96 // - it must be a lightweight operation, to reuse a valid work area
97 // - so it must NOT Initialise anything!
98 // Do not call InitialisePhysicalVolumes();
99}
100
101// ----------------------------------------------------------------------
102//
104{
105 fpLogicalVolumeSIM->UseWorkArea(nullptr);
106 fpPhysicalVolumeSIM->UseWorkArea(nullptr);
107
108 fpReplicaSIM->UseWorkArea(nullptr);
109 fpRegionSIM->UseWorkArea(nullptr);
110}
111
112// ----------------------------------------------------------------------
113//
115{
117 for (std::size_t ip=0; ip<physVolStore->size(); ++ip)
118 {
119 G4VPhysicalVolume* physVol = (*physVolStore)[ip];
120 G4LogicalVolume *logicalVol = physVol->GetLogicalVolume();
121
122 // Use shadow pointer
123 //
124 G4VSolid* solid = logicalVol->GetMasterSolid();
125 G4PVReplica* g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
126 if (g4PVReplica == nullptr)
127 {
128 // Placement volume
129 //
130 logicalVol->InitialiseWorker(logicalVol,solid,nullptr);
131 }
132 else
133 {
134 g4PVReplica->InitialiseWorker(g4PVReplica);
135 logicalVol->InitialiseWorker(logicalVol,solid,nullptr);
136
137 // If the replica's solid (in LV) is changed during navigation,
138 // it must be thread-private
139 //
140 CloneReplicaSolid( g4PVReplica );
141 }
142 }
143}
144
145// ----------------------------------------------------------------------
146// Create a clone of the solid for this replica in this thread
147//
149{
150 G4LogicalVolume* logicalV = replicaPV->GetLogicalVolume();
151 G4VSolid* solid = logicalV->GetSolid();
152
153 G4AutoLock aLock(&mutex_init);
154 G4VSolid* workerSolid = solid->Clone();
155 aLock.unlock();
156
157 if( workerSolid != nullptr )
158 {
159 logicalV->InitialiseWorker(logicalV,workerSolid,nullptr);
160 }
161 else
162 {
163 // In the case that not all solids support(ed) the Clone()
164 // method, we do similar thing here to dynamically cast
165 // and then get the clone method
166 //
168 ed << "ERROR - Unable to initialise geometry for worker node." << "\n"
169 << "A solid lacks the Clone() method - or Clone() failed." << "\n"
170 << " Type of solid: " << solid->GetEntityType() << "\n"
171 << " Parameters: " << *solid;
172 G4Exception("G4GeometryWorkspace::CloneReplicaSolid()",
173 "GeomVol0003", FatalException, ed);
174 return false;
175 }
176 return true; // It Worked
177}
178
179// ----------------------------------------------------------------------
180//
182{
183 // Geometry related, split classes mechanism:
184 // Do *NOT* instantiate sub-instance for this thread, just copy the contents!
185 //
186 fpLogicalVolumeSIM->SlaveCopySubInstanceArray();
187 fpPhysicalVolumeSIM->SlaveCopySubInstanceArray();
188 fpReplicaSIM->SlaveCopySubInstanceArray();
189 fpRegionSIM->SlaveInitializeSubInstance();
190
192}
193
194// ----------------------------------------------------------------------
195//
197{
199 for (std::size_t ip=0; ip<physVolStore->size(); ++ip)
200 {
201 G4VPhysicalVolume* physVol = (*physVolStore)[ip];
202 G4LogicalVolume* logicalVol = physVol->GetLogicalVolume();
203 G4PVReplica* g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
204 if (g4PVReplica != nullptr)
205 {
206 g4PVReplica->TerminateWorker(g4PVReplica);
207 }
208 logicalVol->TerminateWorker(logicalVol);
209 }
210
211 // Threads may attempt to free memory simultaneously.
212 // Need a lock to guarantee thread safety
213 //
214 G4AutoLock aLock(&mutex_init);
215 fpLogicalVolumeSIM->FreeSlave();
216 fpPhysicalVolumeSIM->FreeSlave();
217 fpReplicaSIM->FreeSlave();
218 fpRegionSIM->FreeSlave();
219 aLock.unlock();
220}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
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
void SlaveInitializeSubInstance()
void SlaveCopySubInstanceArray()
void UseWorkArea(T *newOffset)
G4bool CloneReplicaSolid(G4PVReplica *)
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:343
void TerminateWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:400
void InitialiseWorker(G4PVReplica *pMasterObject)
Definition: G4PVReplica.cc:355
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:391
virtual G4GeometryType GetEntityType() const =0