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