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

Last change on this file since 1097 was 1058, checked in by garnier, 17 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.