Geant4  10.03
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 100906 2016-11-03 09:59:32Z 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 #include "G4LogicalVolumeStore.hh"
44 #include "G4VSolid.hh"
45 #include "G4Material.hh"
46 #include "G4VPVParameterisation.hh"
47 #include "G4VisAttributes.hh"
48 
49 #include "G4UnitsTable.hh"
50 
52 : fSolid(0),fSensitiveDetector(0),fFieldManager(0),
53  fMaterial(0),fMass(0.),fCutsCouple(0)
54 {;}
55 
56 // This new field helps to use the class G4LVManager
57 //
59 
60 // These macros change the references to fields that are now encapsulated
61 // in the class G4LVData.
62 //
63 #define G4MT_solid ((subInstanceManager.offset[instanceID]).fSolid)
64 #define G4MT_sdetector ((subInstanceManager.offset[instanceID]).fSensitiveDetector)
65 #define G4MT_fmanager ((subInstanceManager.offset[instanceID]).fFieldManager)
66 #define G4MT_material ((subInstanceManager.offset[instanceID]).fMaterial)
67 #define G4MT_mass ((subInstanceManager.offset[instanceID]).fMass)
68 #define G4MT_ccouple ((subInstanceManager.offset[instanceID]).fCutsCouple)
69 #define G4MT_instance (subInstanceManager.offset[instanceID])
70 
71 // ********************************************************************
72 // Constructor - sets member data and adds to logical Store,
73 // voxel pointer for optimisation set to 0 by default.
74 // Initialises daughter vector to 0 length.
75 // ********************************************************************
76 //
78  G4Material* pMaterial,
79  const G4String& name,
80  G4FieldManager* pFieldMgr,
81  G4VSensitiveDetector* pSDetector,
82  G4UserLimits* pULimits,
83  G4bool optimise )
84  : fDaughters(0,(G4VPhysicalVolume*)0),
85  fVoxel(0), fOptimise(optimise), fRootRegion(false), fLock(false),
86  fSmartless(2.), fVisAttributes(0), fRegion(0), fBiasWeight(1.)
87 {
88  // Initialize 'Shadow'/master pointers - for use in copying to workers
89  fSolid = pSolid;
90  fSensitiveDetector = pSDetector;
91  fFieldManager = pFieldMgr;
92 
94  AssignFieldManager(pFieldMgr); // G4MT_fmanager = pFieldMgr;
95 
96  // fMasterFieldMgr= pFieldMgr;
97  G4MT_mass = 0.;
98  G4MT_ccouple = 0;
99 
100  SetSolid(pSolid);
101  SetMaterial(pMaterial);
102  SetName(name);
103  SetSensitiveDetector(pSDetector);
104  SetUserLimits(pULimits);
105 
106  // Initialize 'Shadow' data structure - for use by object persistency
107  lvdata = new G4LVData();
108  lvdata->fSolid = pSolid;
109  lvdata->fMaterial = pMaterial;
110 
111  //
112  // Add to store
113  //
115 }
116 
117 // ********************************************************************
118 // Fake default constructor - sets only member data and allocates memory
119 // for usage restricted to object persistency.
120 // ********************************************************************
121 //
123  : fDaughters(0,(G4VPhysicalVolume*)0),
124  fName(""), fUserLimits(0),
125  fVoxel(0), fOptimise(true), fRootRegion(false), fLock(false),
126  fSmartless(2.), fVisAttributes(0), fRegion(0), fBiasWeight(1.),
127  fSolid(0), fSensitiveDetector(0), fFieldManager(0), lvdata(0)
128 {
130 
131  SetSensitiveDetector(0); // G4MT_sdetector = 0;
132  SetFieldManager(0, false); // G4MT_fmanager = 0;
133 
134  G4MT_mass = 0.;
135  G4MT_ccouple = 0;
136 
137  // Add to store
138  //
140 }
141 
142 // ********************************************************************
143 // Destructor - Removes itself from solid Store
144 // NOTE: Not virtual
145 // ********************************************************************
146 //
148 {
149  if (!fLock && fRootRegion) // De-register root region first if not locked
150  { // and flagged as root logical-volume
151  fRegion->RemoveRootLogicalVolume(this, true);
152  }
153  delete lvdata;
155 }
156 
157 // ********************************************************************
158 // InitialiseWorker
159 //
160 // This method is similar to the constructor. It is used by each worker
161 // thread to achieve the same effect as that of the master thread exept
162 // to register the new created instance. This method is invoked explicitly.
163 // It does not create a new G4LogicalVolume instance. It only assign the value
164 // for the fields encapsulated by the class G4LVData.
165 // ********************************************************************
166 //
168 InitialiseWorker( G4LogicalVolume* /*pMasterObject*/,
169  G4VSolid* pSolid,
170  G4VSensitiveDetector* pSDetector)
171 {
173 
174  SetSolid(pSolid);
175  SetSensitiveDetector(pSDetector); // How this object is available now ?
176  AssignFieldManager(fFieldManager); // Should be set - but a per-thread copy is not available yet
177  // G4MT_fmanager= fFieldManager;
178  // Must not call SetFieldManager(fFieldManager, false); which propagates FieldMgr
179 
180 #ifdef CLONE_FIELD_MGR
181  // Create a field FieldManager by cloning
182  G4FieldManager workerFldMgr= fFieldManager->GetWorkerClone(G4bool* created);
183  if( created || (GetFieldManager()!=workerFldMgr) )
184  {
185  SetFieldManager(fFieldManager, false); // which propagates FieldMgr
186  }else{
187  // Field manager existed and is equal to current one
188  AssignFieldManager(workerFldMgr);
189  }
190 #endif
191 }
192 
193 // ********************************************************************
194 // TerminateWorker
195 //
196 // This method is similar to the destructor. It is used by each worker
197 // thread to achieve the partial effect as that of the master thread.
198 // For G4LogicalVolume instances, nothing more to do here.
199 // ********************************************************************
200 //
202 TerminateWorker( G4LogicalVolume* /*pMasterObject*/)
203 {
204 }
205 
206 // ********************************************************************
207 // GetSubInstanceManager
208 //
209 // Returns the private data instance manager.
210 // ********************************************************************
211 //
213 {
214  return subInstanceManager;
215 }
216 
217 // ********************************************************************
218 // GetFieldManager
219 // ********************************************************************
220 //
222 {
223  return G4MT_fmanager;
224 }
225 
226 // ********************************************************************
227 // AssignFieldManager
228 // ********************************************************************
229 //
231 {
232  G4MT_fmanager= fldMgr;
234 }
235 
236 // ********************************************************************
237 // IsExtended
238 // ********************************************************************
239 //
241 {
242  return false;
243 }
244 
245 // ********************************************************************
246 // SetFieldManager
247 // ********************************************************************
248 //
249 void
251  G4bool forceAllDaughters)
252 {
253  // G4MT_fmanager = pNewFieldMgr;
254  AssignFieldManager(pNewFieldMgr);
255 
256  G4int NoDaughters = GetNoDaughters();
257  while ( (NoDaughters--)>0 )
258  {
259  G4LogicalVolume* DaughterLogVol;
260  DaughterLogVol = GetDaughter(NoDaughters)->GetLogicalVolume();
261  if ( forceAllDaughters || (DaughterLogVol->GetFieldManager() == 0) )
262  {
263  DaughterLogVol->SetFieldManager(pNewFieldMgr, forceAllDaughters);
264  }
265  }
266 }
267 
268 // ********************************************************************
269 // AddDaughter
270 // ********************************************************************
271 //
273 {
274  if( !fDaughters.empty() && fDaughters[0]->IsReplicated() )
275  {
276  std::ostringstream message;
277  message << "ERROR - Attempt to place a volume in a mother volume" << G4endl
278  << " already containing a replicated volume." << G4endl
279  << " A volume can either contain several placements" << G4endl
280  << " or a unique replica or parameterised volume !" << G4endl
281  << " Mother logical volume: " << GetName() << G4endl
282  << " Placing volume: " << pNewDaughter->GetName() << G4endl;
283  G4Exception("G4LogicalVolume::AddDaughter()", "GeomMgt0002",
284  FatalException, message,
285  "Replica or parameterised volume must be the only daughter !");
286  }
287 
288  // Invalidate previous calculation of mass - if any - for all threads
289  G4MT_mass = 0.;
290  // SignalVolumeChange(); // fVolumeChanged= true;
291  fDaughters.push_back(pNewDaughter);
292 
293  G4LogicalVolume* pDaughterLogical = pNewDaughter->GetLogicalVolume();
294 
295  // Propagate the Field Manager, if the daughter has no field Manager.
296  //
297  G4FieldManager* pDaughterFieldManager = pDaughterLogical->GetFieldManager();
298 
299  if( pDaughterFieldManager == 0 )
300  {
301  pDaughterLogical->SetFieldManager(G4MT_fmanager, false);
302  }
303  if (fRegion)
304  {
305  PropagateRegion();
306  fRegion->RegionModified(true);
307  }
308 }
309 
310 // ********************************************************************
311 // RemoveDaughter
312 // ********************************************************************
313 //
315 {
316  G4PhysicalVolumeList::iterator i;
317  for ( i=fDaughters.begin(); i!=fDaughters.end(); ++i )
318  {
319  if (**i==*p)
320  {
321  fDaughters.erase(i);
322  break;
323  }
324  }
325  if (fRegion)
326  {
327  fRegion->RegionModified(true);
328  }
329  G4MT_mass = 0.;
330 }
331 
332 // ********************************************************************
333 // ClearDaughters
334 // ********************************************************************
335 //
337 {
338  fDaughters.erase(fDaughters.begin(), fDaughters.end());
339  if (fRegion)
340  {
341  fRegion->RegionModified(true);
342  }
343  G4MT_mass = 0.;
344 }
345 
346 // ********************************************************************
347 // ResetMass
348 // ********************************************************************
349 //
351 {
352  G4MT_mass= 0.0;
353 }
354 
355 // ********************************************************************
356 // GetSolid
357 // ********************************************************************
358 //
360 {
361  return instLVdata.fSolid;
362 }
363 
365 {
366  // return G4MT_solid;
367  // return ((subInstanceManager.offset[instanceID]).fSolid);
368  return this->GetSolid( subInstanceManager.offset[instanceID] );
369 }
370 
371 // ********************************************************************
372 // SetSolid
373 // ********************************************************************
374 //
376 {
377 
378  // ((subInstanceManager.offset[instanceID]).fSolid) = pSolid;
379  G4MT_solid=pSolid;
380  // G4MT_mass = 0.;
381  this->ResetMass();
382 }
383 
384 void G4LogicalVolume::SetSolid(G4LVData &instLVdata, G4VSolid *pSolid)
385 {
386  instLVdata.fSolid = pSolid;
387  // G4MT_solid=pSolid;
388  instLVdata.fMass= 0;
389  // A fast way to reset the mass ... ie G4MT_mass = 0.;
390 }
391 
392 // ********************************************************************
393 // GetMaterial
394 // ********************************************************************
395 //
397 {
398  return G4MT_material;
399 }
400 
401 // ********************************************************************
402 // SetMaterial
403 // ********************************************************************
404 //
406 {
407  G4MT_material=pMaterial;
408  G4MT_mass = 0.;
409 }
410 
411 // ********************************************************************
412 // UpdateMaterial
413 // ********************************************************************
414 //
416 {
417  G4MT_material=pMaterial;
418  if(fRegion) { G4MT_ccouple = fRegion->FindCouple(pMaterial); }
419  G4MT_mass = 0.;
420 }
421 
422 // ********************************************************************
423 // GetSensitiveDetector
424 // ********************************************************************
425 //
427 {
428  return G4MT_sdetector;
429 }
430 
431 // ********************************************************************
432 // SetSensitiveDetector
433 // ********************************************************************
434 //
436 {
437  G4MT_sdetector = pSDetector;
439 }
440 
441 // ********************************************************************
442 // GetMaterialCutsCouple
443 // ********************************************************************
444 //
446 {
447  return G4MT_ccouple;
448 }
449 
450 // ********************************************************************
451 // SetMaterialCutsCouple
452 // ********************************************************************
453 //
455 {
456  G4MT_ccouple = cuts;
457 }
458 
459 // ********************************************************************
460 // IsAncestor
461 //
462 // Finds out if the current logical volume is an ancestor of a given
463 // physical volume
464 // ********************************************************************
465 //
466 G4bool
468 {
469  G4bool isDaughter = IsDaughter(aVolume);
470  if (!isDaughter)
471  {
472  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
473  itDau != fDaughters.end(); itDau++)
474  {
475  isDaughter = (*itDau)->GetLogicalVolume()->IsAncestor(aVolume);
476  if (isDaughter) break;
477  }
478  }
479  return isDaughter;
480 }
481 
482 // ********************************************************************
483 // TotalVolumeEntities
484 //
485 // Returns the total number of physical volumes (replicated or placed)
486 // in the tree represented by the current logical volume.
487 // ********************************************************************
488 //
490 {
491  G4int vols = 1;
492  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
493  itDau != fDaughters.end(); itDau++)
494  {
495  G4VPhysicalVolume* physDaughter = (*itDau);
496  vols += physDaughter->GetMultiplicity()
497  *physDaughter->GetLogicalVolume()->TotalVolumeEntities();
498  }
499  return vols;
500 }
501 
502 // ********************************************************************
503 // GetMass
504 //
505 // Returns the mass of the logical volume tree computed from the
506 // estimated geometrical volume of each solid and material associated
507 // to the logical volume and its daughters.
508 // NOTE: the computation may require considerable amount of time,
509 // depending from the complexity of the geometry tree.
510 // The returned value is cached and can be used for successive
511 // calls (default), unless recomputation is forced by providing
512 // 'true' for the boolean argument in input. Computation should
513 // be forced if the geometry setup has changed after the previous
514 // call. By setting the 'propagate' boolean flag to 'false' the
515 // method returns the mass of the present logical volume only
516 // (subtracted for the volume occupied by the daughter volumes).
517 // The extra argument 'parMaterial' is internally used to
518 // consider cases of geometrical parameterisations by material.
519 // ********************************************************************
520 //
522  G4bool propagate,
523  G4Material* parMaterial)
524 {
525  // Return the cached non-zero value, if not forced
526  //
527  if ( (G4MT_mass) && (!forced) ) return G4MT_mass;
528 
529  // Global density and computed mass associated to the logical
530  // volume without considering its daughters
531  //
532  G4Material* logMaterial = parMaterial ? parMaterial : GetMaterial(); // G4MT_material;
533  if (!logMaterial)
534  {
535  std::ostringstream message;
536  message << "No material associated to the logical volume: " << fName << " !"
537  << G4endl
538  << "Sorry, cannot compute the mass ...";
539  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
540  FatalException, message);
541  return 0;
542  }
543  if (! GetSolid() ) // !G4MT_solid)
544  {
545  std::ostringstream message;
546  message << "No solid is associated to the logical volume: " << fName << " !"
547  << G4endl
548  << "Sorry, cannot compute the mass ...";
549  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
550  FatalException, message);
551  return 0;
552  }
553  G4double globalDensity = logMaterial->GetDensity();
554  G4double motherMass= GetSolid()->GetCubicVolume() * globalDensity;
555 
556  // G4MT_mass =
557  // SetMass( motherMmass );
558  G4double massSum= motherMass;
559 
560  // For each daughter in the tree, subtract the mass occupied
561  // and if required by the propagate flag, add the real daughter's
562  // one computed recursively
563 
564  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
565  itDau != fDaughters.end(); itDau++)
566  {
567  G4VPhysicalVolume* physDaughter = (*itDau);
568  G4LogicalVolume* logDaughter = physDaughter->GetLogicalVolume();
569  G4double subMass=0.;
570  G4VSolid* daughterSolid = 0;
571  G4Material* daughterMaterial = 0;
572 
573  // Compute the mass to subtract and to add for each daughter
574  // considering its multiplicity (i.e. replicated or not) and
575  // eventually its parameterisation (by solid and/or by material)
576  //
577  for (G4int i=0; i<physDaughter->GetMultiplicity(); i++)
578  {
580  physParam = physDaughter->GetParameterisation();
581  if (physParam)
582  {
583  daughterSolid = physParam->ComputeSolid(i, physDaughter);
584  daughterSolid->ComputeDimensions(physParam, i, physDaughter);
585  daughterMaterial = physParam->ComputeMaterial(i, physDaughter);
586  }
587  else
588  {
589  daughterSolid = logDaughter->GetSolid();
590  daughterMaterial = logDaughter->GetMaterial();
591  }
592  subMass = daughterSolid->GetCubicVolume() * globalDensity;
593 
594  // Subtract the daughter's portion for the mass and, if required,
595  // add the real daughter's mass computed recursively
596  //
597  massSum -= subMass;
598  if (propagate)
599  {
600  massSum += logDaughter->GetMass(true, true, daughterMaterial);
601  }
602  }
603  }
604  G4MT_mass= massSum;
605  return massSum;
606 }
607 
609 {
611 }
612 
virtual G4Material * ComputeMaterial(const G4int repNo, G4VPhysicalVolume *currentVol, const G4VTouchable *parentTouch=0)
G4Material * GetMaterial() const
void UpdateMaterial(G4Material *pMaterial)
G4String fName
Definition: G4AttUtils.hh:55
G4FieldManager * fFieldManager
static G4GEOM_DLL G4ThreadLocal T * offset
static G4GEOM_DLL G4LVManager subInstanceManager
virtual void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4VSolid.cc:138
static void DeRegister(G4LogicalVolume *pVolume)
G4bool IsAncestor(const G4VPhysicalVolume *p) const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
static const G4LVManager & GetSubInstanceManager()
void SetUserLimits(G4UserLimits *pULimits)
virtual G4double GetCubicVolume()
Definition: G4VSolid.cc:189
G4double fMass
G4double GetDensity() const
Definition: G4Material.hh:180
G4VSolid * GetSolid() const
G4VPhysicalVolume * GetDaughter(const G4int i) const
#define G4MT_ccouple
void SetSolid(G4VSolid *pSolid)
void RegionModified(G4bool flag)
#define G4MT_fmanager
const char * name(G4int ptype)
G4int CreateSubInstance()
int G4int
Definition: G4Types.hh:78
void InitialiseWorker(G4LogicalVolume *ptrMasterObject, G4VSolid *pSolid, G4VSensitiveDetector *pSDetector)
void SetFieldManager(G4FieldManager *pFieldMgr, G4bool forceToAllDaughters)
#define G4MT_sdetector
void AssignFieldManager(G4FieldManager *fldMgr)
const G4String & GetName() const
bool G4bool
Definition: G4Types.hh:79
void SlaveCopySubInstanceArray()
virtual G4VPVParameterisation * GetParameterisation() const =0
#define G4MT_mass
virtual ~G4LogicalVolume()
void SetMaterialCutsCouple(G4MaterialCutsCouple *cuts)
void PropagateRegion()
G4MaterialCutsCouple * FindCouple(G4Material *mat)
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 G4MT_solid
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
#define G4MT_material
#define G4endl
Definition: G4ios.hh:61
G4bool IsMasterThread()
Definition: G4Threading.cc:146
G4FieldManager * GetFieldManager() const
G4double GetMass(G4bool forced=false, G4bool propagate=true, G4Material *parMaterial=0)
const G4String & GetName() const
double G4double
Definition: G4Types.hh:76
void AddDaughter(G4VPhysicalVolume *p)
G4VSensitiveDetector * fSensitiveDetector
void SetMaterial(G4Material *pMaterial)
static void Register(G4LogicalVolume *pVolume)
virtual G4bool IsExtended() const
G4VSensitiveDetector * GetSensitiveDetector() const
void RemoveRootLogicalVolume(G4LogicalVolume *lv, G4bool scan=true)
Definition: G4Region.cc:319
void SetVisAttributes(const G4VisAttributes *pVA)
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)
G4VSolid * fSolid
void RemoveDaughter(const G4VPhysicalVolume *p)
G4PhysicalVolumeList fDaughters
const G4VisAttributes * fVisAttributes