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

Last change on this file since 1290 was 1228, checked in by garnier, 16 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.