ATLAS Offline Software
Loading...
Searching...
No Matches
Geo2G4AssemblyVolume.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "G4PVPlacement.hh"
7#include "G4RotationMatrix.hh"
8#include "G4AffineTransform.hh"
9#include "G4LogicalVolume.hh"
10#include "G4VPhysicalVolume.hh"
11#include "G4ReflectionFactory.hh"
12
13#include <sstream>
14
15std::atomic<unsigned int> Geo2G4AssemblyVolume::s_instanceCounter = 0;
16
17// Default constructor
18//
26
27// Destructor
28//
30{
31 unsigned int howmany = m_triplets.size();
32 if( howmany != 0 )
33 {
34 for( unsigned int i = 0; i < howmany; i++ )
35 {
36 G4RotationMatrix* pRotToClean = m_triplets[i].GetRotation();
37 if( pRotToClean != 0 )
38 {
39 delete pRotToClean;
40 }
41 }
42 }
43 m_triplets.clear();
44
45 howmany = m_PVStore.size();
46 if( howmany != 0 )
47 {
48 for( unsigned int j = 0; j < howmany; j++ )
49 {
50 G4RotationMatrix* pRotToClean = m_PVStore[j]->GetRotation();
51 if( pRotToClean != 0 )
52 {
53 delete pRotToClean;
54 }
55 delete m_PVStore[j];
56 }
57 }
58 m_PVStore.clear();
60}
61
62// Add and place the given volume according to the specified
63// translation and rotation.
64//
65// The rotation matrix passed in can be 0 = identity or an address even of an
66// object on the upper stack frame. During assembly imprint, it creates anyway
67// a new matrix and keeps track of it so it can delete it later at destruction
68// time.
69// This policy has been adopted since user has no control on the way the
70// rotations are combined.
71//
72void Geo2G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume* pVolume,
73 G4ThreeVector& translation,
74 G4RotationMatrix* pRotation,
75 int copyNo, const G4String& userC)
76{
77 G4RotationMatrix* toStore = new G4RotationMatrix;
78
79 if( pRotation != 0 ) { *toStore = *pRotation; }
80
81 Geo2G4AssemblyTriplet toAdd( pVolume, translation, toStore );
82 m_triplets.push_back( toAdd );
83
84 m_copyNumbers.push_back( copyNo );
85 m_userComments.push_back( userC );
86}
87
88// Add and place the given volume according to the specified transformation
89//
90void Geo2G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume* pVolume,
91 G4Transform3D& transformation,
92 int copyNo, const G4String& userC)
93{
94 // Decompose transformation
95 G4Scale3D scale;
96 G4Rotate3D rotation;
97 G4Translate3D translation;
98 transformation.getDecomposition(scale, rotation, translation);
99
100 G4ThreeVector v = translation.getTranslation();
101 G4RotationMatrix* r = new G4RotationMatrix;
102 *r = rotation.getRotation();
103
104 G4bool isReflection = false;
105 if (scale(0,0)*scale(1,1)*scale(2,2) < 0.) { isReflection = true; }
106
107 Geo2G4AssemblyTriplet toAdd( pVolume, v, r, isReflection );
108 m_triplets.push_back( toAdd );
109
110 m_copyNumbers.push_back( copyNo );
111 m_userComments.push_back( userC );
112}
113
114// Add and place the given assembly volume according to the specified
115// translation and rotation.
116//
118 G4ThreeVector& translation,
119 G4RotationMatrix* pRotation )
120{
121 G4RotationMatrix* toStore = new G4RotationMatrix;
122
123 if( pRotation != 0 ) { *toStore = *pRotation; }
124
125 Geo2G4AssemblyTriplet toAdd( pAssembly, translation, toStore );
126 m_triplets.push_back( toAdd );
127}
128
129// Add and place the given assembly volume according to the specified
130// transformation
131//
133 G4Transform3D& transformation )
134{
135 // Decompose transformation
136 //
137 G4Scale3D scale;
138 G4Rotate3D rotation;
139 G4Translate3D translation;
140 transformation.getDecomposition(scale, rotation, translation);
141
142 G4ThreeVector v = translation.getTranslation();
143 G4RotationMatrix* r = new G4RotationMatrix;
144 *r = rotation.getRotation();
145
146 G4bool isReflection = false;
147 if (scale(0,0)*scale(1,1)*scale(2,2) < 0.) { isReflection = true; }
148
149 Geo2G4AssemblyTriplet toAdd( pAssembly, v, r, isReflection );
150 m_triplets.push_back( toAdd );
151}
152
153// Create an instance of an assembly volume inside of the specified
154// mother volume. This works analogically to making stamp imprints.
155// This method makes use of the Geant4 affine transformation class.
156// The algorithm is defined as follows:
157//
158// Having rotation matrix Rm and translation vector Tm to be applied
159// inside the mother and rotation matrix Ra and translation vector Ta
160// to be applied inside the assembly itself for each of the participating
161// volumes the resulting transformation is
162//
163// Tfinal = Ta * Tm
164//
165// where Ta and Tm are constructed as
166//
167// -1 -1
168// Ta = Ra * Ta and Tm = Rm * Tm
169//
170// which in words means that we create first the affine transformations
171// by inverse rotation matrices and translations for mother and assembly.
172// The resulting final transformation to be applied to each of the
173// participating volumes is their product.
174//
175// IMPORTANT NOTE!
176// The order of multiplication is reversed when comparing to CLHEP 3D
177// transformation matrix(G4Transform3D class).
178//
179// The rotation matrix passed in can be 0 = identity or an address even of an
180// object on the upper stack frame. During assembly imprint, it creates anyway
181// a new matrix and keeps track of it so it can delete it later at destruction
182// time.
183// This policy has been adopted since user has no control on the way the
184// rotations are combined.
185//
186// If the assembly volume contains assembly (a'), the function is called
187// recursively with composed transformation:
188//
189// Tanew = Ta * Ta'
190//
192 G4LogicalVolume* pMotherLV,
193 G4Transform3D& transformation,
194 G4int copyNumBase,
195 G4bool ITkScheme,
196 G4bool surfCheck )
197{
198 unsigned int numberOfDaughters;
199
200 if( copyNumBase == 0 )
201 {
202 numberOfDaughters = pMotherLV->GetNoDaughters();
203 }
204 else
205 {
206 numberOfDaughters = copyNumBase;
207 }
208 // We start from the first available index
209 //
210 numberOfDaughters++;
211
213 std::vector<Geo2G4AssemblyTriplet> triplets = pAssembly->m_triplets;
214 for( unsigned int i = 0; i < triplets.size(); i++ )
215 {
216 G4Transform3D Ta( *(triplets[i].GetRotation()),
217 triplets[i].GetTranslation() );
218 if ( triplets[i].IsReflection() ) { Ta = Ta * G4ReflectZ3D(); }
219
220 G4Transform3D Tfinal = transformation * Ta;
221 if ( triplets[i].GetVolume() )
222 {
223 // Generate the unique name for the next PV instance
224 // The name has format:
225 //
226 // av_WWW_impr_XXX_YYY_ZZZ
227 // where the fields mean:
228 // WWW - assembly volume instance number
229 // XXX - assembly volume imprint number
230 // YYY - the name of a log. volume we want to make a placement of
231 // ZZZ - the log. volume index inside the assembly volume
232 //
233
234
235 std::stringstream pvName;
236 pvName << "av_"
237 << GetAssemblyID()
238 << "_impr_"
240 << "_"
241 << triplets[i].GetVolume()->GetName().c_str()
242 << "_pv_"
243 << i;
244 if (i<m_userComments.size() && !(m_userComments[i].empty())) pvName<<"_"<<m_userComments[i];
245 pvName<<std::ends;
246 // Generate a new physical volume instance inside a mother
247 // (as we allow 3D transformation use G4ReflectionFactory to
248 // take into account eventual reflection)
249 //
250 int ccn=numberOfDaughters + i;
251 if (i<m_copyNumbers.size() && m_copyNumbers[i]) {
252 if(ITkScheme) ccn=m_copyNumbers[i];
253 else ccn=m_copyNumbers[i]+copyNumBase;
254 }
255
256 G4PhysicalVolumesPair pvPlaced
257 = G4ReflectionFactory::Instance()->Place( Tfinal,
258 pvName.str().c_str(),
259 triplets[i].GetVolume(),
260 pMotherLV,
261 false,
262 ccn,
263 surfCheck );
264
265
266 // Register the physical volume created by us so we can delete it later
267 //
268 m_PVStore.push_back( pvPlaced.first );
269 if ( pvPlaced.second ) { m_PVStore.push_back( pvPlaced.second ); }
270 }
271 else if ( triplets[i].GetAssembly() )
272 {
273 // Place volumes in this assembly with composed transformation
274 //
275 if(ITkScheme) triplets[i].GetAssembly()->MakeImprint( triplets[i].GetAssembly(), pMotherLV,
276 Tfinal, i*100+copyNumBase, ITkScheme, surfCheck );
277 else MakeImprint( triplets[i].GetAssembly(), pMotherLV,
278 Tfinal, i*100+copyNumBase, ITkScheme, surfCheck );
279 }
280 else
281 {
282 G4Exception("Geo2G4AssemblyVolume::MakeImprint(..)",
283 "NotApplicable", FatalException,
284 "Triplet has no volume and no assembly");
285 }
286 }
287}
288
289void Geo2G4AssemblyVolume::MakeImprint( G4LogicalVolume* pMotherLV,
290 G4ThreeVector& translationInMother,
291 const G4RotationMatrix* pRotationInMother,
292 G4int copyNumBase,
293 G4bool ITkScheme,
294 G4bool surfCheck )
295{
296 // If needed user can specify explicitely the base count from which to start
297 // off for the generation of phys. vol. copy numbers.
298 // The old behaviour is preserved when copyNumBase == 0, e.g. the generated
299 // copy numbers start from the count equal to current number of daughter
300 // volumes before an imprint is made
301
302 // Compose transformation
303 //
304 if( pRotationInMother == 0 )
305 {
306 // Make it by default an indentity matrix
307 //
308 pRotationInMother = &G4RotationMatrix::IDENTITY;
309 }
310
311 G4Transform3D transform( *pRotationInMother,
312 translationInMother );
313 MakeImprint(this, pMotherLV, transform, copyNumBase, ITkScheme, surfCheck);
314}
315
316void Geo2G4AssemblyVolume::MakeImprint( G4LogicalVolume* pMotherLV,
317 G4Transform3D& transformation,
318 G4int copyNumBase,
319 G4bool ITkScheme,
320 G4bool surfCheck )
321{
322 // If needed user can specify explicitely the base count from which to start
323 // off for the generation of phys. vol. copy numbers.
324 // The old behaviour is preserved when copyNumBase == 0, e.g. the generated
325 // copy numbers start from the count equal to current number of daughter
326 // volumes before a imprint is made
327
328 MakeImprint(this, pMotherLV, transformation, copyNumBase, ITkScheme, surfCheck);
329}
330
335
340
unsigned int GetInstanceCount() const
std::vector< int > m_copyNumbers
std::vector< G4String > m_userComments
unsigned int GetAssemblyID() const
void MakeImprint(G4LogicalVolume *pMotherLV, G4ThreeVector &translationInMother, const G4RotationMatrix *pRotationInMother, G4int copyNumBase=0, G4bool ITkScheme=false, G4bool surfCheck=false)
void SetAssemblyID(unsigned int value)
std::vector< G4VPhysicalVolume * > m_PVStore
void AddPlacedAssembly(Geo2G4AssemblyVolume *pAssembly, G4Transform3D &transformation)
void AddPlacedVolume(G4LogicalVolume *pPlacedVolume, G4ThreeVector &translation, G4RotationMatrix *rotation, int copyNo=0, const G4String &userComment="")
static std::atomic< unsigned int > s_instanceCounter
unsigned int GetImprintsCount() const
std::vector< Geo2G4AssemblyTriplet > m_triplets
void SetImprintsCount(unsigned int value)
int r
Definition globals.cxx:22