Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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//
49#include "G4VPhysicalVolume.hh"
50#include "G4SmartVoxelHeader.hh"
51#include "voxeldefs.hh"
52
53// Needed for setting the extent for tolerance value
54//
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//
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//
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
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//
226void 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//
284void 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//
301void 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//
345void
346G4GeometryManager::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}
@ FatalException
double G4double
Definition: G4Types.hh:64
long G4long
Definition: G4Types.hh:68
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
G4bool CloseGeometry(G4bool pOptimise=true, G4bool verbose=false, G4VPhysicalVolume *vol=0)
void OpenGeometry(G4VPhysicalVolume *vol=0)
static G4GeometryManager * GetInstance()
void SetWorldMaximumExtent(G4double worldExtent)
static void SetSurfaceTolerance(G4double worldExtent)
static G4GeometryTolerance * GetInstance()
static G4LogicalVolumeStore * GetInstance()
G4int GetNoDaughters() const
G4String GetName() const
void SetVoxelHeader(G4SmartVoxelHeader *pVoxel)
G4VPhysicalVolume * GetDaughter(const G4int i) const
G4bool IsToOptimise() const
G4SmartVoxelHeader * GetVoxelHeader() const
static G4SolidStore * GetInstance()
void Stop()
G4double GetSystemElapsed() const
Definition: G4Timer.cc:119
G4double GetUserElapsed() const
Definition: G4Timer.cc:130
void Start()
G4LogicalVolume * GetMotherLogical() const
virtual G4bool IsReplicated() const =0
G4LogicalVolume * GetLogicalVolume() const
virtual G4int GetRegularStructureId() const =0
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
const G4int kMinVoxelVolumesLevel1
Definition: voxeldefs.hh:45