Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/divisions/src/G4PVDivision.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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"
 36 #include "G4ParameterisationTubs.hh"
 37 #include "G4ParameterisationCons.hh"
 38 #include "G4ParameterisationTrd.hh"
 39 #include "G4ParameterisationPara.hh"
 40 #include "G4ParameterisationPolycone.hh"
 41 #include "G4ParameterisationPolyhedra.hh"
 42 
 43 //--------------------------------------------------------------------------
 44 G4PVDivision::G4PVDivision(const G4String& pName,
 45                                  G4LogicalVolume* pLogical,
 46                                  G4LogicalVolume* pMotherLogical,
 47                            const EAxis pAxis,
 48                            const G4int nDivs,
 49                            const G4double width,
 50                            const G4double offset )
 51   : G4PVReplica(pName, nDivs, pAxis, pLogical, pMotherLogical)
 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 //--------------------------------------------------------------------------
 79 G4PVDivision::G4PVDivision(const G4String& pName,
 80                                  G4LogicalVolume* pLogical,
 81                                  G4LogicalVolume* pMotherLogical,
 82                            const EAxis pAxis,
 83                            const G4int nDivs,
 84                            const G4double offset )
 85   : G4PVReplica(pName, nDivs, pAxis, pLogical, pMotherLogical)
 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 //--------------------------------------------------------------------------
