ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4PVDivision.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4PVDivision.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 // G4PVDivision Implementation file
27 //
28 // 26.05.03 - P.Arce, Initial version
29 // --------------------------------------------------------------------
30 
31 #include "G4PVDivision.hh"
32 #include "G4LogicalVolume.hh"
33 #include "G4VSolid.hh"
34 #include "G4ReflectedSolid.hh"
35 #include "G4ParameterisationBox.hh"
38 #include "G4ParameterisationTrd.hh"
42 
43 //--------------------------------------------------------------------------
45  G4LogicalVolume* pLogical,
46  G4LogicalVolume* pMotherLogical,
47  const EAxis pAxis,
48  const G4int nDivs,
49  const G4double width,
50  const G4double offset )
51  : G4VPhysicalVolume(nullptr,G4ThreeVector(),pName,pLogical,nullptr)
52 {
53  if (pMotherLogical == nullptr)
54  {
55  std::ostringstream message;
56  message << "Invalid setup." << G4endl
57  << "NULL pointer specified as mother for volume: " << pName;
58  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
59  FatalException, message);
60  return;
61  }
62  if (pLogical == pMotherLogical)
63  {
64  std::ostringstream message;
65  message << "Invalid setup." << G4endl
66  << "Cannot place a volume inside itself! Volume: " << pName;
67  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
68  FatalException, message);
69  }
70  pMotherLogical->AddDaughter(this);
71  SetMotherLogical(pMotherLogical);
72  SetParameterisation(pMotherLogical, pAxis, nDivs,
73  width, offset, DivNDIVandWIDTH);
74  CheckAndSetParameters (pAxis, nDivs, width, offset,
75  DivNDIVandWIDTH, pMotherLogical);
76 }
77 
78 //--------------------------------------------------------------------------
80  G4LogicalVolume* pLogical,
81  G4LogicalVolume* pMotherLogical,
82  const EAxis pAxis,
83  const G4int nDivs,
84  const G4double offset )
85  : G4VPhysicalVolume(nullptr,G4ThreeVector(),pName,pLogical,nullptr)
86 {
87  if (pMotherLogical == nullptr)
88  {
89  std::ostringstream message;
90  message << "Invalid setup." << G4endl
91  << "NULL pointer specified as mother! Volume: " << pName;
92  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
93  FatalException, message);
94  return;
95  }
96  if (pLogical == pMotherLogical)
97  {
98  std::ostringstream message;
99  message << "Invalid setup." << G4endl
100  << "Cannot place a volume inside itself! Volume: " << pName;
101  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
102  FatalException, message);
103  }
104  pMotherLogical->AddDaughter(this);
105  SetMotherLogical(pMotherLogical);
106  SetParameterisation(pMotherLogical, pAxis, nDivs, 0., offset, DivNDIV);
107  CheckAndSetParameters (pAxis, nDivs, 0., offset, DivNDIV, pMotherLogical);
108 }
109 
110 //--------------------------------------------------------------------------
112  G4LogicalVolume* pLogical,
113  G4LogicalVolume* pMotherLogical,
114  const EAxis pAxis,
115  const G4double width,
116  const G4double offset )
117  : G4VPhysicalVolume(nullptr,G4ThreeVector(),pName,pLogical,nullptr)
118 {
119  if (pMotherLogical == nullptr)
120  {
121  std::ostringstream message;
122  message << "Invalid setup." << G4endl
123  << "NULL pointer specified as mother! Volume: " + pName;
124  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
125  FatalException, message);
126  return;
127  }
128  if (pLogical == pMotherLogical)
129  {
130  std::ostringstream message;
131  message << "Invalid setup." << G4endl
132  << "Cannot place a volume inside itself! Volume: "+ pName;
133  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
134  FatalException, message);
135  }
136  pMotherLogical->AddDaughter(this);
137  SetMotherLogical(pMotherLogical);
138  SetParameterisation(pMotherLogical, pAxis, 0, width, offset, DivWIDTH);
139  CheckAndSetParameters (pAxis, 0, width, offset, DivWIDTH, pMotherLogical);
140 }
141 
142 //--------------------------------------------------------------------------
144  G4LogicalVolume* pLogical,
145  G4VPhysicalVolume* pMotherPhysical,
146  const EAxis pAxis,
147  const G4int nDivs,
148  const G4double width,
149  const G4double offset )
150  : G4VPhysicalVolume(nullptr,G4ThreeVector(),pName,pLogical,nullptr)
151 {
152  if (pMotherPhysical == nullptr)
153  {
154  std::ostringstream message;
155  message << "Invalid setup." << G4endl
156  << "NULL pointer specified as mother for volume: " << pName;
157  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
158  FatalException, message);
159  return;
160  }
161  G4LogicalVolume* pMotherLogical = pMotherPhysical->GetLogicalVolume();
162  if (pLogical == pMotherLogical)
163  {
164  std::ostringstream message;
165  message << "Invalid setup." << G4endl
166  << "Cannot place a volume inside itself! Volume: " << pName;
167  G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
168  FatalException, message);
169  }
170  pMotherLogical->AddDaughter(this);
171  SetMotherLogical(pMotherLogical);
172  SetParameterisation(pMotherLogical, pAxis, nDivs,
173  width, offset, DivNDIVandWIDTH);
174  CheckAndSetParameters (pAxis, nDivs, width, offset,
175  DivNDIVandWIDTH, pMotherLogical);
176 }
177 
178 //--------------------------------------------------------------------------
179 void
181  const G4int nDivs,
182  const G4double width,
183  const G4double offset,
184  DivisionType divType,
185  const G4LogicalVolume* pMotherLogical )
186 {
187  if( divType == DivWIDTH )
188  {
190  }
191  else
192  {
193  fnReplicas = nDivs;
194  }
195  if (fnReplicas < 1 )
196  {
197  G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
198  FatalException, "Illegal number of replicas!");
199  }
200 
201  if( divType != DivNDIV)
202  {
203  fwidth = fparam->GetWidth();
204  }
205  else
206  {
207  fwidth = width;
208  }
209  if( fwidth < 0 )
210  {
211  G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
212  FatalException, "Width must be positive!");
213  }
214 
215  foffset = offset;
216  fdivAxis = pAxis;
217 
219  //
220  if( pAxis == kRho || pAxis == kRadial3D || pAxis == kPhi )
221  {
222  faxis = kZAxis;
223  }
224  else
225  {
226  faxis = pAxis;
227  }
228 
229  // Create rotation matrix: for phi axis it will be changed
230  // in G4VPVParameterisation::ComputeTransformation, for others
231  // it will stay the unity
232  //
233  G4RotationMatrix* pRMat = new G4RotationMatrix();
234  SetRotation(pRMat);
235 
236  switch (faxis)
237  {
238  case kPhi:
239  break;
240  case kRho:
241  case kXAxis:
242  case kYAxis:
243  case kZAxis:
244  break;
245  default:
246  G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
247  FatalException, "Unknown axis of replication.");
248  break;
249  }
250 
251 
252  //----- Check that mother solid is of the same type than
253  // daughter solid (otherwise, the corresponding
254  // Parameterisation::ComputeDimension() will not be called)
255  //
256  G4String msolType = pMotherLogical->GetSolid()->GetEntityType();
257  G4String dsolType = GetLogicalVolume()->GetSolid()->GetEntityType();
258  if( msolType != dsolType && ( msolType != "G4Trd" || dsolType != "G4Trap" ) )
259  {
260  std::ostringstream message;
261  message << "Incorrect solid type for division of volume "
262  << GetName() << "." << G4endl
263  << "It is: " << msolType
264  << ", while it should be: " << dsolType << "!";
265  G4Exception("G4PVDivision::CheckAndSetParameters()",
266  "GeomDiv0002", FatalException, message );
267  }
268 }
269 
270 //--------------------------------------------------------------------------
272 {
273 }
274 
275 //--------------------------------------------------------------------------
277 {
278  return fdivAxis;
279 }
280 
281 //--------------------------------------------------------------------------
283 {
284  return true;
285 }
286 
287 //--------------------------------------------------------------------------
289 {
290  return false;
291 }
292 
293 //--------------------------------------------------------------------------
295 {
296  return fcopyNo;
297 }
298 
299 //--------------------------------------------------------------------------
301 {
302  fcopyNo = newCopyNo;
303 }
304 
305 //--------------------------------------------------------------------------
307 {
308  return true;
309 }
310 
311 //--------------------------------------------------------------------------
313 {
314  return fnReplicas;
315 }
316 
317 //--------------------------------------------------------------------------
319 {
320  return fparam;
321 }
322 
323 //--------------------------------------------------------------------------
325  G4int& nDivs,
326  G4double& width,
327  G4double& offset,
328  G4bool& consuming ) const
329 {
330  axis = faxis;
331  nDivs = fnReplicas;
332  width = fwidth;
333  offset = foffset;
334  consuming = false;
335 }
336 
337 //--------------------------------------------------------------------------
339 {
340  return kParameterised;
341 }
342 
343 //--------------------------------------------------------------------------
344 // TODO: this method should check that the child lv is of the correct type,
345 // else the ComputeDimensions will never be called
346 //
348  const EAxis axis,
349  const G4int nDivs,
350  const G4double width,
351  const G4double offset,
352  DivisionType divType )
353 {
354  // Check that solid is compatible with mother solid and axis of division
355  // CheckSolid( solid, motherSolid );
356  // G4cout << " Axis " << axis << G4endl;
357 
358  G4VSolid* mSolid = motherLogical->GetSolid();
359  G4String mSolidType = mSolid->GetEntityType();
360 
361  // If the solid is a reflected one, update type to its
362  // real constituent solid.
363  //
364  if (mSolidType == "G4ReflectedSolid")
365  {
366  mSolidType = ((G4ReflectedSolid*)mSolid)->GetConstituentMovedSolid()
367  ->GetEntityType();
368  }
369 
370  // Parameterisation type depend of mother solid type and axis of division
371  //
372  if( mSolidType == "G4Box" )
373  {
374  switch( axis )
375  {
376  case kXAxis:
377  fparam = new G4ParameterisationBoxX( axis, nDivs, width,
378  offset, mSolid, divType );
379  break;
380  case kYAxis:
381  fparam = new G4ParameterisationBoxY( axis, nDivs, width,
382  offset, mSolid, divType );
383  break;
384  case kZAxis:
385  fparam = new G4ParameterisationBoxZ( axis, nDivs, width,
386  offset, mSolid, divType );
387  break;
388  default:
389  ErrorInAxis( axis, mSolid );
390  break;
391  }
392  }
393  else if( mSolidType == "G4Tubs" )
394  {
395  switch( axis )
396  {
397  case kRho:
398  fparam = new G4ParameterisationTubsRho( axis, nDivs, width,
399  offset, mSolid, divType );
400  break;
401  case kPhi:
402  fparam = new G4ParameterisationTubsPhi( axis, nDivs, width,
403  offset, mSolid, divType );
404  break;
405  case kZAxis:
406  fparam = new G4ParameterisationTubsZ( axis, nDivs, width,
407  offset, mSolid, divType );
408  break;
409  default:
410  ErrorInAxis( axis, mSolid );
411  break;
412  }
413  }
414  else if( mSolidType == "G4Cons" )
415  {
416  switch( axis )
417  {
418  case kRho:
419  fparam = new G4ParameterisationConsRho( axis, nDivs, width,
420  offset, mSolid, divType );
421  break;
422  case kPhi:
423  fparam = new G4ParameterisationConsPhi( axis, nDivs, width,
424  offset, mSolid, divType );
425  break;
426  case kZAxis:
427  fparam = new G4ParameterisationConsZ( axis, nDivs, width,
428  offset, mSolid, divType );
429  break;
430  default:
431  ErrorInAxis( axis, mSolid );
432  break;
433  }
434  }
435  else if( mSolidType == "G4Trd" )
436  {
437  switch( axis )
438  {
439  case kXAxis:
440  fparam = new G4ParameterisationTrdX( axis, nDivs, width,
441  offset, mSolid, divType );
442  break;
443  case kYAxis:
444  fparam = new G4ParameterisationTrdY( axis, nDivs, width,
445  offset, mSolid, divType );
446  break;
447  case kZAxis:
448  fparam = new G4ParameterisationTrdZ( axis, nDivs, width,
449  offset, mSolid, divType );
450  break;
451  default:
452  ErrorInAxis( axis, mSolid );
453  break;
454  }
455  }
456  else if( mSolidType == "G4Para" )
457  {
458  switch( axis )
459  {
460  case kXAxis:
461  fparam = new G4ParameterisationParaX( axis, nDivs, width,
462  offset, mSolid, divType );
463  break;
464  case kYAxis:
465  fparam = new G4ParameterisationParaY( axis, nDivs, width,
466  offset, mSolid, divType );
467  break;
468  case kZAxis:
469  fparam = new G4ParameterisationParaZ( axis, nDivs, width,
470  offset, mSolid, divType );
471  break;
472  default:
473  ErrorInAxis( axis, mSolid );
474  break;
475  }
476  }
477 // else if( mSolidType == "G4Trap" )
478 // {
479 // }
480  else if( mSolidType == "G4Polycone" )
481  {
482  switch( axis )
483  {
484  case kRho:
485  fparam = new G4ParameterisationPolyconeRho( axis, nDivs, width,
486  offset, mSolid, divType );
487  break;
488  case kPhi:
489  fparam = new G4ParameterisationPolyconePhi( axis, nDivs, width,
490  offset, mSolid, divType );
491  break;
492  case kZAxis:
493  fparam = new G4ParameterisationPolyconeZ( axis, nDivs, width,
494  offset, mSolid, divType );
495  break;
496  default:
497  ErrorInAxis( axis, mSolid );
498  break;
499  }
500  }
501  else if( mSolidType == "G4Polyhedra" )
502  {
503  switch( axis )
504  {
505  case kRho:
506  fparam = new G4ParameterisationPolyhedraRho( axis, nDivs, width,
507  offset, mSolid, divType );
508  break;
509  case kPhi:
510  fparam = new G4ParameterisationPolyhedraPhi( axis, nDivs, width,
511  offset, mSolid, divType );
512  break;
513  case kZAxis:
514  fparam = new G4ParameterisationPolyhedraZ( axis, nDivs, width,
515  offset, mSolid, divType );
516  break;
517  default:
518  ErrorInAxis( axis, mSolid );
519  break;
520  }
521  }
522  else
523  {
524  std::ostringstream message;
525  message << "Solid type " << mSolidType << " not supported!" << G4endl
526  << "Divisions for " << mSolidType << " are not implemented.";
527  G4Exception("G4PVDivision::SetParameterisation()", "GeomDiv0001",
528  FatalException, message);
529  }
530 }
531 
532 //--------------------------------------------------------------------------
534 {
535  G4String error = "Trying to divide solid " + solid->GetName()
536  + " of type " + solid->GetEntityType() + " along axis ";
537  switch( axis )
538  {
539  case kXAxis:
540  error += "X.";
541  break;
542  case kYAxis:
543  error += "Y.";
544  break;
545  case kZAxis:
546  error += "Z.";
547  break;
548  case kRho:
549  error += "Rho.";
550  break;
551  case kRadial3D:
552  error += "Radial3D.";
553  break;
554  case kPhi:
555  error += "Phi.";
556  break;
557  default:
558  break;
559  }
560  G4Exception("G4PVDivision::ErrorInAxis()", "GeomDiv0002",
561  FatalException, error);
562 }
563 
564 // The next methods are for specialised repeated volumes (replicas,
565 // parameterised vol.) which are completely regular.
566 // Currently this is not applicable to divisions ( J.A. Nov 2005 )
567 
568 // ----------------------------------------------------------------------
569 // IsRegularStructure()
570 //
572 {
573  return false;
574 }
575 
576 // ----------------------------------------------------------------------
577 // GetRegularStructureId()
578 //
580 {
581  return 0;
582 }