Geant4  10.01.p03
G4LogicalVolume.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 //
27 // $Id: G4LogicalVolume.cc 90701 2015-06-08 09:43:16Z gcosmo $
28 //
29 //
30 // class G4LogicalVolume Implementation
31 //
32 // History:
33 // 15.01.13 G.Cosmo, A.Dotti: Modified for thread-safety for MT
34 // 01.03.05 G.Santin: Added flag for optional propagation of GetMass()
35 // 17.05.02 G.Cosmo: Added flag for optional optimisation
36 // 12.02.99 S.Giani: Default initialization of voxelization quality
37 // 04.08.97 P.M.DeFreitas: Added methods for parameterised simulation
38 // 19.08.96 P.Kent: Modified for G4VSensitive Detector
39 // 11.07.95 P.Kent: Initial version
40 // --------------------------------------------------------------------
41 
42 #include "G4LogicalVolume.hh"
43 #ifdef NO_INLINE
44 #define inline
45 #include "G4LogicalVolume.icc"
46 #undef inline
47 #endif
48 
49 #include "G4LogicalVolumeStore.hh"
50 #include "G4VSolid.hh"
51 #include "G4Material.hh"
52 #include "G4VPVParameterisation.hh"
53 #include "G4VisAttributes.hh"
54 
55 #include "G4UnitsTable.hh"
56 
57 // This static member is thread local. For each thread, it points to the
58 // array of G4LVData instances.
59 //
60 template <class G4LVData> G4ThreadLocal
62 
64 : fSolid(0),fSensitiveDetector(0),fFieldManager(0),
65  fMaterial(0),fMass(0.),fCutsCouple(0)
66 {;}
67 
68 // This new field helps to use the class G4LVManager
69 //
71 
72 // ********************************************************************
73 // InitialiseWorker
74 //
75 // This method is similar to the constructor. It is used by each worker
76 // thread to achieve the same effect as that of the master thread exept
77 // to register the new created instance. This method is invoked explicitly.
78 // It does not create a new G4LogicalVolume instance. It only assign the value
79 // for the fields encapsulated by the class G4LVData.
80 // ********************************************************************
81 //
83 InitialiseWorker( G4LogicalVolume* /*pMasterObject*/,
84  G4VSolid* pSolid,
85  G4VSensitiveDetector* pSDetector)
86 {
88 
89  SetSolid(pSolid);
90  SetSensitiveDetector(pSDetector); // How this object is available now ?
91  AssignFieldManager(fFieldManager); // Should be set - but a per-thread copy is not available yet
92  // G4MT_fmanager= fFieldManager;
93  // Must not call SetFieldManager(fFieldManager, false); which propagates FieldMgr
94 
95 #ifdef CLONE_FIELD_MGR
96  // Create a field FieldManager by cloning
97  G4FieldManager workerFldMgr= fFieldManager->GetWorkerClone(G4bool* created);
98  if( created || (GetFieldManager()!=workerFldMgr) )
99  {
100  SetFieldManager(fFieldManager, false); // which propagates FieldMgr
101  }else{
102  // Field manager existed and is equal to current one
103  AssignFieldManager(workerFldMgr);
104  }
105 #endif
106 }
107 
108 // ********************************************************************
109 // TerminateWorker
110 //
111 // This method is similar to the destructor. It is used by each worker
112 // thread to achieve the partial effect as that of the master thread.
113 // For G4LogicalVolume instances, nothing more to do here.
114 // ********************************************************************
115 //
117 TerminateWorker( G4LogicalVolume* /*pMasterObject*/)
118 {
119 }
120 
121 // ********************************************************************
122 // GetSubInstanceManager
123 //
124 // Returns the private data instance manager.
125 // ********************************************************************
126 //
128 {
129  return subInstanceManager;
130 }
131 
132 // ********************************************************************
133 // Constructor - sets member data and adds to logical Store,
134 // voxel pointer for optimisation set to 0 by default.
135 // Initialises daughter vector to 0 length.
136 // ********************************************************************
137 //
139  G4Material* pMaterial,
140  const G4String& name,
141  G4FieldManager* pFieldMgr,
142  G4VSensitiveDetector* pSDetector,
143  G4UserLimits* pULimits,
144  G4bool optimise )
145  : fDaughters(0,(G4VPhysicalVolume*)0),
146  fVoxel(0), fOptimise(optimise), fRootRegion(false), fLock(false),
147  fSmartless(2.), fVisAttributes(0), fRegion(0), fBiasWeight(1.)
148 {
149  // Initialize 'Shadow'/master pointers - for use in copying to workers
150  fSolid = pSolid;
151  fSensitiveDetector = pSDetector;
152  fFieldManager = pFieldMgr;
153 
155  AssignFieldManager(pFieldMgr); // G4MT_fmanager = pFieldMgr;
156 
157  // fMasterFieldMgr= pFieldMgr;
158  G4MT_mass = 0.;
159  G4MT_ccouple = 0;
160 
161  SetSolid(pSolid);
162  SetMaterial(pMaterial);
163  SetName(name);
164  SetSensitiveDetector(pSDetector);
165  SetUserLimits(pULimits);
166  //
167  // Add to store
168  //
170 }
171 
172 // ********************************************************************
173 // Fake default constructor - sets only member data and allocates memory
174 // for usage restricted to object persistency.
175 // ********************************************************************
176 //
178  : fDaughters(0,(G4VPhysicalVolume*)0),
179  fName(""), fUserLimits(0),
180  fVoxel(0), fOptimise(true), fRootRegion(false), fLock(false),
181  fSmartless(2.), fVisAttributes(0), fRegion(0), fBiasWeight(1.),
182  fSolid(0), fSensitiveDetector(0), fFieldManager(0)
183 {
185 
186  SetSensitiveDetector(0); // G4MT_sdetector = 0;
187  SetFieldManager(0, false); // G4MT_fmanager = 0;
188 
189  G4MT_mass = 0.;
190  G4MT_ccouple = 0;
191 
192  // Add to store
193  //
195 }
196 
197 // ********************************************************************
198 // Destructor - Removes itself from solid Store
199 // NOTE: Not virtual
200 // ********************************************************************
201 //
203 {
204  if (!fLock && fRootRegion) // De-register root region first if not locked
205  { // and flagged as root logical-volume
206  fRegion->RemoveRootLogicalVolume(this, true);
207  }
209 }
210 
211 // ********************************************************************
212 // SetFieldManager
213 // ********************************************************************
214 //
215 void
217  G4bool forceAllDaughters)
218 {
219  // G4MT_fmanager = pNewFieldMgr;
220  AssignFieldManager(pNewFieldMgr);
221 
222  G4int NoDaughters = GetNoDaughters();
223  while ( (NoDaughters--)>0 )
224  {
225  G4LogicalVolume* DaughterLogVol;
226  DaughterLogVol = GetDaughter(NoDaughters)->GetLogicalVolume();
227  if ( forceAllDaughters || (DaughterLogVol->GetFieldManager() == 0) )
228  {
229  DaughterLogVol->SetFieldManager(pNewFieldMgr, forceAllDaughters);
230  }
231  }
232 }
233 
234 
235 // ********************************************************************
236 // IsAncestor
237 //
238 // Finds out if the current logical volume is an ancestor of a given
239 // physical volume
240 // ********************************************************************
241 //
242 G4bool
244 {
245  G4bool isDaughter = IsDaughter(aVolume);
246  if (!isDaughter)
247  {
248  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
249  itDau != fDaughters.end(); itDau++)
250  {
251  isDaughter = (*itDau)->GetLogicalVolume()->IsAncestor(aVolume);
252  if (isDaughter) break;
253  }
254  }
255  return isDaughter;
256 }
257 
258 // ********************************************************************
259 // TotalVolumeEntities
260 //
261 // Returns the total number of physical volumes (replicated or placed)
262 // in the tree represented by the current logical volume.
263 // ********************************************************************
264 //
266 {
267  G4int vols = 1;
268  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
269  itDau != fDaughters.end(); itDau++)
270  {
271  G4VPhysicalVolume* physDaughter = (*itDau);
272  vols += physDaughter->GetMultiplicity()
273  *physDaughter->GetLogicalVolume()->TotalVolumeEntities();
274  }
275  return vols;
276 }
277 
278 // ********************************************************************
279 // GetMass
280 //
281 // Returns the mass of the logical volume tree computed from the
282 // estimated geometrical volume of each solid and material associated
283 // to the logical volume and its daughters.
284 // NOTE: the computation may require considerable amount of time,
285 // depending from the complexity of the geometry tree.
286 // The returned value is cached and can be used for successive
287 // calls (default), unless recomputation is forced by providing
288 // 'true' for the boolean argument in input. Computation should
289 // be forced if the geometry setup has changed after the previous
290 // call. By setting the 'propagate' boolean flag to 'false' the
291 // method returns the mass of the present logical volume only
292 // (subtracted for the volume occupied by the daughter volumes).
293 // The extra argument 'parMaterial' is internally used to
294 // consider cases of geometrical parameterisations by material.
295 // ********************************************************************
296 //
298  G4bool propagate,
299  G4Material* parMaterial)
300 {
301  // Return the cached non-zero value, if not forced
302  //
303  if ( (G4MT_mass) && (!forced) ) return G4MT_mass;
304 
305  // Global density and computed mass associated to the logical
306  // volume without considering its daughters
307  //
308  G4Material* logMaterial = parMaterial ? parMaterial : GetMaterial(); // G4MT_material;
309  if (!logMaterial)
310  {
311  std::ostringstream message;
312  message << "No material associated to the logical volume: " << fName << " !"
313  << G4endl
314  << "Sorry, cannot compute the mass ...";
315  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
316  FatalException, message);
317  return 0;
318  }
319  if (! GetSolid() ) // !G4MT_solid)
320  {
321  std::ostringstream message;
322  message << "No solid is associated to the logical volume: " << fName << " !"
323  << G4endl
324  << "Sorry, cannot compute the mass ...";
325  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
326  FatalException, message);
327  return 0;
328  }
329  G4double globalDensity = logMaterial->GetDensity();
330  G4double motherMass= GetSolid()->GetCubicVolume() * globalDensity;
331 
332  // G4MT_mass =
333  // SetMass( motherMmass );
334  G4double massSum= motherMass;
335 
336  // For each daughter in the tree, subtract the mass occupied
337  // and if required by the propagate flag, add the real daughter's
338  // one computed recursively
339 
340  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
341  itDau != fDaughters.end(); itDau++)
342  {
343  G4VPhysicalVolume* physDaughter = (*itDau);
344  G4LogicalVolume* logDaughter = physDaughter->GetLogicalVolume();
345  G4double subMass=0.;
346  G4VSolid* daughterSolid = 0;
347  G4Material* daughterMaterial = 0;
348 
349  // Compute the mass to subtract and to add for each daughter
350  // considering its multiplicity (i.e. replicated or not) and
351  // eventually its parameterisation (by solid and/or by material)
352  //
353  for (G4int i=0; i<physDaughter->GetMultiplicity(); i++)
354  {
356  physParam = physDaughter->GetParameterisation();
357  if (physParam)
358  {
359  daughterSolid = physParam->ComputeSolid(i, physDaughter);
360  daughterSolid->ComputeDimensions(physParam, i, physDaughter);
361  daughterMaterial = physParam->ComputeMaterial(i, physDaughter);
362  }
363  else
364  {
365  daughterSolid = logDaughter->GetSolid();
366  daughterMaterial = logDaughter->GetMaterial();
367  }
368  subMass = daughterSolid->GetCubicVolume() * globalDensity;
369 
370  // Subtract the daughter's portion for the mass and, if required,
371  // add the real daughter's mass computed recursively
372  //
373  massSum -= subMass;
374  if (propagate)
375  {
376  massSum += logDaughter->GetMass(true, true, daughterMaterial);
377  }
378  }
379  }
380  G4MT_mass= massSum;
381  return massSum;
382 }
383 
385 {
387 }
virtual G4Material * ComputeMaterial(const G4int repNo, G4VPhysicalVolume *currentVol, const G4VTouchable *parentTouch=0)
G4String fName
Definition: G4AttUtils.hh:55
G4FieldManager * fFieldManager
static G4GEOM_DLL G4LVManager subInstanceManager
virtual void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4VSolid.cc:137
static void DeRegister(G4LogicalVolume *pVolume)
G4bool IsAncestor(const G4VPhysicalVolume *p) const
G4Material * GetMaterial() const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
G4String name
Definition: TRTMaterials.hh:40
static const G4LVManager & GetSubInstanceManager()
void SetUserLimits(G4UserLimits *pULimits)
virtual G4double GetCubicVolume()
Definition: G4VSolid.cc:188
G4double GetDensity() const
Definition: G4Material.hh:180
G4VPhysicalVolume * GetDaughter(const G4int i) const
void SetSolid(G4VSolid *pSolid)
#define G4ThreadLocal
Definition: tls.hh:89
G4int CreateSubInstance()
int G4int
Definition: G4Types.hh:78
void InitialiseWorker(G4LogicalVolume *ptrMasterObject, G4VSolid *pSolid, G4VSensitiveDetector *pSDetector)
void SetFieldManager(G4FieldManager *pFieldMgr, G4bool forceToAllDaughters)
void AssignFieldManager(G4FieldManager *fldMgr)
G4FieldManager * GetFieldManager() const
bool G4bool
Definition: G4Types.hh:79
void SlaveCopySubInstanceArray()
virtual G4VPVParameterisation * GetParameterisation() const =0
G4int TotalVolumeEntities() const
G4LogicalVolume(G4VSolid *pSolid, G4Material *pMaterial, const G4String &name, G4FieldManager *pFieldMgr=0, G4VSensitiveDetector *pSDetector=0, G4UserLimits *pULimits=0, G4bool optimise=true)
G4int GetNoDaughters() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
void TerminateWorker(G4LogicalVolume *ptrMasterObject)
G4LogicalVolume * GetLogicalVolume() const
G4bool IsDaughter(const G4VPhysicalVolume *p) const
void SetName(const G4String &pName)
virtual G4int GetMultiplicity() const
#define G4endl
Definition: G4ios.hh:61
G4double GetMass(G4bool forced=false, G4bool propagate=true, G4Material *parMaterial=0)
double G4double
Definition: G4Types.hh:76
G4VSensitiveDetector * fSensitiveDetector
void SetMaterial(G4Material *pMaterial)
static void Register(G4LogicalVolume *pVolume)
void RemoveRootLogicalVolume(G4LogicalVolume *lv, G4bool scan=true)
Definition: G4Region.cc:283
void SetVisAttributes(const G4VisAttributes *pVA)
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)
G4VSolid * GetSolid() const
G4PhysicalVolumeList fDaughters
const G4VisAttributes * fVisAttributes