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

Last change on this file since 834 was 831, checked in by garnier, 17 years ago

import all except CVS

File size: 14.9 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.19.2.1 2008/04/23 09:15:50 gcosmo Exp $
28// GEANT4 tag $Name: geant4-09-01-patch-02 $
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 {
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 G4cerr << "ERROR - Allocation of new VoxelHeader" << G4endl
189 << " for volume " << volume->GetName() << " failed."
190 << G4endl;
191 G4Exception("G4GeometryManager::BuildOptimisations()", "FatalError",
192 FatalException, "VoxelHeader allocation error.");
193 }
194 if (verbose)
195 {
196 timer.Stop();
197 stats.push_back( G4SmartVoxelStat( volume, head,
198 timer.GetSystemElapsed(),
199 timer.GetUserElapsed() ) );
200 }
201 }
202 else
203 {
204 // Don't create voxels for this node
205#ifdef G4GEOMETRY_VOXELDEBUG
206 G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
207 << " Skipping logical volume name = " << volume->GetName()
208 << G4endl;
209#endif
210 }
211 }
212 if (verbose)
213 {
214 allTimer.Stop();
215 ReportVoxelStats( stats, allTimer.GetSystemElapsed()
216 + allTimer.GetUserElapsed() );
217 }
218}
219
220// ***************************************************************************
221// Creates optimisation info for the specified volumes subtree.
222// ***************************************************************************
223//
224void G4GeometryManager::BuildOptimisations(G4bool allOpts,
225 G4VPhysicalVolume* pVolume)
226{
227 if (!pVolume) { return; }
228
229 // Retrieve the mother logical volume, if not NULL,
230 // otherwise apply global optimisation for the world volume
231 //
232 G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
233 if (!tVolume) { return BuildOptimisations(allOpts, false); }
234
235 G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
236 delete head;
237 tVolume->SetVoxelHeader(0);
238 if ( ( (tVolume->IsToOptimise())
239 && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
240 || ( (tVolume->GetNoDaughters()==1)
241 && (tVolume->GetDaughter(0)->IsReplicated()==true) ) )
242 {
243 head = new G4SmartVoxelHeader(tVolume);
244 if (head)
245 {
246 tVolume->SetVoxelHeader(head);
247 }
248 else
249 {
250 G4cerr << "ERROR - Allocation of new VoxelHeader" << G4endl
251 << " for volume " << tVolume->GetName() << " failed."
252 << G4endl;
253 G4Exception("G4GeometryManager::BuildOptimisations()", "FatalError",
254 FatalException, "VoxelHeader allocation error.");
255 }
256 }
257 else
258 {
259 // Don't create voxels for this node
260#ifdef G4GEOMETRY_VOXELDEBUG
261 G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
262 << " Skipping logical volume name = " << volume->GetName()
263 << G4endl;
264#endif
265 }
266
267 // Scan recursively the associated logical volume tree
268 //
269 tVolume = pVolume->GetLogicalVolume();
270 if (tVolume->GetNoDaughters())
271 {
272 BuildOptimisations(allOpts, tVolume->GetDaughter(0));
273 }
274}
275
276// ***************************************************************************
277// Removes all optimisation info.
278// Loops over all logical volumes, deleting non-null voxels pointers,
279// ***************************************************************************
280//
281void G4GeometryManager::DeleteOptimisations()
282{
283 G4LogicalVolume* tVolume = 0;
284 G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
285 for (size_t n=0; n<Store->size(); n++)
286 {
287 tVolume=(*Store)[n];
288 delete tVolume->GetVoxelHeader();
289 tVolume->SetVoxelHeader(0);
290 }
291}
292
293// ***************************************************************************
294// Removes optimisation info for the specified subtree.
295// Scans recursively all daughter volumes, deleting non-null voxels pointers.
296// ***************************************************************************
297//
298void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume)
299{
300 if (!pVolume) { return; }
301
302 // Retrieve the mother logical volume, if not NULL,
303 // otherwise global deletion to world volume.
304 //
305 G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
306 if (!tVolume) { return DeleteOptimisations(); }
307 delete tVolume->GetVoxelHeader();
308 tVolume->SetVoxelHeader(0);
309
310 // Scan recursively the associated logical volume tree
311 //
312 tVolume = pVolume->GetLogicalVolume();
313 if (tVolume->GetNoDaughters())
314 {
315 DeleteOptimisations(tVolume->GetDaughter(0));
316 }
317}
318
319// ***************************************************************************
320// Sets the maximum extent of the world volume. The operation is allowed only
321// if NO solids have been created already.
322// ***************************************************************************
323//
324void G4GeometryManager::SetWorldMaximumExtent(G4double extent)
325{
326 if (G4SolidStore::GetInstance()->size())
327 {
328 // Sanity check to assure that extent is fixed BEFORE creating
329 // any geometry object (solids in this case)
330 //
331 G4Exception("G4GeometryManager::SetMaximumExtent()",
332 "NotApplicable", FatalException,
333 "Extent can be set only BEFORE creating any geometry object!");
334 }
335 G4GeometryTolerance::GetInstance()->SetSurfaceTolerance(extent);
336}
337
338// ***************************************************************************
339// Reports statistics on voxel optimisation when closing geometry.
340// ***************************************************************************
341//
342void
343G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
344 G4double totalCpuTime )
345{
346 G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
347 << G4endl << G4endl;
348
349 //
350 // Get total memory use
351 //
352 G4int i, nStat = stats.size();
353 G4long totalMemory = 0;
354
355 for( i=0;i<nStat;++i ) { totalMemory += stats[i].GetMemoryUse(); }
356
357 G4cout << " Total memory consumed for geometry optimisation: "
358 << totalMemory/1024 << " kByte" << G4endl;
359 G4cout << " Total CPU time elapsed for geometry optimisation: "
360 << std::setprecision(2) << totalCpuTime << " seconds" << G4endl;
361
362 //
363 // First list: sort by total CPU time
364 //
365 std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByCpu() );
366
367 G4int nPrint = nStat > 10 ? 10 : nStat;
368
369 if (nPrint)
370 {
371 G4cout << "\n Voxelisation: top CPU users:" << G4endl;
372 G4cout << " Percent Total CPU System CPU Memory Volume\n"
373 << " ------- ---------- ---------- -------- ----------"
374 << G4endl;
375 // 12345678901.234567890123.234567890123.234567890123k .
376 }
377
378 for(i=0;i<nPrint;++i)
379 {
380 G4double total = stats[i].GetTotalTime();
381 G4double system = stats[i].GetSysTime();
382 G4double perc = 0.0;
383
384 if (system < 0) { system = 0.0; }
385 if ((total < 0) || (totalCpuTime < perMillion))
386 { total = 0; }
387 else
388 { perc = total*100/totalCpuTime; }
389
390 G4cout << std::setprecision(2)
391 << std::setiosflags(std::ios::fixed|std::ios::right)
392 << std::setw(11) << perc
393 << std::setw(13) << total
394 << std::setw(13) << system
395 << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
396 << "k " << std::setiosflags(std::ios::left)
397 << stats[i].GetVolume()->GetName()
398 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
399 << std::setprecision(6)
400 << G4endl;
401 }
402
403 //
404 // Second list: sort by memory use
405 //
406 std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByMemory() );
407
408 if (nPrint)
409 {
410 G4cout << "\n Voxelisation: top memory users:" << G4endl;
411 G4cout << " Percent Memory Heads Nodes Pointers Total CPU Volume\n"
412 << " ------- -------- ------ ------ -------- ---------- ----------"
413 << G4endl;
414 // 12345678901.2345678901k .23456789.23456789.2345678901.234567890123. .
415 }
416
417 for(i=0;i<nPrint;++i)
418 {
419 G4long memory = stats[i].GetMemoryUse();
420 G4double totTime = stats[i].GetTotalTime();
421 if (totTime < 0) { totTime = 0.0; }
422
423 G4cout << std::setprecision(2)
424 << std::setiosflags(std::ios::fixed|std::ios::right)
425 << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
426 << std::setw(11) << memory/1024 << "k "
427 << std::setw( 9) << stats[i].GetNumberHeads()
428 << std::setw( 9) << stats[i].GetNumberNodes()
429 << std::setw(11) << stats[i].GetNumberPointers()
430 << std::setw(13) << totTime << " "
431 << std::setiosflags(std::ios::left)
432 << stats[i].GetVolume()->GetName()
433 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
434 << std::setprecision(6)
435 << G4endl;
436 }
437}
Note: See TracBrowser for help on using the repository browser.