Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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$
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 //
63 G4GeometryManager* G4GeometryManager::fgInstance = 0;
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  {
115  DeleteOptimisations();
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  static G4GeometryManager worldManager;
138  if (!fgInstance)
139  {
140  fgInstance = &worldManager;
141  }
142  return fgInstance;
143 }
144 
145 // ***************************************************************************
146 // Creates optimisation info. Builds all voxels if allOpts=true
147 // otherwise it builds voxels only for replicated volumes.
148 // ***************************************************************************
149 //
150 void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose)
151 {
152  G4Timer timer;
153  G4Timer allTimer;
154  std::vector<G4SmartVoxelStat> stats;
155  if (verbose) { allTimer.Start(); }
156 
158  G4LogicalVolume* volume;
159  G4SmartVoxelHeader* head;
160 
161  for (size_t n=0; n<Store->size(); n++)
162  {
163  if (verbose) timer.Start();
164  volume=(*Store)[n];
165  // For safety, check if there are any existing voxels and
166  // delete before replacement
167  //
168  head = volume->GetVoxelHeader();
169  delete head;
170  volume->SetVoxelHeader(0);
171  if ( ( (volume->IsToOptimise())
172  && (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
173  || ( (volume->GetNoDaughters()==1)
174  && (volume->GetDaughter(0)->IsReplicated()==true)
175  && (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) )
176  {
177 #ifdef G4GEOMETRY_VOXELDEBUG
178  G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
179  << " Examining logical volume name = "
180  << volume->GetName() << G4endl;
181 #endif
182  head = new G4SmartVoxelHeader(volume);
183  if (head)
184  {
185  volume->SetVoxelHeader(head);
186  }
187  else
188  {
189  std::ostringstream message;
190  message << "VoxelHeader allocation error." << G4endl
191  << "Allocation of new VoxelHeader" << G4endl
192  << " for volume " << volume->GetName() << " failed.";
193  G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
194  FatalException, message);
195  }
196  if (verbose)
197  {
198  timer.Stop();
199  stats.push_back( G4SmartVoxelStat( volume, head,
200  timer.GetSystemElapsed(),
201  timer.GetUserElapsed() ) );
202  }
203  }
204  else
205  {
206  // Don't create voxels for this node
207 #ifdef G4GEOMETRY_VOXELDEBUG
208  G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
209  << " Skipping logical volume name = " << volume->GetName()
210  << G4endl;
211 #endif
212  }
213  }
214  if (verbose)
215  {
216  allTimer.Stop();
217  ReportVoxelStats( stats, allTimer.GetSystemElapsed()
218  + allTimer.GetUserElapsed() );
219  }
220 }
221 
222 // ***************************************************************************
223 // Creates optimisation info for the specified volumes subtree.
224 // ***************************************************************************
225 //
226 void G4GeometryManager::BuildOptimisations(G4bool allOpts,
227  G4VPhysicalVolume* pVolume)
228 {
229  if (!pVolume) { return; }
230 
231  // Retrieve the mother logical volume, if not NULL,
232  // otherwise apply global optimisation for the world volume
233  //
234  G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
235  if (!tVolume) { return BuildOptimisations(allOpts, false); }
236 
237  G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
238  delete head;
239  tVolume->SetVoxelHeader(0);
240  if ( ( (tVolume->IsToOptimise())
241  && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
242  || ( (tVolume->GetNoDaughters()==1)
243  && (tVolume->GetDaughter(0)->IsReplicated()==true) ) )
244  {
245  head = new G4SmartVoxelHeader(tVolume);
246  if (head)
247  {
248  tVolume->SetVoxelHeader(head);
249  }
250  else
251  {
252  std::ostringstream message;
253  message << "VoxelHeader allocation error." << G4endl
254  << "Allocation of new VoxelHeader" << G4endl
255  << " for volume " << tVolume->GetName() << " failed.";
256  G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
257  FatalException, message);
258  }
259  }
260  else
261  {
262  // Don't create voxels for this node
263 #ifdef G4GEOMETRY_VOXELDEBUG
264  G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
265  << " Skipping logical volume name = " << tVolume->GetName()
266  << G4endl;
267 #endif
268  }
269 
270  // Scan recursively the associated logical volume tree
271  //
272  tVolume = pVolume->GetLogicalVolume();
273  if (tVolume->GetNoDaughters())
274  {
275  BuildOptimisations(allOpts, tVolume->GetDaughter(0));
276  }
277 }
278 
279 // ***************************************************************************
280 // Removes all optimisation info.
281 // Loops over all logical volumes, deleting non-null voxels pointers,
282 // ***************************************************************************
283 //
284 void G4GeometryManager::DeleteOptimisations()
285 {
286  G4LogicalVolume* tVolume = 0;
288  for (size_t n=0; n<Store->size(); n++)
289  {
290  tVolume=(*Store)[n];
291  delete tVolume->GetVoxelHeader();
292  tVolume->SetVoxelHeader(0);
293  }
294 }
295 
296 // ***************************************************************************
297 // Removes optimisation info for the specified subtree.
298 // Scans recursively all daughter volumes, deleting non-null voxels pointers.
299 // ***************************************************************************
300 //
301 void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume)
302 {
303  if (!pVolume) { return; }
304 
305  // Retrieve the mother logical volume, if not NULL,
306  // otherwise global deletion to world volume.
307  //
308  G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
309  if (!tVolume) { return DeleteOptimisations(); }
310  delete tVolume->GetVoxelHeader();
311  tVolume->SetVoxelHeader(0);
312 
313  // Scan recursively the associated logical volume tree
314  //
315  tVolume = pVolume->GetLogicalVolume();
316  if (tVolume->GetNoDaughters())
317  {
318  DeleteOptimisations(tVolume->GetDaughter(0));
319  }
320 }
321 
322 // ***************************************************************************
323 // Sets the maximum extent of the world volume. The operation is allowed only
324 // if NO solids have been created already.
325 // ***************************************************************************
326 //
328 {
329  if (G4SolidStore::GetInstance()->size())
330  {
331  // Sanity check to assure that extent is fixed BEFORE creating
332  // any geometry object (solids in this case)
333  //
334  G4Exception("G4GeometryManager::SetMaximumExtent()",
335  "GeomMgt0003", FatalException,
336  "Extent can be set only BEFORE creating any geometry object!");
337  }
339 }
340 
341 // ***************************************************************************
342 // Reports statistics on voxel optimisation when closing geometry.
343 // ***************************************************************************
344 //
345 void
346 G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
347  G4double totalCpuTime )
348 {
349  G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
350  << G4endl << G4endl;
351 
352  //
353  // Get total memory use
354  //
355  G4int i, nStat = stats.size();
356  G4long totalMemory = 0;
357 
358  for( i=0;i<nStat;++i ) { totalMemory += stats[i].GetMemoryUse(); }
359 
360  G4cout << " Total memory consumed for geometry optimisation: "
361  << totalMemory/1024 << " kByte" << G4endl;
362  G4cout << " Total CPU time elapsed for geometry optimisation: "
363  << std::setprecision(2) << totalCpuTime << " seconds"
364  << std::setprecision(6) << G4endl;
365 
366  //
367  // First list: sort by total CPU time
368  //
369  std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByCpu() );
370 
371  G4int nPrint = nStat > 10 ? 10 : nStat;
372 
373  if (nPrint)
374  {
375  G4cout << "\n Voxelisation: top CPU users:" << G4endl;
376  G4cout << " Percent Total CPU System CPU Memory Volume\n"
377  << " ------- ---------- ---------- -------- ----------"
378  << G4endl;
379  // 12345678901.234567890123.234567890123.234567890123k .
380  }
381 
382  for(i=0;i<nPrint;++i)
383  {
384  G4double total = stats[i].GetTotalTime();
385  G4double system = stats[i].GetSysTime();
386  G4double perc = 0.0;
387 
388  if (system < 0) { system = 0.0; }
389  if ((total < 0) || (totalCpuTime < perMillion))
390  { total = 0; }
391  else
392  { perc = total*100/totalCpuTime; }
393 
394  G4cout << std::setprecision(2)
395  << std::setiosflags(std::ios::fixed|std::ios::right)
396  << std::setw(11) << perc
397  << std::setw(13) << total
398  << std::setw(13) << system
399  << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
400  << "k " << std::setiosflags(std::ios::left)
401  << stats[i].GetVolume()->GetName()
402  << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
403  << std::setprecision(6)
404  << G4endl;
405  }
406 
407  //
408  // Second list: sort by memory use
409  //
410  std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByMemory() );
411 
412  if (nPrint)
413  {
414  G4cout << "\n Voxelisation: top memory users:" << G4endl;
415  G4cout << " Percent Memory Heads Nodes Pointers Total CPU Volume\n"
416  << " ------- -------- ------ ------ -------- ---------- ----------"
417  << G4endl;
418  // 12345678901.2345678901k .23456789.23456789.2345678901.234567890123. .
419  }
420 
421  for(i=0;i<nPrint;++i)
422  {
423  G4long memory = stats[i].GetMemoryUse();
424  G4double totTime = stats[i].GetTotalTime();
425  if (totTime < 0) { totTime = 0.0; }
426 
427  G4cout << std::setprecision(2)
428  << std::setiosflags(std::ios::fixed|std::ios::right)
429  << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
430  << std::setw(11) << memory/1024 << "k "
431  << std::setw( 9) << stats[i].GetNumberHeads()
432  << std::setw( 9) << stats[i].GetNumberNodes()
433  << std::setw(11) << stats[i].GetNumberPointers()
434  << std::setw(13) << totTime << " "
435  << std::setiosflags(std::ios::left)
436  << stats[i].GetVolume()->GetName()
437  << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
438  << std::setprecision(6)
439  << G4endl;
440  }
441 }