source: trunk/source/geometry/management/src/G4GeometryManager.cc @ 1340

Last change on this file since 1340 was 1340, checked in by garnier, 14 years ago

update ti head

File size: 15.0 KB
Line 
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,v 1.24 2010/07/16 15:52:57 gcosmo Exp $
28// GEANT4 tag $Name: geommng-V09-03-05 $
29//
30// class G4GeometryManager
31//
32// Implementation
33//
34// Author:
35// 26.07.95 P.Kent Initial version, including optimisation Build
36// --------------------------------------------------------------------
37
38#include <iomanip>
39#include "G4Timer.hh"
40#include "G4GeometryManager.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//
63G4GeometryManager* G4GeometryManager::fgInstance = 0;
64
65// ***************************************************************************
66// Constructor. Set the geometry to be open
67// ***************************************************************************
68//
69G4GeometryManager::G4GeometryManager() 
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//
81G4bool G4GeometryManager::CloseGeometry(G4bool pOptimise, G4bool verbose,
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//
105void G4GeometryManager::OpenGeometry(G4VPhysicalVolume* pVolume)
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//
125G4bool G4GeometryManager::IsGeometryClosed()
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//
135G4GeometryManager* G4GeometryManager::GetInstance()
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//
150void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose)
151{
152   G4Timer timer;
153   G4Timer allTimer;
154   std::vector<G4SmartVoxelStat> stats;
155   if (verbose)  { allTimer.Start(); }
156
157   G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
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         G4cerr << "ERROR - Allocation of new VoxelHeader" << G4endl
190                << "        for volume " << volume->GetName() << " failed."
191                << G4endl;
192         G4Exception("G4GeometryManager::BuildOptimisations()", "FatalError",
193                     FatalException, "VoxelHeader allocation error.");
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//
225void G4GeometryManager::BuildOptimisations(G4bool allOpts,
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       G4cerr << "ERROR - Allocation of new VoxelHeader" << G4endl
252              << "        for volume " << tVolume->GetName() << " failed."
253              << G4endl;
254       G4Exception("G4GeometryManager::BuildOptimisations()", "FatalError",
255                   FatalException, "VoxelHeader allocation error.");
256     }
257   }
258   else
259   {
260     // Don't create voxels for this node
261#ifdef G4GEOMETRY_VOXELDEBUG
262     G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
263            << "     Skipping logical volume name = " << tVolume->GetName()
264            << G4endl;
265#endif
266   }
267
268   // Scan recursively the associated logical volume tree
269   //
270  tVolume = pVolume->GetLogicalVolume();
271  if (tVolume->GetNoDaughters())
272  {
273    BuildOptimisations(allOpts, tVolume->GetDaughter(0));
274  }
275}
276
277// ***************************************************************************
278// Removes all optimisation info.
279// Loops over all logical volumes, deleting non-null voxels pointers,
280// ***************************************************************************
281//
282void G4GeometryManager::DeleteOptimisations()
283{
284  G4LogicalVolume* tVolume = 0;
285  G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
286  for (size_t n=0; n<Store->size(); n++)
287  {
288    tVolume=(*Store)[n];
289    delete tVolume->GetVoxelHeader();
290    tVolume->SetVoxelHeader(0);
291  }
292}
293
294// ***************************************************************************
295// Removes optimisation info for the specified subtree.
296// Scans recursively all daughter volumes, deleting non-null voxels pointers.
297// ***************************************************************************
298//
299void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume)
300{
301  if (!pVolume) { return; }
302
303  // Retrieve the mother logical volume, if not NULL,
304  // otherwise global deletion to world volume.
305  //
306  G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
307  if (!tVolume) { return DeleteOptimisations(); }
308  delete tVolume->GetVoxelHeader();
309  tVolume->SetVoxelHeader(0);
310
311  // Scan recursively the associated logical volume tree
312  //
313  tVolume = pVolume->GetLogicalVolume();
314  if (tVolume->GetNoDaughters())
315  {
316    DeleteOptimisations(tVolume->GetDaughter(0));
317  }
318}
319
320// ***************************************************************************
321// Sets the maximum extent of the world volume. The operation is allowed only
322// if NO solids have been created already.
323// ***************************************************************************
324//
325void G4GeometryManager::SetWorldMaximumExtent(G4double extent)
326{
327  if (G4SolidStore::GetInstance()->size())
328  {
329     // Sanity check to assure that extent is fixed BEFORE creating
330     // any geometry object (solids in this case)
331     //
332     G4Exception("G4GeometryManager::SetMaximumExtent()",
333                 "NotApplicable", FatalException,
334                 "Extent can be set only BEFORE creating any geometry object!");
335  }
336  G4GeometryTolerance::GetInstance()->SetSurfaceTolerance(extent);
337}
338
339// ***************************************************************************
340// Reports statistics on voxel optimisation when closing geometry.
341// ***************************************************************************
342//
343void
344G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
345                                     G4double totalCpuTime )
346{
347  G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
348         << G4endl << G4endl;
349 
350  //
351  // Get total memory use
352  //
353  G4int i, nStat = stats.size();
354  G4long totalMemory = 0;
355 
356  for( i=0;i<nStat;++i )  { totalMemory += stats[i].GetMemoryUse(); }
357 
358  G4cout << "    Total memory consumed for geometry optimisation:   "
359         << totalMemory/1024 << " kByte" << G4endl;
360  G4cout << "    Total CPU time elapsed for geometry optimisation: " 
361         << std::setprecision(2) << totalCpuTime << " seconds"
362         << std::setprecision(6) << G4endl;
363 
364  //
365  // First list: sort by total CPU time
366  //
367  std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByCpu() );
368         
369  G4int nPrint = nStat > 10 ? 10 : nStat;
370
371  if (nPrint)
372  {
373    G4cout << "\n    Voxelisation: top CPU users:" << G4endl;
374    G4cout << "    Percent   Total CPU    System CPU       Memory  Volume\n"
375           << "    -------   ----------   ----------     --------  ----------"
376           << G4endl;
377    //         12345678901.234567890123.234567890123.234567890123k .
378  }
379
380  for(i=0;i<nPrint;++i)
381  {
382    G4double total = stats[i].GetTotalTime();
383    G4double system = stats[i].GetSysTime();
384    G4double perc = 0.0;
385
386    if (system < 0) { system = 0.0; }
387    if ((total < 0) || (totalCpuTime < perMillion))
388      { total = 0; }
389    else
390      { perc = total*100/totalCpuTime; }
391
392    G4cout << std::setprecision(2) 
393           << std::setiosflags(std::ios::fixed|std::ios::right)
394           << std::setw(11) << perc
395           << std::setw(13) << total
396           << std::setw(13) << system
397           << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
398           << "k " << std::setiosflags(std::ios::left)
399           << stats[i].GetVolume()->GetName()
400           << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
401           << std::setprecision(6)
402           << G4endl;
403  }
404 
405  //
406  // Second list: sort by memory use
407  //
408  std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByMemory() );
409 
410  if (nPrint)
411  {
412    G4cout << "\n    Voxelisation: top memory users:" << G4endl;
413    G4cout << "    Percent     Memory      Heads    Nodes   Pointers    Total CPU    Volume\n"
414           << "    -------   --------     ------   ------   --------   ----------    ----------"
415           << G4endl;
416    //         12345678901.2345678901k .23456789.23456789.2345678901.234567890123.   .
417  }
418
419  for(i=0;i<nPrint;++i)
420  {
421    G4long memory = stats[i].GetMemoryUse();
422    G4double totTime = stats[i].GetTotalTime();
423    if (totTime < 0) { totTime = 0.0; }
424
425    G4cout << std::setprecision(2) 
426           << std::setiosflags(std::ios::fixed|std::ios::right)
427           << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
428           << std::setw(11) << memory/1024 << "k "
429           << std::setw( 9) << stats[i].GetNumberHeads()
430           << std::setw( 9) << stats[i].GetNumberNodes()
431           << std::setw(11) << stats[i].GetNumberPointers()
432           << std::setw(13) << totTime << "    "
433           << std::setiosflags(std::ios::left)
434           << stats[i].GetVolume()->GetName()
435           << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
436           << std::setprecision(6)
437           << G4endl;
438  }
439}
Note: See TracBrowser for help on using the repository browser.