Geant4  10.02.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 102288 2017-01-20 10:57:03Z 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.),
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 // SetFieldManager
238 // ********************************************************************
239 //
240 void
242  G4bool forceAllDaughters)
243 {
244  // G4MT_fmanager = pNewFieldMgr;
245  AssignFieldManager(pNewFieldMgr);
246 
247  G4int NoDaughters = GetNoDaughters();
248  while ( (NoDaughters--)>0 )
249  {
250  G4LogicalVolume* DaughterLogVol;
251  DaughterLogVol = GetDaughter(NoDaughters)->GetLogicalVolume();
252  if ( forceAllDaughters || (DaughterLogVol->GetFieldManager() == 0) )
253  {
254  DaughterLogVol->SetFieldManager(pNewFieldMgr, forceAllDaughters);
255  }
256  }
257 }
258 
259 // ********************************************************************
260 // AddDaughter
261 // ********************************************************************
262 //
264 {
265  if( !fDaughters.empty() && fDaughters[0]->IsReplicated() )
266  {
267  std::ostringstream message;
268  message << "ERROR - Attempt to place a volume in a mother volume" << G4endl
269  << " already containing a replicated volume." << G4endl
270  << " A volume can either contain several placements" << G4endl
271  << " or a unique replica or parameterised volume !" << G4endl
272  << " Mother logical volume: " << GetName() << G4endl
273  << " Placing volume: " << pNewDaughter->GetName() << G4endl;
274  G4Exception("G4LogicalVolume::AddDaughter()", "GeomMgt0002",
275  FatalException, message,
276  "Replica or parameterised volume must be the only daughter !");
277  }
278 
279  // Invalidate previous calculation of mass - if any - for all threads
280  G4MT_mass = 0.;
281  // SignalVolumeChange(); // fVolumeChanged= true;
282  fDaughters.push_back(pNewDaughter);
283 
284  G4LogicalVolume* pDaughterLogical = pNewDaughter->GetLogicalVolume();
285 
286  // Propagate the Field Manager, if the daughter has no field Manager.
287  //
288  G4FieldManager* pDaughterFieldManager = pDaughterLogical->GetFieldManager();
289 
290  if( pDaughterFieldManager == 0 )
291  {
292  pDaughterLogical->SetFieldManager(G4MT_fmanager, false);
293  }
294  if (fRegion)
295  {
296  PropagateRegion();
297  fRegion->RegionModified(true);
298  }
299 }
300 
301 // ********************************************************************
302 // RemoveDaughter
303 // ********************************************************************
304 //
306 {
307  G4PhysicalVolumeList::iterator i;
308  for ( i=fDaughters.begin(); i!=fDaughters.end(); ++i )
309  {
310  if (**i==*p)
311  {
312  fDaughters.erase(i);
313  break;
314  }
315  }
316  if (fRegion)
317  {
318  fRegion->RegionModified(true);
319  }
320  G4MT_mass = 0.;
321 }
322 
323 // ********************************************************************
324 // ClearDaughters
325 // ********************************************************************
326 //
328 {
329  fDaughters.erase(fDaughters.begin(), fDaughters.end());
330  if (fRegion)
331  {
332  fRegion->RegionModified(true);
333  }
334  G4MT_mass = 0.;
335 }
336 
337 // ********************************************************************
338 // ResetMass
339 // ********************************************************************
340 //
342 {
343  G4MT_mass= 0.0;
344 }
345 
346 // ********************************************************************
347 // GetSolid
348 // ********************************************************************
349 //
351 {
352  return instLVdata.fSolid;
353 }
354 
356 {
357  // return G4MT_solid;
358  // return ((subInstanceManager.offset[instanceID]).fSolid);
359  return this->GetSolid( subInstanceManager.offset[instanceID] );
360 }
361 
362 // ********************************************************************
363 // SetSolid
364 // ********************************************************************
365 //
367 {
368 
369  // ((subInstanceManager.offset[instanceID]).fSolid) = pSolid;
370  G4MT_solid=pSolid;
371  // G4MT_mass = 0.;
372  this->ResetMass();
373 }
374 
375 void G4LogicalVolume::SetSolid(G4LVData &instLVdata, G4VSolid *pSolid)
376 {
377  instLVdata.fSolid = pSolid;
378  // G4MT_solid=pSolid;
379  instLVdata.fMass= 0;
380  // A fast way to reset the mass ... ie G4MT_mass = 0.;
381 }
382 
383 // ********************************************************************
384 // GetMaterial
385 // ********************************************************************
386 //
388 {
389  return G4MT_material;
390 }
391 
392 // ********************************************************************
393 // SetMaterial
394 // ********************************************************************
395 //
397 {
398  G4MT_material=pMaterial;
399  G4MT_mass = 0.;
400 }
401 
402 // ********************************************************************
403 // UpdateMaterial
404 // ********************************************************************
405 //
407 {
408  G4MT_material=pMaterial;
409  if(fRegion) { G4MT_ccouple = fRegion->FindCouple(pMaterial); }
410  G4MT_mass = 0.;
411 }
412 
413 // ********************************************************************
414 // GetSensitiveDetector
415 // ********************************************************************
416 //
418 {
419  return G4MT_sdetector;
420 }
421 
422 // ********************************************************************
423 // SetSensitiveDetector
424 // ********************************************************************
425 //
427 {
428  G4MT_sdetector = pSDetector;
430 }
431 
432 // ********************************************************************
433 // GetMaterialCutsCouple
434 // ********************************************************************
435 //
437 {
438  return G4MT_ccouple;
439 }
440 
441 // ********************************************************************
442 // SetMaterialCutsCouple
443 // ********************************************************************
444 //
446 {
447  G4MT_ccouple = cuts;
448 }
449 
450 // ********************************************************************
451 // IsAncestor
452 //
453 // Finds out if the current logical volume is an ancestor of a given
454 // physical volume
455 // ********************************************************************
456 //
457 G4bool
459 {
460  G4bool isDaughter = IsDaughter(aVolume);
461  if (!isDaughter)
462  {
463  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
464  itDau != fDaughters.end(); itDau++)
465  {
466  isDaughter = (*itDau)->GetLogicalVolume()->IsAncestor(aVolume);
467  if (isDaughter) break;
468  }
469  }
470  return isDaughter;
471 }
472 
473 // ********************************************************************
474 // TotalVolumeEntities
475 //
476 // Returns the total number of physical volumes (replicated or placed)
477 // in the tree represented by the current logical volume.
478 // ********************************************************************
479 //
481 {
482  G4int vols = 1;
483  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
484  itDau != fDaughters.end(); itDau++)
485  {
486  G4VPhysicalVolume* physDaughter = (*itDau);
487  vols += physDaughter->GetMultiplicity()
488  *physDaughter->GetLogicalVolume()->TotalVolumeEntities();
489  }
490  return vols;
491 }
492 
493 // ********************************************************************
494 // GetMass
495 //
496 // Returns the mass of the logical volume tree computed from the
497 // estimated geometrical volume of each solid and material associated
498 // to the logical volume and its daughters.
499 // NOTE: the computation may require considerable amount of time,
500 // depending from the complexity of the geometry tree.
501 // The returned value is cached and can be used for successive
502 // calls (default), unless recomputation is forced by providing
503 // 'true' for the boolean argument in input. Computation should
504 // be forced if the geometry setup has changed after the previous
505 // call. By setting the 'propagate' boolean flag to 'false' the
506 // method returns the mass of the present logical volume only
507 // (subtracted for the volume occupied by the daughter volumes).
508 // The extra argument 'parMaterial' is internally used to
509 // consider cases of geometrical parameterisations by material.
510 // ********************************************************************
511 //
513  G4bool propagate,
514  G4Material* parMaterial)
515 {
516  // Return the cached non-zero value, if not forced
517  //
518  if ( (G4MT_mass) && (!forced) ) return G4MT_mass;
519 
520  // Global density and computed mass associated to the logical
521  // volume without considering its daughters
522  //
523  G4Material* logMaterial = parMaterial ? parMaterial : GetMaterial(); // G4MT_material;
524  if (!logMaterial)
525  {
526  std::ostringstream message;
527  message << "No material associated to the logical volume: " << fName << " !"
528  << G4endl
529  << "Sorry, cannot compute the mass ...";
530  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
531  FatalException, message);
532  return 0;
533  }
534  if (! GetSolid() ) // !G4MT_solid)
535  {
536  std::ostringstream message;
537  message << "No solid is associated to the logical volume: " << fName << " !"
538  << G4endl
539  << "Sorry, cannot compute the mass ...";
540  G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002",
541  FatalException, message);
542  return 0;
543  }
544  G4double globalDensity = logMaterial->GetDensity();
545  G4double motherMass= GetSolid()->GetCubicVolume() * globalDensity;
546 
547  // G4MT_mass =
548  // SetMass( motherMmass );
549  G4double massSum= motherMass;
550 
551  // For each daughter in the tree, subtract the mass occupied
552  // and if required by the propagate flag, add the real daughter's
553  // one computed recursively
554 
555  for (G4PhysicalVolumeList::const_iterator itDau = fDaughters.begin();
556  itDau != fDaughters.end(); itDau++)
557  {
558  G4VPhysicalVolume* physDaughter = (*itDau);
559  G4LogicalVolume* logDaughter = physDaughter->GetLogicalVolume();
560  G4double subMass=0.;
561  G4VSolid* daughterSolid = 0;
562  G4Material* daughterMaterial = 0;
563 
564  // Compute the mass to subtract and to add for each daughter
565  // considering its multiplicity (i.e. replicated or not) and
566  // eventually its parameterisation (by solid and/or by material)
567  //
568  for (G4int i=0; i<physDaughter->GetMultiplicity(); i++)
569  {
571  physParam = physDaughter->GetParameterisation();
572  if (physParam)
573  {
574  daughterSolid = physParam->ComputeSolid(i, physDaughter);
575  daughterSolid->ComputeDimensions(physParam, i, physDaughter);
576  daughterMaterial = physParam->ComputeMaterial(i, physDaughter);
577  }
578  else
579  {
580  daughterSolid = logDaughter->GetSolid();
581  daughterMaterial = logDaughter->GetMaterial();
582  }
583  subMass = daughterSolid->GetCubicVolume() * globalDensity;
584 
585  // Subtract the daughter's portion for the mass and, if required,
586  // add the real daughter's mass computed recursively
587  //
588  massSum -= subMass;
589  if (propagate)
590  {
591  massSum += logDaughter->GetMass(true, true, daughterMaterial);
592  }
593  }
594  }
595  G4MT_mass= massSum;
596  return massSum;
597 }
598 
600 {
602 }
603 
G4SmartVoxelHeader * fVoxel
virtual G4Material * ComputeMaterial(const G4int repNo, G4VPhysicalVolume *currentVol, const G4VTouchable *parentTouch=0)
void UpdateMaterial(G4Material *pMaterial)
G4int GetNoDaughters() const
G4FieldManager * fFieldManager
virtual G4int GetMultiplicity() const
G4int TotalVolumeEntities() const
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:137
static void DeRegister(G4LogicalVolume *pVolume)
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
G4String name
Definition: TRTMaterials.hh:40
G4bool IsAncestor(const G4VPhysicalVolume *p) const
static const G4LVManager & GetSubInstanceManager()
void SetUserLimits(G4UserLimits *pULimits)
G4Material * GetMaterial() const
virtual G4double GetCubicVolume()
Definition: G4VSolid.cc:188
G4double fMass
G4double GetDensity() const
Definition: G4Material.hh:180
#define G4MT_ccouple
void SetSolid(G4VSolid *pSolid)
void RegionModified(G4bool flag)
#define G4MT_fmanager
G4int CreateSubInstance()
int G4int
Definition: G4Types.hh:78
G4bool IsDaughter(const G4VPhysicalVolume *p) const
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
G4FieldManager * GetFieldManager() const
void SlaveCopySubInstanceArray()
virtual G4VPVParameterisation * GetParameterisation() const =0
#define G4MT_mass
void SetMaterialCutsCouple(G4MaterialCutsCouple *cuts)
void PropagateRegion()
G4MaterialCutsCouple * FindCouple(G4Material *mat)
G4LogicalVolume(G4VSolid *pSolid, G4Material *pMaterial, const G4String &name, G4FieldManager *pFieldMgr=0, G4VSensitiveDetector *pSDetector=0, G4UserLimits *pULimits=0, G4bool optimise=true)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4Material * fMaterial
const G4String & GetName() const
void TerminateWorker(G4LogicalVolume *ptrMasterObject)
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
void SetName(const G4String &pName)
G4VSensitiveDetector * GetSensitiveDetector() const
#define G4MT_solid
#define G4MT_material
#define G4endl
Definition: G4ios.hh:61
G4VPhysicalVolume * GetDaughter(const G4int i) const
G4bool IsMasterThread()
Definition: G4Threading.cc:136
G4double GetMass(G4bool forced=false, G4bool propagate=true, G4Material *parMaterial=0)
double G4double
Definition: G4Types.hh:76
void AddDaughter(G4VPhysicalVolume *p)
G4LogicalVolume * GetLogicalVolume() const
G4VSensitiveDetector * fSensitiveDetector
void SetMaterial(G4Material *pMaterial)
static void Register(G4LogicalVolume *pVolume)
void RemoveRootLogicalVolume(G4LogicalVolume *lv, G4bool scan=true)
Definition: G4Region.cc:319
G4UserLimits * fUserLimits
G4VSolid * GetSolid() const
void SetVisAttributes(const G4VisAttributes *pVA)
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)
G4VSolid * fSolid
void RemoveDaughter(const G4VPhysicalVolume *p)
G4PhysicalVolumeList fDaughters
const G4VisAttributes * fVisAttributes