source: trunk/source/geometry/divisions/src/G4PVDivision.cc @ 936

Last change on this file since 936 was 850, checked in by garnier, 16 years ago

geant4.8.2 beta

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