81G4bool G4GeometryManager::fParallelVoxelOptimisationRequested =
false;
84G4bool G4GeometryManager::fOptimiseInParallelConfigured =
false;
88std::vector<G4LogicalVolume*> G4GeometryManager::fVolumesToOptimise;
89std::vector<G4LogicalVolume*>::const_iterator G4GeometryManager::fLogVolumeIterator;
91std::vector<G4SmartVoxelStat> G4GeometryManager::fGlobVoxelStats;
95G4bool G4GeometryManager::fVerboseParallel =
false;
96G4bool G4GeometryManager::fParallelVoxelOptimisationUnderway =
false;
97G4bool G4GeometryManager::fParallelVoxelOptimisationFinished =
false;
98G4double G4GeometryManager::fSumVoxelTime = 0.0;
100G4int G4GeometryManager::fNumberThreadsReporting = 0;
101unsigned int G4GeometryManager::fTotalNumberVolumesOptimised = 0U;
104G4Timer* G4GeometryManager::fWallClockTimer =
nullptr;
105G4bool G4GeometryManager::fWallClockStarted =
false;
113 fgInstance =
nullptr;
118 delete fWallClockTimer;
119 fWallClockTimer=
nullptr;
135 if (pVolume !=
nullptr)
137 BuildOptimisations(pOptimise, pVolume);
141 BuildOptimisations(pOptimise, verbose);
158 if (pVolume !=
nullptr)
160 DeleteOptimisations(pVolume);
164 DeleteOptimisations();
177 if (fgInstance ==
nullptr)
179 fgInstance =
new G4GeometryManager;
212G4GeometryManager::ReportVoxelInfo(
G4LogicalVolume* logVolume, std::ostream& os)
215 if( head !=
nullptr )
217 os <<
"** Created optimisations for logical-volume '"
219 <<
"- Result VoxelInfo - START: " <<
" ptr= " << head <<
G4endl
221 <<
"- Result VoxelInfo - END. " <<
G4endl;
225 os <<
"** No optimisation for log-vol " << logVolume->
GetName() <<
G4endl;
227 os <<
"*** Report Voxel Info: END " <<
G4endl;
238 G4bool finishedOptimisation =
false;
240 fOptimiseInParallelConfigured = fParallelVoxelOptimisationRequested
243 static unsigned int NumCallsBuildOptimisations = 0;
244 if( fOptimiseInParallelConfigured && (NumCallsBuildOptimisations==0) )
246 PrepareParallelOptimisation(allOpts, verbose);
247 ++NumCallsBuildOptimisations;
251 BuildOptimisationsSequential(allOpts, verbose);
252 finishedOptimisation=
true;
255 return finishedOptimisation;
267void G4GeometryManager::BuildOptimisationsSequential(
G4bool allOpts,
272 std::vector<G4SmartVoxelStat> stats;
274 if (verbose) { allTimer.
Start(); }
277 G4LogicalVolume* volume;
278 G4SmartVoxelHeader* head;
280#ifdef G4GEOMETRY_VOXELDEBUG
282 <<
"*** G4GeometryManager::BuildOptimisationsSequential() called on tid "
286 for (
auto & n : *Store)
288 if (verbose) timer.
Start();
302#ifdef G4GEOMETRY_VOXELDEBUG
303 G4cout <<
"** G4GeometryManager::BuildOptimisationsSequential()"
304 <<
" Examining logical volume name = '" << volume->
GetName()
307 head =
new G4SmartVoxelHeader(volume);
315 std::ostringstream message;
316 message <<
"VoxelHeader allocation error." <<
G4endl
317 <<
"Allocation of new VoxelHeader" <<
G4endl
318 <<
" for volume '" << volume->
GetName() <<
"' failed.";
319 G4Exception(
"G4GeometryManager::BuildOptimisations()",
"GeomMgt0003",
325 stats.emplace_back( volume, head,
333#ifdef G4GEOMETRY_VOXELDEBUG
335 G4cout <<
"- Skipping logical volume with " << numDaughters
336 <<
" daughters and name = '" << volume->
GetName() <<
"' " <<
G4endl;
337 if( numDaughters > 1 )
343 if( numDaughters == 1 )
374G4GeometryManager::CreateListOfVolumesToOptimise(
G4bool allOpts,
G4bool verbose)
380 if( !fVolumesToOptimise.empty() )
382 ResetListOfVolumesToOptimise();
385 for (
auto & n : *Store)
387 G4LogicalVolume* volume=
n;
395 fVolumesToOptimise.push_back(volume);
403#ifdef G4GEOMETRY_VOXELDEBUG
405 <<
" daughters and name = '" << volume->
GetName() <<
"' "
406 <<
" -- for optimisation (ie voxels will be built for it). " <<
G4endl;
411#ifdef G4GEOMETRY_VOXELDEBUG
413 <<
" daughters and name = '" << volume->
GetName() <<
"' " <<
G4endl;
419 G4cout <<
"** G4GeometryManager::PrepareOptimisationWork: "
420 <<
" Number of volumes for voxelisation = "
421 << fVolumesToOptimise.size() <<
G4endl;
423 fLogVolumeIterator = fVolumesToOptimise.cbegin();
434 G4LogicalVolume* logVolume =
nullptr;
438 if( fLogVolumeIterator != fVolumesToOptimise.cend() )
440 logVolume = *fLogVolumeIterator;
441 ++fLogVolumeIterator;
450void G4GeometryManager::ResetListOfVolumesToOptimise()
454 std::vector<G4LogicalVolume*>().swap(fVolumesToOptimise);
459 assert(fVolumesToOptimise.empty());
460 fLogVolumeIterator = fVolumesToOptimise.cbegin();
462 fGlobVoxelStats.clear();
472 fParallelVoxelOptimisationRequested = flag;
475 ConfigureParallelOptimisation(verbose);
483void G4GeometryManager::ConfigureParallelOptimisation(
G4bool verbose)
487 G4cout <<
"** G4GeometryManager::ConfigureParallelOptimisation() called. "
488 <<
" LEAVING all the work (of voxel optimisation) to the threads/tasks !"
491 fParallelVoxelOptimisationRequested =
true;
492 fParallelVoxelOptimisationUnderway =
false;
493 fParallelVoxelOptimisationFinished =
false;
496 fVerboseParallel = verbose;
500 fNumberThreadsReporting = 0;
501 fTotalNumberVolumesOptimised = 0;
503 fWallClockStarted =
false;
511G4GeometryManager::PrepareParallelOptimisation(
G4bool allOpts,
G4bool verbose)
515 G4cout <<
"** G4GeometryManager::PrepareParallelOptimisation() called."
518 CreateListOfVolumesToOptimise(allOpts, verbose);
519 ConfigureParallelOptimisation(verbose);
528 G4bool verbose = fVerboseParallel;
531 fParallelVoxelOptimisationUnderway =
true;
534 if( ( !fWallClockStarted ) && verbose )
536 G4AutoLock startTimeLock(wallClockTimerMutex);
537 if( !fWallClockStarted )
539 fWallClockTimer->Start();
540 fWallClockStarted=
true;
545 unsigned int numVolumesOptimised = 0;
547 while( (logVolume = ObtainVolumeToOptimise()) !=
nullptr )
549 if (verbose) fetimer.
Start();
561 ++numVolumesOptimised;
566 message <<
"VoxelHeader allocation error." <<
G4endl
567 <<
"Allocation of new VoxelHeader" <<
G4endl
568 <<
"for logical volume " << logVolume->
GetName() <<
" failed.";
569 G4Exception(
"G4GeometryManager::BuildOptimisationsParallel()",
581 fGlobVoxelStats.emplace_back( logVolume, head,
584 fSumVoxelTime += feRealElapsed;
591 myCount = ReportWorkerIsDoneOptimising(numVolumesOptimised);
596 G4int badVolumes = CheckOptimisation();
600 errmsg <<
" Expected that all voxelisation work is done, "
601 <<
"but found that voxels headers are missing in "
602 << badVolumes <<
" volumes.";
603 G4Exception(
"G4GeometryManager::UndertakeOptimisation()",
611 fWallClockTimer->Stop();
613 std::ostream& report_stream = std::cout;
615 <<
"G4GeometryManager::UndertakeOptimisation"
616 <<
" -- Timing for Voxel Optimisation" <<
G4endl;
617 report_stream <<
" - Elapsed time (real) = " << std::setprecision(4)
618 << fWallClockTimer->GetRealElapsed() <<
"s (wall clock)"
619 <<
", user " << fWallClockTimer->GetUserElapsed() <<
"s"
620 <<
", system " << fWallClockTimer->GetSystemElapsed() <<
"s."
622 report_stream <<
" - Sum voxel time (real) = " << fSumVoxelTime
624 report_stream << std::setprecision(6) <<
G4endl <<
G4endl;
626 ReportVoxelStats( fGlobVoxelStats, fSumVoxelTime, report_stream );
627 report_stream.flush();
632 WaitForVoxelisationFinish(
false);
641void G4GeometryManager::WaitForVoxelisationFinish(
G4bool verbose)
644 using namespace std::chrono_literals;
645 unsigned int trials = 0;
648 std::ostream& out_stream = std::cout;
652 std::this_thread::sleep_for(250ms);
660 <<
"** UndertakeOptimisation done on tid= " << tid
661 <<
" after waiting for " << trials <<
" trials." <<
G4endl;
670G4int G4GeometryManager::CheckOptimisation()
672 unsigned int numErrors = 0;
673 for (
const auto& logical : fVolumesToOptimise )
675 if( logical->GetVoxelHeader() ==
nullptr ) { ++numErrors; }
691G4GeometryManager::ReportWorkerIsDoneOptimising(
unsigned int numVolumesOptimised)
694 G4int orderReporting;
697 orderReporting = ++fNumberThreadsReporting;
698 fTotalNumberVolumesOptimised += numVolumesOptimised;
702 InformOptimisationIsFinished(fVerboseParallel);
705 return orderReporting;
712void G4GeometryManager::InformOptimisationIsFinished(
G4bool verbose)
716 std::cout <<
"** G4GeometryManager: All voxel optimisation work is completed!"
718 std::cout <<
" Total number of volumes optimised = "
719 << fTotalNumberVolumesOptimised
720 <<
" of " << fVolumesToOptimise.size() <<
" expected\n";
721 std::cout <<
" Number of workers reporting = "
722 << fNumberThreadsReporting
726 assert ( fTotalNumberVolumesOptimised == fVolumesToOptimise.size() );
728 fParallelVoxelOptimisationFinished =
true;
730 fParallelVoxelOptimisationUnderway =
false;
737void G4GeometryManager::BuildOptimisations(
G4bool allOpts,
740 if (pVolume ==
nullptr) {
return; }
746 if (tVolume ==
nullptr)
748 BuildOptimisations(allOpts,
false);
760 head =
new G4SmartVoxelHeader(tVolume);
767 std::ostringstream message;
768 message <<
"VoxelHeader allocation error." <<
G4endl
769 <<
"Allocation of new VoxelHeader" <<
G4endl
770 <<
" for volume " << tVolume->
GetName() <<
" failed.";
771 G4Exception(
"G4GeometryManager::BuildOptimisations()",
"GeomMgt0003",
778#ifdef G4GEOMETRY_VOXELDEBUG
779 G4cout <<
"** G4GeometryManager::BuildOptimisations()" <<
G4endl
780 <<
" Skipping logical volume name = " << tVolume->
GetName()
790 BuildOptimisations(allOpts, tVolume->
GetDaughter(0));
799void G4GeometryManager::DeleteOptimisations()
801 G4LogicalVolume* tVolume =
nullptr;
803 for (
auto & n : *Store)
818 if (pVolume ==
nullptr) {
return; }
824 if (tVolume ==
nullptr) {
return DeleteOptimisations(); }
849 G4Exception(
"G4GeometryManager::SetMaximumExtent()",
851 "Extent can be set only BEFORE creating any geometry object!");
861G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
865 os <<
"--------------------------------------------------------------------------------"
867 os <<
"G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
876 for( i=0; i<nStat; ++i ) { totalMemory += stats[i].GetMemoryUse(); }
878 os <<
" Total memory consumed for geometry optimisation: "
879 << totalMemory/1024 <<
" kByte" <<
G4endl;
880 os <<
" Total CPU time elapsed for geometry optimisation: "
881 << std::setprecision(4) << totalCpuTime <<
" seconds"
882 << std::setprecision(6) <<
G4endl;
887 std::sort( stats.begin(), stats.end(),
888 [](
const G4SmartVoxelStat& a,
const G4SmartVoxelStat& b)
890 return a.GetTotalTime() > b.GetTotalTime();
893 const G4int maxPrint = 20;
894 G4int nPrint = std::min ( nStat, maxPrint );
898 os <<
"\n Voxelisation: top CPU users:" <<
G4endl;
899 os <<
" Percent Total CPU System CPU Memory Volume\n"
900 <<
" ------- ---------- ---------- -------- ----------"
904 for(i=0; i<nPrint; ++i)
907 G4double system = stats[i].GetSysTime();
910 if (system < 0) { system = 0.0; }
911 if ((total < 0) || (totalCpuTime < perMillion))
914 { perc =
total*100/totalCpuTime; }
916 os << std::setprecision(2)
917 << std::setiosflags(std::ios::fixed|std::ios::right)
918 << std::setw(11) << perc
919 << std::setw(13) <<
total
920 << std::setw(13) << system
921 << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
922 <<
"k " << std::setiosflags(std::ios::left)
923 << stats[i].GetVolume()->GetName()
924 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
925 << std::setprecision(6)
932 std::sort( stats.begin(), stats.end(),
933 [](
const G4SmartVoxelStat& a,
const G4SmartVoxelStat& b)
935 return a.GetMemoryUse() > b.GetMemoryUse();
940 os <<
"\n Voxelisation: top memory users:" <<
G4endl;
941 os <<
" Percent Memory Heads Nodes Pointers Total CPU Volume\n"
942 <<
" ------- -------- ------ ------ -------- ---------- ----------"
946 for(i=0; i<nPrint; ++i)
948 G4long memory = stats[i].GetMemoryUse();
949 G4double totTime = stats[i].GetTotalTime();
950 if (totTime < 0) { totTime = 0.0; }
952 os << std::setprecision(2)
953 << std::setiosflags(std::ios::fixed|std::ios::right)
955 << std::setw(11) << memory/1024 <<
"k "
956 << std::setw( 9) << stats[i].GetNumberHeads()
957 << std::setw( 9) << stats[i].GetNumberNodes()
958 << std::setw(11) << stats[i].GetNumberPointers()
959 << std::setw(13) << totTime <<
" "
960 << std::setiosflags(std::ios::left)
961 << stats[i].GetVolume()->GetName()
962 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
963 << std::setprecision(6)
966 os <<
"--------------------------------------------------------------------------------"
976 return fOptimiseInParallelConfigured;
985 return fParallelVoxelOptimisationFinished;
G4TemplateAutoLock< G4Mutex > G4AutoLock
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
static G4GeometryManager * GetInstance()
G4bool CloseGeometry(G4bool pOptimise=true, G4bool verbose=false, G4VPhysicalVolume *vol=nullptr)
void SetWorldMaximumExtent(G4double worldExtent)
void OptimiseInParallel(G4bool val=true)
void RequestParallelOptimisation(G4bool val=true, G4bool verbose=true)
G4bool IsParallelOptimisationConfigured()
void OpenGeometry(G4VPhysicalVolume *vol=nullptr)
void UndertakeOptimisation()
static G4GeometryManager * GetInstanceIfExist()
G4bool IsParallelOptimisationFinished()
void SetSurfaceTolerance(G4double worldExtent)
static G4GeometryTolerance * GetInstance()
static G4LogicalVolumeStore * GetInstance()
void SetVoxelHeader(G4SmartVoxelHeader *pVoxel)
std::size_t GetNoDaughters() const
G4VPhysicalVolume * GetDaughter(const std::size_t i) const
G4bool IsToOptimise() const
const G4String & GetName() const
G4SmartVoxelHeader * GetVoxelHeader() const
static G4SolidStore * GetInstance()
G4double GetSystemElapsed() const
G4double GetUserElapsed() const
G4double GetRealElapsed() const
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)
G4bool IsMultithreadedApplication()
G4int GetNumberOfRunningWorkerThreads()
const G4int kMinVoxelVolumesLevel1