Geant4 10.7.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// Class G4GeometryManager implementation
27//
28// 26.07.95, P.Kent - Initial version, including optimisation build
29// --------------------------------------------------------------------
30
31#include <iomanip>
32#include "G4Timer.hh"
33#include "G4GeometryManager.hh"
34#include "G4SystemOfUnits.hh"
35
36#ifdef G4GEOMETRY_VOXELDEBUG
37#include "G4ios.hh"
38#endif
39
40// Needed for building optimisations
41//
43#include "G4VPhysicalVolume.hh"
44#include "G4SmartVoxelHeader.hh"
45#include "voxeldefs.hh"
46
47// Needed for setting the extent for tolerance value
48//
50#include "G4SolidStore.hh"
51#include "G4VSolid.hh"
52
53// ***************************************************************************
54// Static class data
55// ***************************************************************************
56//
57G4ThreadLocal G4GeometryManager* G4GeometryManager::fgInstance = nullptr;
58G4ThreadLocal G4bool G4GeometryManager::fIsClosed = false;
59
60// ***************************************************************************
61// Constructor. Set the geometry to be open
62// ***************************************************************************
63//
65{
66}
67
68// ***************************************************************************
69// Destructor
70// ***************************************************************************
71//
73{
74 fgInstance = nullptr;
75 fIsClosed = false;
76}
77
78// ***************************************************************************
79// Closes geometry - performs sanity checks and optionally builds optimisation
80// for placed volumes (always built for replicas & parameterised).
81// NOTE: Currently no sanity checks are performed.
82// Applies to just a specific subtree if a physical volume is specified.
83// ***************************************************************************
84//
86 G4VPhysicalVolume* pVolume)
87{
88 if (!fIsClosed)
89 {
90 if (pVolume != nullptr)
91 {
92 BuildOptimisations(pOptimise, pVolume);
93 }
94 else
95 {
96 BuildOptimisations(pOptimise, verbose);
97 }
98 fIsClosed = true;
99 }
100 return true;
101}
102
103// ***************************************************************************
104// Opens the geometry and removes optimisations (optionally, related to just
105// the specified logical-volume).
106// Applies to just a specific subtree if a physical volume is specified.
107// ***************************************************************************
108//
110{
111 if (fIsClosed)
112 {
113 if (pVolume != nullptr)
114 {
115 DeleteOptimisations(pVolume);
116 }
117 else
118 {
119 DeleteOptimisations();
120 }
121 fIsClosed = false;
122 }
123}
124
125// ***************************************************************************
126// Returns status of geometry
127// ***************************************************************************
128//
130{
131 return fIsClosed;
132}
133
134// ***************************************************************************
135// Returns the instance of the singleton.
136// Creates it in case it's called for the first time.
137// ***************************************************************************
138//
140{
141 if (fgInstance == nullptr)
142 {
143 fgInstance = new G4GeometryManager;
144 }
145 return fgInstance;
146}
147
148// ***************************************************************************
149// Returns the instance of the singleton.
150// ***************************************************************************
151//
153{
154 return fgInstance;
155}
156
157// ***************************************************************************
158// Creates optimisation info. Builds all voxels if allOpts=true
159// otherwise it builds voxels only for replicated volumes.
160// ***************************************************************************
161//
162void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose)
163{
164 G4Timer timer;
165 G4Timer allTimer;
166 std::vector<G4SmartVoxelStat> stats;
167 if (verbose) { allTimer.Start(); }
168
170 G4LogicalVolume* volume;
171 G4SmartVoxelHeader* head;
172
173 for (size_t n=0; n<Store->size(); ++n)
174 {
175 if (verbose) timer.Start();
176 volume=(*Store)[n];
177 // For safety, check if there are any existing voxels and
178 // delete before replacement
179 //
180 head = volume->GetVoxelHeader();
181 delete head;
182 volume->SetVoxelHeader(0);
183 if ( ( (volume->IsToOptimise())
184 && (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
185 || ( (volume->GetNoDaughters()==1)
186 && (volume->GetDaughter(0)->IsReplicated()==true)
187 && (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) )
188 {
189#ifdef G4GEOMETRY_VOXELDEBUG
190 G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
191 << " Examining logical volume name = "
192 << volume->GetName() << G4endl;
193#endif
194 head = new G4SmartVoxelHeader(volume);
195 if (head != nullptr)
196 {
197 volume->SetVoxelHeader(head);
198 }
199 else
200 {
201 std::ostringstream message;
202 message << "VoxelHeader allocation error." << G4endl
203 << "Allocation of new VoxelHeader" << G4endl
204 << " for volume " << volume->GetName() << " failed.";
205 G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
206 FatalException, message);
207 }
208 if (verbose)
209 {
210 timer.Stop();
211 stats.push_back( G4SmartVoxelStat( volume, head,
212 timer.GetSystemElapsed(),
213 timer.GetUserElapsed() ) );
214 }
215 }
216 else
217 {
218 // Don't create voxels for this node
219#ifdef G4GEOMETRY_VOXELDEBUG
220 G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
221 << " Skipping logical volume name = " << volume->GetName()
222 << G4endl;
223#endif
224 }
225 }
226 if (verbose)
227 {
228 allTimer.Stop();
229 ReportVoxelStats( stats, allTimer.GetSystemElapsed()
230 + allTimer.GetUserElapsed() );
231 }
232}
233
234// ***************************************************************************
235// Creates optimisation info for the specified volumes subtree.
236// ***************************************************************************
237//
238void G4GeometryManager::BuildOptimisations(G4bool allOpts,
239 G4VPhysicalVolume* pVolume)
240{
241 if (pVolume == nullptr) { return; }
242
243 // Retrieve the mother logical volume, if not NULL,
244 // otherwise apply global optimisation for the world volume
245 //
246 G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
247 if (tVolume == nullptr) { return BuildOptimisations(allOpts, false); }
248
249 G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
250 delete head;
251 tVolume->SetVoxelHeader(nullptr);
252 if ( ( (tVolume->IsToOptimise())
253 && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
254 || ( (tVolume->GetNoDaughters()==1)
255 && (tVolume->GetDaughter(0)->IsReplicated()==true) ) )
256 {
257 head = new G4SmartVoxelHeader(tVolume);
258 if (head != nullptr)
259 {
260 tVolume->SetVoxelHeader(head);
261 }
262 else
263 {
264 std::ostringstream message;
265 message << "VoxelHeader allocation error." << G4endl
266 << "Allocation of new VoxelHeader" << G4endl
267 << " for volume " << tVolume->GetName() << " failed.";
268 G4Exception("G4GeometryManager::BuildOptimisations()", "GeomMgt0003",
269 FatalException, message);
270 }
271 }
272 else
273 {
274 // Don't create voxels for this node
275#ifdef G4GEOMETRY_VOXELDEBUG
276 G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl
277 << " Skipping logical volume name = " << tVolume->GetName()
278 << G4endl;
279#endif
280 }
281
282 // Scan recursively the associated logical volume tree
283 //
284 tVolume = pVolume->GetLogicalVolume();
285 if (tVolume->GetNoDaughters())
286 {
287 BuildOptimisations(allOpts, tVolume->GetDaughter(0));
288 }
289}
290
291// ***************************************************************************
292// Removes all optimisation info.
293// Loops over all logical volumes, deleting non-null voxels pointers,
294// ***************************************************************************
295//
296void G4GeometryManager::DeleteOptimisations()
297{
298 G4LogicalVolume* tVolume = nullptr;
300 for (size_t n=0; n<Store->size(); ++n)
301 {
302 tVolume=(*Store)[n];
303 delete tVolume->GetVoxelHeader();
304 tVolume->SetVoxelHeader(nullptr);
305 }
306}
307
308// ***************************************************************************
309// Removes optimisation info for the specified subtree.
310// Scans recursively all daughter volumes, deleting non-null voxels pointers.
311// ***************************************************************************
312//
313void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume)
314{
315 if (!pVolume) { return; }
316
317 // Retrieve the mother logical volume, if not NULL,
318 // otherwise global deletion to world volume.
319 //
320 G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
321 if (tVolume == nullptr) { return DeleteOptimisations(); }
322 delete tVolume->GetVoxelHeader();
323 tVolume->SetVoxelHeader(nullptr);
324
325 // Scan recursively the associated logical volume tree
326 //
327 tVolume = pVolume->GetLogicalVolume();
328 if (tVolume->GetNoDaughters())
329 {
330 DeleteOptimisations(tVolume->GetDaughter(0));
331 }
332}
333
334// ***************************************************************************
335// Sets the maximum extent of the world volume. The operation is allowed only
336// if NO solids have been created already.
337// ***************************************************************************
338//
340{
341 if (G4SolidStore::GetInstance()->size())
342 {
343 // Sanity check to assure that extent is fixed BEFORE creating
344 // any geometry object (solids in this case)
345 //
346 G4Exception("G4GeometryManager::SetMaximumExtent()",
347 "GeomMgt0003", FatalException,
348 "Extent can be set only BEFORE creating any geometry object!");
349 }
351}
352
353// ***************************************************************************
354// Reports statistics on voxel optimisation when closing geometry.
355// ***************************************************************************
356//
357void
358G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
359 G4double totalCpuTime )
360{
361 G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
362 << G4endl << G4endl;
363
364 //
365 // Get total memory use
366 //
367 G4int i, nStat = stats.size();
368 G4long totalMemory = 0;
369
370 for( i=0; i<nStat; ++i ) { totalMemory += stats[i].GetMemoryUse(); }
371
372 G4cout << " Total memory consumed for geometry optimisation: "
373 << totalMemory/1024 << " kByte" << G4endl;
374 G4cout << " Total CPU time elapsed for geometry optimisation: "
375 << std::setprecision(2) << totalCpuTime << " seconds"
376 << std::setprecision(6) << G4endl;
377
378 //
379 // First list: sort by total CPU time
380 //
381 std::sort( stats.begin(), stats.end(),
382 [](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
383 {
384 return a.GetTotalTime() > b.GetTotalTime();
385 } );
386
387 G4int nPrint = nStat > 10 ? 10 : nStat;
388
389 if (nPrint)
390 {
391 G4cout << "\n Voxelisation: top CPU users:" << G4endl;
392 G4cout << " Percent Total CPU System CPU Memory Volume\n"
393 << " ------- ---------- ---------- -------- ----------"
394 << G4endl;
395 // 12345678901.234567890123.234567890123.234567890123k .
396 }
397
398 for(i=0; i<nPrint; ++i)
399 {
400 G4double total = stats[i].GetTotalTime();
401 G4double system = stats[i].GetSysTime();
402 G4double perc = 0.0;
403
404 if (system < 0) { system = 0.0; }
405 if ((total < 0) || (totalCpuTime < perMillion))
406 { total = 0; }
407 else
408 { perc = total*100/totalCpuTime; }
409
410 G4cout << std::setprecision(2)
411 << std::setiosflags(std::ios::fixed|std::ios::right)
412 << std::setw(11) << perc
413 << std::setw(13) << total
414 << std::setw(13) << system
415 << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
416 << "k " << std::setiosflags(std::ios::left)
417 << stats[i].GetVolume()->GetName()
418 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
419 << std::setprecision(6)
420 << G4endl;
421 }
422
423 //
424 // Second list: sort by memory use
425 //
426 std::sort( stats.begin(), stats.end(),
427 [](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
428 {
429 return a.GetMemoryUse() > b.GetMemoryUse();
430 } );
431
432 if (nPrint)
433 {
434 G4cout << "\n Voxelisation: top memory users:" << G4endl;
435 G4cout << " Percent Memory Heads Nodes Pointers Total CPU Volume\n"
436 << " ------- -------- ------ ------ -------- ---------- ----------"
437 << G4endl;
438 // 12345678901.2345678901k .23456789.23456789.2345678901.234567890123. .
439 }
440
441 for(i=0; i<nPrint; ++i)
442 {
443 G4long memory = stats[i].GetMemoryUse();
444 G4double totTime = stats[i].GetTotalTime();
445 if (totTime < 0) { totTime = 0.0; }
446
447 G4cout << std::setprecision(2)
448 << std::setiosflags(std::ios::fixed|std::ios::right)
449 << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
450 << std::setw(11) << memory/1024 << "k "
451 << std::setw( 9) << stats[i].GetNumberHeads()
452 << std::setw( 9) << stats[i].GetNumberNodes()
453 << std::setw(11) << stats[i].GetNumberPointers()
454 << std::setw(13) << totTime << " "
455 << std::setiosflags(std::ios::left)
456 << stats[i].GetVolume()->GetName()
457 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
458 << std::setprecision(6)
459 << G4endl;
460 }
461}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
static G4bool IsGeometryClosed()
static G4GeometryManager * GetInstance()
G4bool CloseGeometry(G4bool pOptimise=true, G4bool verbose=false, G4VPhysicalVolume *vol=nullptr)
void SetWorldMaximumExtent(G4double worldExtent)
void OpenGeometry(G4VPhysicalVolume *vol=nullptr)
static G4GeometryManager * GetInstanceIfExist()
void SetSurfaceTolerance(G4double worldExtent)
static G4GeometryTolerance * GetInstance()
static G4LogicalVolumeStore * GetInstance()
void SetVoxelHeader(G4SmartVoxelHeader *pVoxel)
size_t GetNoDaughters() const
G4VPhysicalVolume * GetDaughter(const G4int i) const
G4bool IsToOptimise() const
const G4String & GetName() const
G4SmartVoxelHeader * GetVoxelHeader() const
static G4SolidStore * GetInstance()
void Stop()
G4double GetSystemElapsed() const
Definition: G4Timer.cc:132
G4double GetUserElapsed() const
Definition: G4Timer.cc:143
void Start()
G4LogicalVolume * GetMotherLogical() const
virtual G4bool IsReplicated() const =0
G4LogicalVolume * GetLogicalVolume() const
virtual G4int GetRegularStructureId() const =0
G4double total(Particle const *const p1, Particle const *const p2)
#define G4ThreadLocal
Definition: tls.hh:77
const G4int kMinVoxelVolumesLevel1
Definition: voxeldefs.hh:39