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.6)


  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          26 // Class G4GeometryManager implementation
 27 //                                                 27 //
 28 // 26.07.95, P.Kent - Initial version, includi     28 // 26.07.95, P.Kent - Initial version, including optimisation build
 29 // 12.06.24, J.Apostolakis - Added parallel op << 
 30 // -------------------------------------------     29 // --------------------------------------------------------------------
 31                                                    30 
 32 #include <iomanip>                                 31 #include <iomanip>
 33                                                << 
 34 #include "G4ios.hh"                            << 
 35 #include "G4Timer.hh"                              32 #include "G4Timer.hh"
 36 #include "G4GeometryManager.hh"                    33 #include "G4GeometryManager.hh"
 37 #include "G4SystemOfUnits.hh"                      34 #include "G4SystemOfUnits.hh"
 38 #include "G4Threading.hh"                      <<  35 
                                                   >>  36 #ifdef  G4GEOMETRY_VOXELDEBUG
                                                   >>  37 #include "G4ios.hh"
                                                   >>  38 #endif
 39                                                    39 
 40 // Needed for building optimisations               40 // Needed for building optimisations
 41 //                                                 41 //
 42 #include "G4LogicalVolumeStore.hh"                 42 #include "G4LogicalVolumeStore.hh"
 43 #include "G4VPhysicalVolume.hh"                    43 #include "G4VPhysicalVolume.hh"
 44 #include "G4SmartVoxelHeader.hh"                   44 #include "G4SmartVoxelHeader.hh"
 45 #include "voxeldefs.hh"                            45 #include "voxeldefs.hh"
 46                                                    46 
 47 // Needed for setting the extent for tolerance     47 // Needed for setting the extent for tolerance value
 48 //                                                 48 //
 49 #include "G4GeometryTolerance.hh"                  49 #include "G4GeometryTolerance.hh"
 50 #include "G4SolidStore.hh"                         50 #include "G4SolidStore.hh"
 51 #include "G4VSolid.hh"                             51 #include "G4VSolid.hh"
 52                                                    52 
 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 // *******************************************     53 // ***************************************************************************
 75 // Static class data                               54 // Static class data
 76 // *******************************************     55 // ***************************************************************************
 77 //                                                 56 //
 78 G4ThreadLocal G4GeometryManager* G4GeometryMan     57 G4ThreadLocal G4GeometryManager* G4GeometryManager::fgInstance = nullptr;
                                                   >>  58 G4ThreadLocal G4bool G4GeometryManager::fIsClosed = false;
 79                                                    59 
 80 // Static *global* class data                  <<  60 // ***************************************************************************
 81 G4bool G4GeometryManager::fParallelVoxelOptimi <<  61 // Constructor. Set the geometry to be open
 82   // Records User choice to use parallel voxel <<  62 // ***************************************************************************
 83                                                <<  63 //
 84 G4bool  G4GeometryManager::fOptimiseInParallel <<  64 G4GeometryManager::G4GeometryManager() 
 85   // Configured = requested && available (ie i <<  65 {
 86   // Value calculated during each effort to op <<  66 }
 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                                                    67 
