source: trunk/source/geometry/volumes/src/G4AssemblyVolume.cc @ 1228

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

update geant4.9.3 tag

File size: 12.6 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: G4AssemblyVolume.cc,v 1.12 2009/09/22 13:58:48 gcosmo Exp $
28// GEANT4 tag $Name: geant4-09-03 $
29//
30//
31// Class G4AssemblyVolume - implementation
32//
33// ----------------------------------------------------------------------
34
35#include "G4AssemblyVolume.hh"
36#include "G4PVPlacement.hh"
37#include "G4RotationMatrix.hh"
38#include "G4AffineTransform.hh"
39#include "G4LogicalVolume.hh"
40#include "G4VPhysicalVolume.hh"
41#include "G4ReflectionFactory.hh"
42
43#include <sstream>
44
45unsigned int G4AssemblyVolume::fsInstanceCounter = 0;
46
47// Default constructor
48//
49G4AssemblyVolume::G4AssemblyVolume()
50  : fAssemblyID( 0 )
51{
52  InstanceCountPlus();
53  SetAssemblyID( GetInstanceCount() );
54  SetImprintsCount( 0 );
55}
56
57// Composing constructor
58//
59G4AssemblyVolume::G4AssemblyVolume( G4LogicalVolume* volume,
60                                    G4ThreeVector& translation,
61                                    G4RotationMatrix* rotation )
62  : fAssemblyID( 0 )
63{
64  InstanceCountPlus();
65  SetAssemblyID( GetInstanceCount() );
66  SetImprintsCount( 0 );
67  AddPlacedVolume(volume, translation, rotation);
68}
69
70// Destructor
71//
72G4AssemblyVolume::~G4AssemblyVolume()
73{
74  unsigned int howmany = fTriplets.size();
75  if( howmany != 0 )
76  {
77    for( unsigned int i = 0; i < howmany; i++ )
78    {
79      G4RotationMatrix* pRotToClean = fTriplets[i].GetRotation();
80      if( pRotToClean != 0 )
81      {
82        delete pRotToClean;
83      }
84    }
85  }
86  fTriplets.clear();
87 
88  howmany = fPVStore.size();
89  if( howmany != 0 )
90  {
91    for( unsigned int j = 0; j < howmany; j++ )
92    {
93      delete fPVStore[j];
94    }
95  }
96  fPVStore.clear();
97  InstanceCountMinus();
98}
99
100// Add and place the given volume according to the specified
101// translation and rotation.
102//
103// The rotation matrix passed in can be 0 = identity or an address even of an
104// object on the upper stack frame. During assembly imprint, it creates anyway
105// a new matrix and keeps track of it so it can delete it later at destruction
106// time.
107// This policy has been adopted since user has no control on the way the
108// rotations are combined.
109//
110void G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume*  pVolume,
111                                        G4ThreeVector&    translation,
112                                        G4RotationMatrix* pRotation )
113{
114  G4RotationMatrix*  toStore  = new G4RotationMatrix;
115 
116  if( pRotation != 0 )  { *toStore = *pRotation; }
117 
118  G4AssemblyTriplet toAdd( pVolume, translation, toStore );
119  fTriplets.push_back( toAdd );
120}
121
122// Add and place the given volume according to the specified transformation
123//
124void G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume*  pVolume,
125                                        G4Transform3D&    transformation )
126{
127  // Decompose transformation
128  G4Scale3D     scale;
129  G4Rotate3D    rotation;
130  G4Translate3D translation;
131  transformation.getDecomposition(scale, rotation, translation);
132
133  G4ThreeVector      v = translation.getTranslation();
134  G4RotationMatrix*  r = new G4RotationMatrix;
135                    *r = rotation.getRotation();
136 
137  G4bool isReflection = false;
138  if (scale(0,0)*scale(1,1)*scale(2,2) < 0.)  { isReflection = true; }
139
140  G4AssemblyTriplet toAdd( pVolume, v, r, isReflection );
141  fTriplets.push_back( toAdd );
142}
143
144// Add and place the given assembly volume according to the specified
145// translation and rotation.
146//
147void G4AssemblyVolume::AddPlacedAssembly( G4AssemblyVolume* pAssembly,
148                                          G4ThreeVector&    translation,
149                                          G4RotationMatrix* pRotation )
150{
151  G4RotationMatrix*  toStore  = new G4RotationMatrix;
152 
153  if( pRotation != 0 )  { *toStore = *pRotation; }
154 
155  G4AssemblyTriplet toAdd( pAssembly, translation, toStore );
156  fTriplets.push_back( toAdd );
157}
158
159// Add and place the given assembly volume according to the specified
160// transformation
161//
162void G4AssemblyVolume::AddPlacedAssembly( G4AssemblyVolume* pAssembly,
163                                          G4Transform3D&    transformation )
164{
165  // Decompose transformation
166  //
167  G4Scale3D     scale;
168  G4Rotate3D    rotation;
169  G4Translate3D translation;
170  transformation.getDecomposition(scale, rotation, translation);
171
172  G4ThreeVector      v = translation.getTranslation();
173  G4RotationMatrix*  r = new G4RotationMatrix;
174                    *r = rotation.getRotation();
175 
176  G4bool isReflection = false;
177  if (scale(0,0)*scale(1,1)*scale(2,2) < 0.)  { isReflection = true; }
178 
179  G4AssemblyTriplet toAdd( pAssembly, v, r, isReflection );
180  fTriplets.push_back( toAdd );
181}
182
183// Create an instance of an assembly volume inside of the specified
184// mother volume. This works analogically to making stamp imprints.
185// This method makes use of the Geant4 affine transformation class.
186// The algorithm is defined as follows:
187// 
188// Having rotation matrix Rm and translation vector Tm to be applied
189// inside the mother and rotation matrix Ra and translation vector Ta
190// to be applied inside the assembly itself for each of the participating
191// volumes the resulting transformation is
192// 
193// Tfinal = Ta * Tm
194// 
195// where Ta and Tm are constructed as
196// 
197//        -1                                     -1
198// Ta = Ra  * Ta           and            Tm = Rm  * Tm
199// 
200// which in words means that we create first the affine transformations
201// by inverse rotation matrices and translations for mother and assembly.
202// The resulting final transformation to be applied to each of the
203// participating volumes is their product.
204//
205// IMPORTANT NOTE!
206// The order of multiplication is reversed when comparing to CLHEP 3D
207// transformation matrix(G4Transform3D class).
208// 
209// The rotation matrix passed in can be 0 = identity or an address even of an
210// object on the upper stack frame. During assembly imprint, it creates anyway
211// a new matrix and keeps track of it so it can delete it later at destruction
212// time.
213// This policy has been adopted since user has no control on the way the
214// rotations are combined.
215//
216// If the assembly volume contains assembly (a'), the function is called
217// recursively with composed transformation:
218//
219// Tanew =  Ta * Ta'
220//
221void G4AssemblyVolume::MakeImprint( G4AssemblyVolume* pAssembly,
222                                    G4LogicalVolume*  pMotherLV,
223                                    G4Transform3D&    transformation,
224                                    G4int copyNumBase,
225                                    G4bool surfCheck )
226{
227  unsigned int  numberOfDaughters;
228 
229  if( copyNumBase == 0 )
230  {
231    numberOfDaughters = pMotherLV->GetNoDaughters();
232  }
233  else
234  {
235    numberOfDaughters = copyNumBase;
236  }
237
238  // We start from the first available index
239  //
240  numberOfDaughters++;
241
242  ImprintsCountPlus();
243 
244  std::vector<G4AssemblyTriplet> triplets = pAssembly->fTriplets;
245
246  for( unsigned int   i = 0; i < triplets.size(); i++ )
247  {
248    G4Transform3D Ta( *(triplets[i].GetRotation()),
249                      triplets[i].GetTranslation() );
250    if ( triplets[i].IsReflection() )  { Ta = Ta * G4ReflectZ3D(); }
251
252    G4Transform3D Tfinal = transformation * Ta;
253   
254    if ( triplets[i].GetVolume() )
255    {
256      // Generate the unique name for the next PV instance
257      // The name has format:
258      //
259      // av_WWW_impr_XXX_YYY_ZZZ
260      // where the fields mean:
261      // WWW - assembly volume instance number
262      // XXX - assembly volume imprint number
263      // YYY - the name of a log. volume we want to make a placement of
264      // ZZZ - the log. volume index inside the assembly volume
265      //
266      std::stringstream pvName;
267      pvName << "av_"
268             << GetAssemblyID()
269             << "_impr_"
270             << GetImprintsCount()
271             << "_"
272             << triplets[i].GetVolume()->GetName().c_str()
273             << "_pv_"
274             << i
275             << std::ends;
276
277      // Generate a new physical volume instance inside a mother
278      // (as we allow 3D transformation use G4ReflectionFactory to
279      //  take into account eventual reflection)
280      //
281      G4PhysicalVolumesPair pvPlaced
282        = G4ReflectionFactory::Instance()->Place( Tfinal,
283                                                  pvName.str().c_str(),
284                                                  triplets[i].GetVolume(),
285                                                  pMotherLV,
286                                                  false,
287                                                  numberOfDaughters + i,
288                                                  surfCheck );
289
290      // Register the physical volume created by us so we can delete it later
291      //
292      fPVStore.push_back( pvPlaced.first );
293      if ( pvPlaced.second )  { fPVStore.push_back( pvPlaced.second ); }
294    }
295    else if ( triplets[i].GetAssembly() )
296    {
297      // Place volumes in this assembly with composed transformation
298      //
299      MakeImprint( triplets[i].GetAssembly(), pMotherLV,
300                   Tfinal, i*100+copyNumBase, surfCheck ); 
301    }
302    else
303    {
304      G4Exception("G4AssemblyVolume::MakeImprint(..)",
305                  "NotApplicable", FatalException,
306                  "Triplet has no volume and no assembly");
307    } 
308  } 
309}   
310
311void G4AssemblyVolume::MakeImprint( G4LogicalVolume*  pMotherLV,
312                                    G4ThreeVector&    translationInMother,
313                                    G4RotationMatrix* pRotationInMother,
314                                    G4int copyNumBase,
315                                    G4bool surfCheck )
316{
317  // If needed user can specify explicitely the base count from which to start
318  // off for the generation of phys. vol. copy numbers.
319  // The old behaviour is preserved when copyNumBase == 0, e.g. the generated
320  // copy numbers start from the count equal to current number of daughter
321  // volumes before an imprint is made
322
323  // Compose transformation
324  //
325  if( pRotationInMother == 0 )
326  {
327    // Make it by default an indentity matrix
328    //
329    pRotationInMother =
330      const_cast<G4RotationMatrix*>( &G4RotationMatrix::IDENTITY );
331  }
332
333  G4Transform3D transform( *pRotationInMother,
334                            translationInMother );
335  MakeImprint(this, pMotherLV, transform, copyNumBase, surfCheck);
336}
337
338void G4AssemblyVolume::MakeImprint( G4LogicalVolume*  pMotherLV,
339                                    G4Transform3D&    transformation,
340                                    G4int copyNumBase,
341                                    G4bool surfCheck )
342{
343  // If needed user can specify explicitely the base count from which to start
344  // off for the generation of phys. vol. copy numbers.
345  // The old behaviour is preserved when copyNumBase == 0, e.g. the generated
346  // copy numbers start from the count equal to current number of daughter
347  // volumes before a imprint is made
348
349  MakeImprint(this, pMotherLV, transformation, copyNumBase, surfCheck);
350}
351
352unsigned int G4AssemblyVolume::GetInstanceCount() const
353{
354  return G4AssemblyVolume::fsInstanceCounter;
355}
356
357void         G4AssemblyVolume::SetInstanceCount( unsigned int value )
358{
359  G4AssemblyVolume::fsInstanceCounter = value;
360}
361
362void         G4AssemblyVolume::InstanceCountPlus()
363{
364  G4AssemblyVolume::fsInstanceCounter++;
365}
366
367void         G4AssemblyVolume::InstanceCountMinus()
368{
369  G4AssemblyVolume::fsInstanceCounter--;
370}
Note: See TracBrowser for help on using the repository browser.