ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Region.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4Region.cc
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 // G4Region class implementation
27 //
28 // 18.09.02, G.Cosmo - Initial version
29 // --------------------------------------------------------------------
30 
31 #include "G4Region.hh"
32 #include "G4RegionStore.hh"
33 #include "G4LogicalVolume.hh"
34 #include "G4VPhysicalVolume.hh"
35 #include "G4LogicalVolumeStore.hh"
38 #include "G4Material.hh"
39 
40 // These macros changes the references to fields that are now encapsulated
41 // in the class G4RegionData.
42 //
43 #define G4MT_fsmanager ((subInstanceManager.offset[instanceID]).fFastSimulationManager)
44 #define G4MT_rsaction ((subInstanceManager.offset[instanceID]).fRegionalSteppingAction)
45 
46 // This new field helps to use the class G4RegionManager
47 //
49 
50 // *******************************************************************
51 // GetSubInstanceManager:
52 // - Returns the private data instance manager.
53 // *******************************************************************
54 //
56 {
57  return subInstanceManager;
58 }
59 
60 // *******************************************************************
61 // Constructor:
62 // - Adds self to region Store
63 // *******************************************************************
64 //
66  : fName(pName)
67 {
68 
70  G4MT_fsmanager = nullptr;
71  G4MT_rsaction = nullptr;
72 
74  if (rStore->GetRegion(pName, false))
75  {
76  std::ostringstream message;
77  message << "The region has NOT been registered !" << G4endl
78  << " Region " << pName << " already existing in store !"
79  << G4endl;
80  G4Exception("G4Region::G4Region()", "GeomMgt1001",
81  JustWarning, message);
82  }
83  else
84  {
85  rStore->Register(this);
86  }
87 }
88 
89 // ********************************************************************
90 // Fake default constructor - sets only member data and allocates memory
91 // for usage restricted to object persistency.
92 // ********************************************************************
93 //
94 G4Region::G4Region( __void__& )
95  : fName("")
96 {
98  G4MT_fsmanager = nullptr;
99  G4MT_rsaction = nullptr;
100 
101  // Register to store
102  //
104 }
105 
106 // *******************************************************************
107 // Destructor:
108 // - Removes self from region Store
109 // *******************************************************************
110 //
112 {
114  if(fUserInfo != nullptr) { delete fUserInfo; }
115 }
116 
117 // ********************************************************************
118 // SetFastSimulationManager
119 // ********************************************************************
120 //
122 {
123  G4MT_fsmanager = fsm;
124 }
125 
126 // ********************************************************************
127 // GetFastSimulationManager
128 // ********************************************************************
129 //
131 {
132  return G4MT_fsmanager;
133 }
134 
135 // ********************************************************************
136 // SetRegionalSteppingAction
137 // ********************************************************************
138 //
140 {
141  G4MT_rsaction = rusa;
142 }
143 
144 // ********************************************************************
145 // GetRegionalSteppingAction
146 // ********************************************************************
147 //
149 {
150  return G4MT_rsaction;
151 }
152 
153 // *******************************************************************
154 // ScanVolumeTree:
155 // - Scans recursively the 'lv' logical volume tree, retrieves
156 // and places all materials in the list.
157 // - The boolean flag 'region' identifies if the volume tree must
158 // have region reset (false) or if the current region must be
159 // associated to the logical volume 'lv' and its tree (true).
160 // *******************************************************************
161 //
163 {
164  // If logical volume is going to become a region, add
165  // its material to the list if not already present
166  //
167  G4Region* currentRegion = nullptr;
168  size_t noDaughters = lv->GetNoDaughters();
169  G4Material* volMat = lv->GetMaterial();
170  if((volMat == nullptr) && fInMassGeometry)
171  {
172  std::ostringstream message;
173  message << "Logical volume <" << lv->GetName() << ">" << G4endl
174  << "does not have a valid material pointer." << G4endl
175  << "A logical volume belonging to the (tracking) world volume "
176  << "must have a valid material.";
177  G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002",
178  FatalException, message, "Check your geometry construction.");
179  }
180  if (region)
181  {
182  currentRegion = this;
183  if (volMat != nullptr)
184  {
185  AddMaterial(volMat);
186  G4Material* baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial());
187  if (baseMat != nullptr) { AddMaterial(baseMat); }
188  }
189  }
190 
191  // Set the LV region to be either the current region or NULL,
192  // according to the boolean selector
193  //
194  lv->SetRegion(currentRegion);
195 
196  // Stop recursion here if no further daughters are involved
197  //
198  if(noDaughters==0) return;
199 
200  G4VPhysicalVolume* daughterPVol = lv->GetDaughter(0);
201  if (daughterPVol->IsParameterised())
202  {
203  // Adopt special treatment in case of parameterised volumes,
204  // where parameterisation involves a new material scan
205  //
206  G4VPVParameterisation* pParam = daughterPVol->GetParameterisation();
207 
208  if (pParam->GetMaterialScanner() != nullptr)
209  {
210  size_t matNo = pParam->GetMaterialScanner()->GetNumberOfMaterials();
211  for (size_t mat=0; mat<matNo; ++mat)
212  {
213  volMat = pParam->GetMaterialScanner()->GetMaterial(mat);
214  if(!volMat && fInMassGeometry)
215  {
216  std::ostringstream message;
217  message << "The parameterisation for the physical volume <"
218  << daughterPVol->GetName() << ">" << G4endl
219  << "does not return a valid material pointer." << G4endl
220  << "A volume belonging to the (tracking) world volume must "
221  << "have a valid material.";
222  G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002",
223  FatalException, message, "Check your parameterisation.");
224  }
225  if (volMat != nullptr)
226  {
227  AddMaterial(volMat);
228  G4Material* baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial());
229  if (baseMat != nullptr) { AddMaterial(baseMat); }
230  }
231  }
232  }
233  else
234  {
235  size_t repNo = daughterPVol->GetMultiplicity();
236  for (size_t rep=0; rep<repNo; ++rep)
237  {
238  volMat = pParam->ComputeMaterial(rep, daughterPVol);
239  if((volMat == nullptr) && fInMassGeometry)
240  {
241  std::ostringstream message;
242  message << "The parameterisation for the physical volume <"
243  << daughterPVol->GetName() << ">" << G4endl
244  << "does not return a valid material pointer." << G4endl
245  << "A volume belonging to the (tracking) world volume must "
246  << "have a valid material.";
247  G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002",
248  FatalException, message, "Check your parameterisation.");
249  }
250  if(volMat != nullptr)
251  {
252  AddMaterial(volMat);
253  G4Material* baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial());
254  if (baseMat != nullptr) { AddMaterial(baseMat); }
255  }
256  }
257  }
258  G4LogicalVolume* daughterLVol = daughterPVol->GetLogicalVolume();
259  ScanVolumeTree(daughterLVol, region);
260  }
261  else
262  {
263  for (size_t i=0; i<noDaughters; ++i)
264  {
265  G4LogicalVolume* daughterLVol = lv->GetDaughter(i)->GetLogicalVolume();
266  if (!daughterLVol->IsRootRegion())
267  {
268  // Set daughter's LV to be a region and store materials in
269  // the materials list, if the LV is not already a root region
270  //
271  ScanVolumeTree(daughterLVol, region);
272  }
273  }
274  }
275 }
276 
277 // *******************************************************************
278 // AddRootLogicalVolume:
279 // - Adds a root logical volume and sets its daughters flags as
280 // regions. It also recomputes the materials list for the region.
281 // *******************************************************************
282 //
284 {
285  // Check the logical volume is not already in the list
286  //
287  if (search)
288  {
289  auto pos = std::find(fRootVolumes.cbegin(),fRootVolumes.cend(),lv);
290  if (pos == fRootVolumes.cend())
291  {
292  // Insert the root volume in the list and set it as root region
293  //
294  fRootVolumes.push_back(lv);
295  lv->SetRegionRootFlag(true);
296  }
297  }
298  else // WARNING: user *MUST* guarantee lv is not already inserted.
299  { // Providing speedup for very complex flat geometries
300  fRootVolumes.push_back(lv);
301  lv->SetRegionRootFlag(true);
302  }
303  // Scan recursively the tree of daugther volumes and set regions
304  //
305  ScanVolumeTree(lv, true);
306 
307  // Set region as modified
308  //
309  fRegionMod = true;
310 }
311 
312 // *******************************************************************
313 // RemoveRootLogicalVolume:
314 // - Removes a root logical volume and resets its daughters flags as
315 // regions. It also recomputes the materials list for the region.
316 // *******************************************************************
317 //
319 {
320  // Find and remove logical volume from the list
321  //
322  auto pos = std::find(fRootVolumes.cbegin(),fRootVolumes.cend(),lv);
323  if (pos != fRootVolumes.cend())
324  {
325  if (fRootVolumes.size() != 1) // Avoid resetting flag for world since
326  { // volume may be already deleted !
327  lv->SetRegionRootFlag(false);
328  }
329  fRootVolumes.erase(pos);
330  }
331 
332  if (scan) // Update the materials list
333  {
335  }
336 
337  // Set region as modified
338  //
339  fRegionMod = true;
340 }
341 
342 // ********************************************************************
343 // Clean
344 // ********************************************************************
345 //
347 {
349 }
350 
351 // *******************************************************************
352 // ClearMaterialList:
353 // - Clears the material list.
354 // *******************************************************************
355 //
357 {
358  fMaterials.clear();
359 }
360 
361 // *******************************************************************
362 // UpdateMaterialList:
363 // - computes material list looping through
364 // each root logical volume in the region.
365 // *******************************************************************
366 //
368 {
369  // Reset the materials list
370  //
372 
373  // Loop over the root logical volumes and rebuild the list
374  // of materials from scratch
375  //
376  for (auto pLV=fRootVolumes.cbegin(); pLV!=fRootVolumes.cend(); ++pLV)
377  {
378  ScanVolumeTree(*pLV, true);
379  }
380 }
381 
382 // *******************************************************************
383 // SetWorld:
384 // - Set the world physical volume if this region belongs to this
385 // world. If the given pointer is null, reset the pointer.
386 // *******************************************************************
387 //
389 {
390  if(!wp)
391  { fWorldPhys = 0; }
392  else
393  { if(BelongsTo(wp)) fWorldPhys = wp; }
394 
395  return;
396 }
397 
398 // *******************************************************************
399 // BelongsTo:
400 // - Returns whether this region belongs to the given physical volume
401 // (recursively scanned to the bottom of the hierarchy)
402 // *******************************************************************
403 //
405 {
406  G4LogicalVolume* currLog = thePhys->GetLogicalVolume();
407  if (currLog->GetRegion()==this) {return true;}
408 
409  G4int nDaughters = currLog->GetNoDaughters();
410  while (nDaughters--) // Loop checking, 06.08.2015, G.Cosmo
411  {
412  if (BelongsTo(currLog->GetDaughter(nDaughters))) {return true;}
413  }
414 
415  return false;
416 }
417 
418 // *******************************************************************
419 // ClearFastSimulationManager:
420 // - Set G4FastSimulationManager pointer to the one for the parent region
421 // if it exists. Otherwise set to null.
422 // *******************************************************************
423 //
425 {
426  G4bool isUnique;
427  G4Region* parent = GetParentRegion(isUnique);
428  if(parent != nullptr)
429  {
430  if (isUnique)
431  {
433  }
434  else
435  {
436  std::ostringstream message;
437  message << "Region <" << fName << "> belongs to more than"
438  << " one parent region !" << G4endl
439  << "A region cannot belong to more than one direct parent region,"
440  << G4endl
441  << "to have fast-simulation assigned.";
442  G4Exception("G4Region::ClearFastSimulationManager()",
443  "GeomMgt1002", JustWarning, message);
444  G4MT_fsmanager = nullptr;
445  }
446  }
447  else
448  {
449  G4MT_fsmanager = nullptr;
450  }
451 }
452 
453 // *******************************************************************
454 // GetParentRegion:
455 // - Returns a region that contains this region.
456 // Otherwise null is returned.
457 // *******************************************************************
458 //
460 {
461  G4Region* parent = nullptr; unique = true;
463 
464  // Loop over all logical volumes in the store
465  //
466  for(auto lvItr=lvStore->cbegin(); lvItr!=lvStore->cend(); ++lvItr)
467  {
468  G4int nD = (*lvItr)->GetNoDaughters();
469  G4Region* aR = (*lvItr)->GetRegion();
470 
471  // Loop over all daughters of each logical volume
472  //
473  for(auto iD=0; iD<nD; ++iD)
474  {
475  if((*lvItr)->GetDaughter(iD)->GetLogicalVolume()->GetRegion()==this)
476  {
477  if(parent)
478  {
479  if(parent!=aR) { unique = false; }
480  }
481  else // Cache LV parent region which includes a daughter volume
482  // with the same associated region as the current one
483  {
484  parent = aR;
485  }
486  }
487  }
488  }
489  return parent;
490 }