Geant4  10.02.p01
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 93287 2015-10-15 09:50:22Z 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  // Initialize 'Shadow' data structure - for use by object persistency
168  lvdata = new G4LVData();
169  lvdata->fSolid = pSolid;
170  lvdata->fMaterial = pMaterial;
171 
172  //
173  // Add to store
174  //
176 }
177 
178 // ********************************************************************
179 // Fake default constructor - sets only member data and allocates memory
180 // for usage restricted to object persistency.
181 // ********************************************************************
182 //
184  : fDaughters(0,(G4VPhysicalVolume*)0),
185  fName(""), fUserLimits(0),
186  fVoxel(0), fOptimise(true), fRootRegion(false), fLock(false),
187  fSmartless(2.), fVisAttributes(0), fRegion(0), fBiasWeight(1.),
188  fSolid(0), fSensitiveDetector(0), fFieldManager(0), lvdata(0)
189 {
191 
192  SetSensitiveDetector(0); // G4MT_sdetector = 0;
193  SetFieldManager(0, false); // G4MT_fmanager = 0;
194 
195  G4MT_mass = 0.;
196  G4MT_ccouple = 0;
197 
198  // Add to store
199  //
201 }
202 
203 // ********************************************************************
204 // Destructor - Removes itself from solid Store
205 // NOTE: Not virtual
206 // ********************************************************************
207 //
209 {
210  if (!fLock && fRootRegion) // De-register root region first if not locked
211  { // and flagged as root logical-volume
212  fRegion->RemoveRootLogicalVolume(this, true);
213  }
214  delete lvdata;
216 }
217 
218 // ********************************************************************
219 // SetFieldManager
220 // ********************************************************************
221 //
222 void
224  G4bool forceAllDaughters)
225 {
226  // G4MT_fmanager = pNewFieldMgr;
227  AssignFieldManager(pNewFieldMgr);
228 
229  G4int NoDaughters = GetNoDaughters();
230  while ( (NoDaughters--)>0 )
231  {
232  G4LogicalVolume* DaughterLogVol;
233  DaughterLogVol = GetDaughter(NoDaughters)->GetLogicalVolume();
234  if ( forceAllDaughters || (DaughterLogVol->GetFieldManager() == 0) )
235  {
236  DaughterLogVol->SetFieldManager(pNewFieldMgr, forceAllDaughters);
237  }
238  }
239 }
240 
241 
242 // ********************************************************************
243 // IsAncestor
244 //
245 // Finds out if the current logical volume is an ancestor of a given
246 // physical volume
247 // ********************************************************************
248 //
249 G4bool
251 {
252  G4bool isDaughter = IsDaughter(aVolume);
253  if (!isDaughter)
254  {
255  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
256  itDau != fDaughters.end(); itDau++)
257  {
258  isDaughter = (*itDau)->GetLogicalVolume()->IsAncestor(aVolume);
259  if (isDaughter) break;
260  }
261  }
262  return isDaughter;
263 }
264 
265 // ********************************************************************
266 // TotalVolumeEntities
267 //
268 // Returns the total number of physical volumes (replicated or placed)
269 // in the tree represented by the current logical volume.
270 // ********************************************************************
271 //
273 {
274  G4int vols = 1;
275  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
276  itDau != fDaughters.end(); itDau++)
277  {
278  G4VPhysicalVolume* physDaughter = (*itDau);
279  vols += physDaughter->GetMultiplicity()
280  *physDaughter->GetLogicalVolume()->TotalVolumeEntities();
281  }
282  return vols;
283 }
284 
285 // ********************************************************************
286 // GetMass
287 //
288 // Returns the mass of the logical volume tree computed from the
289 // estimated geometrical volume of each solid and material associated
290 // to the logical volume and its daughters.
291 // NOTE: the computation may require considerable amount of time,
292 // depending from the complexity of the geometry tree.
293 // The returned value is cached and can be used for successive
294 // calls (default), unless recomputation is forced by providing
295 // 'true' for the boolean argument in input. Computation should
296 // be forced if the geometry setup has changed after the previous
297 // call. By setting the 'propagate' boolean flag to 'false' the
298 // method returns the mass of the present logical volume only
299 // (subtracted for the volume occupied by the daughter volumes).
300 // The extra argument 'parMaterial' is internally used to
301 // consider cases of geometrical parameterisations by material.
302 // ********************************************************************
303 //
305  G4bool propagate,
306  G4Material* parMaterial)
307 {
308  // Return the cached non-zero value, if not forced
309  //
310  if ( (G4MT_mass) && (!forced) ) return G4MT_mass;
311 
312  // Global density and computed mass associated to the logical
313  // volume without considering its daughters
314  //
315  G4Material* logMaterial = parMaterial ? parMaterial : GetMaterial(); // G4MT_material;
316  if (!logMaterial)
317  {
318  std::ostringstream message;
319  message << "No material associated to the logical volume: " << fName << " !"
320  << G4endl
321  << "Sorry, cannot compute the mass ...";
322  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
323  FatalException, message);
324  return 0;
325  }
326  if (! GetSolid() ) // !G4MT_solid)
327  {
328  std::ostringstream message;
329  message << "No solid is associated to the logical volume: " << fName << " !"
330  << G4endl
331  << "Sorry, cannot compute the mass ...";
332  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
333  FatalException, message);
334  return 0;
335  }
336  G4double globalDensity = logMaterial->GetDensity();
337  G4double motherMass= GetSolid()->GetCubicVolume() * globalDensity;
338 
339  // G4MT_mass =
340  // SetMass( motherMmass );
341  G4double massSum= motherMass;
342 
343  // For each daughter in the tree, subtract the mass occupied
344  // and if required by the propagate flag, add the real daughter's
345  // one computed recursively
346 
347  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
348  itDau != fDaughters.end(); itDau++)
349  {
350  G4VPhysicalVolume* physDaughter = (*itDau);
351  G4LogicalVolume* logDaughter = physDaughter->GetLogicalVolume();
352  G4double subMass=0.;
353  G4VSolid* daughterSolid = 0;
354  G4Material* daughterMaterial = 0;
355 
356  // Compute the mass to subtract and to add for each daughter
357  // considering its multiplicity (i.e. replicated or not) and
358  // eventually its parameterisation (by solid and/or by material)
359  //
360  for (G4int i=0; i<physDaughter->GetMultiplicity(); i++)
361  {
363  physParam = physDaughter->GetParameterisation();
364  if (physParam)
365  {
366  daughterSolid = physParam->ComputeSolid(i, physDaughter);
367  daughterSolid->ComputeDimensions(physParam, i, physDaughter);
368  daughterMaterial = physParam->ComputeMaterial(i, physDaughter);
369  }
370  else
371  {
372  daughterSolid = logDaughter->GetSolid();
373  daughterMaterial = logDaughter->GetMaterial();
374  }
375  subMass = daughterSolid->GetCubicVolume() * globalDensity;
376 
377  // Subtract the daughter's portion for the mass and, if required,
378  // add the real daughter's mass computed recursively
379  //
380  massSum -= subMass;
381  if (propagate)
382  {
383  massSum += logDaughter->GetMass(true, true, daughterMaterial);
384  }
385  }
386  }
387  G4MT_mass= massSum;
388  return massSum;
389 }
390 
392 {
394 }
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
G4Material * fMaterial
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
G4VSolid * fSolid
G4PhysicalVolumeList fDaughters
const G4VisAttributes * fVisAttributes