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

Last change on this file since 1202 was 1058, checked in by garnier, 15 years ago

file release beta

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