Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/management/src/G4GeometryManager.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /geometry/management/src/G4GeometryManager.cc (Version 11.3.0) and /geometry/management/src/G4GeometryManager.cc (Version 10.4.p3)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 // Class G4GeometryManager implementation      << 
 27 //                                                 26 //
 28 // 26.07.95, P.Kent - Initial version, includi <<  27 // $Id$
 29 // 12.06.24, J.Apostolakis - Added parallel op <<  28 //
                                                   >>  29 // class G4GeometryManager
                                                   >>  30 //
                                                   >>  31 // Implementation
                                                   >>  32 //
                                                   >>  33 // Author:
                                                   >>  34 // 26.07.95 P.Kent Initial version, including optimisation Build
 30 // -------------------------------------------     35 // --------------------------------------------------------------------
 31                                                    36 
 32 #include <iomanip>                                 37 #include <iomanip>
 33                                                << 
 34 #include "G4ios.hh"                            << 
 35 #include "G4Timer.hh"                              38 #include "G4Timer.hh"
 36 #include "G4GeometryManager.hh"                    39 #include "G4GeometryManager.hh"
 37 #include "G4SystemOfUnits.hh"                      40 #include "G4SystemOfUnits.hh"
 38 #include "G4Threading.hh"                      <<  41 
                                                   >>  42 #ifdef  G4GEOMETRY_VOXELDEBUG
                                                   >>  43 #include "G4ios.hh"
                                                   >>  44 #endif
 39                                                    45 
 40 // Needed for building optimisations               46 // Needed for building optimisations
 41 //                                                 47 //
 42 #include "G4LogicalVolumeStore.hh"                 48 #include "G4LogicalVolumeStore.hh"
 43 #include "G4VPhysicalVolume.hh"                    49 #include "G4VPhysicalVolume.hh"
 44 #include "G4SmartVoxelHeader.hh"                   50 #include "G4SmartVoxelHeader.hh"
 45 #include "voxeldefs.hh"                            51 #include "voxeldefs.hh"
 46                                                    52 
 47 // Needed for setting the extent for tolerance     53 // Needed for setting the extent for tolerance value
 48 //                                                 54 //
 49 #include "G4GeometryTolerance.hh"                  55 #include "G4GeometryTolerance.hh"
 50 #include "G4SolidStore.hh"                         56 #include "G4SolidStore.hh"
 51 #include "G4VSolid.hh"                             57 #include "G4VSolid.hh"
 52                                                    58 
 53 // Needed for parallel optimisation            << 
 54 #include "G4AutoLock.hh"                       << 
 55                                                << 
 56 namespace  // Data structures / mutexes for pa << 
 57 {                                              << 
 58   // Mutex to obtain a volume to optimise      << 
 59   G4Mutex obtainVolumeMutex = G4MUTEX_INITIALI << 
 60                                                << 
 61   // Mutex to lock saving of voxel statistics  << 
 62   G4Mutex voxelStatsMutex = G4MUTEX_INITIALIZE << 
 63                                                << 
 64   // Mutex to provide Statistics Results       << 
 65   G4Mutex statResultsMutex = G4MUTEX_INITIALIZ << 
 66                                                << 
 67   // Mutex to start wall clock (global) timer  << 
 68   G4Mutex wallClockTimerMutex = G4MUTEX_INITIA << 
 69                                                << 
 70   // Mutex to write debug output               << 
 71   G4Mutex outputDbgMutex = G4MUTEX_INITIALIZER << 
 72 }                                              << 
 73                                                << 
 74 // *******************************************     59 // ***************************************************************************
 75 // Static class data                               60 // Static class data
 76 // *******************************************     61 // ***************************************************************************
 77 //                                                 62 //
 78 G4ThreadLocal G4GeometryManager* G4GeometryMan <<  63 G4ThreadLocal G4GeometryManager* G4GeometryManager::fgInstance = 0;
                                                   >>  64 G4ThreadLocal G4bool G4GeometryManager::fIsClosed = false;
 79                                                    65 
 80 // Static *global* class data                  <<  66 // ***************************************************************************
 81 G4bool G4GeometryManager::fParallelVoxelOptimi <<  67 // Constructor. Set the geometry to be open
 82   // Records User choice to use parallel voxel <<  68 // ***************************************************************************
 83                                                <<  69 //
 84 G4bool  G4GeometryManager::fOptimiseInParallel <<  70 G4GeometryManager::G4GeometryManager() 
 85   // Configured = requested && available (ie i <<  71 {
 86   // Value calculated during each effort to op <<  72 }
 87                                                << 
 88 std::vector<G4LogicalVolume*> G4GeometryManage << 
 89 std::vector<G4LogicalVolume*>::const_iterator  << 
 90                                                << 
 91 std::vector<G4SmartVoxelStat> G4GeometryManage << 
 92 // Container for statistics                    << 
 93                                                << 
 94 // Derived state                               << 
 95 G4bool G4GeometryManager::fVerboseParallel = f << 
 96 G4bool G4GeometryManager::fParallelVoxelOptimi << 
 97 G4bool G4GeometryManager::fParallelVoxelOptimi << 
 98 G4double G4GeometryManager::fSumVoxelTime = 0. << 
 99                                                << 
