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