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

Last change on this file since 846 was 831, checked in by garnier, 16 years ago

import all except CVS

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.23 2007/04/26 21:20:53 asaim Exp $
28// GEANT4 tag $Name:  $
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->IsNested())
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)
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  // Scan recursively the tree of daugther volumes and reset regions
250  //
251  //ScanVolumeTree(lv, false);
252
253  // Update the materials list
254  //
255  //UpdateMaterialList();
256
257  // Set region as modified
258  //
259  fRegionMod = true;
260}
261
262// *******************************************************************
263// ClearMaterialList:
264//  - Clears the material list.
265// *******************************************************************
266//
267void G4Region::ClearMaterialList()
268{
269  fMaterials.clear();
270}
271
272// *******************************************************************
273// UpdateMaterialList:
274//  - computes material list looping through
275//    each root logical volume in the region.
276// *******************************************************************
277//
278void G4Region::UpdateMaterialList()
279{
280  // Reset the materials list
281  //
282  ClearMaterialList();
283
284  // Loop over the root logical volumes and rebuild the list
285  // of materials from scratch
286  //
287  G4RootLVList::iterator pLV;
288  for (pLV=fRootVolumes.begin(); pLV!=fRootVolumes.end(); pLV++)
289  {
290    ScanVolumeTree(*pLV, true);
291  }
292}
293
294// *******************************************************************
295// SetWorld:
296//  - Set the world physical volume if this region belongs to this
297//    world. If the given pointer is null, reset the pointer.
298// *******************************************************************
299//
300void G4Region::SetWorld(G4VPhysicalVolume* wp)
301{
302  if(!wp)
303  { fWorldPhys = 0; }
304  else
305  { if(BelongsTo(wp)) fWorldPhys = wp; }
306
307  return;
308}
309
310// *******************************************************************
311// BelongsTo:
312//  - Returns whether this region belongs to the given physical volume
313//    (recursively scanned to the bottom of the hierarchy)
314// *******************************************************************
315//
316G4bool G4Region::BelongsTo(G4VPhysicalVolume* thePhys) const
317{
318  G4LogicalVolume* currLog = thePhys->GetLogicalVolume();
319  if (currLog->GetRegion()==this) {return true;}
320
321  G4int nDaughters = currLog->GetNoDaughters();
322  while (nDaughters--)
323  {
324    if (BelongsTo(currLog->GetDaughter(nDaughters))) {return true;}
325  }
326
327  return false;
328}
329
330// *******************************************************************
331// ClearFastSimulationManager:
332//  - Set G4FastSimulationManager pointer to the one for the parent region
333//    if it exists. Otherwise set to null.
334// *******************************************************************
335//
336void G4Region::ClearFastSimulationManager()
337{
338  G4bool isUnique;
339  G4Region* parent = GetParentRegion(isUnique);
340  if(parent)
341  {
342    if (isUnique)
343    {
344      fFastSimulationManager = parent->GetFastSimulationManager();
345    }
346    else
347    {
348      G4cout << "WARNING - G4Region::GetParentRegion()" << G4endl
349             << "          Region <" << fName << "> belongs to more than"
350             << " one parent region !" << G4endl;
351      G4String message =
352           "A region (" + fName + ") cannot belong to more than one \n"
353         + "direct parent region, to have fast-simulation assigned.";
354      G4Exception("G4Region::ClearFastSimulationManager()",
355                  "InvalidSetup", JustWarning, message);
356      fFastSimulationManager = 0;
357    }
358  }
359  else
360  {
361    fFastSimulationManager = 0;
362  }
363}
364
365// *******************************************************************
366// GetParentRegion:
367//  - Returns a region that contains this region.
368//    Otherwise null is returned.
369// *******************************************************************
370//
371G4Region* G4Region::GetParentRegion(G4bool& unique) const
372{
373  G4Region* parent = 0; unique = true;
374  G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
375  G4LogicalVolumeStore::iterator lvItr;
376
377  // Loop over all logical volumes in the store
378  //
379  for(lvItr=lvStore->begin(); lvItr!=lvStore->end(); lvItr++)
380  {
381    G4int nD = (*lvItr)->GetNoDaughters();
382    G4Region* aR = (*lvItr)->GetRegion();
383
384    // Loop over all daughters of each logical volume
385    //
386    for(G4int iD=0; iD<nD; iD++)
387    {
388      if((*lvItr)->GetDaughter(iD)->GetLogicalVolume()->GetRegion()==this)
389      { 
390        if(parent)
391        {
392          if(parent!=aR) { unique = false; }
393        }
394        else  // Cache LV parent region which includes a daughter volume
395              // with the same associated region as the current one
396        {
397          parent = aR;
398        }
399      }
400    }
401  }
402  return parent;
403}
Note: See TracBrowser for help on using the repository browser.