Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4AssemblyVolume.cc
Go to the documentation of this file.
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"
38
39#include <sstream>
40
41G4ThreadLocal unsigned int G4AssemblyVolume::fsInstanceCounter = 0;
42
43// Default constructor
44//
46{
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{
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 std::size_t howmany = fTriplets.size();
97 if( howmany != 0 )
98 {
99 for( std::size_t 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
146 G4Scale3D scale;
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 //
185 G4Scale3D scale;
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 std::size_t 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( std::size_t 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_"
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 G4int(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, (G4int)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{
379 return G4AssemblyVolume::fsInstanceCounter;
380}
381
382void G4AssemblyVolume::SetInstanceCount( unsigned int value )
383{
384 G4AssemblyVolume::fsInstanceCounter = value;
385}
386
388{
389 G4AssemblyVolume::fsInstanceCounter++;
390}
391
393{
394 G4AssemblyVolume::fsInstanceCounter--;
395}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::pair< G4VPhysicalVolume *, G4VPhysicalVolume * > G4PhysicalVolumesPair
CLHEP::HepRotation G4RotationMatrix
HepGeom::ReflectZ3D G4ReflectZ3D
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
static DLL_API const HepRotation IDENTITY
Definition: Rotation.h:366
static G4AssemblyStore * GetInstance()
static void DeRegister(G4AssemblyVolume *pAssembly)
G4AssemblyVolume * GetAssembly(unsigned int id, G4bool verbose=true) const
static void Register(G4AssemblyVolume *pAssembly)
unsigned int GetImprintsCount() const
void MakeImprint(G4LogicalVolume *pMotherLV, G4ThreeVector &translationInMother, G4RotationMatrix *pRotationInMother, G4int copyNumBase=0, G4bool surfCheck=false)
void SetAssemblyID(unsigned int value)
void AddPlacedAssembly(G4AssemblyVolume *pAssembly, G4Transform3D &transformation)
unsigned int GetAssemblyID() const
void SetInstanceCount(unsigned int value)
void AddPlacedVolume(G4LogicalVolume *pPlacedVolume, G4ThreeVector &translation, G4RotationMatrix *rotation)
void ImprintsCountPlus()
void SetImprintsCount(unsigned int value)
unsigned int GetInstanceCount() const
std::size_t GetNoDaughters() const
static G4ReflectionFactory * Instance()
G4PhysicalVolumesPair Place(const G4Transform3D &transform3D, const G4String &name, G4LogicalVolume *LV, G4LogicalVolume *motherLV, G4bool isMany, G4int copyNo, G4bool surfCheck=false)
CLHEP::HepRotation getRotation() const
void getDecomposition(Scale3D &scale, Rotate3D &rotation, Translate3D &translation) const
Definition: Transform3D.cc:173
CLHEP::Hep3Vector getTranslation() const
#define G4ThreadLocal
Definition: tls.hh:77