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