ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4PVReplica.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4PVReplica.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 G4PVReplica Implementation
27 //
28 // 29.07.95, P.Kent - First non-stub version
29 // ----------------------------------------------------------------------
30 
31 #include "G4PVReplica.hh"
32 #include "G4LogicalVolume.hh"
33 
35  // Helping in the use of the class G4PVRManager.
36 
38  G4LogicalVolume* pLogical,
39  G4VPhysicalVolume* pMother,
40  const EAxis pAxis,
41  const G4int nReplicas,
42  const G4double width,
43  const G4double offset )
44  : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, pMother)
45 {
46 
48 
49  G4MT_copyNo = -1;
50 
51  if ((pMother == nullptr) || (pMother->GetLogicalVolume() == nullptr))
52  {
53  std::ostringstream message;
54  message << "NULL pointer specified as mother volume." << G4endl
55  << "The world volume cannot be sliced or parameterised !";
56  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
57  FatalException, message);
58  return;
59  }
60  G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
61  if (pLogical == motherLogical)
62  {
63  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
64  FatalException, "Cannot place a volume inside itself!");
65  return;
66  }
67  SetMotherLogical(motherLogical);
68  motherLogical->AddDaughter(this);
69  if (motherLogical->GetNoDaughters() != 1)
70  {
71  std::ostringstream message;
72  message << "Replica or parameterised volume must be the only daughter !"
73  << G4endl
74  << " Mother physical volume: " << pMother->GetName() << G4endl
75  << " Replicated volume: " << pName;
76  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
77  FatalException, message);
78  return;
79  }
80  CheckAndSetParameters (pAxis, nReplicas, width, offset);
81 }
82 
84  G4LogicalVolume* pLogical,
85  G4LogicalVolume* pMotherLogical,
86  const EAxis pAxis,
87  const G4int nReplicas,
88  const G4double width,
89  const G4double offset )
90  : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, nullptr)
91 {
92 
94  G4MT_copyNo = -1;
95 
96  if (pMotherLogical == nullptr)
97  {
98  std::ostringstream message;
99  message << "NULL pointer specified as mother volume for "
100  << pName << ".";
101  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
102  FatalException, message);
103  return;
104  }
105  if (pLogical == pMotherLogical)
106  {
107  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
108  FatalException, "Cannot place a volume inside itself!");
109  return;
110  }
111 
112  pMotherLogical->AddDaughter(this);
113  SetMotherLogical(pMotherLogical);
114  if (pMotherLogical->GetNoDaughters() != 1)
115  {
116  std::ostringstream message;
117  message << "Replica or parameterised volume must be the only daughter !"
118  << G4endl
119  << " Mother logical volume: " << pMotherLogical->GetName()
120  << G4endl
121  << " Replicated volume: " << pName;
122  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
123  FatalException, message);
124  return;
125  }
126  CheckAndSetParameters (pAxis, nReplicas, width, offset);
127 }
128 
130  G4int nReplicas,
131  EAxis pAxis,
132  G4LogicalVolume* pLogical,
133  G4LogicalVolume* pMotherLogical
134  )
135  : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, nullptr)
136 {
137  // Constructor for derived type(s)
138  // Does not set mother volume or register this one in mother volume
139  // ( To allow the correct type to be found in mother->AddDaughter )
140 
142  G4MT_copyNo = -1;
143 
144  if (pMotherLogical == nullptr)
145  {
146  std::ostringstream message;
147  message << "NULL pointer specified as mother volume for "
148  << pName << ".";
149  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
150  FatalException, message);
151  return;
152  }
153  if (pLogical == pMotherLogical)
154  {
155  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
156  FatalException, "Cannot place a volume inside itself!");
157  return;
158  }
159  CheckOnlyDaughter(pMotherLogical);
160  /***
161  if (pMotherLogical->GetNoDaughters() != 0)
162  {
163  std::ostringstream message;
164  message << "Replica or parameterised volume must be the only daughter !"
165  << G4endl
166  << " Mother logical volume: " << pMotherLogical->GetName()
167  << G4endl
168  << " Replicated volume: " << pName;
169  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
170  FatalException, message);
171  return;
172  }
173  **/
174  CheckAndSetParameters (pAxis, nReplicas, 0.0, 0.0);
175 }
176 
178 {
179  if (pMotherLogical->GetNoDaughters() != 0)
180  {
181  std::ostringstream message;
182  message << "Replica or parameterised volume must be the only daughter !"
183  << G4endl
184  << " Mother logical volume: " << pMotherLogical->GetName()
185  << G4endl
186  << " Replicated volume: " << this->GetName() << G4endl
187  << " Existing 'sister': " << pMotherLogical->GetDaughter(0)
188  ->GetName();
189  G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
190  FatalException, message);
191  return;
192  }
193 }
194 
196  const G4int nReplicas,
197  const G4double width,
198  const G4double offset)
199 {
200  if (nReplicas<1)
201  {
202  G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
203  FatalException, "Illegal number of replicas.");
204  }
205  fnReplicas=nReplicas;
206  if (width<0)
207  {
208  G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
209  FatalException, "Width must be positive.");
210  }
211  fwidth = width;
212  foffset = offset;
213  faxis = pAxis;
214 
215  // Create rotation matrix for phi axis case & check axis is valid
216  //
217  G4RotationMatrix* pRMat = nullptr;
218  switch (faxis)
219  {
220  case kPhi:
221  pRMat = new G4RotationMatrix();
222  if (pRMat == nullptr)
223  {
224  G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0003",
225  FatalException, "Rotation matrix allocation failed.");
226  }
227  SetRotation(pRMat);
228  break;
229  case kRho:
230  case kXAxis:
231  case kYAxis:
232  case kZAxis:
233  case kUndefined:
234  break;
235  default:
236  G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
237  FatalException, "Unknown axis of replication.");
238  break;
239  }
240 }
241 
243  : G4VPhysicalVolume(a), faxis(kZAxis), fnReplicas(0), fwidth(0.), foffset(0.)
244 {
246  G4MT_copyNo = -1;
247 }
248 
250 {
251  if ( faxis==kPhi )
252  {
253  delete GetRotation();
254  }
255 }
256 
258 {
259  return false;
260 }
261 
263 {
264  return G4MT_copyNo;
265 }
266 
268 {
269  G4MT_copyNo = newCopyNo;
270 }
271 
273 {
274  return true;
275 }
276 
278 {
279  return false;
280 }
281 
283 {
284  return nullptr;
285 }
286 
288 {
289  return fnReplicas;
290 }
291 
293 {
294  return kReplica;
295 }
296 
298  G4int& nReplicas,
299  G4double& width,
300  G4double& offset,
301  G4bool& consuming ) const
302 {
303  axis = faxis;
304  nReplicas = fnReplicas;
305  width = fwidth;
306  offset = foffset;
307  consuming = true;
308 }
309 
311 {
312  return (fRegularVolsId != 0);
313 }
314 
316 {
317  return fRegularVolsId;
318 }
319 
321 {
322  fRegularVolsId = code;
323 }
324 
325 // Returns the private data instance manager.
326 //
328 {
329  return subInstanceManager;
330 }
331 
332 // This method is similar to the constructor. It is used by each worker
333 // thread to achieve the same effect as that of the master thread exept
334 // to register the new created instance. This method is invoked explicitly.
335 // It does not create a new G4PVReplica instance. It only assigns the value
336 // for the fields encapsulated by the class G4ReplicaData.
337 //
339 {
340 
341  G4VPhysicalVolume::InitialiseWorker( pMasterObject, nullptr, G4ThreeVector());
343  G4MT_copyNo = -1;
344 
345  // This call causes "self-assignment" of the input paramters
346  // Issue reported by DRD since TerminateWorker below can be called
347  // at the same time by another thread
348  // What we need here is the splic-class component of this funciton
349  // that is copied here
350  // CheckAndSetParameters (faxis, fnReplicas, fwidth, foffset);
351 
352  // Create rotation matrix for phi axis case & check axis is valid
353  //
354  G4RotationMatrix* pRMat = nullptr;
355  switch (faxis)
356  {
357  case kPhi:
358  pRMat = new G4RotationMatrix();
359  if (pRMat == nullptr)
360  {
361  G4Exception("G4PVReplica::InitialiseWorker(...)", "GeomVol0003",
362  FatalException, "Rotation matrix allocation failed.");
363  }
364  SetRotation(pRMat);
365  break;
366  case kRho:
367  case kXAxis:
368  case kYAxis:
369  case kZAxis:
370  case kUndefined:
371  break;
372  default:
373  G4Exception("G4PVReplica::InitialiseWorker(...)", "GeomVol0002",
374  FatalException, "Unknown axis of replication.");
375  break;
376  }
377 }
378 
379 // This method is similar to the destructor. It is used by each worker
380 // thread to achieve the partial effect as that of the master thread.
381 // For G4PVReplica instances, it destories the rotation matrix.
382 //
384 {
385  if ( faxis==kPhi )
386  {
387  delete GetRotation();
388  }
389 }