Geant4  10.02.p01
G4GeometryManager.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: G4GeometryManager.cc 67975 2013-03-13 10:19:44Z gcosmo $
28 //
29 // class G4GeometryManager
30 //
31 // Implementation
32 //
33 // Author:
34 // 26.07.95 P.Kent Initial version, including optimisation Build
35 // --------------------------------------------------------------------
36 
37 #include <iomanip>
38 #include "G4Timer.hh"
39 #include "G4GeometryManager.hh"
40 #include "G4SystemOfUnits.hh"
41 
42 #ifdef G4GEOMETRY_VOXELDEBUG
43 #include "G4ios.hh"
44 #endif
45 
46 // Needed for building optimisations
47 //
48 #include "G4LogicalVolumeStore.hh"
49 #include "G4VPhysicalVolume.hh"
50 #include "G4SmartVoxelHeader.hh"
51 #include "voxeldefs.hh"
52 
53 // Needed for setting the extent for tolerance value
54 //
55 #include "G4GeometryTolerance.hh"
56 #include "G4SolidStore.hh"
57 #include "G4VSolid.hh"
58 
59 // ***************************************************************************
60 // Static class variable: ptr to single instance of class
61 // ***************************************************************************
62 //
64 
65 // ***************************************************************************
66 // Constructor. Set the geometry to be open
67 // ***************************************************************************
68 //
70  : fIsClosed(false)
71 {
72 }
73 
74 // ***************************************************************************
75 // Closes geometry - performs sanity checks and optionally builds optimisation
76 // for placed volumes (always built for replicas & parameterised).
77 // NOTE: Currently no sanity checks are performed.
78 // Applies to just a specific subtree if a physical volume is specified.
79 // ***************************************************************************
80 //
82  G4VPhysicalVolume* pVolume)
83 {
84  if (!fIsClosed)
85  {
86  if (pVolume)
87  {
88  BuildOptimisations(pOptimise, pVolume);
89  }
90  else
91  {
92  BuildOptimisations(pOptimise, verbose);
93  }
94  fIsClosed=true;
95  }
96  return true;
97 }
98 
99 // ***************************************************************************
100 // Opens the geometry and removes optimisations (optionally, related to just
101 // the specified logical-volume).
102 // Applies to just a specific subtree if a physical volume is specified.
103 // ***************************************************************************
104 //
106 {
107  if (fIsClosed)
108  {
109  if (pVolume)
110  {
111  DeleteOptimisations(pVolume);
112  }
113  else
114  {
116  }
117  fIsClosed=false;
118  }
119 }
120 
121 // ***************************************************************************
122 // Returns status of geometry
123 // ***************************************************************************
124 //
126 {
127  return fIsClosed;
128 }
129 
130 // ***************************************************************************
131 // Returns the instance of the singleton.
132 // Creates it in case it's called for the first time.
133 // ***************************************************************************
134 //
136 {
137  if (!fgInstance)
138  {
140  }
141  return fgInstance;
142 }
143 
144 // ***************************************************************************
145 // Creates optimisation info. Builds all voxels if allOpts=true
146 // otherwise it builds voxels only for replicated volumes.
147 // ***************************************************************************
148 //
150 {
151  G4Timer timer;
152  G4Timer allTimer;
153  std::vector<G4SmartVoxelStat> stats;
154  if (verbose) { allTimer.Start(); }
155 
157  G4LogicalVolume* volume;
158  G4SmartVoxelHeader* head;
159 
160  for (size_t n=0; n<Store->size(); n++)
161  {
162  if (verbose) timer.Start();
163  volume=(*Store)[n];
164  // For safety, check if there are any existing voxels and
165  // delete before replacement
166  //
167  head = volume->GetVoxelHeader();
168  delete head;
169  volume->SetVoxelHeader(0);
170  if ( ( (volume->IsToOptimise())
171  && (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
172  || ( (volume->GetNoDaughters()==1)
173  && (volume->GetDaughter(0)->IsReplicated()==true)
174  && (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) )
175  {
176 #ifdef G4GEOMETRY_VOXELDEBUG
177  G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
178  << " Examining logical volume name = "
179  << volume->GetName() << G4endl;
180 #endif
181  head = new G4SmartVoxelHeader(volume);
182  if (head)
183  {
184  volume->SetVoxelHeader(head);
185  }
186  else
187  {
188  std::ostringstream message;
189  message << "VoxelHeader allocation error." << G4endl
190  << "Allocation of new VoxelHeader" << G4endl
191  << " for volume " << volume->GetName() << " failed.";
192  G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
193  FatalException, message);
194  }
195  if (verbose)
196  {
197  timer.Stop();
198  stats.push_back( G4SmartVoxelStat( volume, head,
199  timer.GetSystemElapsed(),
200  timer.GetUserElapsed() ) );
201  }
202  }
203  else
204  {
205  // Don't create voxels for this node
206 #ifdef G4GEOMETRY_VOXELDEBUG
207  G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
208  << " Skipping logical volume name = " << volume->GetName()
209  << G4endl;
210 #endif
211  }
212  }
213  if (verbose)
214  {
215  allTimer.Stop();
216  ReportVoxelStats( stats, allTimer.GetSystemElapsed()
217  + allTimer.GetUserElapsed() );
218  }
219 }
220 
221 // ***************************************************************************
222 // Creates optimisation info for the specified volumes subtree.
223 // ***************************************************************************
224 //
226  G4VPhysicalVolume* pVolume)
227 {
228  if (!pVolume) { return; }
229 
230  // Retrieve the mother logical volume, if not NULL,
231  // otherwise apply global optimisation for the world volume
232  //
233  G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
234  if (!tVolume) { return BuildOptimisations(allOpts, false); }
235 
236  G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
237  delete head;
238  tVolume->SetVoxelHeader(0);
239  if ( ( (tVolume->IsToOptimise())
240  && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
241  || ( (tVolume->GetNoDaughters()==1)
242  && (tVolume->GetDaughter(0)->IsReplicated()==true) ) )
243  {
244  head = new G4SmartVoxelHeader(tVolume);
245  if (head)
246  {
247  tVolume->SetVoxelHeader(head);
248  }
249  else
250  {
251  std::ostringstream message;
252  message << "VoxelHeader allocation error." << G4endl
253  << "Allocation of new VoxelHeader" << G4endl
254  << " for volume " << tVolume->GetName() << " failed.";
255  G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
256  FatalException, message);
257  }
258  }
259  else
260  {
261  // Don't create voxels for this node
262 #ifdef G4GEOMETRY_VOXELDEBUG
263  G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
264  << " Skipping logical volume name = " << tVolume->GetName()
265  << G4endl;
266 #endif
267  }
268 
269  // Scan recursively the associated logical volume tree
270  //
271  tVolume = pVolume->GetLogicalVolume();
272  if (tVolume->GetNoDaughters())
273  {
274  BuildOptimisations(allOpts, tVolume->GetDaughter(0));
275  }
276 }
277 
278 // ***************************************************************************
279 // Removes all optimisation info.
280 // Loops over all logical volumes, deleting non-null voxels pointers,
281 // ***************************************************************************
282 //
284 {
285  G4LogicalVolume* tVolume = 0;
287  for (size_t n=0; n<Store->size(); n++)
288  {
289  tVolume=(*Store)[n];
290  delete tVolume->GetVoxelHeader();
291  tVolume->SetVoxelHeader(0);
292  }
293 }
294 
295 // ***************************************************************************
296 // Removes optimisation info for the specified subtree.
297 // Scans recursively all daughter volumes, deleting non-null voxels pointers.
298 // ***************************************************************************
299 //
301 {
302  if (!pVolume) { return; }
303 
304  // Retrieve the mother logical volume, if not NULL,
305  // otherwise global deletion to world volume.
306  //
307  G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
308  if (!tVolume) { return DeleteOptimisations(); }
309  delete tVolume->GetVoxelHeader();
310  tVolume->SetVoxelHeader(0);
311 
312  // Scan recursively the associated logical volume tree
313  //
314  tVolume = pVolume->GetLogicalVolume();
315  if (tVolume->GetNoDaughters())
316  {
317  DeleteOptimisations(tVolume->GetDaughter(0));
318  }
319 }
320 
321 // ***************************************************************************
322 // Sets the maximum extent of the world volume. The operation is allowed only
323 // if NO solids have been created already.
324 // ***************************************************************************
325 //
327 {
328  if (G4SolidStore::GetInstance()->size())
329  {
330  // Sanity check to assure that extent is fixed BEFORE creating
331  // any geometry object (solids in this case)
332  //
333  G4Exception("G4GeometryManager::SetMaximumExtent()",
334  "GeomMgt0003", FatalException,
335  "Extent can be set only BEFORE creating any geometry object!");
336  }
338 }
339 
340 // ***************************************************************************
341 // Reports statistics on voxel optimisation when closing geometry.
342 // ***************************************************************************
343 //
344 void
345 G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
346  G4double totalCpuTime )
347 {
348  G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
349  << G4endl << G4endl;
350 
351  //
352  // Get total memory use
353  //
354  G4int i, nStat = stats.size();
355  G4long totalMemory = 0;
356 
357  for( i=0;i<nStat;++i ) { totalMemory += stats[i].GetMemoryUse(); }
358 
359  G4cout << " Total memory consumed for geometry optimisation: "
360  << totalMemory/1024 << " kByte" << G4endl;
361  G4cout << " Total CPU time elapsed for geometry optimisation: "
362  << std::setprecision(2) << totalCpuTime << " seconds"
363  << std::setprecision(6) << G4endl;
364 
365  //
366  // First list: sort by total CPU time
367  //
368  std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByCpu() );
369 
370  G4int nPrint = nStat > 10 ? 10 : nStat;
371 
372  if (nPrint)
373  {
374  G4cout << "\n Voxelisation: top CPU users:" << G4endl;
375  G4cout << " Percent Total CPU System CPU Memory Volume\n"
376  << " ------- ---------- ---------- -------- ----------"
377  << G4endl;
378  // 12345678901.234567890123.234567890123.234567890123k .
379  }
380 
381  for(i=0;i<nPrint;++i)
382  {
383  G4double total = stats[i].GetTotalTime();
384  G4double system = stats[i].GetSysTime();
385  G4double perc = 0.0;
386 
387  if (system < 0) { system = 0.0; }
388  if ((total < 0) || (totalCpuTime < perMillion))
389  { total = 0; }
390  else
391  { perc = total*100/totalCpuTime; }
392 
393  G4cout << std::setprecision(2)
394  << std::setiosflags(std::ios::fixed|std::ios::right)
395  << std::setw(11) << perc
396  << std::setw(13) << total
397  << std::setw(13) << system
398  << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
399  << "k " << std::setiosflags(std::ios::left)
400  << stats[i].GetVolume()->GetName()
401  << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
402  << std::setprecision(6)
403  << G4endl;
404  }
405 
406  //
407  // Second list: sort by memory use
408  //
409  std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByMemory() );
410 
411  if (nPrint)
412  {
413  G4cout << "\n Voxelisation: top memory users:" << G4endl;
414  G4cout << " Percent Memory Heads Nodes Pointers Total CPU Volume\n"
415  << " ------- -------- ------ ------ -------- ---------- ----------"
416  << G4endl;
417  // 12345678901.2345678901k .23456789.23456789.2345678901.234567890123. .
418  }
419 
420  for(i=0;i<nPrint;++i)
421  {
422  G4long memory = stats[i].GetMemoryUse();
423  G4double totTime = stats[i].GetTotalTime();
424  if (totTime < 0) { totTime = 0.0; }
425 
426  G4cout << std::setprecision(2)
427  << std::setiosflags(std::ios::fixed|std::ios::right)
428  << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
429  << std::setw(11) << memory/1024 << "k "
430  << std::setw( 9) << stats[i].GetNumberHeads()
431  << std::setw( 9) << stats[i].GetNumberNodes()
432  << std::setw(11) << stats[i].GetNumberPointers()
433  << std::setw(13) << totTime << " "
434  << std::setiosflags(std::ios::left)
435  << stats[i].GetVolume()->GetName()
436  << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
437  << std::setprecision(6)
438  << G4endl;
439  }
440 }
G4SmartVoxelHeader * GetVoxelHeader() const
static G4ThreadLocal G4GeometryManager * fgInstance
G4double GetSystemElapsed() const
Definition: G4Timer.cc:119
virtual G4bool IsReplicated() const =0
long G4long
Definition: G4Types.hh:80
G4VPhysicalVolume * GetDaughter(const G4int i) const
#define G4ThreadLocal
Definition: tls.hh:89
void SetWorldMaximumExtent(G4double worldExtent)
int G4int
Definition: G4Types.hh:78
void SetVoxelHeader(G4SmartVoxelHeader *pVoxel)
void BuildOptimisations(G4bool allOpt, G4bool verbose=false)
G4GLOB_DLL std::ostream G4cout
bool G4bool
Definition: G4Types.hh:79
virtual G4int GetRegularStructureId() const =0
G4double GetUserElapsed() const
Definition: G4Timer.cc:130
static G4LogicalVolumeStore * GetInstance()
static G4SolidStore * GetInstance()
const G4int n
static G4GeometryManager * GetInstance()
G4LogicalVolume * GetMotherLogical() const
G4int GetNoDaughters() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static const double perMillion
Definition: G4SIunits.hh:331
G4LogicalVolume * GetLogicalVolume() const
G4double total(Particle const *const p1, Particle const *const p2)
static void ReportVoxelStats(std::vector< G4SmartVoxelStat > &stats, G4double totalCpuTime)
void Stop()
const G4int kMinVoxelVolumesLevel1
Definition: voxeldefs.hh:45
#define G4endl
Definition: G4ios.hh:61
void OpenGeometry(G4VPhysicalVolume *vol=0)
void Start()
const G4String & GetName() const
G4bool IsToOptimise() const
double G4double
Definition: G4Types.hh:76
static void SetSurfaceTolerance(G4double worldExtent)
G4bool CloseGeometry(G4bool pOptimise=true, G4bool verbose=false, G4VPhysicalVolume *vol=0)
static G4GeometryTolerance * GetInstance()