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