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

Last change on this file since 1202 was 1058, checked in by garnier, 15 years ago

file release beta

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