107 // *******************************************     68 // ***************************************************************************
108 // Destructor                                      69 // Destructor
109 // *******************************************     70 // ***************************************************************************
110 //                                                 71 //
111 G4GeometryManager::~G4GeometryManager()            72 G4GeometryManager::~G4GeometryManager()
112 {                                                  73 {
113   fgInstance = nullptr;                            74   fgInstance = nullptr;
114   fIsClosed = false;                               75   fIsClosed = false;
115                                                << 
116   if( fWallClockTimer && G4Threading::IsMaster << 
117   {                                            << 
118     delete fWallClockTimer;                    << 
119     fWallClockTimer= nullptr;                  << 
120   }                                            << 
121 }                                                  76 }
122                                                    77 
123 // *******************************************     78 // ***************************************************************************
124 // Closes geometry - performs sanity checks an     79 // Closes geometry - performs sanity checks and optionally builds optimisation
125 // for placed volumes (always built for replic     80 // for placed volumes (always built for replicas & parameterised).
126 // NOTE: Currently no sanity checks are perfor     81 // NOTE: Currently no sanity checks are performed.
127 // Applies to just a specific subtree if a phy     82 // Applies to just a specific subtree if a physical volume is specified.
128 // *******************************************     83 // ***************************************************************************
129 //                                                 84 //
130 G4bool G4GeometryManager::CloseGeometry(G4bool     85 G4bool G4GeometryManager::CloseGeometry(G4bool pOptimise, G4bool verbose,
131                                         G4VPhy     86                                         G4VPhysicalVolume* pVolume)
132 {                                                  87 {
133   if (!fIsClosed && G4Threading::IsMasterThrea <<  88   if (!fIsClosed)
134   {                                                89   {
135     if (pVolume != nullptr)                        90     if (pVolume != nullptr)
136     {                                              91     {
137       BuildOptimisations(pOptimise, pVolume);      92       BuildOptimisations(pOptimise, pVolume);
138     }                                              93     }
139     else                                           94     else
140     {                                              95     {
141       BuildOptimisations(pOptimise, verbose);      96       BuildOptimisations(pOptimise, verbose);
142     }                                              97     }
143     fIsClosed = true;                              98     fIsClosed = true;
144   }                                                99   }
145   return true;                                    100   return true;
146 }                                                 101 }
147                                                   102 
148 // *******************************************    103 // ***************************************************************************
149 // Opens the geometry and removes optimisation    104 // Opens the geometry and removes optimisations (optionally, related to just
150 // the specified logical-volume).                 105 // the specified logical-volume).
151 // Applies to just a specific subtree if a phy    106 // Applies to just a specific subtree if a physical volume is specified.
152 // *******************************************    107 // ***************************************************************************
153 //                                                108 //
154 void G4GeometryManager::OpenGeometry(G4VPhysic    109 void G4GeometryManager::OpenGeometry(G4VPhysicalVolume* pVolume)
155 {                                                 110 {
156   if (fIsClosed && G4Threading::IsMasterThread << 111   if (fIsClosed)
157   {                                               112   {
158     if (pVolume != nullptr)                       113     if (pVolume != nullptr)
159     {                                             114     {
160       DeleteOptimisations(pVolume);               115       DeleteOptimisations(pVolume);
161     }                                             116     }
162     else                                          117     else
163     {                                             118     {
164       DeleteOptimisations();                      119       DeleteOptimisations();
165     }                                             120     }
166     fIsClosed = false;                            121     fIsClosed = false;
167   }                                               122   }
168 }                                                 123 }
169                                                   124 
170 // *******************************************    125 // ***************************************************************************
                                                   >> 126 // Returns status of geometry
                                                   >> 127 // ***************************************************************************
                                                   >> 128 //
                                                   >> 129 G4bool G4GeometryManager::IsGeometryClosed()
                                                   >> 130 {
                                                   >> 131   return fIsClosed;
                                                   >> 132 }
                                                   >> 133 
                                                   >> 134 // ***************************************************************************
171 // Returns the instance of the singleton.         135 // Returns the instance of the singleton.
172 // Creates it in case it's called for the firs    136 // Creates it in case it's called for the first time.
173 // *******************************************    137 // ***************************************************************************
174 //                                                138 //
175 G4GeometryManager* G4GeometryManager::GetInsta    139 G4GeometryManager* G4GeometryManager::GetInstance()
176 {                                                 140 {
177   if (fgInstance == nullptr)                      141   if (fgInstance == nullptr)
178   {                                               142   {
179     fgInstance = new G4GeometryManager;           143     fgInstance = new G4GeometryManager;
180                                                << 
181     if( (fWallClockTimer == nullptr) && G4Thre << 
182     {                                          << 
183       fWallClockTimer = new G4Timer;           << 
184     }                                          << 
185   }                                               144   }
186   return fgInstance;                              145   return fgInstance;
187 }                                                 146 }
188                                                   147 
189 // *******************************************    148 // ***************************************************************************
190 // Returns the instance of the singleton.         149 // Returns the instance of the singleton.
191 // *******************************************    150 // ***************************************************************************
192 //                                                151 //
193 G4GeometryManager* G4GeometryManager::GetInsta    152 G4GeometryManager* G4GeometryManager::GetInstanceIfExist()
194 {                                                 153 {
195   return fgInstance;                              154   return fgInstance;
196 }                                                 155 }
197                                                   156 
198 // *******************************************    157 // ***************************************************************************
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    158 // Creates optimisation info. Builds all voxels if allOpts=true
232 // otherwise it builds voxels only for replica    159 // otherwise it builds voxels only for replicated volumes.
233 // *******************************************    160 // ***************************************************************************
234 // Returns whether optimisation is finished    << 
235 //                                                161 //
236 G4bool G4GeometryManager::BuildOptimisations(G << 162 void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose)
237 {                                                 163 {
238   G4bool finishedOptimisation = false;         << 164    G4Timer timer;
239                                                << 165    G4Timer allTimer;
240   fOptimiseInParallelConfigured = fParallelVox << 166    std::vector<G4SmartVoxelStat> stats;
241                                && G4Threading: << 167    if (verbose)  { allTimer.Start(); }
242                                                << 168 
243   static unsigned int NumCallsBuildOptimisatio << 169    G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
244   if( fOptimiseInParallelConfigured && (NumCal << 170    G4LogicalVolume* volume;
245   {                                            << 171    G4SmartVoxelHeader* head;
246     PrepareParallelOptimisation(allOpts, verbo << 172  
247     ++NumCallsBuildOptimisations;              << 173    for (size_t n=0; n<Store->size(); ++n)
248   }                                            << 174    {
249   else                                         << 175      if (verbose) timer.Start();
250   {                                            << 176      volume=(*Store)[n];
251     BuildOptimisationsSequential(allOpts, verb << 177      // For safety, check if there are any existing voxels and
252     finishedOptimisation= true;                << 178      // delete before replacement
253   }                                            << 179      //
254                                                << 180      head = volume->GetVoxelHeader();
255   return finishedOptimisation;                 << 181      delete head;
256 }                                              << 182      volume->SetVoxelHeader(0);
257                                                << 183      if (    ( (volume->IsToOptimise())
258 // ******************************************* << 184             && (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
259 // Creates optimisation info. Builds all voxel << 185           || ( (volume->GetNoDaughters()==1)
260 // otherwise it builds voxels only for replica << 186             && (volume->GetDaughter(0)->IsReplicated()==true)
261 //                                             << 187             && (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) ) 
262 // This is the original sequential implementat << 188      {
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                      189 #ifdef G4GEOMETRY_VOXELDEBUG
303     G4cout << "** G4GeometryManager::BuildOpti << 190        G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
304            << "   Examining logical volume nam << 191               << "     Examining logical volume name = "
305            << "'  #daughters= " << volume->Get << 192               << volume->GetName() << G4endl;
306 #endif                                            193 #endif
307       head = new G4SmartVoxelHeader(volume);   << 194        head = new G4SmartVoxelHeader(volume);
308                                                << 195        if (head != nullptr)
309       if (head != nullptr)                     << 196        {
310       {                                        << 197          volume->SetVoxelHeader(head);
311         volume->SetVoxelHeader(head);          << 198        }
312       }                                        << 199        else
313       else                                     << 200        {
314       {                                        << 201          std::ostringstream message;
315         std::ostringstream message;            << 202          message << "VoxelHeader allocation error." << G4endl
316         message << "VoxelHeader allocation err << 203                  << "Allocation of new VoxelHeader" << G4endl
317                 << "Allocation of new VoxelHea << 204                  << "        for volume " << volume->GetName() << " failed.";
318                 << "        for volume '" << v << 205          G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
319         G4Exception("G4GeometryManager::BuildO << 206                      FatalException, message);
320                     FatalException, message);  << 207        }
321       }                                        << 208        if (verbose)
322       if (verbose)                             << 209        {
323       {                                        << 210          timer.Stop();
324         timer.Stop();                          << 211          stats.push_back( G4SmartVoxelStat( volume, head,
325         stats.emplace_back( volume, head,      << 212                                             timer.GetSystemElapsed(),
326                            timer.GetSystemElap << 213                                             timer.GetUserElapsed() ) );
327                            timer.GetUserElapse << 214        }
328       }                                        << 215      }
329     }                                          << 216      else
330     else                                       << 217      {
331     {                                          << 218        // Don't create voxels for this node
332       // Don't create voxels for this node     << 
333 #ifdef G4GEOMETRY_VOXELDEBUG                      219 #ifdef G4GEOMETRY_VOXELDEBUG
334       auto numDaughters = volume->GetNoDaughte << 220        G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
335       G4cout << "- Skipping logical volume wit << 221               << "     Skipping logical volume name = " << volume->GetName()
336              << " daughters and name = '" << v << 222               << 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                                            223 #endif
351     }                                          << 224      }
352   }                                               225   }
353   if (verbose)                                    226   if (verbose)
354   {                                               227   {
355     allTimer.Stop();                           << 228      allTimer.Stop();
356                                                << 229      ReportVoxelStats( stats, allTimer.GetSystemElapsed()
357     ReportVoxelStats( stats, allTimer.GetSyste << 230                             + 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   }                                               231   }
704                                                << 
705   return orderReporting;                       << 
706 }                                                 232 }
707                                                   233 
708 // *******************************************    234 // ***************************************************************************
709 // Inform that all work for parallel optimisat << 235 // Creates optimisation info for the specified volumes subtree.
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   }                                            << 
726   assert ( fTotalNumberVolumesOptimised == fVo << 
727                                                << 
728   fParallelVoxelOptimisationFinished  = true;  << 
729   // fParallelVoxelOptimisationRequested = fal << 
730   fParallelVoxelOptimisationUnderway  = false; << 
731 }                                              << 
732                                                << 
733 // ******************************************* << 
734 // Creates Optimisation info for the specified << 
735 // *******************************************    236 // ***************************************************************************
736 //                                                237 //
737 void G4GeometryManager::BuildOptimisations(G4b    238 void G4GeometryManager::BuildOptimisations(G4bool allOpts,
738                                            G4V    239                                            G4VPhysicalVolume* pVolume)
739 {                                                 240 {
740   if (pVolume == nullptr) { return; }          << 241    if (pVolume == nullptr) { return; }
741                                                   242 
742   // Retrieve the mother logical volume, if no << 243    // Retrieve the mother logical volume, if not NULL,
743   // otherwise apply global optimisation for t << 244    // otherwise apply global optimisation for the world volume
744   //                                           << 245    //
745   G4LogicalVolume* tVolume = pVolume->GetMothe << 246    G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
746   if (tVolume == nullptr)                      << 247    if (tVolume == nullptr) { return BuildOptimisations(allOpts, false); }
747   {                                            << 248 
748     BuildOptimisations(allOpts, false);        << 249    G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
749     return;                                    << 250    delete head;
750   }                                            << 251    tVolume->SetVoxelHeader(nullptr);
751                                                << 252    if (    ( (tVolume->IsToOptimise())
752   G4SmartVoxelHeader* head = tVolume->GetVoxel << 253           && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
753   delete head;                                 << 254         || ( (tVolume->GetNoDaughters()==1)
754   tVolume->SetVoxelHeader(nullptr);            << 255           && (tVolume->GetDaughter(0)->IsReplicated()==true) ) ) 
755   if (    ( (tVolume->IsToOptimise())          << 256    {
756          && (tVolume->GetNoDaughters()>=kMinVo << 257      head = new G4SmartVoxelHeader(tVolume);
757        || ( (tVolume->GetNoDaughters()==1)     << 258      if (head != nullptr)
758          && (tVolume->GetDaughter(0)->IsReplic << 259      {
759   {                                            << 260        tVolume->SetVoxelHeader(head);
760     head = new G4SmartVoxelHeader(tVolume);    << 261      }
761     if (head != nullptr)                       << 262      else
762     {                                          << 263      {
763       tVolume->SetVoxelHeader(head);           << 264        std::ostringstream message;
764     }                                          << 265        message << "VoxelHeader allocation error." << G4endl
765     else                                       << 266                << "Allocation of new VoxelHeader" << G4endl
766     {                                          << 267                << "        for volume " << tVolume->GetName() << " failed.";
767       std::ostringstream message;              << 268        G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
768       message << "VoxelHeader allocation error << 269                    FatalException, message);
769               << "Allocation of new VoxelHeade << 270      }
770               << "        for volume " << tVol << 271    }
771       G4Exception("G4GeometryManager::BuildOpt << 272    else
772                   FatalException, message);    << 273    {
773     }                                          << 274      // Don't create voxels for this node
774   }                                            << 
775   else                                         << 
776   {                                            << 
777     // Don't create voxels for this node       << 
778 #ifdef G4GEOMETRY_VOXELDEBUG                      275 #ifdef G4GEOMETRY_VOXELDEBUG
779     G4cout << "** G4GeometryManager::BuildOpti << 276      G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
780            << "     Skipping logical volume na << 277             << "     Skipping logical volume name = " << tVolume->GetName()
781            << G4endl;                          << 278             << G4endl;
782 #endif                                            279 #endif
783   }                                            << 280    }
784                                                   281 
785   // Scan recursively the associated logical v << 282    // Scan recursively the associated logical volume tree
786   //                                           << 283    //
787   tVolume = pVolume->GetLogicalVolume();          284   tVolume = pVolume->GetLogicalVolume();
788   if (tVolume->GetNoDaughters() != 0)          << 285   if (tVolume->GetNoDaughters())
789   {                                               286   {
790     BuildOptimisations(allOpts, tVolume->GetDa    287     BuildOptimisations(allOpts, tVolume->GetDaughter(0));
791   }                                               288   }
792 }                                                 289 }
793                                                   290 
794 // *******************************************    291 // ***************************************************************************
795 // Removes all optimisation info.                 292 // Removes all optimisation info.
796 // Loops over all logical volumes, deleting no << 293 // Loops over all logical volumes, deleting non-null voxels pointers,
797 // *******************************************    294 // ***************************************************************************
798 //                                                295 //
799 void G4GeometryManager::DeleteOptimisations()     296 void G4GeometryManager::DeleteOptimisations()
800 {                                                 297 {
801   G4LogicalVolume* tVolume = nullptr;             298   G4LogicalVolume* tVolume = nullptr;
802   G4LogicalVolumeStore* Store = G4LogicalVolum    299   G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
803   for (auto & n : *Store)                      << 300   for (size_t n=0; n<Store->size(); ++n)
804   {                                               301   {
805     tVolume=n;                                 << 302     tVolume=(*Store)[n];
806     delete tVolume->GetVoxelHeader();             303     delete tVolume->GetVoxelHeader();
807     tVolume->SetVoxelHeader(nullptr);             304     tVolume->SetVoxelHeader(nullptr);
808   }                                               305   }
809 }                                                 306 }
810                                                   307 
811 // *******************************************    308 // ***************************************************************************
812 // Removes optimisation info for the specified    309 // Removes optimisation info for the specified subtree.
813 // Scans recursively all daughter volumes, del    310 // Scans recursively all daughter volumes, deleting non-null voxels pointers.
814 // *******************************************    311 // ***************************************************************************
815 //                                                312 //
816 void G4GeometryManager::DeleteOptimisations(G4    313 void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume)
817 {                                                 314 {
818   if (pVolume == nullptr) { return; }          << 315   if (!pVolume) { return; }
819                                                   316 
820   // Retrieve the mother logical volume, if no    317   // Retrieve the mother logical volume, if not NULL,
821   // otherwise global deletion to world volume    318   // otherwise global deletion to world volume.
822   //                                              319   //
823   G4LogicalVolume* tVolume = pVolume->GetMothe    320   G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
824   if (tVolume == nullptr) { return DeleteOptim    321   if (tVolume == nullptr) { return DeleteOptimisations(); }
825   delete tVolume->GetVoxelHeader();               322   delete tVolume->GetVoxelHeader();
826   tVolume->SetVoxelHeader(nullptr);               323   tVolume->SetVoxelHeader(nullptr);
827                                                   324 
828   // Scan recursively the associated logical v    325   // Scan recursively the associated logical volume tree
829   //                                              326   //
830   tVolume = pVolume->GetLogicalVolume();          327   tVolume = pVolume->GetLogicalVolume();
831   if (tVolume->GetNoDaughters() != 0)          << 328   if (tVolume->GetNoDaughters())
832   {                                               329   {
833     DeleteOptimisations(tVolume->GetDaughter(0    330     DeleteOptimisations(tVolume->GetDaughter(0));
834   }                                               331   }
835 }                                                 332 }
836                                                   333 
837 // *******************************************    334 // ***************************************************************************
838 // Sets the maximum extent of the world volume    335 // Sets the maximum extent of the world volume. The operation is allowed only
839 // if NO solids have been created already.        336 // if NO solids have been created already.
840 // *******************************************    337 // ***************************************************************************
841 //                                                338 //
842 void G4GeometryManager::SetWorldMaximumExtent(    339 void G4GeometryManager::SetWorldMaximumExtent(G4double extent)
843 {                                                 340 {
844   if (!G4SolidStore::GetInstance()->empty())   << 341   if (G4SolidStore::GetInstance()->size())
845   {                                               342   {
846      // Sanity check to assure that extent is     343      // Sanity check to assure that extent is fixed BEFORE creating
847      // any geometry object (solids in this ca    344      // any geometry object (solids in this case)
848      //                                           345      //
849      G4Exception("G4GeometryManager::SetMaximu    346      G4Exception("G4GeometryManager::SetMaximumExtent()",
850                  "GeomMgt0003", FatalException    347                  "GeomMgt0003", FatalException,
851                  "Extent can be set only BEFOR    348                  "Extent can be set only BEFORE creating any geometry object!");
852   }                                               349   }
853   G4GeometryTolerance::GetInstance()->SetSurfa    350   G4GeometryTolerance::GetInstance()->SetSurfaceTolerance(extent);
854 }                                                 351 }
855                                                   352 
856 // *******************************************    353 // ***************************************************************************
857 // Reports statistics on voxel optimisation wh    354 // Reports statistics on voxel optimisation when closing geometry.
858 // *******************************************    355 // ***************************************************************************
859 //                                                356 //
860 void                                              357 void
861 G4GeometryManager::ReportVoxelStats( std::vect    358 G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
862                                      G4double  << 359                                      G4double totalCpuTime )
863                                      std::ostr << 
864 {                                                 360 {
865   os << "------------------------------------- << 361   G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
866      << G4endl;                                << 
867   os << "G4GeometryManager::ReportVoxelStats - << 
868          << G4endl << G4endl;                     362          << G4endl << G4endl;
869                                                   363  
870   //                                              364   //
871   // Get total memory use                         365   // Get total memory use
872   //                                              366   //
873   G4int i, nStat = (G4int)stats.size();        << 367   G4int i, nStat = stats.size();
874   G4long totalMemory = 0;                         368   G4long totalMemory = 0;
875                                                   369  
876   for( i=0; i<nStat; ++i )  { totalMemory += s    370   for( i=0; i<nStat; ++i )  { totalMemory += stats[i].GetMemoryUse(); }
877                                                   371  
878   os << "    Total memory consumed for geometr << 372   G4cout << "    Total memory consumed for geometry optimisation:   "
879          << totalMemory/1024 << " kByte" << G4    373          << totalMemory/1024 << " kByte" << G4endl;
880   os << "    Total CPU time elapsed for geomet << 374   G4cout << "    Total CPU time elapsed for geometry optimisation: " 
881          << std::setprecision(4) << totalCpuTi << 375          << std::setprecision(2) << totalCpuTime << " seconds"
882          << std::setprecision(6) << G4endl;       376          << std::setprecision(6) << G4endl;
883                                                   377  
884   //                                              378   //
885   // First list: sort by total CPU time           379   // First list: sort by total CPU time
886   //                                              380   //
887   std::sort( stats.begin(), stats.end(),          381   std::sort( stats.begin(), stats.end(),
888     [](const G4SmartVoxelStat& a, const G4Smar    382     [](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
889   {                                               383   {
890     return a.GetTotalTime() > b.GetTotalTime()    384     return a.GetTotalTime() > b.GetTotalTime();
891   } );                                            385   } );
892                                                   386          
893   const G4int maxPrint = 20;                   << 387   G4int nPrint = nStat > 10 ? 10 : nStat;
894   G4int nPrint = std::min ( nStat, maxPrint ); << 
895                                                   388 
896   if (nPrint != 0)                             << 389   if (nPrint)
897   {                                               390   {
898     os << "\n    Voxelisation: top CPU users:" << 391     G4cout << "\n    Voxelisation: top CPU users:" << G4endl;
899     os << "    Percent   Total CPU    System C << 392     G4cout << "    Percent   Total CPU    System CPU       Memory  Volume\n"
900        << "    -------   ----------   -------- << 393            << "    -------   ----------   ----------     --------  ----------"
901        << G4endl;                              << 394            << G4endl;
                                                   >> 395     //         12345678901.234567890123.234567890123.234567890123k .
902   }                                               396   }
903                                                   397 
904   for(i=0; i<nPrint; ++i)                         398   for(i=0; i<nPrint; ++i)
905   {                                               399   {
906     G4double total = stats[i].GetTotalTime();     400     G4double total = stats[i].GetTotalTime();
907     G4double system = stats[i].GetSysTime();      401     G4double system = stats[i].GetSysTime();
908     G4double perc = 0.0;                          402     G4double perc = 0.0;
909                                                   403 
910     if (system < 0) { system = 0.0; }             404     if (system < 0) { system = 0.0; }
911     if ((total < 0) || (totalCpuTime < perMill    405     if ((total < 0) || (totalCpuTime < perMillion))
912       { total = 0; }                              406       { total = 0; }
913     else                                          407     else
914       { perc = total*100/totalCpuTime; }          408       { perc = total*100/totalCpuTime; }
915                                                   409 
916     os << std::setprecision(2)                 << 410     G4cout << std::setprecision(2) 
917            << std::setiosflags(std::ios::fixed    411            << std::setiosflags(std::ios::fixed|std::ios::right)
918            << std::setw(11) << perc               412            << std::setw(11) << perc
919            << std::setw(13) << total              413            << std::setw(13) << total
920            << std::setw(13) << system             414            << std::setw(13) << system
921            << std::setw(13) << (stats[i].GetMe    415            << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
922            << "k " << std::setiosflags(std::io    416            << "k " << std::setiosflags(std::ios::left)
923            << stats[i].GetVolume()->GetName()     417            << stats[i].GetVolume()->GetName()
924            << std::resetiosflags(std::ios::flo    418            << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
925            << std::setprecision(6)                419            << std::setprecision(6)
926            << G4endl;                             420            << G4endl;
927   }                                               421   }
928                                                   422  
929   //                                              423   //
930   // Second list: sort by memory use              424   // Second list: sort by memory use
931   //                                              425   //
932   std::sort( stats.begin(), stats.end(),          426   std::sort( stats.begin(), stats.end(),
933     [](const G4SmartVoxelStat& a, const G4Smar    427     [](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
934   {                                               428   {
935     return a.GetMemoryUse() > b.GetMemoryUse()    429     return a.GetMemoryUse() > b.GetMemoryUse();
936   } );                                            430   } );
937                                                   431  
938   if (nPrint != 0)                             << 432   if (nPrint)
939   {                                               433   {
940     os << "\n    Voxelisation: top memory user << 434     G4cout << "\n    Voxelisation: top memory users:" << G4endl;
941     os << "    Percent     Memory      Heads   << 435     G4cout << "    Percent     Memory      Heads    Nodes   Pointers    Total CPU    Volume\n"
942        << "    -------   --------     ------   << 436            << "    -------   --------     ------   ------   --------   ----------    ----------"
943        << G4endl;                              << 437            << G4endl;
                                                   >> 438     //         12345678901.2345678901k .23456789.23456789.2345678901.234567890123.   .
944   }                                               439   }
945                                                   440 
946   for(i=0; i<nPrint; ++i)                         441   for(i=0; i<nPrint; ++i)
947   {                                               442   {
948     G4long memory = stats[i].GetMemoryUse();      443     G4long memory = stats[i].GetMemoryUse();
949     G4double totTime = stats[i].GetTotalTime()    444     G4double totTime = stats[i].GetTotalTime();
950     if (totTime < 0) { totTime = 0.0; }           445     if (totTime < 0) { totTime = 0.0; }
951                                                   446 
952     os << std::setprecision(2)                 << 447     G4cout << std::setprecision(2) 
953        << std::setiosflags(std::ios::fixed|std << 448            << std::setiosflags(std::ios::fixed|std::ios::right)
954        << std::setw(11) << G4double(memory*100 << 449            << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
955        << std::setw(11) << memory/1024 << "k " << 450            << std::setw(11) << memory/1024 << "k "
956        << std::setw( 9) << stats[i].GetNumberH << 451            << std::setw( 9) << stats[i].GetNumberHeads()
957        << std::setw( 9) << stats[i].GetNumberN << 452            << std::setw( 9) << stats[i].GetNumberNodes()
958        << std::setw(11) << stats[i].GetNumberP << 453            << std::setw(11) << stats[i].GetNumberPointers()
959        << std::setw(13) << totTime << "    "   << 454            << std::setw(13) << totTime << "    "
960        << std::setiosflags(std::ios::left)     << 455            << std::setiosflags(std::ios::left)
961        << stats[i].GetVolume()->GetName()      << 456            << stats[i].GetVolume()->GetName()
962        << std::resetiosflags(std::ios::floatfi << 457            << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
963        << std::setprecision(6)                 << 458            << std::setprecision(6)
964        << G4endl;                              << 459            << G4endl;
965   }                                               460   }
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 }                                                 461 }
987                                                   462