Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4PVReplica.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 G4PVReplica Implementation
27//
28// Original author: Paul Kent (CERN), 29 July 1995 - First non-stub version
29// - G.Cosmo, A.Dotti (CERN), 13 January 2013 - Modified for MT thread-safety
30// ----------------------------------------------------------------------
31
32#include "G4PVReplica.hh"
33#include "G4LogicalVolume.hh"
34
35// ----------------------------------------------------------------------
36G4PVRManager G4PVReplica::subInstanceManager;
37 // Helping in the use of the class G4PVRManager.
38
39#define G4MT_copyNo ((subInstanceManager.offset[instanceID]).fcopyNo)
40 // This macro changes the references to fields that are now encapsulated
41 // in the class G4ReplicaData.
42
43// ----------------------------------------------------------------------
44G4PVReplica::G4PVReplica( const G4String& pName,
45 G4LogicalVolume* pLogical,
46 G4VPhysicalVolume* pMother,
47 const EAxis pAxis,
48 const G4int nReplicas,
49 const G4double width,
50 const G4double offset )
51 : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, pMother)
52{
53
54 instanceID = subInstanceManager.CreateSubInstance();
55
56 if ((pMother == nullptr) || (pMother->GetLogicalVolume() == nullptr))
57 {
58 std::ostringstream message;
59 message << "NULL pointer specified as mother volume." << G4endl
60 << "The world volume cannot be sliced or parameterised !";
61 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
62 FatalException, message);
63 return;
64 }
65 G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
66 if (pLogical == motherLogical)
67 {
68 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
69 FatalException, "Cannot place a volume inside itself!");
70 return;
71 }
72 SetMotherLogical(motherLogical);
73 motherLogical->AddDaughter(this);
74 if (motherLogical->GetNoDaughters() != 1)
75 {
76 std::ostringstream message;
77 message << "Replica or parameterised volume must be the only daughter !"
78 << G4endl
79 << " Mother physical volume: " << pMother->GetName() << G4endl
80 << " Replicated volume: " << pName;
81 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
82 FatalException, message);
83 return;
84 }
85 CheckAndSetParameters (pAxis, nReplicas, width, offset);
86}
87
88// ----------------------------------------------------------------------
89G4PVReplica::G4PVReplica( const G4String& pName,
90 G4LogicalVolume* pLogical,
91 G4LogicalVolume* pMotherLogical,
92 const EAxis pAxis,
93 const G4int nReplicas,
94 const G4double width,
95 const G4double offset )
96 : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, nullptr)
97{
98
99 instanceID = subInstanceManager.CreateSubInstance();
100
101 if (pMotherLogical == nullptr)
102 {
103 std::ostringstream message;
104 message << "NULL pointer specified as mother volume for "
105 << pName << ".";
106 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
107 FatalException, message);
108 return;
109 }
110 if (pLogical == pMotherLogical)
111 {
112 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
113 FatalException, "Cannot place a volume inside itself!");
114 return;
115 }
116
117 pMotherLogical->AddDaughter(this);
118 SetMotherLogical(pMotherLogical);
119 if (pMotherLogical->GetNoDaughters() != 1)
120 {
121 std::ostringstream message;
122 message << "Replica or parameterised volume must be the only daughter !"
123 << G4endl
124 << " Mother logical volume: " << pMotherLogical->GetName()
125 << G4endl
126 << " Replicated volume: " << pName;
127 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
128 FatalException, message);
129 return;
130 }
131 CheckAndSetParameters (pAxis, nReplicas, width, offset);
132}
133
134// ----------------------------------------------------------------------
135G4PVReplica::G4PVReplica( const G4String& pName,
136 G4int nReplicas,
137 EAxis pAxis,
138 G4LogicalVolume* pLogical,
139 G4LogicalVolume* pMotherLogical )
140 : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, nullptr)
141{
142 // Constructor for derived type(s)
143 // Does not set mother volume or register this one in mother volume
144 // ( To allow the correct type to be found in mother->AddDaughter )
145
146 instanceID = subInstanceManager.CreateSubInstance();
147
148 if (pMotherLogical == nullptr)
149 {
150 std::ostringstream message;
151 message << "NULL pointer specified as mother volume for "
152 << pName << ".";
153 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
154 FatalException, message);
155 return;
156 }
157 if (pLogical == pMotherLogical)
158 {
159 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
160 FatalException, "Cannot place a volume inside itself!");
161 return;
162 }
163 CheckOnlyDaughter(pMotherLogical);
164 /***
165 if (pMotherLogical->GetNoDaughters() != 0)
166 {
167 std::ostringstream message;
168 message << "Replica or parameterised volume must be the only daughter !"
169 << G4endl
170 << " Mother logical volume: " << pMotherLogical->GetName()
171 << G4endl
172 << " Replicated volume: " << pName;
173 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
174 FatalException, message);
175 return;
176 }
177 **/
178 CheckAndSetParameters (pAxis, nReplicas, 0.0, 0.0);
179}
180
181// ----------------------------------------------------------------------
182void G4PVReplica::CheckOnlyDaughter(G4LogicalVolume* pMotherLogical)
183{
184 if (pMotherLogical->GetNoDaughters() != 0)
185 {
186 std::ostringstream message;
187 message << "Replica or parameterised volume must be the only daughter !"
188 << G4endl
189 << " Mother logical volume: " << pMotherLogical->GetName()
190 << G4endl
191 << " Replicated volume: " << this->GetName() << G4endl
192 << " Existing 'sister': " << pMotherLogical->GetDaughter(0)
193 ->GetName();
194 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
195 FatalException, message);
196 return;
197 }
198}
199
200// ----------------------------------------------------------------------
201void G4PVReplica::CheckAndSetParameters( const EAxis pAxis,
202 const G4int nReplicas,
203 const G4double width,
204 const G4double offset)
205{
206 if (nReplicas<1)
207 {
208 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
209 FatalException, "Illegal number of replicas.");
210 }
211 fnReplicas=nReplicas;
212 if (width<0)
213 {
214 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
215 FatalException, "Width must be positive.");
216 }
217 fwidth = width;
218 foffset = offset;
219 faxis = pAxis;
220
221 // Create rotation matrix for phi axis case & check axis is valid
222 //
223 G4RotationMatrix* pRMat = nullptr;
224 switch (faxis)
225 {
226 case kPhi:
227 pRMat = new G4RotationMatrix();
228 if (pRMat == nullptr)
229 {
230 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0003",
231 FatalException, "Rotation matrix allocation failed.");
232 }
233 SetRotation(pRMat);
234 break;
235 case kRho:
236 case kXAxis:
237 case kYAxis:
238 case kZAxis:
239 case kUndefined:
240 break;
241 default:
242 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
243 FatalException, "Unknown axis of replication.");
244 break;
245 }
246}
247
248// ----------------------------------------------------------------------
249G4PVReplica::G4PVReplica( __void__& a )
251{
252 instanceID = subInstanceManager.CreateSubInstance();
253}
254
255// ----------------------------------------------------------------------
256G4bool G4PVReplica::IsMany() const
257{
258 return false;
259}
260
261// ----------------------------------------------------------------------
262G4int G4PVReplica::GetCopyNo() const
263{
264 return G4MT_copyNo;
265}
266
267// ----------------------------------------------------------------------
268void G4PVReplica::SetCopyNo(G4int newCopyNo)
269{
270 G4MT_copyNo = newCopyNo;
271}
272
273// ----------------------------------------------------------------------
274G4bool G4PVReplica::IsReplicated() const
275{
276 return true;
277}
278
279// ----------------------------------------------------------------------
280G4bool G4PVReplica::IsParameterised() const
281{
282 return false;
283}
284
285// ----------------------------------------------------------------------
286G4VPVParameterisation* G4PVReplica::GetParameterisation() const
287{
288 return nullptr;
289}
290
291// ----------------------------------------------------------------------
292G4int G4PVReplica::GetMultiplicity() const
293{
294 return fnReplicas;
295}
296
297// ----------------------------------------------------------------------
298EVolume G4PVReplica::VolumeType() const
299{
300 return kReplica;
301}
302
303// ----------------------------------------------------------------------
304void G4PVReplica::GetReplicationData( EAxis& axis,
305 G4int& nReplicas,
306 G4double& width,
308 G4bool& consuming ) const
309{
310 axis = faxis;
311 nReplicas = fnReplicas;
312 width = fwidth;
313 offset = foffset;
314 consuming = true;
315}
316
317// ----------------------------------------------------------------------
318G4bool G4PVReplica::IsRegularStructure() const
319{
320 return (fRegularVolsId != 0);
321}
322
323// ----------------------------------------------------------------------
324G4int G4PVReplica::GetRegularStructureId() const
325{
326 return fRegularVolsId;
327}
328
329// ----------------------------------------------------------------------
330void G4PVReplica::SetRegularStructureId( G4int code )
331{
332 fRegularVolsId = code;
333}
334
335// ----------------------------------------------------------------------
336// Returns the private data instance manager.
337//
338const G4PVRManager& G4PVReplica::GetSubInstanceManager()
339{
340 return subInstanceManager;
341}
342
343// ----------------------------------------------------------------------
344// This method is similar to the constructor. It is used by each worker
345// thread to achieve the same effect as that of the master thread exept
346// to register the new created instance. This method is invoked explicitly.
347// It does not create a new G4PVReplica instance. It only assigns the value
348// for the fields encapsulated by the class G4ReplicaData.
349//
350void G4PVReplica::InitialiseWorker(G4PVReplica* pMasterObject)
351{
352
353 G4VPhysicalVolume::InitialiseWorker( pMasterObject, nullptr, G4ThreeVector());
354 subInstanceManager.SlaveCopySubInstanceArray();
355 G4MT_copyNo = -1;
356
357 // This call causes "self-assignment" of the input parameters
358 // Issue reported by DRD since TerminateWorker() below can be called
359 // at the same time by another thread.
360 // What we need here is the split-class component of CheckAndSetParameters()
361 // funciton copied here.
362
363 // Create rotation matrix for phi axis case & check axis is valid
364 //
365 G4RotationMatrix* pRMat = nullptr;
366 switch (faxis)
367 {
368 case kPhi:
369 pRMat = new G4RotationMatrix();
370 if (pRMat == nullptr)
371 {
372 G4Exception("G4PVReplica::InitialiseWorker(...)", "GeomVol0003",
373 FatalException, "Rotation matrix allocation failed.");
374 }
375 SetRotation(pRMat);
376 break;
377 case kRho:
378 case kXAxis:
379 case kYAxis:
380 case kZAxis:
381 case kUndefined:
382 break;
383 default:
384 G4Exception("G4PVReplica::InitialiseWorker(...)", "GeomVol0002",
385 FatalException, "Unknown axis of replication.");
386 break;
387 }
388}
389
390// ----------------------------------------------------------------------
391// This method is similar to the destructor. It is used by each worker
392// thread to achieve the partial effect as that of the master thread.
393// For G4PVReplica instances, it destroys the rotation matrix.
394//
395void G4PVReplica::TerminateWorker(G4PVReplica* /*pMasterObject*/)
396{
397 if ( faxis==kPhi )
398 {
399 delete GetRotation();
400 }
401}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4ThreadLocal T * G4GeomSplitter< T >::offset
EAxis faxis
G4int fnReplicas
G4double fwidth
G4double foffset
#define G4MT_copyNo
G4PVReplica(const G4String &pName, G4LogicalVolume *pLogical, G4LogicalVolume *pMother, const EAxis pAxis, const G4int nReplicas, const G4double width, const G4double offset=0.)
G4PVReplica represents many touchable detector elements differing only in their positioning....
G4GeomSplitter< G4ReplicaData > G4PVRManager
CLHEP::HepRotation G4RotationMatrix
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4LogicalVolume represents a leaf node or unpositioned subtree in the geometry hierarchy....
void AddDaughter(G4VPhysicalVolume *p)
std::size_t GetNoDaughters() const
G4VPhysicalVolume * GetDaughter(const std::size_t i) const
const G4String & GetName() const
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
void InitialiseWorker(G4VPhysicalVolume *pMasterObject, G4RotationMatrix *pRot, const G4ThreeVector &tlate)
EAxis
Definition geomdefs.hh:54
@ kPhi
Definition geomdefs.hh:60
@ kYAxis
Definition geomdefs.hh:56
@ kXAxis
Definition geomdefs.hh:55
@ kZAxis
Definition geomdefs.hh:57
@ kUndefined
Definition geomdefs.hh:61
@ kRho
Definition geomdefs.hh:58
EVolume
Definition geomdefs.hh:83
@ kReplica
Definition geomdefs.hh:85
const axis_t axis_to_type< N >::axis
Definition pugixml.cc:9668