ATLAS Offline Software
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 
5 #include "Geo2G4AssemblyVolume.h"
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 
15 std::atomic<unsigned int> Geo2G4AssemblyVolume::s_instanceCounter = 0;
16 
17 // Default constructor
18 //
20 : m_assemblyID( 0 )
21 {
24  SetImprintsCount( 0 );
25 }
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 //
72 void 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 //
90 void 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_"
239  << GetImprintsCount()
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 
289 void 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 
316 void 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 
332 {
334 }
335 
337 {
339 }
340 
342 {
344 }
Geo2G4AssemblyVolume::m_userComments
std::vector< G4String > m_userComments
Definition: Geo2G4AssemblyVolume.h:154
beamspotman.r
def r
Definition: beamspotman.py:676
Geo2G4AssemblyVolume.h
Geo2G4AssemblyVolume::GetAssemblyID
unsigned int GetAssemblyID() const
Definition: Geo2G4AssemblyVolume.h:210
Geo2G4AssemblyVolume::GetImprintsCount
unsigned int GetImprintsCount() const
Definition: Geo2G4AssemblyVolume.h:185
Geo2G4AssemblyVolume::Geo2G4AssemblyVolume
Geo2G4AssemblyVolume()
Definition: Geo2G4AssemblyVolume.cxx:19
Geo2G4AssemblyVolume::SetAssemblyID
void SetAssemblyID(unsigned int value)
Definition: Geo2G4AssemblyVolume.h:216
Geo2G4AssemblyVolume::MakeImprint
void MakeImprint(G4LogicalVolume *pMotherLV, G4ThreeVector &translationInMother, const G4RotationMatrix *pRotationInMother, G4int copyNumBase=0, G4bool ITkScheme=false, G4bool surfCheck=false)
Definition: Geo2G4AssemblyVolume.cxx:289
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
Geo2G4AssemblyVolume::m_copyNumbers
std::vector< int > m_copyNumbers
Definition: Geo2G4AssemblyVolume.h:153
Geo2G4AssemblyVolume::ImprintsCountPlus
void ImprintsCountPlus()
Definition: Geo2G4AssemblyVolume.h:198
Geo2G4AssemblyVolume::s_instanceCounter
static std::atomic< unsigned int > s_instanceCounter
Definition: Geo2G4AssemblyVolume.h:174
Geo2G4AssemblyVolume::AddPlacedVolume
void AddPlacedVolume(G4LogicalVolume *pPlacedVolume, G4ThreeVector &translation, G4RotationMatrix *rotation, int copyNo=0, const G4String &userComment="")
Definition: Geo2G4AssemblyVolume.cxx:72
lumiFormat.i
int i
Definition: lumiFormat.py:92
Geo2G4AssemblyVolume::~Geo2G4AssemblyVolume
~Geo2G4AssemblyVolume()
Definition: Geo2G4AssemblyVolume.cxx:29
xAOD::rotation
rotation
Definition: TrackSurface_v1.cxx:15
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
Geo2G4AssemblyVolume::InstanceCountPlus
void InstanceCountPlus()
Definition: Geo2G4AssemblyVolume.cxx:336
DeMoUpdate.toAdd
bool toAdd
Definition: DeMoUpdate.py:1304
Geo2G4AssemblyTriplet
Definition: Geo2G4AssemblyTriplet.h:15
Geo2G4AssemblyVolume
Definition: Geo2G4AssemblyVolume.h:16
Geo2G4AssemblyVolume::AddPlacedAssembly
void AddPlacedAssembly(Geo2G4AssemblyVolume *pAssembly, G4Transform3D &transformation)
Definition: Geo2G4AssemblyVolume.cxx:132
python.PyAthena.v
v
Definition: PyAthena.py:157
Geo2G4AssemblyVolume::SetImprintsCount
void SetImprintsCount(unsigned int value)
Definition: Geo2G4AssemblyVolume.h:191
Geo2G4AssemblyVolume::m_PVStore
std::vector< G4VPhysicalVolume * > m_PVStore
Definition: Geo2G4AssemblyVolume.h:159
Geo2G4AssemblyVolume::m_triplets
std::vector< Geo2G4AssemblyTriplet > m_triplets
Definition: Geo2G4AssemblyVolume.h:152
Geo2G4AssemblyVolume::InstanceCountMinus
void InstanceCountMinus()
Definition: Geo2G4AssemblyVolume.cxx:341
Geo2G4AssemblyVolume::GetInstanceCount
unsigned int GetInstanceCount() const
Definition: Geo2G4AssemblyVolume.cxx:331