source: trunk/source/geometry/management/src/G4Region.cc @ 1253

Last change on this file since 1253 was 1228, checked in by garnier, 14 years ago

update geant4.9.3 tag

File size: 13.3 KB
Line 
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: G4Region.cc,v 1.27 2009/11/27 16:34:37 gcosmo Exp $
28// GEANT4 tag $Name: geant4-09-03 $
29//
30//
31// class G4Region Implementation
32//
33// --------------------------------------------------------------------
34
35#include "G4Region.hh"
36#include "G4RegionStore.hh"
37#include "G4LogicalVolume.hh"
38#include "G4VPhysicalVolume.hh"
39#include "G4LogicalVolumeStore.hh"
40#include "G4VNestedParameterisation.hh"
41#include "G4VUserRegionInformation.hh"
42
43// *******************************************************************
44// Constructor:
45//  - Adds self to region Store
46// *******************************************************************
47//
48G4Region::G4Region(const G4String& pName)
49  : fName(pName), fRegionMod(true), fCut(0), fUserInfo(0), fUserLimits(0),
50    fFieldManager(0), fFastSimulationManager(0), fWorldPhys(0),
51    fRegionalSteppingAction(0)
52{
53  G4RegionStore* rStore = G4RegionStore::GetInstance();
54  if (rStore->GetRegion(pName,false))
55  {
56    G4cerr << "WARNING - G4Region::G4Region()" << G4endl
57           << "          Region " << pName << " already existing in store !"
58           << G4endl;
59    G4Exception("G4Region::G4Region()", "InvalidSetup", JustWarning,
60                "The region has NOT been registered !");
61  }
62  else
63  {
64    rStore->Register(this);
65  }
66}
67
68// ********************************************************************
69// Fake default constructor - sets only member data and allocates memory
70//                            for usage restricted to object persistency.
71// ********************************************************************
72//
73G4Region::G4Region( __void__& )
74  : fName(""), fRegionMod(true), fCut(0), fUserInfo(0), fUserLimits(0),
75    fFieldManager(0), fFastSimulationManager(0), fWorldPhys(0),
76    fRegionalSteppingAction(0)
77{
78  // Register to store
79  //
80  G4RegionStore::GetInstance()->Register(this);
81}
82
83// *******************************************************************
84// Destructor:
85//  - Removes self from region Store
86// *******************************************************************
87//
88G4Region::~G4Region()
89{
90  G4RegionStore::GetInstance()->DeRegister(this);
91  if(fUserInfo) delete fUserInfo;
92}
93
94// *******************************************************************
95// ScanVolumeTree:
96//  - Scans recursively the 'lv' logical volume tree, retrieves
97//    and places all materials in the list.
98//  - The boolean flag 'region' identifies if the volume tree must
99//    have region reset (false) or if the current region must be
100//    associated to the logical volume 'lv' and its tree (true).
101// *******************************************************************
102//
103void G4Region::ScanVolumeTree(G4LogicalVolume* lv, G4bool region)
104{
105  // If logical volume is going to become a region, add
106  // its material to the list if not already present
107  //
108  G4Region* currentRegion = 0;
109  size_t noDaughters = lv->GetNoDaughters();
110  G4Material* volMat = lv->GetMaterial();
111  if(!volMat)
112  {
113    G4String errmsg = "Logical volume <";
114    errmsg += lv->GetName();
115    errmsg += "> does not have a valid material pointer.\n";
116    errmsg += "A logical volume belonging to the (tracking) world volume ";
117    errmsg += "must have a valid material.\nCheck your geometry construction.";
118    G4Exception("G4Region::ScanVolumeTree()", "SetupError",
119                FatalException, errmsg);
120  }
121  if (region)
122  {
123    currentRegion = this;
124    AddMaterial(volMat);
125  }
126
127  // Set the LV region to be either the current region or NULL,
128  // according to the boolean selector
129  //
130  lv->SetRegion(currentRegion);
131
132  // Stop recursion here if no further daughters are involved
133  //
134  if(noDaughters==0) return;
135
136  G4VPhysicalVolume* daughterPVol = lv->GetDaughter(0);
137  if (daughterPVol->IsParameterised())
138  {
139    // Adopt special treatment in case of parameterised volumes,
140    // where parameterisation involves a new material scan
141    //
142    G4VPVParameterisation* pParam = daughterPVol->GetParameterisation();
143
144    if (pParam->GetMaterialScanner())
145    {
146      size_t matNo = pParam->GetMaterialScanner()->GetNumberOfMaterials();
147      for (register size_t mat=0; mat<matNo; mat++)
148      {
149        volMat = pParam->GetMaterialScanner()->GetMaterial(mat);
150        if(!volMat)
151        {
152          G4String errmsg = "The parameterisation for the physical volume <";
153          errmsg += daughterPVol->GetName();
154          errmsg += ">\n does not return a valid material pointer.\n";
155          errmsg += "A volume belonging to the (tracking) world volume must ";
156          errmsg += "have a valid material.\nCheck your parameterisation.";
157          G4Exception("G4Region::ScanVolumeTree()",
158                      "SetupError", FatalException, errmsg);
159        }
160        AddMaterial(volMat);
161      }
162    }
163    else
164    {
165      size_t repNo = daughterPVol->GetMultiplicity();
166      for (register size_t rep=0; rep<repNo; rep++)
167      {
168        volMat = pParam->ComputeMaterial(rep, daughterPVol);
169        if(!volMat)
170        {
171          G4String errmsg = "The parameterisation for the physical volume <";
172          errmsg += daughterPVol->GetName();
173          errmsg += ">\n does not return a valid material pointer.\n";
174          errmsg += "A volume belonging to the (tracking) world volume must ";
175          errmsg += "have a valid material.\nCheck your parameterisation.";
176          G4Exception("G4Region::ScanVolumeTree()",
177                      "SetupError", FatalException, errmsg);
178        }
179        AddMaterial(volMat);
180      }
181    }
182    G4LogicalVolume* daughterLVol = daughterPVol->GetLogicalVolume();
183    ScanVolumeTree(daughterLVol, region);
184  }
185  else
186  {
187    for (register size_t i=0; i<noDaughters; i++)
188    {
189      G4LogicalVolume* daughterLVol = lv->GetDaughter(i)->GetLogicalVolume();
190      if (!daughterLVol->IsRootRegion())
191      {
192        // Set daughter's LV to be a region and store materials in
193        // the materials list, if the LV is not already a root region
194        //
195        ScanVolumeTree(daughterLVol, region);
196      }
197    }
198  }
199}
200
201// *******************************************************************
202// AddRootLogicalVolume:
203//  - Adds a root logical volume and sets its daughters flags as
204//    regions. It also recomputes the materials list for the region.
205// *******************************************************************
206//
207void G4Region::AddRootLogicalVolume(G4LogicalVolume* lv)
208{
209  // Check the logical volume is not already in the list
210  //
211  G4RootLVList::iterator pos;
212  pos = std::find(fRootVolumes.begin(),fRootVolumes.end(),lv);
213  if (pos == fRootVolumes.end())
214  {
215    // Insert the root volume in the list and set it as root region
216    //
217    fRootVolumes.push_back(lv);
218    lv->SetRegionRootFlag(true);
219  }
220
221  // Scan recursively the tree of daugther volumes and set regions
222  //
223  ScanVolumeTree(lv, true);
224
225  // Set region as modified
226  //
227  fRegionMod = true;
228}
229
230// *******************************************************************
231// RemoveRootLogicalVolume:
232//  - Removes a root logical volume and resets its daughters flags as
233//    regions. It also recomputes the materials list for the region.
234// *******************************************************************
235//
236void G4Region::RemoveRootLogicalVolume(G4LogicalVolume* lv, G4bool scan)
237{
238  // Find and remove logical volume from the list
239  //
240  G4RootLVList::iterator pos;
241  pos = std::find(fRootVolumes.begin(),fRootVolumes.end(),lv);
242  if (pos != fRootVolumes.end())
243  {
244    if (fRootVolumes.size() != 1)  // Avoid resetting flag for world since
245    {                              // volume may be already deleted !
246      lv->SetRegionRootFlag(false);
247    }
248    fRootVolumes.erase(pos);
249  }
250
251  if (scan)  // Update the materials list
252  {
253    UpdateMaterialList();
254  }
255
256  // Set region as modified
257  //
258  fRegionMod = true;
259}
260
261// *******************************************************************
262// ClearMaterialList:
263//  - Clears the material list.
264// *******************************************************************
265//
266void G4Region::ClearMaterialList()
267{
268  fMaterials.clear();
269}
270
271// *******************************************************************
272// UpdateMaterialList:
273//  - computes material list looping through
274//    each root logical volume in the region.
275// *******************************************************************
276//
277void G4Region::UpdateMaterialList()
278{
279  // Reset the materials list
280  //
281  ClearMaterialList();
282
283  // Loop over the root logical volumes and rebuild the list
284  // of materials from scratch
285  //
286  G4RootLVList::iterator pLV;
287  for (pLV=fRootVolumes.begin(); pLV!=fRootVolumes.end(); pLV++)
288  {
289    ScanVolumeTree(*pLV, true);
290  }
291}
292
293// *******************************************************************
294// SetWorld:
295//  - Set the world physical volume if this region belongs to this
296//    world. If the given pointer is null, reset the pointer.
297// *******************************************************************
298//
299void G4Region::SetWorld(G4VPhysicalVolume* wp)
300{
301  if(!wp)
302  { fWorldPhys = 0; }
303  else
304  { if(BelongsTo(wp)) fWorldPhys = wp; }
305
306  return;
307}
308
309// *******************************************************************
310// BelongsTo:
311//  - Returns whether this region belongs to the given physical volume
312//    (recursively scanned to the bottom of the hierarchy)
313// *******************************************************************
314//
315G4bool G4Region::BelongsTo(G4VPhysicalVolume* thePhys) const
316{
317  G4LogicalVolume* currLog = thePhys->GetLogicalVolume();
318  if (currLog->GetRegion()==this) {return true;}
319
320  G4int nDaughters = currLog->GetNoDaughters();
321  while (nDaughters--)
322  {
323    if (BelongsTo(currLog->GetDaughter(nDaughters))) {return true;}
324  }
325
326  return false;
327}
328
329// *******************************************************************
330// ClearFastSimulationManager:
331//  - Set G4FastSimulationManager pointer to the one for the parent region
332//    if it exists. Otherwise set to null.
333// *******************************************************************
334//
335void G4Region::ClearFastSimulationManager()
336{
337  G4bool isUnique;
338  G4Region* parent = GetParentRegion(isUnique);
339  if(parent)
340  {
341    if (isUnique)
342    {
343      fFastSimulationManager = parent->GetFastSimulationManager();
344    }
345    else
346    {
347      G4cout << "WARNING - G4Region::GetParentRegion()" << G4endl
348             << "          Region <" << fName << "> belongs to more than"
349             << " one parent region !" << G4endl;
350      G4String message =
351           "A region (" + fName + ") cannot belong to more than one \n"
352         + "direct parent region, to have fast-simulation assigned.";
353      G4Exception("G4Region::ClearFastSimulationManager()",
354                  "InvalidSetup", JustWarning, message);
355      fFastSimulationManager = 0;
356    }
357  }
358  else
359  {
360    fFastSimulationManager = 0;
361  }
362}
363
364// *******************************************************************
365// GetParentRegion:
366//  - Returns a region that contains this region.
367//    Otherwise null is returned.
368// *******************************************************************
369//
370G4Region* G4Region::GetParentRegion(G4bool& unique) const
371{
372  G4Region* parent = 0; unique = true;
373  G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
374  G4LogicalVolumeStore::iterator lvItr;
375
376  // Loop over all logical volumes in the store
377  //
378  for(lvItr=lvStore->begin(); lvItr!=lvStore->end(); lvItr++)
379  {
380    G4int nD = (*lvItr)->GetNoDaughters();
381    G4Region* aR = (*lvItr)->GetRegion();
382
383    // Loop over all daughters of each logical volume
384    //
385    for(G4int iD=0; iD<nD; iD++)
386    {
387      if((*lvItr)->GetDaughter(iD)->GetLogicalVolume()->GetRegion()==this)
388      { 
389        if(parent)
390        {
391          if(parent!=aR) { unique = false; }
392        }
393        else  // Cache LV parent region which includes a daughter volume
394              // with the same associated region as the current one
395        {
396          parent = aR;
397        }
398      }
399    }
400  }
401  return parent;
402}
Note: See TracBrowser for help on using the repository browser.