100 G4int G4GeometryManager::fNumberThreadsReporti << 
101 unsigned int G4GeometryManager::fTotalNumberVo << 
102                                                << 
103 // For Wall clock                              << 
104 G4Timer* G4GeometryManager::fWallClockTimer =  << 
105 G4bool G4GeometryManager::fWallClockStarted =  << 
106                                                    73 
107 // *******************************************     74 // ***************************************************************************
108 // Destructor                                      75 // Destructor
109 // *******************************************     76 // ***************************************************************************
110 //                                                 77 //
111 G4GeometryManager::~G4GeometryManager()            78 G4GeometryManager::~G4GeometryManager()
112 {                                                  79 {
113   fgInstance = nullptr;                        <<  80   fgInstance = 0;
114   fIsClosed = false;                               81   fIsClosed = false;
115                                                << 
116   if( fWallClockTimer && G4Threading::IsMaster << 
117   {                                            << 
118     delete fWallClockTimer;                    << 
119     fWallClockTimer= nullptr;                  << 
120   }                                            << 
121 }                                                  82 }
122                                                    83 
123 // *******************************************     84 // ***************************************************************************
124 // Closes geometry - performs sanity checks an     85 // Closes geometry - performs sanity checks and optionally builds optimisation
125 // for placed volumes (always built for replic     86 // for placed volumes (always built for replicas & parameterised).
126 // NOTE: Currently no sanity checks are perfor     87 // NOTE: Currently no sanity checks are performed.
127 // Applies to just a specific subtree if a phy     88 // Applies to just a specific subtree if a physical volume is specified.
128 // *******************************************     89 // ***************************************************************************
129 //                                                 90 //
130 G4bool G4GeometryManager::CloseGeometry(G4bool     91 G4bool G4GeometryManager::CloseGeometry(G4bool pOptimise, G4bool verbose,
131                                         G4VPhy     92                                         G4VPhysicalVolume* pVolume)
132 {                                                  93 {
133   if (!fIsClosed && G4Threading::IsMasterThrea <<  94   if (!fIsClosed)
134   {                                                95   {
135     if (pVolume != nullptr)                    <<  96     if (pVolume)
136     {                                              97     {
137       BuildOptimisations(pOptimise, pVolume);      98       BuildOptimisations(pOptimise, pVolume);
138     }                                              99     }
139     else                                          100     else
140     {                                             101     {
141       BuildOptimisations(pOptimise, verbose);     102       BuildOptimisations(pOptimise, verbose);
142     }                                             103     }
143     fIsClosed = true;                          << 104     fIsClosed=true;
144   }                                               105   }
145   return true;                                    106   return true;
146 }                                                 107 }
147                                                   108 
148 // *******************************************    109 // ***************************************************************************
149 // Opens the geometry and removes optimisation    110 // Opens the geometry and removes optimisations (optionally, related to just
150 // the specified logical-volume).                 111 // the specified logical-volume).
151 // Applies to just a specific subtree if a phy    112 // Applies to just a specific subtree if a physical volume is specified.
152 // *******************************************    113 // ***************************************************************************
153 //                                                114 //
154 void G4GeometryManager::OpenGeometry(G4VPhysic    115 void G4GeometryManager::OpenGeometry(G4VPhysicalVolume* pVolume)
155 {                                                 116 {
156   if (fIsClosed && G4Threading::IsMasterThread << 117   if (fIsClosed)
157   {                                               118   {
158     if (pVolume != nullptr)                    << 119     if (pVolume)
159     {                                             120     {
160       DeleteOptimisations(pVolume);               121       DeleteOptimisations(pVolume);
161     }                                             122     }
162     else                                          123     else
163     {                                             124     {
164       DeleteOptimisations();                      125       DeleteOptimisations();
165     }                                             126     }
166     fIsClosed = false;                         << 127     fIsClosed=false;
167   }                                               128   }
168 }                                                 129 }
169                                                   130 
170 // *******************************************    131 // ***************************************************************************
                                                   >> 132 // Returns status of geometry
                                                   >> 133 // ***************************************************************************
                                                   >> 134 //
                                                   >> 135 G4bool G4GeometryManager::IsGeometryClosed()
                                                   >> 136 {
                                                   >> 137   return fIsClosed;
                                                   >> 138 }
                                                   >> 139 
                                                   >> 140 // ***************************************************************************
171 // Returns the instance of the singleton.         141 // Returns the instance of the singleton.
172 // Creates it in case it's called for the firs    142 // Creates it in case it's called for the first time.
173 // *******************************************    143 // ***************************************************************************
174 //                                                144 //
175 G4GeometryManager* G4GeometryManager::GetInsta    145 G4GeometryManager* G4GeometryManager::GetInstance()
176 {                                                 146 {
177   if (fgInstance == nullptr)                   << 147   if (!fgInstance)
178   {                                               148   {
179     fgInstance = new G4GeometryManager;           149     fgInstance = new G4GeometryManager;
180                                                << 
181     if( (fWallClockTimer == nullptr) && G4Thre << 
182     {                                          << 
183       fWallClockTimer = new G4Timer;           << 
184     }                                          << 
185   }                                               150   }
186   return fgInstance;                              151   return fgInstance;
187 }                                                 152 }
188                                                   153 
189 // *******************************************    154 // ***************************************************************************
190 // Returns the instance of the singleton.         155 // Returns the instance of the singleton.
191 // *******************************************    156 // ***************************************************************************
192 //                                                157 //
193 G4GeometryManager* G4GeometryManager::GetInsta    158 G4GeometryManager* G4GeometryManager::GetInstanceIfExist()
194 {                                                 159 {
195   return fgInstance;                              160   return fgInstance;
196 }                                                 161 }
197                                                   162 
198 // *******************************************    163 // ***************************************************************************
199 // Simplest user method to request parallel op << 
200 // ******************************************* << 
201 //                                             << 
202 void G4GeometryManager::OptimiseInParallel( G4 << 
203 {                                              << 
204   RequestParallelOptimisation(val);            << 
205 }                                              << 
206                                                << 
207 // ******************************************* << 
208 // Report about Voxel(isation) of a logical vo << 
209 // ******************************************* << 
210 //                                             << 
211 void                                           << 
212 G4GeometryManager::ReportVoxelInfo(G4LogicalVo << 
213 {                                              << 
214   G4SmartVoxelHeader* head = logVolume->GetVox << 
215   if( head != nullptr )                        << 
216   {                                            << 
217     os << "** Created optimisations for logica << 
218        << std::setw(50) << logVolume->GetName( << 
219        << "- Result VoxelInfo - START: " << "  << 
220        << *head                                << 
221        << "- Result VoxelInfo -   END. " << G4 << 
222   }                                            << 
223   else                                         << 
224   {                                            << 
225     os << "** No optimisation for log-vol " << << 
226   }                                            << 
227   os << "*** Report Voxel Info: END " <<  G4en << 
228 }                                              << 
229                                                << 
230 // ******************************************* << 
231 // Creates optimisation info. Builds all voxel    164 // Creates optimisation info. Builds all voxels if allOpts=true
232 // otherwise it builds voxels only for replica    165 // otherwise it builds voxels only for replicated volumes.
233 // *******************************************    166 // ***************************************************************************
234 // Returns whether optimisation is finished    << 
235 //                                                167 //
236 G4bool G4GeometryManager::BuildOptimisations(G << 168 void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose)
237 {                                                 169 {
238   G4bool finishedOptimisation = false;         << 170    G4Timer timer;
239                                                << 171    G4Timer allTimer;
240   fOptimiseInParallelConfigured = fParallelVox << 172    std::vector<G4SmartVoxelStat> stats;
241                                && G4Threading: << 173    if (verbose)  { allTimer.Start(); }
242                                                << 174 
243   static unsigned int NumCallsBuildOptimisatio << 175    G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
244   if( fOptimiseInParallelConfigured && (NumCal << 176    G4LogicalVolume* volume;
245   {                                            << 177    G4SmartVoxelHeader* head;
246     PrepareParallelOptimisation(allOpts, verbo << 178  
247     ++NumCallsBuildOptimisations;              << 179    for (size_t n=0; n<Store->size(); n++)
248   }                                            << 180    {
249   else                                         << 181      if (verbose) timer.Start();
250   {                                            << 182      volume=(*Store)[n];
251     BuildOptimisationsSequential(allOpts, verb << 183      // For safety, check if there are any existing voxels and
252     finishedOptimisation= true;                << 184      // delete before replacement
253   }                                            << 185      //
254                                                << 186      head = volume->GetVoxelHeader();
255   return finishedOptimisation;                 << 187      delete head;
256 }                                              << 188      volume->SetVoxelHeader(0);
257                                                << 189      if (    ( (volume->IsToOptimise())
258 // ******************************************* << 190             && (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
259 // Creates optimisation info. Builds all voxel << 191           || ( (volume->GetNoDaughters()==1)
260 // otherwise it builds voxels only for replica << 192             && (volume->GetDaughter(0)->IsReplicated()==true)
261 //                                             << 193             && (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) ) 
262 // This is the original sequential implementat << 194      {
263 // - at first initialisation to create voxels, << 
264 // - at re-initialisation if the geometry has  << 
265 // ******************************************* << 
266 //                                             << 
267 void G4GeometryManager::BuildOptimisationsSequ << 
268                                                << 
269 {                                              << 
270   G4Timer timer;                               << 
271   G4Timer allTimer;                            << 
272   std::vector<G4SmartVoxelStat> stats;         << 
273                                                << 
274   if (verbose)  { allTimer.Start(); }          << 
275                                                << 
276   G4LogicalVolumeStore* Store = G4LogicalVolum << 
277   G4LogicalVolume* volume;                     << 
278   G4SmartVoxelHeader* head;                    << 
279                                                << 
280 #ifdef G4GEOMETRY_VOXELDEBUG                   << 
281   G4cout << G4endl                             << 
282      << "*** G4GeometryManager::BuildOptimisat << 
283      << G4Threading::G4GetThreadId() << " all- << 
284 #endif                                         << 
285                                                << 
286   for (auto & n : *Store)                      << 
287   {                                            << 
288     if (verbose) timer.Start();                << 
289     volume=n;                                  << 
290     // For safety, check if there are any exis << 
291     // delete before replacement               << 
292     //                                         << 
293     head = volume->GetVoxelHeader();           << 
294     delete head;                               << 
295     volume->SetVoxelHeader(nullptr);           << 
296     if (    ( (volume->IsToOptimise())         << 
297              && (volume->GetNoDaughters()>=kMi << 
298         || ( (volume->GetNoDaughters()==1)     << 
299             && (volume->GetDaughter(0)->IsRepl << 
300             && (volume->GetDaughter(0)->GetReg << 
301     {                                          << 
302 #ifdef G4GEOMETRY_VOXELDEBUG                      195 #ifdef G4GEOMETRY_VOXELDEBUG
303     G4cout << "** G4GeometryManager::BuildOpti << 196        G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
304            << "   Examining logical volume nam << 197               << "     Examining logical volume name = "
305            << "'  #daughters= " << volume->Get << 198               << volume->GetName() << G4endl;
306 #endif                                            199 #endif
307       head = new G4SmartVoxelHeader(volume);   << 200        head = new G4SmartVoxelHeader(volume);
308                                                << 201        if (head)
309       if (head != nullptr)                     << 202        {
310       {                                        << 203          volume->SetVoxelHeader(head);
311         volume->SetVoxelHeader(head);          << 204        }
312       }                                        << 205        else
313       else                                     << 206        {
314       {                                        << 207          std::ostringstream message;
315         std::ostringstream message;            << 208          message << "VoxelHeader allocation error." << G4endl
316         message << "VoxelHeader allocation err << 209                  << "Allocation of new VoxelHeader" << G4endl
317                 << "Allocation of new VoxelHea << 210                  << "        for volume " << volume->GetName() << " failed.";
318                 << "        for volume '" << v << 211          G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
319         G4Exception("G4GeometryManager::BuildO << 212                      FatalException, message);
320                     FatalException, message);  << 213        }
321       }                                        << 214        if (verbose)
322       if (verbose)                             << 215        {
323       {                                        << 216          timer.Stop();
324         timer.Stop();                          << 217          stats.push_back( G4SmartVoxelStat( volume, head,
325         stats.emplace_back( volume, head,      << 218                                             timer.GetSystemElapsed(),
326                            timer.GetSystemElap << 219                                             timer.GetUserElapsed() ) );
327                            timer.GetUserElapse << 220        }
328       }                                        << 221      }
329     }                                          << 222      else
330     else                                       << 223      {
331     {                                          << 224        // Don't create voxels for this node
332       // Don't create voxels for this node     << 
333 #ifdef G4GEOMETRY_VOXELDEBUG                      225 #ifdef G4GEOMETRY_VOXELDEBUG
334       auto numDaughters = volume->GetNoDaughte << 226        G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
335       G4cout << "- Skipping logical volume wit << 227               << "     Skipping logical volume name = " << volume->GetName()
336              << " daughters and name = '" << v << 228               << G4endl;
337       if( numDaughters > 1 )                   << 
338       {                                        << 
339         G4cout << "[Placement]";               << 
340       }                                        << 
341       else                                     << 
342       {                                        << 
343         if( numDaughters == 1 )                << 
344         {                                      << 
345           G4cout << ( volume->GetDaughter(0)-> << 
346                                                << 
347         }                                      << 
348       }                                        << 
349       G4cout << G4endl;                        << 
350 #endif                                            229 #endif
351     }                                          << 230      }
352   }                                               231   }
353   if (verbose)                                    232   if (verbose)
354   {                                               233   {
355     allTimer.Stop();                           << 234      allTimer.Stop();
356                                                << 235      ReportVoxelStats( stats, allTimer.GetSystemElapsed()
357     ReportVoxelStats( stats, allTimer.GetSyste << 236                             + allTimer.GetUserElapsed() );
358                      + allTimer.GetUserElapsed << 
359   }                                            << 
360 }                                              << 
361                                                << 
362 // ******************************************* << 
363 // Creates a list of logical volumes which wil << 
364 //    if allOpts=true it lists all voxels      << 
365 //    otherwise       it lists only the voxels << 
366 // This list will be used subsequently to buil << 
367 //                                             << 
368 // Note: this method is NOT thread safe!       << 
369 //    It expects to be called only once in eac << 
370 //    i.e. either by master thread or a select << 
371 // ******************************************* << 
372 //                                             << 
373 void                                           << 
374 G4GeometryManager::CreateListOfVolumesToOptimi << 
375 {                                              << 
376   // Prepare the work - must be called only in << 
377                                                << 
378   G4LogicalVolumeStore* Store = G4LogicalVolum << 
379                                                << 
380   if( !fVolumesToOptimise.empty() )            << 
381   {                                            << 
382     ResetListOfVolumesToOptimise();            << 
383   }                                            << 
384                                                << 
385   for (auto & n : *Store)                      << 
386   {                                            << 
387     G4LogicalVolume* volume=n;                 << 
388                                                << 
389     if (    ( (volume->IsToOptimise())         << 
390              && (volume->GetNoDaughters()>=kMi << 
391         || ( (volume->GetNoDaughters()==1)     << 
392             && (volume->GetDaughter(0)->IsRepl << 
393             && (volume->GetDaughter(0)->GetReg << 
394     {                                          << 
395       fVolumesToOptimise.push_back(volume);    << 
396                                                << 
397       // For safety, must check (later) if the << 
398       //     delete before replacement:        << 
399       // All 'clients' of this code must do th << 
400       //   delete volume->GetVoxelHeader();    << 
401       //   volume->SetVoxelHeader(nullptr);    << 
402                                                << 
403 #ifdef G4GEOMETRY_VOXELDEBUG                   << 
404       G4cout << "- Booking  logical volume wit << 
405       << " daughters and name = '" << volume-> << 
406       << " -- for optimisation (ie voxels will << 
407 #endif                                         << 
408     }                                          << 
409     else                                       << 
410     {                                          << 
411 #ifdef G4GEOMETRY_VOXELDEBUG                   << 
412       G4cout << "- Skipping logical volume wit << 
413       << " daughters and name = '" << volume-> << 
414 #endif                                         << 
415     }                                          << 
416   }                                            << 
417                                                << 
418   if(verbose)                                  << 
419     G4cout << "** G4GeometryManager::PrepareOp << 
420            << "  Number of volumes for voxelis << 
421            << fVolumesToOptimise.size() << G4e << 
422                                                << 
423   fLogVolumeIterator = fVolumesToOptimise.cbeg << 
424 }                                              << 
425                                                << 
426 // ******************************************* << 
427 // Obtain a logical volume from the list of vo << 
428 // Must be thread-safe: its role is to be call << 
429 // Critical method for parallel optimisation - << 
430 // ******************************************* << 
431 //                                             << 
432 G4LogicalVolume* G4GeometryManager::ObtainVolu << 
433 {                                              << 
434   G4LogicalVolume* logVolume = nullptr;        << 
435                                                << 
436   G4AutoLock lock(obtainVolumeMutex);          << 
437                                                << 
438   if( fLogVolumeIterator != fVolumesToOptimise << 
439   {                                            << 
440     logVolume = *fLogVolumeIterator;           << 
441     ++fLogVolumeIterator;                      << 
442   }                                            << 
443   return logVolume;                            << 
444 }                                              << 
445                                                << 
446 // ******************************************* << 
447 // Thread-safe method to clear the list of vol << 
448 // ******************************************* << 
449 //                                             << 
450 void G4GeometryManager::ResetListOfVolumesToOp << 
451 {                                              << 
452   G4AutoLock lock(obtainVolumeMutex);          << 
453                                                << 
454   std::vector<G4LogicalVolume*>().swap(fVolume << 
455   // Swapping with an empty vector in order to << 
456   // without calling destructors of logical vo << 
457   // Must not call clear: i.e. fVolumesToOptim << 
458                                                << 
459   assert(fVolumesToOptimise.empty());          << 
460   fLogVolumeIterator = fVolumesToOptimise.cbeg << 
461                                                << 
462   fGlobVoxelStats.clear();                     << 
463   // Reset also the statistics of volumes -- t << 
464 }                                              << 
465                                                << 
466 // ******************************************* << 
467 // Method which user calls to ask for parallel << 
468 // ******************************************* << 
469 //                                             << 
470 void G4GeometryManager::RequestParallelOptimis << 
471 {                                              << 
472   fParallelVoxelOptimisationRequested = flag;  << 
473   if( flag )                                   << 
474   {                                            << 
475     ConfigureParallelOptimisation(verbose);    << 
476   }                                            << 
477 }                                              << 
478                                                << 
479 // ******************************************* << 
480 // Setup up state to enable parallel optimisat << 
481 // ******************************************* << 
482 //                                             << 
483 void G4GeometryManager::ConfigureParallelOptim << 
484 {                                              << 
485   if(verbose)                                  << 
486   {                                            << 
487     G4cout << "** G4GeometryManager::Configure << 
488     << " LEAVING all the work (of voxel optimi << 
489     << G4endl;                                 << 
490   }                                            << 
491   fParallelVoxelOptimisationRequested = true;  << 
492   fParallelVoxelOptimisationUnderway = false;  << 
493   fParallelVoxelOptimisationFinished = false;  << 
494                                                << 
495   // Keep values of options / verbosity for us << 
496   fVerboseParallel = verbose;                  << 
497                                                << 
498   // New effort -- reset the total time -- and << 
499   fSumVoxelTime = 0.0;                         << 
500   fNumberThreadsReporting = 0;                 << 
501   fTotalNumberVolumesOptimised = 0;   // Numbe << 
502                                                << 
503   fWallClockStarted = false;  // Will need to  << 
504 }                                              << 
505                                                << 
506 // ******************************************* << 
507 // Build voxel optimisation in parallel -- pre << 
508 // ******************************************* << 
509 //                                             << 
510 void                                           << 
511 G4GeometryManager::PrepareParallelOptimisation << 
512 {                                              << 
513   if( verbose )                                << 
514   {                                            << 
515     G4cout << "** G4GeometryManager::PreparePa << 
516            << G4endl;                          << 
517   }                                            << 
518   CreateListOfVolumesToOptimise(allOpts, verbo << 
519   ConfigureParallelOptimisation(verbose);      << 
520 }                                              << 
521                                                << 
522 // ******************************************* << 
523 // Method for a thread/task to contribute dyna << 
524 // ******************************************* << 
525 //                                             << 
526 void G4GeometryManager::UndertakeOptimisation( << 
527 {                                              << 
528   G4bool verbose = fVerboseParallel;           << 
529   G4LogicalVolume* logVolume = nullptr;        << 
530                                                << 
531   fParallelVoxelOptimisationUnderway  = true;  << 
532                                                << 
533   // Start timer - if not already done         << 
534   if( ( !fWallClockStarted ) && verbose )      << 
535   {                                            << 
536     G4AutoLock startTimeLock(wallClockTimerMut << 
537     if( !fWallClockStarted )                   << 
538     {                                          << 
539       fWallClockTimer->Start();                << 
540       fWallClockStarted= true;                 << 
541     }                                          << 
542   }                                            << 
543                                                << 
544   G4Timer fetimer;                             << 
545   unsigned int numVolumesOptimised = 0;        << 
546                                                << 
547   while( (logVolume = ObtainVolumeToOptimise() << 
548   {                                            << 
549     if (verbose) fetimer.Start();              << 
550                                                << 
551     G4SmartVoxelHeader* head = logVolume->GetV << 
552     delete head;                               << 
553     logVolume->SetVoxelHeader(nullptr);        << 
554                                                << 
555     head = new G4SmartVoxelHeader(logVolume);  << 
556     //     *********************************   << 
557     logVolume->SetVoxelHeader(head);           << 
558                                                << 
559     if (head != nullptr)                       << 
560     {                                          << 
561       ++numVolumesOptimised;                   << 
562     }                                          << 
563     else                                       << 
564     {                                          << 
565       G4ExceptionDescription message;          << 
566       message << "VoxelHeader allocation error << 
567               << "Allocation of new VoxelHeade << 
568               << "for logical volume " << logV << 
569       G4Exception("G4GeometryManager::BuildOpt << 
570                   "GeomMgt0003", FatalExceptio << 
571     }                                          << 
572                                                << 
573     if(verbose)                                << 
574     {                                          << 
575       fetimer.Stop();                          << 
576       auto feRealElapsed = fetimer.GetRealElap << 
577       // Must use 'real' elapsed time -- canno << 
578       // (it accounts for all threads)         << 
579                                                << 
580       G4AutoLock lock(voxelStatsMutex);        << 
581       fGlobVoxelStats.emplace_back( logVolume, << 
582                           0.0,             //  << 
583                           feRealElapsed ); //  << 
584       fSumVoxelTime += feRealElapsed;          << 
585     }                                          << 
586   }                                            << 
587                                                << 
588   G4bool allDone = false;                      << 
589   G4int myCount= -1;                           << 
590                                                << 
591   myCount = ReportWorkerIsDoneOptimising(numVo << 
592   allDone = IsParallelOptimisationFinished();  << 
593                                                << 
594   if( allDone && (myCount == G4Threading::GetN << 
595   {                                            << 
596     G4int badVolumes = CheckOptimisation(); // << 
597     if( badVolumes > 0 )                       << 
598     {                                          << 
599       G4ExceptionDescription errmsg;           << 
600       errmsg <<" Expected that all voxelisatio << 
601              << "but found that voxels headers << 
602              << badVolumes << " volumes.";     << 
603       G4Exception("G4GeometryManager::Undertak << 
604                   "GeomMng002", FatalException << 
605     }                                          << 
606                                                << 
607     // Create report                           << 
608                                                << 
609     if( verbose )                              << 
610     {                                          << 
611       fWallClockTimer->Stop();                 << 
612                                                << 
613       std::ostream& report_stream = std::cout; << 
614       report_stream << G4endl                  << 
615         << "G4GeometryManager::UndertakeOptimi << 
616         << " -- Timing for Voxel Optimisation" << 
617       report_stream << "  - Elapsed time (real << 
618         << fWallClockTimer->GetRealElapsed() < << 
619         << ", user " << fWallClockTimer->GetUs << 
620         << ", system " << fWallClockTimer->Get << 
621         << G4endl;                             << 
622       report_stream << "  - Sum voxel time (re << 
623                     << "s.";                   << 
624       report_stream << std::setprecision(6) << << 
625                                                << 
626       ReportVoxelStats( fGlobVoxelStats, fSumV << 
627       report_stream.flush();                   << 
628     }                                          << 
629   }                                            << 
630   else                                         << 
631   {                                            << 
632     WaitForVoxelisationFinish(false);          << 
633   }                                            << 
634 }                                              << 
635                                                << 
636 // ******************************************* << 
637 // Ensure that all the work of voxelisation is << 
638 // Can be called in GeometryManager methods or << 
639 // ******************************************* << 
640 //                                             << 
641 void G4GeometryManager::WaitForVoxelisationFin << 
642 {                                              << 
643   // Must wait until all workers are done ...  << 
644   using namespace std::chrono_literals;        << 
645   unsigned int trials = 0;                     << 
646   auto tid = G4Threading::G4GetThreadId();     << 
647                                                << 
648   std::ostream& out_stream = std::cout; // G4c << 
649   while( ! IsParallelOptimisationFinished() )  << 
650   {                                            << 
651     // Each thread must wait until all are don << 
652     std::this_thread::sleep_for(250ms);        << 
653     ++trials;                                  << 
654   }                                            << 
655                                                << 
656   if( verbose )                                << 
657   {                                            << 
658     G4AutoLock lock(outputDbgMutex);           << 
659     out_stream << G4endl                       << 
660                << "** UndertakeOptimisation do << 
661                <<  " after waiting for " << tr << 
662     out_stream.flush();                        << 
663   }                                            << 
664 }                                              << 
665                                                << 
666 // ******************************************* << 
667 // Ensure that all logical volumes in list hav << 
668 // ******************************************* << 
669 //                                             << 
670 G4int G4GeometryManager::CheckOptimisation()   << 
671 {                                              << 
672   unsigned int numErrors = 0;                  << 
673   for ( const auto& logical : fVolumesToOptimi << 
674   {                                            << 
675     if( logical->GetVoxelHeader() == nullptr ) << 
676   }                                            << 
677   return numErrors;                            << 
678 }                                              << 
679                                                << 
680 // ******************************************* << 
681 // Report that current thread/task is done opt << 
682 // A thread call this method to reports that i << 
683 // many volumes it optimised. The method:      << 
684 //   - increments the count of workers that ha << 
685 //   - keeps count of number of volumes optimi << 
686 //   - if all works is done (ie all workers ha << 
687 //     in the 'Finished' state.                << 
688 // ******************************************* << 
689 //                                             << 
690 G4int                                          << 
691 G4GeometryManager::ReportWorkerIsDoneOptimisin << 
692 {                                              << 
693   // Check that all are done and, if so, signa << 
694   G4int orderReporting;                        << 
695                                                << 
696   G4AutoLock lock(statResultsMutex);           << 
697   orderReporting = ++fNumberThreadsReporting;  << 
698   fTotalNumberVolumesOptimised += numVolumesOp << 
699                                                << 
700   if (fNumberThreadsReporting == G4Threading:: << 
701   {                                            << 
702     InformOptimisationIsFinished(fVerboseParal << 
703   }                                            << 
704                                                << 
705   return orderReporting;                       << 
706 }                                              << 
707                                                << 
708 // ******************************************* << 
709 // Inform that all work for parallel optimisat << 
710 // ******************************************* << 
711 //                                             << 
712 void G4GeometryManager::InformOptimisationIsFi << 
713 {                                              << 
714   if(verbose)   // G4cout does not work!       << 
715   {                                            << 
716     std::cout << "** G4GeometryManager: All vo << 
717               << G4endl;                       << 
718     std::cout << "   Total number of volumes o << 
719               << fTotalNumberVolumesOptimised  << 
720               << " of " << fVolumesToOptimise. << 
721     std::cout << "   Number of workers reporti << 
722               << fNumberThreadsReporting       << 
723               << " of " << G4Threading::GetNum << 
724               << " expected\n";                << 
725   }                                               237   }
726   assert ( fTotalNumberVolumesOptimised == fVo << 
727                                                << 
728   fParallelVoxelOptimisationFinished  = true;  << 
729   // fParallelVoxelOptimisationRequested = fal << 
730   fParallelVoxelOptimisationUnderway  = false; << 
731 }                                                 238 }
732                                                   239 
733 // *******************************************    240 // ***************************************************************************
734 // Creates Optimisation info for the specified << 241 // Creates optimisation info for the specified volumes subtree.
735 // *******************************************    242 // ***************************************************************************
736 //                                                243 //
737 void G4GeometryManager::BuildOptimisations(G4b    244 void G4GeometryManager::BuildOptimisations(G4bool allOpts,
738                                            G4V    245                                            G4VPhysicalVolume* pVolume)
739 {                                                 246 {
740   if (pVolume == nullptr) { return; }          << 247    if (!pVolume) { return; }
741                                                   248 
742   // Retrieve the mother logical volume, if no << 249    // Retrieve the mother logical volume, if not NULL,
743   // otherwise apply global optimisation for t << 250    // otherwise apply global optimisation for the world volume
744   //                                           << 251    //
745   G4LogicalVolume* tVolume = pVolume->GetMothe << 252    G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
746   if (tVolume == nullptr)                      << 253    if (!tVolume) { return BuildOptimisations(allOpts, false); }
747   {                                            << 254 
748     BuildOptimisations(allOpts, false);        << 255    G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
749     return;                                    << 256    delete head;
750   }                                            << 257    tVolume->SetVoxelHeader(0);
751                                                << 258    if (    ( (tVolume->IsToOptimise())
752   G4SmartVoxelHeader* head = tVolume->GetVoxel << 259           && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
753   delete head;                                 << 260         || ( (tVolume->GetNoDaughters()==1)
754   tVolume->SetVoxelHeader(nullptr);            << 261           && (tVolume->GetDaughter(0)->IsReplicated()==true) ) ) 
755   if (    ( (tVolume->IsToOptimise())          << 262    {
756          && (tVolume->GetNoDaughters()>=kMinVo << 263      head = new G4SmartVoxelHeader(tVolume);
757        || ( (tVolume->GetNoDaughters()==1)     << 264      if (head)
758          && (tVolume->GetDaughter(0)->IsReplic << 265      {
759   {                                            << 266        tVolume->SetVoxelHeader(head);
760     head = new G4SmartVoxelHeader(tVolume);    << 267      }
761     if (head != nullptr)                       << 268      else
762     {                                          << 269      {
763       tVolume->SetVoxelHeader(head);           << 270        std::ostringstream message;
764     }                                          << 271        message << "VoxelHeader allocation error." << G4endl
765     else                                       << 272                << "Allocation of new VoxelHeader" << G4endl
766     {                                          << 273                << "        for volume " << tVolume->GetName() << " failed.";
767       std::ostringstream message;              << 274        G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
768       message << "VoxelHeader allocation error << 275                    FatalException, message);
769               << "Allocation of new VoxelHeade << 276      }
770               << "        for volume " << tVol << 277    }
771       G4Exception("G4GeometryManager::BuildOpt << 278    else
772                   FatalException, message);    << 279    {
773     }                                          << 280      // Don't create voxels for this node
774   }                                            << 
775   else                                         << 
776   {                                            << 
777     // Don't create voxels for this node       << 
778 #ifdef G4GEOMETRY_VOXELDEBUG                      281 #ifdef G4GEOMETRY_VOXELDEBUG
779     G4cout << "** G4GeometryManager::BuildOpti << 282      G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
780            << "     Skipping logical volume na << 283             << "     Skipping logical volume name = " << tVolume->GetName()
781            << G4endl;                          << 284             << G4endl;
782 #endif                                            285 #endif
783   }                                            << 286    }
784                                                   287 
785   // Scan recursively the associated logical v << 288    // Scan recursively the associated logical volume tree
786   //                                           << 289    //
787   tVolume = pVolume->GetLogicalVolume();          290   tVolume = pVolume->GetLogicalVolume();
788   if (tVolume->GetNoDaughters() != 0)          << 291   if (tVolume->GetNoDaughters())
789   {                                               292   {
790     BuildOptimisations(allOpts, tVolume->GetDa    293     BuildOptimisations(allOpts, tVolume->GetDaughter(0));
791   }                                               294   }
792 }                                                 295 }
793                                                   296 
794 // *******************************************    297 // ***************************************************************************
795 // Removes all optimisation info.                 298 // Removes all optimisation info.
796 // Loops over all logical volumes, deleting no << 299 // Loops over all logical volumes, deleting non-null voxels pointers,
797 // *******************************************    300 // ***************************************************************************
798 //                                                301 //
799 void G4GeometryManager::DeleteOptimisations()     302 void G4GeometryManager::DeleteOptimisations()
800 {                                                 303 {
801   G4LogicalVolume* tVolume = nullptr;          << 304   G4LogicalVolume* tVolume = 0;
802   G4LogicalVolumeStore* Store = G4LogicalVolum    305   G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
803   for (auto & n : *Store)                      << 306   for (size_t n=0; n<Store->size(); n++)
804   {                                               307   {
805     tVolume=n;                                 << 308     tVolume=(*Store)[n];
806     delete tVolume->GetVoxelHeader();             309     delete tVolume->GetVoxelHeader();
807     tVolume->SetVoxelHeader(nullptr);          << 310     tVolume->SetVoxelHeader(0);
808   }                                               311   }
809 }                                                 312 }
810                                                   313 
811 // *******************************************    314 // ***************************************************************************
812 // Removes optimisation info for the specified    315 // Removes optimisation info for the specified subtree.
813 // Scans recursively all daughter volumes, del    316 // Scans recursively all daughter volumes, deleting non-null voxels pointers.
814 // *******************************************    317 // ***************************************************************************
815 //                                                318 //
816 void G4GeometryManager::DeleteOptimisations(G4    319 void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume)
817 {                                                 320 {
818   if (pVolume == nullptr) { return; }          << 321   if (!pVolume) { return; }
819                                                   322 
820   // Retrieve the mother logical volume, if no    323   // Retrieve the mother logical volume, if not NULL,
821   // otherwise global deletion to world volume    324   // otherwise global deletion to world volume.
822   //                                              325   //
823   G4LogicalVolume* tVolume = pVolume->GetMothe    326   G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
824   if (tVolume == nullptr) { return DeleteOptim << 327   if (!tVolume) { return DeleteOptimisations(); }
825   delete tVolume->GetVoxelHeader();               328   delete tVolume->GetVoxelHeader();
826   tVolume->SetVoxelHeader(nullptr);            << 329   tVolume->SetVoxelHeader(0);
827                                                   330 
828   // Scan recursively the associated logical v    331   // Scan recursively the associated logical volume tree
829   //                                              332   //
830   tVolume = pVolume->GetLogicalVolume();          333   tVolume = pVolume->GetLogicalVolume();
831   if (tVolume->GetNoDaughters() != 0)          << 334   if (tVolume->GetNoDaughters())
832   {                                               335   {
833     DeleteOptimisations(tVolume->GetDaughter(0    336     DeleteOptimisations(tVolume->GetDaughter(0));
834   }                                               337   }
835 }                                                 338 }
836                                                   339 
837 // *******************************************    340 // ***************************************************************************
838 // Sets the maximum extent of the world volume    341 // Sets the maximum extent of the world volume. The operation is allowed only
839 // if NO solids have been created already.        342 // if NO solids have been created already.
840 // *******************************************    343 // ***************************************************************************
841 //                                                344 //
842 void G4GeometryManager::SetWorldMaximumExtent(    345 void G4GeometryManager::SetWorldMaximumExtent(G4double extent)
843 {                                                 346 {
844   if (!G4SolidStore::GetInstance()->empty())   << 347   if (G4SolidStore::GetInstance()->size())
845   {                                               348   {
846      // Sanity check to assure that extent is     349      // Sanity check to assure that extent is fixed BEFORE creating
847      // any geometry object (solids in this ca    350      // any geometry object (solids in this case)
848      //                                           351      //
849      G4Exception("G4GeometryManager::SetMaximu    352      G4Exception("G4GeometryManager::SetMaximumExtent()",
850                  "GeomMgt0003", FatalException    353                  "GeomMgt0003", FatalException,
851                  "Extent can be set only BEFOR    354                  "Extent can be set only BEFORE creating any geometry object!");
852   }                                               355   }
853   G4GeometryTolerance::GetInstance()->SetSurfa    356   G4GeometryTolerance::GetInstance()->SetSurfaceTolerance(extent);
854 }                                                 357 }
855                                                   358 
856 // *******************************************    359 // ***************************************************************************
857 // Reports statistics on voxel optimisation wh    360 // Reports statistics on voxel optimisation when closing geometry.
858 // *******************************************    361 // ***************************************************************************
859 //                                                362 //
860 void                                              363 void
861 G4GeometryManager::ReportVoxelStats( std::vect    364 G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
862                                      G4double  << 365                                      G4double totalCpuTime )
863                                      std::ostr << 
864 {                                                 366 {
865   os << "------------------------------------- << 367   G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
866      << G4endl;                                << 
867   os << "G4GeometryManager::ReportVoxelStats - << 
868          << G4endl << G4endl;                     368          << G4endl << G4endl;
869                                                   369  
870   //                                              370   //
871   // Get total memory use                         371   // Get total memory use
872   //                                              372   //
873   G4int i, nStat = (G4int)stats.size();        << 373   G4int i, nStat = stats.size();
874   G4long totalMemory = 0;                         374   G4long totalMemory = 0;
875                                                   375  
876   for( i=0; i<nStat; ++i )  { totalMemory += s << 376   for( i=0;i<nStat;++i )  { totalMemory += stats[i].GetMemoryUse(); }
877                                                   377  
878   os << "    Total memory consumed for geometr << 378   G4cout << "    Total memory consumed for geometry optimisation:   "
879          << totalMemory/1024 << " kByte" << G4    379          << totalMemory/1024 << " kByte" << G4endl;
880   os << "    Total CPU time elapsed for geomet << 380   G4cout << "    Total CPU time elapsed for geometry optimisation: " 
881          << std::setprecision(4) << totalCpuTi << 381          << std::setprecision(2) << totalCpuTime << " seconds"
882          << std::setprecision(6) << G4endl;       382          << std::setprecision(6) << G4endl;
883                                                   383  
884   //                                              384   //
885   // First list: sort by total CPU time           385   // First list: sort by total CPU time
886   //                                              386   //
887   std::sort( stats.begin(), stats.end(),       << 387   std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByCpu() );
888     [](const G4SmartVoxelStat& a, const G4Smar << 
889   {                                            << 
890     return a.GetTotalTime() > b.GetTotalTime() << 
891   } );                                         << 
892                                                   388          
893   const G4int maxPrint = 20;                   << 389   G4int nPrint = nStat > 10 ? 10 : nStat;
894   G4int nPrint = std::min ( nStat, maxPrint ); << 
895                                                   390 
896   if (nPrint != 0)                             << 391   if (nPrint)
897   {                                               392   {
898     os << "\n    Voxelisation: top CPU users:" << 393     G4cout << "\n    Voxelisation: top CPU users:" << G4endl;
899     os << "    Percent   Total CPU    System C << 394     G4cout << "    Percent   Total CPU    System CPU       Memory  Volume\n"
900        << "    -------   ----------   -------- << 395            << "    -------   ----------   ----------     --------  ----------"
901        << G4endl;                              << 396            << G4endl;
                                                   >> 397     //         12345678901.234567890123.234567890123.234567890123k .
902   }                                               398   }
903                                                   399 
904   for(i=0; i<nPrint; ++i)                      << 400   for(i=0;i<nPrint;++i)
905   {                                               401   {
906     G4double total = stats[i].GetTotalTime();     402     G4double total = stats[i].GetTotalTime();
907     G4double system = stats[i].GetSysTime();      403     G4double system = stats[i].GetSysTime();
908     G4double perc = 0.0;                          404     G4double perc = 0.0;
909                                                   405 
910     if (system < 0) { system = 0.0; }             406     if (system < 0) { system = 0.0; }
911     if ((total < 0) || (totalCpuTime < perMill    407     if ((total < 0) || (totalCpuTime < perMillion))
912       { total = 0; }                              408       { total = 0; }
913     else                                          409     else
914       { perc = total*100/totalCpuTime; }          410       { perc = total*100/totalCpuTime; }
915                                                   411 
916     os << std::setprecision(2)                 << 412     G4cout << std::setprecision(2) 
917            << std::setiosflags(std::ios::fixed    413            << std::setiosflags(std::ios::fixed|std::ios::right)
918            << std::setw(11) << perc               414            << std::setw(11) << perc
919            << std::setw(13) << total              415            << std::setw(13) << total
920            << std::setw(13) << system             416            << std::setw(13) << system
921            << std::setw(13) << (stats[i].GetMe    417            << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
922            << "k " << std::setiosflags(std::io    418            << "k " << std::setiosflags(std::ios::left)
923            << stats[i].GetVolume()->GetName()     419            << stats[i].GetVolume()->GetName()
924            << std::resetiosflags(std::ios::flo    420            << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
925            << std::setprecision(6)                421            << std::setprecision(6)
926            << G4endl;                             422            << G4endl;
927   }                                               423   }
928                                                   424  
929   //                                              425   //
930   // Second list: sort by memory use              426   // Second list: sort by memory use
931   //                                              427   //
932   std::sort( stats.begin(), stats.end(),       << 428   std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByMemory() );
933     [](const G4SmartVoxelStat& a, const G4Smar << 
934   {                                            << 
935     return a.GetMemoryUse() > b.GetMemoryUse() << 
936   } );                                         << 
937                                                   429  
938   if (nPrint != 0)                             << 430   if (nPrint)
939   {                                               431   {
940     os << "\n    Voxelisation: top memory user << 432     G4cout << "\n    Voxelisation: top memory users:" << G4endl;
941     os << "    Percent     Memory      Heads   << 433     G4cout << "    Percent     Memory      Heads    Nodes   Pointers    Total CPU    Volume\n"
942        << "    -------   --------     ------   << 434            << "    -------   --------     ------   ------   --------   ----------    ----------"
943        << G4endl;                              << 435            << G4endl;
                                                   >> 436     //         12345678901.2345678901k .23456789.23456789.2345678901.234567890123.   .
944   }                                               437   }
945                                                   438 
946   for(i=0; i<nPrint; ++i)                      << 439   for(i=0;i<nPrint;++i)
947   {                                               440   {
948     G4long memory = stats[i].GetMemoryUse();      441     G4long memory = stats[i].GetMemoryUse();
949     G4double totTime = stats[i].GetTotalTime()    442     G4double totTime = stats[i].GetTotalTime();
950     if (totTime < 0) { totTime = 0.0; }           443     if (totTime < 0) { totTime = 0.0; }
951                                                   444 
952     os << std::setprecision(2)                 << 445     G4cout << std::setprecision(2) 
953        << std::setiosflags(std::ios::fixed|std << 446            << std::setiosflags(std::ios::fixed|std::ios::right)
954        << std::setw(11) << G4double(memory*100 << 447            << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
955        << std::setw(11) << memory/1024 << "k " << 448            << std::setw(11) << memory/1024 << "k "
956        << std::setw( 9) << stats[i].GetNumberH << 449            << std::setw( 9) << stats[i].GetNumberHeads()
957        << std::setw( 9) << stats[i].GetNumberN << 450            << std::setw( 9) << stats[i].GetNumberNodes()
958        << std::setw(11) << stats[i].GetNumberP << 451            << std::setw(11) << stats[i].GetNumberPointers()
959        << std::setw(13) << totTime << "    "   << 452            << std::setw(13) << totTime << "    "
960        << std::setiosflags(std::ios::left)     << 453            << std::setiosflags(std::ios::left)
961        << stats[i].GetVolume()->GetName()      << 454            << stats[i].GetVolume()->GetName()
962        << std::resetiosflags(std::ios::floatfi << 455            << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
963        << std::setprecision(6)                 << 456            << std::setprecision(6)
964        << G4endl;                              << 457            << G4endl;
965   }                                               458   }
966   os << "------------------------------------- << 
967      << G4endl << G4endl;                      << 
968 }                                              << 
969                                                << 
970 // ******************************************* << 
971 // Check whether parallel optimisation was req << 
972 // ******************************************* << 
973 //                                             << 
974 G4bool G4GeometryManager::IsParallelOptimisati << 
975 {                                              << 
976   return fOptimiseInParallelConfigured;        << 
977 }                                              << 
978                                                << 
979 // ******************************************* << 
980 // Report whether parallel optimisation is don << 
981 // ******************************************* << 
982 //                                             << 
983 G4bool G4GeometryManager::IsParallelOptimisati << 
984 {                                              << 
985   return fParallelVoxelOptimisationFinished;   << 
986 }                                                 459 }
987                                                   460