G4Region.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // 
00030 // class G4Region Implementation
00031 //
00032 // --------------------------------------------------------------------
00033 
00034 #include "G4Region.hh"
00035 #include "G4RegionStore.hh"
00036 #include "G4LogicalVolume.hh"
00037 #include "G4VPhysicalVolume.hh"
00038 #include "G4LogicalVolumeStore.hh"
00039 #include "G4VNestedParameterisation.hh"
00040 #include "G4VUserRegionInformation.hh"
00041 #include "G4Material.hh"
00042 
00043 // *******************************************************************
00044 // Constructor:
00045 //  - Adds self to region Store
00046 // *******************************************************************
00047 //
00048 G4Region::G4Region(const G4String& pName)
00049   : fName(pName), fRegionMod(true), fCut(0), fUserInfo(0), fUserLimits(0),
00050     fFieldManager(0), fFastSimulationManager(0), fWorldPhys(0),
00051     fRegionalSteppingAction(0),
00052     fInMassGeometry(false), fInParallelGeometry(false)
00053 {
00054   G4RegionStore* rStore = G4RegionStore::GetInstance();
00055   if (rStore->GetRegion(pName,false))
00056   {
00057     std::ostringstream message;
00058     message << "The region has NOT been registered !" << G4endl
00059             << "          Region " << pName << " already existing in store !"
00060             << G4endl;
00061     G4Exception("G4Region::G4Region()", "GeomMgt1001",
00062                 JustWarning, message);
00063   }
00064   else
00065   {
00066     rStore->Register(this);
00067   }
00068 }
00069 
00070 // ********************************************************************
00071 // Fake default constructor - sets only member data and allocates memory
00072 //                            for usage restricted to object persistency.
00073 // ********************************************************************
00074 //
00075 G4Region::G4Region( __void__& )
00076   : fName(""), fRegionMod(true), fCut(0), fUserInfo(0), fUserLimits(0),
00077     fFieldManager(0), fFastSimulationManager(0), fWorldPhys(0),
00078     fRegionalSteppingAction(0),
00079     fInMassGeometry(false), fInParallelGeometry(false)
00080 {
00081   // Register to store
00082   //
00083   G4RegionStore::GetInstance()->Register(this);
00084 }
00085 
00086 // *******************************************************************
00087 // Destructor:
00088 //  - Removes self from region Store
00089 // *******************************************************************
00090 //
00091 G4Region::~G4Region()
00092 {
00093   G4RegionStore::GetInstance()->DeRegister(this);
00094   if(fUserInfo) delete fUserInfo;
00095 }
00096 
00097 // *******************************************************************
00098 // ScanVolumeTree:
00099 //  - Scans recursively the 'lv' logical volume tree, retrieves
00100 //    and places all materials in the list.
00101 //  - The boolean flag 'region' identifies if the volume tree must
00102 //    have region reset (false) or if the current region must be
00103 //    associated to the logical volume 'lv' and its tree (true).
00104 // *******************************************************************
00105 //
00106 void G4Region::ScanVolumeTree(G4LogicalVolume* lv, G4bool region)
00107 {
00108   // If logical volume is going to become a region, add 
00109   // its material to the list if not already present
00110   //
00111   G4Region* currentRegion = 0;
00112   size_t noDaughters = lv->GetNoDaughters();
00113   G4Material* volMat = lv->GetMaterial();
00114   if(!volMat && fInMassGeometry)
00115   {
00116     std::ostringstream message;
00117     message << "Logical volume <" << lv->GetName() << ">" << G4endl
00118             << "does not have a valid material pointer." << G4endl
00119             << "A logical volume belonging to the (tracking) world volume "
00120             << "must have a valid material.";
00121     G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002",
00122                 FatalException, message, "Check your geometry construction.");
00123   }
00124   if (region)
00125   {
00126     currentRegion = this;
00127     if (volMat)
00128     { 
00129       AddMaterial(volMat); 
00130       G4Material* baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial());
00131       if (baseMat) { AddMaterial(baseMat); }
00132     }
00133   }
00134 
00135   // Set the LV region to be either the current region or NULL,
00136   // according to the boolean selector
00137   //
00138   lv->SetRegion(currentRegion);
00139 
00140   // Stop recursion here if no further daughters are involved
00141   //
00142   if(noDaughters==0) return;
00143 
00144   G4VPhysicalVolume* daughterPVol = lv->GetDaughter(0);
00145   if (daughterPVol->IsParameterised())
00146   {
00147     // Adopt special treatment in case of parameterised volumes,
00148     // where parameterisation involves a new material scan
00149     //
00150     G4VPVParameterisation* pParam = daughterPVol->GetParameterisation();
00151 
00152     if (pParam->GetMaterialScanner())
00153     {
00154       size_t matNo = pParam->GetMaterialScanner()->GetNumberOfMaterials();
00155       for (register size_t mat=0; mat<matNo; mat++)
00156       {
00157         volMat = pParam->GetMaterialScanner()->GetMaterial(mat);
00158         if(!volMat && fInMassGeometry)
00159         {
00160           std::ostringstream message;
00161           message << "The parameterisation for the physical volume <"
00162                   << daughterPVol->GetName() << ">" << G4endl
00163                   << "does not return a valid material pointer." << G4endl
00164                   << "A volume belonging to the (tracking) world volume must "
00165                   << "have a valid material.";
00166           G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002",
00167                       FatalException, message, "Check your parameterisation.");
00168         }
00169         if (volMat)
00170         { 
00171           AddMaterial(volMat); 
00172           G4Material* baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial());
00173           if (baseMat) { AddMaterial(baseMat); }
00174         }
00175       }
00176     }
00177     else
00178     {
00179       size_t repNo = daughterPVol->GetMultiplicity();
00180       for (register size_t rep=0; rep<repNo; rep++)
00181       {
00182         volMat = pParam->ComputeMaterial(rep, daughterPVol);
00183         if(!volMat && fInMassGeometry)
00184         {
00185           std::ostringstream message;
00186           message << "The parameterisation for the physical volume <"
00187                   << daughterPVol->GetName() << ">" << G4endl
00188                   << "does not return a valid material pointer." << G4endl
00189                   << "A volume belonging to the (tracking) world volume must "
00190                   << "have a valid material.";
00191           G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002",
00192                       FatalException, message, "Check your parameterisation.");
00193         }
00194         if(volMat)
00195         { 
00196           AddMaterial(volMat);
00197           G4Material* baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial());
00198           if (baseMat) { AddMaterial(baseMat); }
00199         }
00200       }
00201     }
00202     G4LogicalVolume* daughterLVol = daughterPVol->GetLogicalVolume();
00203     ScanVolumeTree(daughterLVol, region);
00204   }
00205   else
00206   {
00207     for (register size_t i=0; i<noDaughters; i++)
00208     {
00209       G4LogicalVolume* daughterLVol = lv->GetDaughter(i)->GetLogicalVolume();
00210       if (!daughterLVol->IsRootRegion())
00211       {
00212         // Set daughter's LV to be a region and store materials in
00213         // the materials list, if the LV is not already a root region
00214         //
00215         ScanVolumeTree(daughterLVol, region);
00216       }
00217     }
00218   }
00219 }
00220 
00221 // *******************************************************************
00222 // AddRootLogicalVolume:
00223 //  - Adds a root logical volume and sets its daughters flags as
00224 //    regions. It also recomputes the materials list for the region.
00225 // *******************************************************************
00226 //
00227 void G4Region::AddRootLogicalVolume(G4LogicalVolume* lv)
00228 {
00229   // Check the logical volume is not already in the list
00230   //
00231   G4RootLVList::iterator pos;
00232   pos = std::find(fRootVolumes.begin(),fRootVolumes.end(),lv);
00233   if (pos == fRootVolumes.end())
00234   {
00235     // Insert the root volume in the list and set it as root region
00236     //
00237     fRootVolumes.push_back(lv);
00238     lv->SetRegionRootFlag(true);
00239   }
00240 
00241   // Scan recursively the tree of daugther volumes and set regions
00242   //
00243   ScanVolumeTree(lv, true);
00244 
00245   // Set region as modified
00246   //
00247   fRegionMod = true;
00248 }
00249 
00250 // *******************************************************************
00251 // RemoveRootLogicalVolume:
00252 //  - Removes a root logical volume and resets its daughters flags as
00253 //    regions. It also recomputes the materials list for the region.
00254 // *******************************************************************
00255 //
00256 void G4Region::RemoveRootLogicalVolume(G4LogicalVolume* lv, G4bool scan)
00257 {
00258   // Find and remove logical volume from the list
00259   //
00260   G4RootLVList::iterator pos;
00261   pos = std::find(fRootVolumes.begin(),fRootVolumes.end(),lv);
00262   if (pos != fRootVolumes.end())
00263   {
00264     if (fRootVolumes.size() != 1)  // Avoid resetting flag for world since
00265     {                              // volume may be already deleted !
00266       lv->SetRegionRootFlag(false);
00267     }
00268     fRootVolumes.erase(pos);
00269   }
00270 
00271   if (scan)  // Update the materials list
00272   {
00273     UpdateMaterialList();
00274   }
00275 
00276   // Set region as modified
00277   //
00278   fRegionMod = true;
00279 }
00280 
00281 // *******************************************************************
00282 // ClearMaterialList:
00283 //  - Clears the material list.
00284 // *******************************************************************
00285 //
00286 void G4Region::ClearMaterialList()
00287 {
00288   fMaterials.clear();
00289 }
00290 
00291 // *******************************************************************
00292 // UpdateMaterialList:
00293 //  - computes material list looping through
00294 //    each root logical volume in the region.
00295 // *******************************************************************
00296 //
00297 void G4Region::UpdateMaterialList()
00298 {
00299   // Reset the materials list
00300   //
00301   ClearMaterialList();
00302 
00303   // Loop over the root logical volumes and rebuild the list
00304   // of materials from scratch
00305   //
00306   G4RootLVList::iterator pLV;
00307   for (pLV=fRootVolumes.begin(); pLV!=fRootVolumes.end(); pLV++)
00308   {
00309     ScanVolumeTree(*pLV, true);
00310   }
00311 }
00312 
00313 // *******************************************************************
00314 // SetWorld:
00315 //  - Set the world physical volume if this region belongs to this
00316 //    world. If the given pointer is null, reset the pointer.
00317 // *******************************************************************
00318 //
00319 void G4Region::SetWorld(G4VPhysicalVolume* wp)
00320 {
00321   if(!wp)
00322   { fWorldPhys = 0; }
00323   else
00324   { if(BelongsTo(wp)) fWorldPhys = wp; }
00325 
00326   return;
00327 }
00328 
00329 // *******************************************************************
00330 // BelongsTo:
00331 //  - Returns whether this region belongs to the given physical volume
00332 //    (recursively scanned to the bottom of the hierarchy)
00333 // *******************************************************************
00334 // 
00335 G4bool G4Region::BelongsTo(G4VPhysicalVolume* thePhys) const
00336 {
00337   G4LogicalVolume* currLog = thePhys->GetLogicalVolume();
00338   if (currLog->GetRegion()==this) {return true;}
00339 
00340   G4int nDaughters = currLog->GetNoDaughters();
00341   while (nDaughters--)
00342   {
00343     if (BelongsTo(currLog->GetDaughter(nDaughters))) {return true;}
00344   }
00345 
00346   return false;
00347 }
00348 
00349 // *******************************************************************
00350 // ClearFastSimulationManager:
00351 //  - Set G4FastSimulationManager pointer to the one for the parent region
00352 //    if it exists. Otherwise set to null.
00353 // *******************************************************************
00354 //
00355 void G4Region::ClearFastSimulationManager()
00356 {
00357   G4bool isUnique;
00358   G4Region* parent = GetParentRegion(isUnique);
00359   if(parent)
00360   {
00361     if (isUnique)
00362     {
00363       fFastSimulationManager = parent->GetFastSimulationManager();
00364     }
00365     else
00366     {
00367       std::ostringstream message;
00368       message << "Region <" << fName << "> belongs to more than"
00369               << " one parent region !" << G4endl
00370               << "A region cannot belong to more than one direct parent region,"
00371               << G4endl
00372               << "to have fast-simulation assigned.";
00373       G4Exception("G4Region::ClearFastSimulationManager()",
00374                   "GeomMgt1002", JustWarning, message);
00375       fFastSimulationManager = 0;
00376     }
00377   }
00378   else
00379   {
00380     fFastSimulationManager = 0;
00381   }
00382 }
00383 
00384 // *******************************************************************
00385 // GetParentRegion:
00386 //  - Returns a region that contains this region.
00387 //    Otherwise null is returned.
00388 // *******************************************************************
00389 // 
00390 G4Region* G4Region::GetParentRegion(G4bool& unique) const
00391 {
00392   G4Region* parent = 0; unique = true;
00393   G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
00394   G4LogicalVolumeStore::iterator lvItr;
00395 
00396   // Loop over all logical volumes in the store
00397   //
00398   for(lvItr=lvStore->begin(); lvItr!=lvStore->end(); lvItr++)
00399   {
00400     G4int nD = (*lvItr)->GetNoDaughters();
00401     G4Region* aR = (*lvItr)->GetRegion();
00402 
00403     // Loop over all daughters of each logical volume
00404     //
00405     for(G4int iD=0; iD<nD; iD++)
00406     {
00407       if((*lvItr)->GetDaughter(iD)->GetLogicalVolume()->GetRegion()==this)
00408       { 
00409         if(parent)
00410         {
00411           if(parent!=aR) { unique = false; }
00412         }
00413         else  // Cache LV parent region which includes a daughter volume
00414               // with the same associated region as the current one
00415         {
00416           parent = aR;
00417         }
00418       }
00419     }
00420   }
00421   return parent;
00422 }

Generated on Mon May 27 17:49:43 2013 for Geant4 by  doxygen 1.4.7