Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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