G4GeometryManager.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 // class G4GeometryManager
00030 //
00031 // Implementation
00032 //
00033 // Author:
00034 // 26.07.95 P.Kent Initial version, including optimisation Build
00035 // --------------------------------------------------------------------
00036 
00037 #include <iomanip>
00038 #include "G4Timer.hh"
00039 #include "G4GeometryManager.hh"
00040 #include "G4SystemOfUnits.hh"
00041 
00042 #ifdef  G4GEOMETRY_VOXELDEBUG
00043 #include "G4ios.hh"
00044 #endif
00045 
00046 // Needed for building optimisations
00047 //
00048 #include "G4LogicalVolumeStore.hh"
00049 #include "G4VPhysicalVolume.hh"
00050 #include "G4SmartVoxelHeader.hh"
00051 #include "voxeldefs.hh"
00052 
00053 // Needed for setting the extent for tolerance value
00054 //
00055 #include "G4GeometryTolerance.hh"
00056 #include "G4SolidStore.hh"
00057 #include "G4VSolid.hh"
00058 
00059 // ***************************************************************************
00060 // Static class variable: ptr to single instance of class
00061 // ***************************************************************************
00062 //
00063 G4GeometryManager* G4GeometryManager::fgInstance = 0;
00064 
00065 // ***************************************************************************
00066 // Constructor. Set the geometry to be open
00067 // ***************************************************************************
00068 //
00069 G4GeometryManager::G4GeometryManager() 
00070   : fIsClosed(false)
00071 {
00072 }
00073 
00074 // ***************************************************************************
00075 // Closes geometry - performs sanity checks and optionally builds optimisation
00076 // for placed volumes (always built for replicas & parameterised).
00077 // NOTE: Currently no sanity checks are performed.
00078 // Applies to just a specific subtree if a physical volume is specified.
00079 // ***************************************************************************
00080 //
00081 G4bool G4GeometryManager::CloseGeometry(G4bool pOptimise, G4bool verbose,
00082                                         G4VPhysicalVolume* pVolume)
00083 {
00084    if (!fIsClosed)
00085   {
00086     if (pVolume)
00087     {
00088       BuildOptimisations(pOptimise, pVolume);
00089     }
00090     else
00091     {
00092       BuildOptimisations(pOptimise, verbose);
00093     }
00094     fIsClosed=true;
00095   }
00096   return true;
00097 }
00098 
00099 // ***************************************************************************
00100 // Opens the geometry and removes optimisations (optionally, related to just
00101 // the specified logical-volume).
00102 // Applies to just a specific subtree if a physical volume is specified.
00103 // ***************************************************************************
00104 //
00105 void G4GeometryManager::OpenGeometry(G4VPhysicalVolume* pVolume)
00106 {
00107   if (fIsClosed)
00108   {
00109     if (pVolume)
00110     {
00111       DeleteOptimisations(pVolume);
00112     }
00113     else
00114     {
00115       DeleteOptimisations();
00116     }
00117     fIsClosed=false;
00118   }
00119 }
00120 
00121 // ***************************************************************************
00122 // Returns status of geometry
00123 // ***************************************************************************
00124 //
00125 G4bool G4GeometryManager::IsGeometryClosed()
00126 {
00127   return fIsClosed;
00128 }
00129 
00130 // ***************************************************************************
00131 // Returns the instance of the singleton.
00132 // Creates it in case it's called for the first time.
00133 // ***************************************************************************
00134 //
00135 G4GeometryManager* G4GeometryManager::GetInstance()
00136 {
00137   static G4GeometryManager worldManager;
00138   if (!fgInstance)
00139   {
00140     fgInstance = &worldManager;
00141   }
00142   return fgInstance;    
00143 }
00144 
00145 // ***************************************************************************
00146 // Creates optimisation info. Builds all voxels if allOpts=true
00147 // otherwise it builds voxels only for replicated volumes.
00148 // ***************************************************************************
00149 //
00150 void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose)
00151 {
00152    G4Timer timer;
00153    G4Timer allTimer;
00154    std::vector<G4SmartVoxelStat> stats;
00155    if (verbose)  { allTimer.Start(); }
00156 
00157    G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
00158    G4LogicalVolume* volume;
00159    G4SmartVoxelHeader* head;
00160  
00161    for (size_t n=0; n<Store->size(); n++)
00162    {
00163      if (verbose) timer.Start();
00164      volume=(*Store)[n];
00165      // For safety, check if there are any existing voxels and
00166      // delete before replacement
00167      //
00168      head = volume->GetVoxelHeader();
00169      delete head;
00170      volume->SetVoxelHeader(0);
00171      if (    ( (volume->IsToOptimise())
00172             && (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
00173           || ( (volume->GetNoDaughters()==1)
00174             && (volume->GetDaughter(0)->IsReplicated()==true)
00175             && (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) ) 
00176      {
00177 #ifdef G4GEOMETRY_VOXELDEBUG
00178        G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
00179               << "     Examining logical volume name = "
00180               << volume->GetName() << G4endl;
00181 #endif
00182        head = new G4SmartVoxelHeader(volume);
00183        if (head)
00184        {
00185          volume->SetVoxelHeader(head);
00186        }
00187        else
00188        {
00189          std::ostringstream message;
00190          message << "VoxelHeader allocation error." << G4endl
00191                  << "Allocation of new VoxelHeader" << G4endl
00192                  << "        for volume " << volume->GetName() << " failed.";
00193          G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
00194                      FatalException, message);
00195        }
00196        if (verbose)
00197        {
00198          timer.Stop();
00199          stats.push_back( G4SmartVoxelStat( volume, head,
00200                                             timer.GetSystemElapsed(),
00201                                             timer.GetUserElapsed() ) );
00202        }
00203      }
00204      else
00205      {
00206        // Don't create voxels for this node
00207 #ifdef G4GEOMETRY_VOXELDEBUG
00208        G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
00209               << "     Skipping logical volume name = " << volume->GetName()
00210               << G4endl;
00211 #endif
00212      }
00213   }
00214   if (verbose)
00215   {
00216      allTimer.Stop();
00217      ReportVoxelStats( stats, allTimer.GetSystemElapsed()
00218                             + allTimer.GetUserElapsed() );
00219   }
00220 }
00221 
00222 // ***************************************************************************
00223 // Creates optimisation info for the specified volumes subtree.
00224 // ***************************************************************************
00225 //
00226 void G4GeometryManager::BuildOptimisations(G4bool allOpts,
00227                                            G4VPhysicalVolume* pVolume)
00228 {
00229    if (!pVolume) { return; }
00230 
00231    // Retrieve the mother logical volume, if not NULL,
00232    // otherwise apply global optimisation for the world volume
00233    //
00234    G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
00235    if (!tVolume) { return BuildOptimisations(allOpts, false); }
00236 
00237    G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
00238    delete head;
00239    tVolume->SetVoxelHeader(0);
00240    if (    ( (tVolume->IsToOptimise())
00241           && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
00242         || ( (tVolume->GetNoDaughters()==1)
00243           && (tVolume->GetDaughter(0)->IsReplicated()==true) ) ) 
00244    {
00245      head = new G4SmartVoxelHeader(tVolume);
00246      if (head)
00247      {
00248        tVolume->SetVoxelHeader(head);
00249      }
00250      else
00251      {
00252        std::ostringstream message;
00253        message << "VoxelHeader allocation error." << G4endl
00254                << "Allocation of new VoxelHeader" << G4endl
00255                << "        for volume " << tVolume->GetName() << " failed.";
00256        G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
00257                    FatalException, message);
00258      }
00259    }
00260    else
00261    {
00262      // Don't create voxels for this node
00263 #ifdef G4GEOMETRY_VOXELDEBUG
00264      G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
00265             << "     Skipping logical volume name = " << tVolume->GetName()
00266             << G4endl;
00267 #endif
00268    }
00269 
00270    // Scan recursively the associated logical volume tree
00271    //
00272   tVolume = pVolume->GetLogicalVolume();
00273   if (tVolume->GetNoDaughters())
00274   {
00275     BuildOptimisations(allOpts, tVolume->GetDaughter(0));
00276   }
00277 }
00278 
00279 // ***************************************************************************
00280 // Removes all optimisation info.
00281 // Loops over all logical volumes, deleting non-null voxels pointers,
00282 // ***************************************************************************
00283 //
00284 void G4GeometryManager::DeleteOptimisations()
00285 {
00286   G4LogicalVolume* tVolume = 0;
00287   G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
00288   for (size_t n=0; n<Store->size(); n++)
00289   {
00290     tVolume=(*Store)[n];
00291     delete tVolume->GetVoxelHeader();
00292     tVolume->SetVoxelHeader(0);
00293   }
00294 }
00295 
00296 // ***************************************************************************
00297 // Removes optimisation info for the specified subtree.
00298 // Scans recursively all daughter volumes, deleting non-null voxels pointers.
00299 // ***************************************************************************
00300 //
00301 void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume)
00302 {
00303   if (!pVolume) { return; }
00304 
00305   // Retrieve the mother logical volume, if not NULL,
00306   // otherwise global deletion to world volume.
00307   //
00308   G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
00309   if (!tVolume) { return DeleteOptimisations(); }
00310   delete tVolume->GetVoxelHeader();
00311   tVolume->SetVoxelHeader(0);
00312 
00313   // Scan recursively the associated logical volume tree
00314   //
00315   tVolume = pVolume->GetLogicalVolume();
00316   if (tVolume->GetNoDaughters())
00317   {
00318     DeleteOptimisations(tVolume->GetDaughter(0));
00319   }
00320 }
00321 
00322 // ***************************************************************************
00323 // Sets the maximum extent of the world volume. The operation is allowed only
00324 // if NO solids have been created already.
00325 // ***************************************************************************
00326 //
00327 void G4GeometryManager::SetWorldMaximumExtent(G4double extent)
00328 {
00329   if (G4SolidStore::GetInstance()->size())
00330   {
00331      // Sanity check to assure that extent is fixed BEFORE creating
00332      // any geometry object (solids in this case)
00333      //
00334      G4Exception("G4GeometryManager::SetMaximumExtent()",
00335                  "GeomMgt0003", FatalException,
00336                  "Extent can be set only BEFORE creating any geometry object!");
00337   }
00338   G4GeometryTolerance::GetInstance()->SetSurfaceTolerance(extent);
00339 }
00340 
00341 // ***************************************************************************
00342 // Reports statistics on voxel optimisation when closing geometry.
00343 // ***************************************************************************
00344 //
00345 void
00346 G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
00347                                      G4double totalCpuTime )
00348 {
00349   G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
00350          << G4endl << G4endl;
00351  
00352   //
00353   // Get total memory use
00354   //
00355   G4int i, nStat = stats.size();
00356   G4long totalMemory = 0;
00357  
00358   for( i=0;i<nStat;++i )  { totalMemory += stats[i].GetMemoryUse(); }
00359  
00360   G4cout << "    Total memory consumed for geometry optimisation:   "
00361          << totalMemory/1024 << " kByte" << G4endl;
00362   G4cout << "    Total CPU time elapsed for geometry optimisation: " 
00363          << std::setprecision(2) << totalCpuTime << " seconds"
00364          << std::setprecision(6) << G4endl;
00365  
00366   //
00367   // First list: sort by total CPU time
00368   //
00369   std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByCpu() );
00370          
00371   G4int nPrint = nStat > 10 ? 10 : nStat;
00372 
00373   if (nPrint)
00374   {
00375     G4cout << "\n    Voxelisation: top CPU users:" << G4endl;
00376     G4cout << "    Percent   Total CPU    System CPU       Memory  Volume\n"
00377            << "    -------   ----------   ----------     --------  ----------"
00378            << G4endl;
00379     //         12345678901.234567890123.234567890123.234567890123k .
00380   }
00381 
00382   for(i=0;i<nPrint;++i)
00383   {
00384     G4double total = stats[i].GetTotalTime();
00385     G4double system = stats[i].GetSysTime();
00386     G4double perc = 0.0;
00387 
00388     if (system < 0) { system = 0.0; }
00389     if ((total < 0) || (totalCpuTime < perMillion))
00390       { total = 0; }
00391     else
00392       { perc = total*100/totalCpuTime; }
00393 
00394     G4cout << std::setprecision(2) 
00395            << std::setiosflags(std::ios::fixed|std::ios::right)
00396            << std::setw(11) << perc
00397            << std::setw(13) << total
00398            << std::setw(13) << system
00399            << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
00400            << "k " << std::setiosflags(std::ios::left)
00401            << stats[i].GetVolume()->GetName()
00402            << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
00403            << std::setprecision(6)
00404            << G4endl;
00405   }
00406  
00407   //
00408   // Second list: sort by memory use
00409   //
00410   std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByMemory() );
00411  
00412   if (nPrint)
00413   {
00414     G4cout << "\n    Voxelisation: top memory users:" << G4endl;
00415     G4cout << "    Percent     Memory      Heads    Nodes   Pointers    Total CPU    Volume\n"
00416            << "    -------   --------     ------   ------   --------   ----------    ----------"
00417            << G4endl;
00418     //         12345678901.2345678901k .23456789.23456789.2345678901.234567890123.   .
00419   }
00420 
00421   for(i=0;i<nPrint;++i)
00422   {
00423     G4long memory = stats[i].GetMemoryUse();
00424     G4double totTime = stats[i].GetTotalTime();
00425     if (totTime < 0) { totTime = 0.0; }
00426 
00427     G4cout << std::setprecision(2) 
00428            << std::setiosflags(std::ios::fixed|std::ios::right)
00429            << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
00430            << std::setw(11) << memory/1024 << "k "
00431            << std::setw( 9) << stats[i].GetNumberHeads()
00432            << std::setw( 9) << stats[i].GetNumberNodes()
00433            << std::setw(11) << stats[i].GetNumberPointers()
00434            << std::setw(13) << totTime << "    "
00435            << std::setiosflags(std::ios::left)
00436            << stats[i].GetVolume()->GetName()
00437            << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
00438            << std::setprecision(6)
00439            << G4endl;
00440   }
00441 }

Generated on Mon May 27 17:48:22 2013 for Geant4 by  doxygen 1.4.7