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

Last change on this file since 1337 was 1337, checked in by garnier, 14 years ago

tag geant4.9.4 beta 1 + modifs locales

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