111 G4PVDivision::G4PVDivision(const G4String& pName,
112                                  G4LogicalVolume* pLogical,
113                                  G4LogicalVolume* pMotherLogical,
114                            const EAxis pAxis,
115                            const G4double width,
116                            const G4double offset )
117   : G4PVReplica(pName, 0, pAxis, pLogical, pMotherLogical)
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 //--------------------------------------------------------------------------
143 G4PVDivision::G4PVDivision(const G4String& pName,
144                                  G4LogicalVolume* pLogical,
145                                  G4VPhysicalVolume* pMotherPhysical,
146                            const EAxis pAxis,
147                            const G4int nDivs,
148                            const G4double width,
149                            const G4double offset )
150   : G4PVReplica(pName, nDivs, pAxis, pLogical,
151                 pMotherPhysical != nullptr ? pMotherPhysical->GetLogicalVolume() : nullptr)
152 {
153   if (pMotherPhysical == nullptr)
154   {
155     std::ostringstream message;
156     message << "Invalid setup." << G4endl
157             << "NULL pointer specified as mother for volume: " << pName;
158     G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
159                 FatalException, message);
160     return;
161   }
162   G4LogicalVolume* pMotherLogical = pMotherPhysical->GetLogicalVolume();
163   if (pLogical == pMotherLogical)
164   {
165     std::ostringstream message;
166     message << "Invalid setup." << G4endl
167             << "Cannot place a volume inside itself! Volume: " << pName;
168     G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
169                 FatalException, message);
170   }
171   pMotherLogical->AddDaughter(this);
172   SetMotherLogical(pMotherLogical);
173   SetParameterisation(pMotherLogical, pAxis, nDivs,
174                       width, offset, DivNDIVandWIDTH);
175   CheckAndSetParameters (pAxis, nDivs, width, offset,
176                          DivNDIVandWIDTH, pMotherLogical);
177 }
178 
179 //--------------------------------------------------------------------------
180 void
181 G4PVDivision::CheckAndSetParameters( const EAxis pAxis,
182                                      const G4int nDivs,
183                                      const G4double width,
184                                      const G4double offset, 
185                                            DivisionType divType,
186                                      const G4LogicalVolume* pMotherLogical )
187 {
188   if( divType == DivWIDTH )
189   {
190     fnReplicas = fparam->GetNoDiv();
191   }
192   else
193   {
194     fnReplicas = nDivs;
195   }
196   if (fnReplicas < 1 )
197   {
198     G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
199                 FatalException, "Illegal number of replicas!");
200   }
201 
202   if( divType != DivNDIV)
203   {
204     fwidth = fparam->GetWidth();
205   }
206   else
207   {
208     fwidth = width;
209   }
210   if( fwidth < 0 )
211   {
212     G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
213                 FatalException, "Width must be positive!");
214   }
215   
216   foffset = offset;
217   fdivAxis = pAxis;
218 
219   //!!!!! axis has to be x/y/z in G4VoxelLimits::GetMinExtent
220   //
221   if( pAxis == kRho || pAxis == kRadial3D || pAxis == kPhi )
222   {
223     faxis = kZAxis;
224   }
225   else
226   {
227     faxis = pAxis;
228   }
229   
230   // Create rotation matrix: for phi axis it will be changed
231   // in G4VPVParameterisation::ComputeTransformation, for others
232   // it will stay the unity
233   //
234   auto  pRMat = new G4RotationMatrix();
235   SetRotation(pRMat);
236   
237   switch (faxis)
238   {
239     case kPhi:
240       break;
241     case kRho:
242     case kXAxis:
243     case kYAxis:
244     case kZAxis:
245       break;
246     default:
247       G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
248                   FatalException, "Unknown axis of replication.");
249       break;
250   }
251 
252 
253   //----- Check that mother solid is of the same type than
254   //      daughter solid (otherwise, the corresponding
255   //      Parameterisation::ComputeDimension() will not be called)
256   //
257   G4String msolType = pMotherLogical->GetSolid()->GetEntityType();
258   G4String dsolType = GetLogicalVolume()->GetSolid()->GetEntityType();
259   if( msolType != dsolType && ( msolType != "G4Trd" || dsolType != "G4Trap" ) )
260   {
261     std::ostringstream message;
262     message << "Incorrect solid type for division of volume "
263             << GetName() << "." << G4endl
264             << "It is: " << msolType
265             << ", while it should be: " << dsolType << "!";
266     G4Exception("G4PVDivision::CheckAndSetParameters()",
267                 "GeomDiv0002", FatalException, message );
268   }
269 }
270 
271 //--------------------------------------------------------------------------
272 G4PVDivision::~G4PVDivision() = default;
273 
274 //--------------------------------------------------------------------------
275 EAxis G4PVDivision::GetDivisionAxis() const
276 {
277   return fdivAxis;
278 }
279 
280 //--------------------------------------------------------------------------
281 G4bool G4PVDivision::IsParameterised() const
282 { 
283   return true;
284 }
285 
286 //--------------------------------------------------------------------------
287 G4bool G4PVDivision::IsMany() const
288 {
289   return false; 
290 }
291 
292 //--------------------------------------------------------------------------
293 G4bool G4PVDivision::IsReplicated() const
294 {
295   return true;
296 }
297 
298 //--------------------------------------------------------------------------
299 G4int G4PVDivision::GetMultiplicity() const
300 {
301   return fnReplicas;
302 }
303 
304 //--------------------------------------------------------------------------
305 G4VPVParameterisation* G4PVDivision::GetParameterisation() const
306 {
307   return fparam;
308 }
309 
310 //--------------------------------------------------------------------------
311 void G4PVDivision::GetReplicationData(EAxis& axis,
312                                       G4int& nDivs,
313                                       G4double& width,
314                                       G4double& offset,
315                                       G4bool& consuming ) const
316 {
317   axis = faxis;
318   nDivs = fnReplicas;
319   width = fwidth;
320   offset = foffset;
321   consuming = false;
322 }
323 
324 //--------------------------------------------------------------------------
325 EVolume G4PVDivision::VolumeType() const
326 {
327   return kParameterised;
328 }
329 
330 //--------------------------------------------------------------------------
331 // TODO: this method should check that the child lv is of the correct type,
332 //       else the ComputeDimensions will never be called
333 //
334 void G4PVDivision::SetParameterisation( G4LogicalVolume* motherLogical,
335                                   const EAxis axis,
336                                   const G4int nDivs,
337                                   const G4double width,
338                                   const G4double offset,
339                                         DivisionType divType )
340 {
341   // Check that solid is compatible with mother solid and axis of division   
342   // CheckSolid( solid, motherSolid );
343   // G4cout << " Axis " << axis << G4endl;
344 
345   G4VSolid* mSolid = motherLogical->GetSolid();
346   G4String mSolidType = mSolid->GetEntityType();
347 
348   // If the solid is a reflected one, update type to its
349   // real constituent solid.
350   // 
351   if (mSolidType == "G4ReflectedSolid")
352   {
353       mSolidType = ((G4ReflectedSolid*)mSolid)->GetConstituentMovedSolid()
354                  ->GetEntityType(); 
355   }    
356 
357   // Parameterisation type depend of mother solid type and axis of division
358   //
359   if( mSolidType == "G4Box" )
360   {
361     switch( axis )
362     {
363       case kXAxis:
364         fparam = new G4ParameterisationBoxX( axis, nDivs, width,
365                                              offset, mSolid, divType );
366         break;
367       case kYAxis:
368         fparam = new G4ParameterisationBoxY( axis, nDivs, width,
369                                              offset, mSolid, divType );
370         break;
371       case kZAxis:
372         fparam = new G4ParameterisationBoxZ( axis, nDivs, width,
373                                              offset, mSolid, divType );
374         break;
375       default:
376         ErrorInAxis( axis, mSolid );
377         break;
378     }
379   }
380   else if( mSolidType == "G4Tubs" )
381   {
382     switch( axis )
383     {
384       case kRho:
385         fparam = new G4ParameterisationTubsRho( axis, nDivs, width,
386                                                 offset, mSolid, divType );
387         break;
388       case kPhi:
389         fparam = new G4ParameterisationTubsPhi( axis, nDivs, width,
390                                                 offset, mSolid, divType );
391         break;
392       case kZAxis:
393         fparam = new G4ParameterisationTubsZ( axis, nDivs, width,
394                                               offset, mSolid, divType );
395         break;
396       default:
397         ErrorInAxis( axis, mSolid );
398         break;
399     }
400   }
401   else if( mSolidType == "G4Cons" )
402   {
403     switch( axis )
404     {
405       case kRho:
406         fparam = new G4ParameterisationConsRho( axis, nDivs, width,
407                                                 offset, mSolid, divType );
408         break;
409       case kPhi:
410         fparam = new G4ParameterisationConsPhi( axis, nDivs, width,
411                                                 offset, mSolid, divType );
412         break;
413       case kZAxis:
414         fparam = new G4ParameterisationConsZ( axis, nDivs, width,
415                                               offset, mSolid, divType );
416         break;
417       default:
418         ErrorInAxis( axis, mSolid );
419         break;
420     }
421   }
422   else if( mSolidType == "G4Trd" )
423   { 
424     switch( axis )
425     {
426       case kXAxis:
427         fparam = new G4ParameterisationTrdX( axis, nDivs, width,
428                                              offset, mSolid, divType );
429         break;
430       case kYAxis:
431         fparam = new G4ParameterisationTrdY( axis, nDivs, width,
432                                              offset, mSolid, divType );
433         break;
434       case kZAxis:
435         fparam = new G4ParameterisationTrdZ( axis, nDivs, width,
436                                              offset, mSolid, divType );
437         break;
438       default:
439         ErrorInAxis( axis, mSolid );
440         break;
441     }
442   }
443   else if( mSolidType == "G4Para" )
444   { 
445     switch( axis )
446     {
447       case kXAxis:
448         fparam = new G4ParameterisationParaX( axis, nDivs, width,
449                                              offset, mSolid, divType );
450         break;
451       case kYAxis:
452         fparam = new G4ParameterisationParaY( axis, nDivs, width,
453                                              offset, mSolid, divType );
454         break;
455       case kZAxis:
456         fparam = new G4ParameterisationParaZ( axis, nDivs, width,
457                                              offset, mSolid, divType );
458         break;
459       default:
460         ErrorInAxis( axis, mSolid );
461         break;
462     }
463   }
464 //  else if( mSolidType == "G4Trap" )
465 //  {
466 //  }
467   else if( mSolidType == "G4Polycone" )
468   {
469     switch( axis )
470     {
471       case kRho:
472         fparam = new G4ParameterisationPolyconeRho( axis, nDivs, width,
473                                                     offset, mSolid, divType );
474         break;
475       case kPhi:
476         fparam = new G4ParameterisationPolyconePhi( axis, nDivs, width,
477                                                     offset, mSolid, divType );
478         break;
479       case kZAxis:
480         fparam = new G4ParameterisationPolyconeZ( axis, nDivs, width,
481                                                   offset, mSolid, divType );
482         break;
483       default:
484         ErrorInAxis( axis, mSolid );
485       break;
486     }
487   }
488   else if( mSolidType == "G4Polyhedra" )
489   {
490     switch( axis )
491     {
492       case kRho:
493         fparam = new G4ParameterisationPolyhedraRho( axis, nDivs, width,
494                                                     offset, mSolid, divType );
495         break;
496       case kPhi:
497         fparam = new G4ParameterisationPolyhedraPhi( axis, nDivs, width,
498                                                     offset, mSolid, divType );
499         break;
500       case kZAxis:
501         fparam = new G4ParameterisationPolyhedraZ( axis, nDivs, width,
502                                                   offset, mSolid, divType );
503         break;
504       default:
505         ErrorInAxis( axis, mSolid );
506       break;
507     }
508   }
509   else
510   {
511     std::ostringstream message;
512     message << "Solid type " << mSolidType << " not supported!"  << G4endl
513             << "Divisions for " << mSolidType << " are not implemented.";
514     G4Exception("G4PVDivision::SetParameterisation()", "GeomDiv0001",
515                 FatalException, message);
516   }
517 }
518 
519 //--------------------------------------------------------------------------
520 void G4PVDivision::ErrorInAxis( EAxis axis, G4VSolid* solid )
521 {
522   G4String error = "Trying to divide solid " + solid->GetName()
523                  + " of type " + solid->GetEntityType() + " along axis ";
524   switch( axis )
525   {
526     case kXAxis:
527       error += "X.";
528       break;
529     case kYAxis:
530       error += "Y.";
531       break;
532     case kZAxis:
533       error += "Z.";
534       break;
535     case kRho:
536       error += "Rho.";
537       break;
538     case kRadial3D:
539       error += "Radial3D.";
540       break;
541     case kPhi:
542       error += "Phi.";
543       break;
544     default:
545       break;
546   }
547   G4Exception("G4PVDivision::ErrorInAxis()", "GeomDiv0002",
548               FatalException, error);
549 }
550 
551 // The next methods are for specialised repeated volumes (replicas,
552 // parameterised vol.) which are completely regular.
553 // Currently this is not applicable to divisions  ( J.A. Nov 2005 )
554 
555 // ----------------------------------------------------------------------
556 // IsRegularStructure()
557 //
558 G4bool G4PVDivision::IsRegularStructure() const
559 {
560   return false;
561 }           
562 
563 // ----------------------------------------------------------------------
564 // GetRegularStructureId()
565 //
566 G4int G4PVDivision::GetRegularStructureId() const
567 {
568   return 0;  
569 }           
570