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

Last change on this file since 1347 was 1347, checked in by garnier, 13 years ago

geant4 tag 9.4

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