Import Geant4 11.4.0 source tree

This commit is contained in:
Gabriele Cosmo
2025-12-05 08:54:02 +01:00
parent a499fb82e9
commit b4a16de652
6484 changed files with 232674 additions and 221097 deletions
@@ -25,6 +25,7 @@
//
// class G4BlockingList Implementation
//
// Author: Paul Kent (CERN), 24.07.1996
// --------------------------------------------------------------------
#include "G4BlockingList.hh"
@@ -25,7 +25,7 @@
//
// Implementation of G4BoundingEnvelope
//
// 2016.05.25, E.Tcherniaev - initial version
// Author: Evgueni Tcherniaev (CERN), 25.05.2016 - Initial version
// --------------------------------------------------------------------
#include <cmath>
@@ -642,9 +642,9 @@ TransformVertices(const G4Transform3D& pTransform3D,
G4ThreeVector offset = pTransform3D.getTranslation();
for (auto i = ia; i != iaend; ++i)
{
for (auto k = (*i)->cbegin(); k != (*i)->cend(); ++k)
for (const auto & k : **i)
{
pVertices.emplace_back((*k) + offset);
pVertices.emplace_back(k + offset);
}
}
}
@@ -652,9 +652,9 @@ TransformVertices(const G4Transform3D& pTransform3D,
{
for (auto i = ia; i != iaend; ++i)
{
for (auto k = (*i)->cbegin(); k != (*i)->cend(); ++k)
for (const auto & k : **i)
{
pVertices.push_back(pTransform3D*G4Point3D(*k));
pVertices.push_back(pTransform3D*G4Point3D(k));
}
}
}
@@ -25,7 +25,7 @@
//
// G4ErrorCylSurfaceTarget class implementation
//
// Created: P.Arce, September 2004
// Author: Pedro Arce (CIEMAT), September 2004
// --------------------------------------------------------------------
#include "G4ErrorCylSurfaceTarget.hh"
@@ -25,7 +25,7 @@
//
// G4ErrorPlaneSurfaceTarget class implementation
//
// Created: P.Arce, September 2004
// Author: Pedro Arce (CIEMAT), September 2004
// --------------------------------------------------------------------
#include "G4ErrorPlaneSurfaceTarget.hh"
@@ -1,33 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ErrorSurfaceTarget class implementation
//
// Created: P.Arce, September 2004
// --------------------------------------------------------------------
#include "G4ErrorSurfaceTarget.hh"
G4ErrorSurfaceTarget::G4ErrorSurfaceTarget() = default;
@@ -1,33 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ErrorTanPlaneTarget class implementation
//
// Created: P.Arce, September 2004
// --------------------------------------------------------------------
#include "G4ErrorTanPlaneTarget.hh"
G4ErrorTanPlaneTarget::G4ErrorTanPlaneTarget() = default;
@@ -25,7 +25,7 @@
//
// G4ErrorTarget class implementation
//
// Created: P.Arce, September 2004
// Author: Pedro Arce (CIEMAT), September 2004
// --------------------------------------------------------------------
#include "G4ErrorTarget.hh"
+22 -12
View File
@@ -23,9 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// class G4GeomTools implementation
// G4GeomTools implementation
//
// 10.10.2016, E.Tcherniaev: initial version.
// Author: Evgueni Tcherniaev (CERN), 10.10.2016
// --------------------------------------------------------------------
#include "G4GeomTools.hh"
@@ -76,8 +76,8 @@ G4double G4GeomTools::QuadArea(const G4TwoVector& A,
G4double G4GeomTools::PolygonArea(const G4TwoVectorList& p)
{
auto n = (G4int)p.size();
if (n < 3) { return 0.0; // degenerate polygon
}
if (n < 3) { return 0.0; } // degenerate polygon
G4double area = p[n-1].x()*p[0].y() - p[0].x()*p[n-1].y();
for(G4int i=1; i<n; ++i)
{
@@ -221,11 +221,14 @@ G4bool G4GeomTools::TriangulatePolygon(const G4TwoVectorList& polygon,
//
G4double area = G4GeomTools::PolygonArea(polygon);
auto V = new G4int[n];
if (area > 0.) {
if (area > 0.)
{
for (G4int i=0; i<n; ++i) { V[i] = i; }
} else {
}
else
{
for (G4int i=0; i<n; ++i) { V[i] = (n-1)-i; }
}
}
// Triangulation: remove nv-2 Vertices, creating 1 triangle every time
//
@@ -376,10 +379,14 @@ void G4GeomTools::RemoveRedundantVertices(G4TwoVectorList& polygon,
}
for (G4int i=0; i<nv; ++i) // move points, if required
{
if (polygon[i].x() != removeIt) {
if (polygon[i].x() != removeIt)
{
polygon[icur++] = polygon[i];
} else {
iout.push_back(i); }
}
else
{
iout.push_back(i);
}
}
if (icur < nv) { polygon.resize(icur); }
return;
@@ -724,9 +731,12 @@ G4GeomTools::ClosestPointOnTriangle(const G4ThreeVector& P,
*/
G4int region = -1;
if (t0+t1 <= det) {
if (t0+t1 <= det)
{
region = (t0 < 0) ? ((t1 < 0) ? 4 : 3) : ((t1 < 0) ? 5 : 0);
} else {
}
else
{
region = (t0 < 0) ? 2 : ((t1 < 0) ? 6 : 1);
}
@@ -25,8 +25,8 @@
//
// Class G4GeometryManager implementation
//
// 26.07.95, P.Kent - Initial version, including optimisation build
// 12.06.24, J.Apostolakis - Added parallel optimisation in workers
// Author: Paul Kent (CERN), 26.07.1995 - Initial version
// John Apostolakis (CERN), 12.06.2024 - Added parallel optimisation
// --------------------------------------------------------------------
#include <iomanip>
@@ -52,23 +52,12 @@
// Needed for parallel optimisation
#include "G4AutoLock.hh"
#include "G4VoxelisationHelper.hh"
namespace // Data structures / mutexes for parallel optimisation
namespace
{
// Mutex to obtain a volume to optimise
G4Mutex obtainVolumeMutex = G4MUTEX_INITIALIZER;
// Mutex to lock saving of voxel statistics
G4Mutex voxelStatsMutex = G4MUTEX_INITIALIZER;
// Mutex to provide Statistics Results
G4Mutex statResultsMutex = G4MUTEX_INITIALIZER;
// Mutex to start wall clock (global) timer
G4Mutex wallClockTimerMutex = G4MUTEX_INITIALIZER;
// Mutex to write debug output
G4Mutex outputDbgMutex = G4MUTEX_INITIALIZER;
G4Mutex createHelperMutex = G4MUTEX_INITIALIZER;
}
// ***************************************************************************
@@ -77,32 +66,35 @@ namespace // Data structures / mutexes for parallel optimisation
//
G4ThreadLocal G4GeometryManager* G4GeometryManager::fgInstance = nullptr;
G4VoxelisationHelper* G4GeometryManager::fParallelVoxeliser = nullptr;
// Only one instance created by the master thread's G4GeometryManager
// Expected Future: data member (when only one instance)
// Static *global* class data
G4bool G4GeometryManager::fParallelVoxelOptimisationRequested = true;
// Records User choice to use parallel voxel optimisation (or not)
G4bool G4GeometryManager::fOptimiseInParallelConfigured = false;
G4bool G4GeometryManager::fOptimiseInParallelConfigured = false;
// Configured = requested && available (ie if MT or Threads is used)
// Value calculated during each effort to optimise
std::vector<G4LogicalVolume*> G4GeometryManager::fVolumesToOptimise;
std::vector<G4LogicalVolume*>::const_iterator G4GeometryManager::fLogVolumeIterator;
// ***************************************************************************
// Contructor
// ***************************************************************************
//
G4GeometryManager::G4GeometryManager()
{
fIsClosed = false;
std::vector<G4SmartVoxelStat> G4GeometryManager::fGlobVoxelStats;
// Container for statistics
// Derived state
G4bool G4GeometryManager::fVerboseParallel = false;
G4bool G4GeometryManager::fParallelVoxelOptimisationUnderway = false;
G4bool G4GeometryManager::fParallelVoxelOptimisationFinished = false;
G4double G4GeometryManager::fSumVoxelTime = 0.0;
G4int G4GeometryManager::fNumberThreadsReporting = 0;
unsigned int G4GeometryManager::fTotalNumberVolumesOptimised = 0U;
// For Wall clock
G4Timer* G4GeometryManager::fWallClockTimer = nullptr;
G4bool G4GeometryManager::fWallClockStarted = false;
// Ensure that the helper objects are created
// even if there is no master thread
// Note: no longer needed once G4GeometryManager is a canonical Singleton
G4AutoLock lock(createHelperMutex);
if( fParallelVoxeliser == nullptr )
{
fParallelVoxeliser= new G4VoxelisationHelper();
}
}
// ***************************************************************************
// Destructor
@@ -112,11 +104,17 @@ G4GeometryManager::~G4GeometryManager()
{
fgInstance = nullptr;
fIsClosed = false;
if( (fWallClockTimer != nullptr) && G4Threading::IsMasterThread() )
// Only the master thread can delete the helper objects
// - a different mechanism is needed for setups with no master
// TODO: See if shared_ptr could help here?
if( G4Threading::IsMasterThread() )
{
delete fWallClockTimer;
fWallClockTimer= nullptr;
if( fParallelVoxeliser != nullptr )
{
delete fParallelVoxeliser;
fParallelVoxeliser = nullptr;
}
}
}
@@ -132,19 +130,33 @@ G4bool G4GeometryManager::CloseGeometry(G4bool pOptimise, G4bool verbose,
{
if (!fIsClosed && G4Threading::IsMasterThread())
{
G4bool workDone= false;
if (pVolume != nullptr)
{
BuildOptimisations(pOptimise, pVolume);
workDone= BuildOptimisations(pOptimise, pVolume);
}
else
{
BuildOptimisations(pOptimise, verbose);
workDone= BuildOptimisations(pOptimise, verbose);
}
fIsClosed = true;
fIsClosed = workDone; // Sequential will be done; parallel ongoing
}
return true;
}
// ***************************************************************************
// Inform whether closing of geometry has finished
// ***************************************************************************
G4bool G4GeometryManager::IsGeometryClosed()
{
if( fOptimiseInParallelConfigured )
{
fIsClosed= fParallelVoxeliser->IsParallelOptimisationFinished();
}
return fIsClosed;
}
// ***************************************************************************
// Opens the geometry and removes optimisations (optionally, related to just
// the specified logical-volume).
@@ -164,6 +176,7 @@ void G4GeometryManager::OpenGeometry(G4VPhysicalVolume* pVolume)
DeleteOptimisations();
}
fIsClosed = false;
// fGeometryCloseRequested= false;
}
}
@@ -177,11 +190,6 @@ G4GeometryManager* G4GeometryManager::GetInstance()
if (fgInstance == nullptr)
{
fgInstance = new G4GeometryManager;
if( (fWallClockTimer == nullptr) && G4Threading::IsMasterThread() )
{
fWallClockTimer = new G4Timer;
}
}
return fgInstance;
}
@@ -196,26 +204,31 @@ G4GeometryManager* G4GeometryManager::GetInstanceIfExist()
}
// ***************************************************************************
// Report about Voxel(isation) of a logical volume.
// Simplest user method to request parallel optimisation.
// ***************************************************************************
//
void
G4GeometryManager::ReportVoxelInfo(G4LogicalVolume* logVolume, std::ostream& os)
void G4GeometryManager::OptimiseInParallel( G4bool val )
{
G4SmartVoxelHeader* head = logVolume->GetVoxelHeader();
if( head != nullptr )
{
os << "** Created optimisations for logical-volume '"
<< std::setw(50) << logVolume->GetName() << "'" << G4endl
<< "- Result VoxelInfo - START: " << " ptr= " << head << G4endl
<< *head
<< "- Result VoxelInfo - END. " << G4endl;
}
else
{
os << "** No optimisation for log-vol " << logVolume->GetName() << G4endl;
}
os << "*** Report Voxel Info: END " << G4endl;
RequestParallelOptimisation(val);
}
// ***************************************************************************
// Respond whether parallel optimisation is done
// ***************************************************************************
//
G4bool G4GeometryManager::IsParallelOptimisationFinished()
{
return fParallelVoxeliser->IsParallelOptimisationFinished();
}
// ***************************************************************************
// Respond whether parallel optimisation is configured
// ***************************************************************************
//
G4bool G4GeometryManager::IsParallelOptimisationConfigured()
{
return fOptimiseInParallelConfigured;
}
// ***************************************************************************
@@ -233,12 +246,13 @@ G4bool G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose)
if( fOptimiseInParallelConfigured )
{
PrepareParallelOptimisation(allOpts, verbose);
fParallelVoxeliser->PrepareParallelOptimisation(allOpts, verbose);
}
else
{
BuildOptimisationsSequential(allOpts, verbose);
finishedOptimisation= true;
fIsClosed= true;
}
return finishedOptimisation;
@@ -343,117 +357,11 @@ void G4GeometryManager::BuildOptimisationsSequential(G4bool allOpts,
{
allTimer.Stop();
ReportVoxelStats( stats, allTimer.GetSystemElapsed()
+ allTimer.GetUserElapsed() );
G4VoxelisationHelper::ReportVoxelStats( stats, allTimer.GetSystemElapsed()
+ allTimer.GetUserElapsed() );
}
}
// ***************************************************************************
// Creates a list of logical volumes which will be optimised
// if allOpts=true it lists all voxels
// otherwise it lists only the voxels of replicated volumes.
// This list will be used subsequently to build their voxels.
//
// Note: this method is NOT thread safe!
// It expects to be called only once in each (re)initalisation
// i.e. either by master thread or a selected thread.
// ***************************************************************************
//
void
G4GeometryManager::CreateListOfVolumesToOptimise(G4bool allOpts, G4bool verbose)
{
// Prepare the work - must be called only in one thread !!
G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
if( !fVolumesToOptimise.empty() )
{
ResetListOfVolumesToOptimise();
}
for (auto & n : *Store)
{
G4LogicalVolume* volume=n;
if ( ( (volume->IsToOptimise())
&& (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
|| ( (volume->GetNoDaughters()==1)
&& (volume->GetDaughter(0)->IsReplicated())
&& (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) )
{
fVolumesToOptimise.push_back(volume);
// For safety, must check (later) if there are any existing voxels and
// delete before replacement:
// All 'clients' of this code must do the following:
// delete volume->GetVoxelHeader();
// volume->SetVoxelHeader(nullptr);
#ifdef G4GEOMETRY_VOXELDEBUG
G4cout << "- Booking logical volume with " << volume->GetNoDaughters()
<< " daughters and name = '" << volume->GetName() << "' "
<< " -- for optimisation (ie voxels will be built for it). " << G4endl;
#endif
}
else
{
#ifdef G4GEOMETRY_VOXELDEBUG
G4cout << "- Skipping logical volume with " << volume->GetNoDaughters()
<< " daughters and name = '" << volume->GetName() << "' " << G4endl;
#endif
}
}
if(verbose)
{
G4cout << "** G4GeometryManager::CreateListOfVolumesToOptimise: "
<< " Number of volumes for voxelisation = "
<< fVolumesToOptimise.size() << G4endl;
}
fLogVolumeIterator = fVolumesToOptimise.cbegin();
}
// ***************************************************************************
// Obtain a logical volume from the list of volumes to optimise
// Must be thread-safe: its role is to be called in parallel by threads/tasks!
// Critical method for parallel optimisation - must be correct and fast.
// ***************************************************************************
//
G4LogicalVolume* G4GeometryManager::ObtainVolumeToOptimise()
{
G4LogicalVolume* logVolume = nullptr;
G4AutoLock lock(obtainVolumeMutex);
if( fLogVolumeIterator != fVolumesToOptimise.cend() )
{
logVolume = *fLogVolumeIterator;
++fLogVolumeIterator;
}
return logVolume;
}
// ***************************************************************************
// Thread-safe method to clear the list of volumes to Optimise.
// ***************************************************************************
//
void G4GeometryManager::ResetListOfVolumesToOptimise()
{
G4AutoLock lock(obtainVolumeMutex);
std::vector<G4LogicalVolume*>().swap(fVolumesToOptimise);
// Swapping with an empty vector in order to empty it
// without calling destructors of logical volumes.
// Must not call clear: i.e. fVolumesToOptimise.clear();
assert(fVolumesToOptimise.empty());
fLogVolumeIterator = fVolumesToOptimise.cbegin();
fGlobVoxelStats.clear();
// Reset also the statistics of volumes -- to avoid double recording.
}
// ***************************************************************************
// Method which user calls to ask for parallel optimisation (or turn it off).
// ***************************************************************************
@@ -463,350 +371,29 @@ void G4GeometryManager::RequestParallelOptimisation(G4bool flag, G4bool verbose)
fParallelVoxelOptimisationRequested = flag;
if( flag )
{
ConfigureParallelOptimisation(verbose);
fParallelVoxeliser->SetVerbosity(verbose);
}
}
// ***************************************************************************
// Simplest user method to request parallel optimisation.
// ***************************************************************************
//
void G4GeometryManager::OptimiseInParallel( G4bool val )
{
RequestParallelOptimisation(val);
}
// ***************************************************************************
// Setup up state to enable parallel optimisation by workers.
// ***************************************************************************
//
void G4GeometryManager::ConfigureParallelOptimisation(G4bool verbose)
{
static G4ThreadLocal unsigned int numCallsConfig = 0;
++numCallsConfig;
if(verbose)
{
G4cout << "** G4GeometryManager::ConfigureParallelOptimisation() called "
<< " for the " << numCallsConfig << " time. "
<< " LEAVING all the work (of voxel optimisation) to the threads/tasks !"
<< G4endl;
}
fParallelVoxelOptimisationRequested = true;
fParallelVoxelOptimisationUnderway = false;
fParallelVoxelOptimisationFinished = false;
// Keep values of options / verbosity for use in threads
fVerboseParallel = verbose;
// New effort -- reset the total time -- and number of threads reporting
fSumVoxelTime = 0.0;
fNumberThreadsReporting = 0;
fTotalNumberVolumesOptimised = 0; // Number of volumes done
fWallClockStarted = false; // Will need to restart it!
fLogVolumeIterator = fVolumesToOptimise.cbegin();
// Reset the iterator -- else to be sure that work is done correctly
}
// ***************************************************************************
// Build voxel optimisation in parallel -- prepare the work for threads/tasks
// ***************************************************************************
//
void
G4GeometryManager::PrepareParallelOptimisation(G4bool allOpts, G4bool verbose)
{
if( verbose )
{
G4cout << "** G4GeometryManager::PrepareParallelOptimisation() called."
<< G4endl;
}
CreateListOfVolumesToOptimise(allOpts, verbose);
ConfigureParallelOptimisation(verbose);
}
// ***************************************************************************
// Method for a thread/task to contribute dynamically to Optimisation
// ***************************************************************************
//
void G4GeometryManager::UndertakeOptimisation()
{
G4bool verbose = fVerboseParallel;
G4LogicalVolume* logVolume = nullptr;
fParallelVoxelOptimisationUnderway = true;
// Start timer - if not already done
if( ( !fWallClockStarted ) && verbose )
{
G4AutoLock startTimeLock(wallClockTimerMutex);
if( !fWallClockStarted )
{
fWallClockTimer->Start();
fWallClockStarted= true;
}
}
G4Timer fetimer;
unsigned int numVolumesOptimised = 0;
while( (logVolume = ObtainVolumeToOptimise()) != nullptr )
{
if (verbose) { fetimer.Start(); }
G4SmartVoxelHeader* head = logVolume->GetVoxelHeader();
delete head;
logVolume->SetVoxelHeader(nullptr);
head = new G4SmartVoxelHeader(logVolume);
// *********************************
logVolume->SetVoxelHeader(head);
if (head != nullptr)
{
++numVolumesOptimised;
}
else
{
G4ExceptionDescription message;
message << "VoxelHeader allocation error." << G4endl
<< "Allocation of new VoxelHeader" << G4endl
<< "for logical volume " << logVolume->GetName() << " failed.";
G4Exception("G4GeometryManager::BuildOptimisationsParallel()",
"GeomMgt0003", FatalException, message);
}
if(verbose)
{
fetimer.Stop();
auto feRealElapsed = fetimer.GetRealElapsed();
// Must use 'real' elapsed time -- cannot trust user/system time
// (it accounts for all threads)
G4AutoLock lock(voxelStatsMutex);
fGlobVoxelStats.emplace_back( logVolume, head,
0.0, // Cannot estimate system time
feRealElapsed ); // Use real time instead of user time
fSumVoxelTime += feRealElapsed;
}
}
G4bool allDone = false;
G4int myCount= -1;
myCount = ReportWorkerIsDoneOptimising(numVolumesOptimised);
allDone = IsParallelOptimisationFinished();
if( allDone && (myCount == G4Threading::GetNumberOfRunningWorkerThreads()) )
{
G4int badVolumes = CheckOptimisation(); // Check all voxels are created!
if( badVolumes > 0 )
{
G4ExceptionDescription errmsg;
errmsg <<" Expected that all voxelisation work is done, "
<< "but found that voxels headers are missing in "
<< badVolumes << " volumes.";
G4Exception("G4GeometryManager::UndertakeOptimisation()",
"GeomMgt002", FatalException, errmsg);
}
// Create report
if( verbose )
{
fWallClockTimer->Stop();
std::ostream& report_stream = std::cout; // G4cout; does not work!
report_stream << G4endl
<< "G4GeometryManager::UndertakeOptimisation"
<< " -- Timing for Voxel Optimisation" << G4endl;
report_stream << " - Elapsed time (real) = " << std::setprecision(4)
<< fWallClockTimer->GetRealElapsed() << "s (wall clock)"
<< ", user " << fWallClockTimer->GetUserElapsed() << "s"
<< ", system " << fWallClockTimer->GetSystemElapsed() << "s."
<< G4endl;
report_stream << " - Sum voxel time (real) = " << fSumVoxelTime
<< "s.";
report_stream << std::setprecision(6) << G4endl << G4endl;
ReportVoxelStats( fGlobVoxelStats, fSumVoxelTime, report_stream );
report_stream.flush();
}
}
else
{
WaitForVoxelisationFinish(false);
}
fParallelVoxeliser->UndertakeOptimisation();
}
// ***************************************************************************
// Ensure that all the work of voxelisation is done.
// Can be called in GeometryManager methods or externally.
// ***************************************************************************
//
void G4GeometryManager::WaitForVoxelisationFinish(G4bool verbose)
{
// Must wait until all workers are done ...
using namespace std::chrono_literals;
unsigned int trials = 0;
auto tid = G4Threading::G4GetThreadId();
std::ostream& out_stream = std::cout; // G4cout; does not work!
while( ! IsParallelOptimisationFinished() )
{
// Each thread must wait until all are done ...
std::this_thread::sleep_for(250ms);
++trials;
}
if( verbose )
{
G4AutoLock lock(outputDbgMutex);
out_stream << G4endl
<< "** UndertakeOptimisation done on tid= " << tid
<< " after waiting for " << trials << " trials." << G4endl;
out_stream.flush();
}
}
// ***************************************************************************
// Ensure that all logical volumes in list have a voxel-header.
// ***************************************************************************
//
G4int G4GeometryManager::CheckOptimisation()
{
unsigned int numErrors = 0;
for ( const auto& logical : fVolumesToOptimise )
{
if( logical->GetVoxelHeader() == nullptr ) { ++numErrors; }
}
return numErrors;
}
// ***************************************************************************
// Report that current thread/task is done optimising.
// A thread call this method to reports that is is done (finished), and how
// many volumes it optimised. The method:
// - increments the count of workers that have finished, and return it;
// - keeps count of number of volumes optimised;
// - if all works is done (ie all workers have reported) it will result
// in the 'Finished' state.
// ***************************************************************************
//
G4int
G4GeometryManager::ReportWorkerIsDoneOptimising(unsigned int nVolOptimised)
{
// Check that all are done and, if so, signal that optimisation is finished
G4int orderReporting;
G4AutoLock lock(statResultsMutex);
orderReporting = ++fNumberThreadsReporting;
fTotalNumberVolumesOptimised += nVolOptimised;
if( fVerboseParallel )
{
std::cout << "G4GeometryManager: the " << orderReporting
<< " worker has finished. "
<< " Total volumes voxelised = "
<< fTotalNumberVolumesOptimised
<< " out of " << fVolumesToOptimise.size() << G4endl;
}
if ( fNumberThreadsReporting == G4Threading::GetNumberOfRunningWorkerThreads()
|| fTotalNumberVolumesOptimised == fVolumesToOptimise.size() )
{
const auto TotalThreads = G4Threading::GetNumberOfRunningWorkerThreads();
auto tid= G4Threading::G4GetThreadId();
// -- Some Checks
if( fTotalNumberVolumesOptimised != fVolumesToOptimise.size() )
{
G4ExceptionDescription errmsg;
errmsg << " [thread " << tid << " ] "
<< " ERROR: Number of volumes 'voxelised' = "
<< fTotalNumberVolumesOptimised
<< " is not equal to the total number requested "
<< fVolumesToOptimise.size() << " !! " << G4endl;
G4Exception("G4GeometryManager::ReportWorkerIsDoneOptimising()",
"GeomMgt0003", FatalException, errmsg);
}
if( fVerboseParallel )
{
if( fNumberThreadsReporting > TotalThreads )
{
G4ExceptionDescription errmsg;
errmsg << " [thread " << tid << " ] "
<< " WARNING: Number of threads 'reporting' = "
<< fNumberThreadsReporting
<< " exceeds the total number of threads "
<< TotalThreads << " !! " << G4endl
<< " *Missed* calling ConfigureParallelOptimisation() to reset. ";
G4Exception("G4GeometryManager::ReportWorkerIsDoneOptimising()",
"GeomMgt1002", JustWarning, errmsg);
}
else
{
if( fTotalNumberVolumesOptimised == fVolumesToOptimise.size()
&& ( fNumberThreadsReporting < TotalThreads ) )
{
G4ExceptionDescription errmsg;
errmsg << " [thread " << tid << " ] "
<< " WARNING: All volumes optimised, yet only "
<< fNumberThreadsReporting << " threads reported out of "
<< TotalThreads;
G4Exception("G4GeometryManager::ReportWorkerIsDoneOptimising()",
"GeomMgt1002", JustWarning, errmsg);
}
}
}
// -- End of Checks
// Report the end
if( fNumberThreadsReporting <= G4Threading::GetNumberOfRunningWorkerThreads() )
{
// Close the work, and (if verbosity is on) report statistics
InformOptimisationIsFinished(fVerboseParallel);
}
}
return orderReporting;
}
// ***************************************************************************
// Inform that all work for parallel optimisation is finished.
// ***************************************************************************
//
void G4GeometryManager::InformOptimisationIsFinished(G4bool verbose)
{
if(verbose) // G4cout does not work!
{
std::cout << "** G4GeometryManager: All voxel optimisation work is completed!"
<< G4endl;
std::cout << " Total number of volumes optimised = "
<< fTotalNumberVolumesOptimised
<< " of " << fVolumesToOptimise.size() << " expected\n";
std::cout << " Number of workers reporting = "
<< fNumberThreadsReporting
<< " of " << G4Threading::GetNumberOfRunningWorkerThreads()
<< " expected\n";
}
assert ( fTotalNumberVolumesOptimised == fVolumesToOptimise.size() );
fParallelVoxelOptimisationFinished = true;
// fParallelVoxelOptimisationRequested = false; // Maintain request for next one!
fParallelVoxelOptimisationUnderway = false; // It's no longer underway!
}
// ***************************************************************************
// Creates Optimisation info for the specified volumes subtree.
// ***************************************************************************
// Returns whether all work is done
//
void G4GeometryManager::BuildOptimisations(G4bool allOpts,
G4VPhysicalVolume* pVolume)
G4bool G4GeometryManager::BuildOptimisations(G4bool allOpts,
G4VPhysicalVolume* pVolume)
{
if (pVolume == nullptr) { return; }
if (pVolume == nullptr) { return false; }
// Retrieve the mother logical volume, if not NULL,
// otherwise apply global optimisation for the world volume
@@ -814,8 +401,8 @@ void G4GeometryManager::BuildOptimisations(G4bool allOpts,
G4LogicalVolume* tVolume = pVolume->GetMotherLogical();
if (tVolume == nullptr)
{
BuildOptimisations(allOpts, false);
return;
G4bool done=BuildOptimisations(allOpts, false);
return done;
}
G4SmartVoxelHeader* head = tVolume->GetVoxelHeader();
@@ -858,6 +445,8 @@ void G4GeometryManager::BuildOptimisations(G4bool allOpts,
{
BuildOptimisations(allOpts, tVolume->GetDaughter(0));
}
return true; // Work is all done -- no parallelism currently
}
// ***************************************************************************
@@ -921,134 +510,3 @@ void G4GeometryManager::SetWorldMaximumExtent(G4double extent)
}
G4GeometryTolerance::GetInstance()->SetSurfaceTolerance(extent);
}
// ***************************************************************************
// Reports statistics on voxel optimisation when closing geometry.
// ***************************************************************************
//
void
G4GeometryManager::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
G4double totalCpuTime, std::ostream &os )
{
os << "--------------------------------------------------------------------------------"
<< G4endl;
os << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics"
<< G4endl << G4endl;
//
// Get total memory use
//
G4int i, nStat = (G4int)stats.size();
G4long totalMemory = 0;
for( i=0; i<nStat; ++i ) { totalMemory += stats[i].GetMemoryUse(); }
os << " Total memory consumed for geometry optimisation: "
<< totalMemory/1024 << " kByte" << G4endl;
os << " Total CPU time elapsed for geometry optimisation: "
<< std::setprecision(4) << totalCpuTime << " seconds"
<< std::setprecision(6) << G4endl;
//
// First list: sort by total CPU time
//
std::sort( stats.begin(), stats.end(),
[](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
{
return a.GetTotalTime() > b.GetTotalTime();
} );
const G4int maxPrint = 20;
G4int nPrint = std::min ( nStat, maxPrint );
if (nPrint != 0)
{
os << "\n Voxelisation: top CPU users:" << G4endl;
os << " Percent Total CPU System CPU Memory Volume\n"
<< " ------- ---------- ---------- -------- ----------"
<< G4endl;
}
for(i=0; i<nPrint; ++i)
{
G4double total = stats[i].GetTotalTime();
G4double system = stats[i].GetSysTime();
G4double perc = 0.0;
if (system < 0) { system = 0.0; }
if ((total < 0) || (totalCpuTime < perMillion))
{ total = 0; }
else
{ perc = total*100/totalCpuTime; }
os << std::setprecision(2)
<< std::setiosflags(std::ios::fixed|std::ios::right)
<< std::setw(11) << perc
<< std::setw(13) << total
<< std::setw(13) << system
<< std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
<< "k " << std::setiosflags(std::ios::left)
<< stats[i].GetVolume()->GetName()
<< std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
<< std::setprecision(6)
<< G4endl;
}
//
// Second list: sort by memory use
//
std::sort( stats.begin(), stats.end(),
[](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
{
return a.GetMemoryUse() > b.GetMemoryUse();
} );
if (nPrint != 0)
{
os << "\n Voxelisation: top memory users:" << G4endl;
os << " Percent Memory Heads Nodes Pointers Total CPU Volume\n"
<< " ------- -------- ------ ------ -------- ---------- ----------"
<< G4endl;
}
for(i=0; i<nPrint; ++i)
{
G4long memory = stats[i].GetMemoryUse();
G4double totTime = stats[i].GetTotalTime();
if (totTime < 0) { totTime = 0.0; }
os << std::setprecision(2)
<< std::setiosflags(std::ios::fixed|std::ios::right)
<< std::setw(11) << G4double(memory*100)/G4double(totalMemory)
<< std::setw(11) << memory/1024 << "k "
<< std::setw( 9) << stats[i].GetNumberHeads()
<< std::setw( 9) << stats[i].GetNumberNodes()
<< std::setw(11) << stats[i].GetNumberPointers()
<< std::setw(13) << totTime << " "
<< std::setiosflags(std::ios::left)
<< stats[i].GetVolume()->GetName()
<< std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
<< std::setprecision(6)
<< G4endl;
}
os << "--------------------------------------------------------------------------------"
<< G4endl << G4endl;
}
// ***************************************************************************
// Check whether parallel optimisation was requested -- static (class) data.
// ***************************************************************************
//
G4bool G4GeometryManager::IsParallelOptimisationConfigured()
{
return fOptimiseInParallelConfigured;
}
// ***************************************************************************
// Report whether parallel optimisation is done -- static (class) data.
// ***************************************************************************
//
G4bool G4GeometryManager::IsParallelOptimisationFinished()
{
return fParallelVoxelOptimisationFinished;
}
@@ -23,9 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Class G4IdentityTrajectoryFilter implementation
// G4IdentityTrajectoryFilter implementation
//
// First version: Nov 19, 2002 - Jacek Generowicz
// Author: Jacek Generowicz (CERN), 19.11.2002
// ------------------------------------------------------------------------
#include "G4IdentityTrajectoryFilter.hh"
@@ -25,7 +25,7 @@
//
// Implementation of G4LogicalCrystalVolume
//
// 21-04-16, created by E.Bagli
// Author: Enrico Bagli (Ferrara Univ.), 21.04.2016
// --------------------------------------------------------------------
#include "G4LogicalCrystalVolume.hh"
@@ -25,13 +25,13 @@
//
// G4LogicalSurface class implementation
//
// Created: John Apostolakis & Peter Gumplinger, 26-06-1997
// Authors: John Apostolakis (CERN) & Peter Gumplinger (TRIUMF), 26.06.1997
// ------------------------------------------------------------------------
#include "G4LogicalSurface.hh"
G4LogicalSurface::G4LogicalSurface(const G4String& name,
G4SurfaceProperty* surfaceProperty)
G4SurfaceProperty* surfaceProperty)
: theName(name), theSurfaceProperty(surfaceProperty)
{
}
@@ -23,14 +23,18 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// class G4LogicalVolume implementation
// G4LogicalVolume implementation
//
// 15.01.13 G.Cosmo, A.Dotti: Modified for thread-safety for MT
// 01.03.05 G.Santin: Added flag for optional propagation of GetMass()
// 17.05.02 G.Cosmo: Added flag for optional optimisation
// 12.02.99 S.Giani: Default initialization of voxelization quality
// 04.08.97 P.M.DeFreitas: Added methods for parameterised simulation
// 11.07.95 P.Kent: Initial version
// 04.08.97 P.M.DeFreitas: Added methods for parameterised simulation
// 09.11.98 M.Verderi, J.Apostolakis: Added BiasWeight member and accessors
// 12.02.99 S.Giani: Added user defined optimisation quality
// 18.04.01 G.Cosmo: Migrated to STL vector
// 17.05.02 G.Cosmo: Added IsToOptimise() method and related flag
// 24.09.02 G.Cosmo: Added flags and accessors for region cuts handling
// 12.11.04 G.Cosmo: Added GetMass() method for computing mass of the tree
// 01.03.05 G.Santin: Added flag for optional propagation of GetMass()
// 15.01.13 G.Cosmo, A.Dotti: Modified for thread-safety for MT
// --------------------------------------------------------------------
#include "G4LogicalVolume.hh"
@@ -515,8 +519,7 @@ G4LogicalVolume::IsAncestor(const G4VPhysicalVolume* aVolume) const
for (const auto & daughter : fDaughters)
{
isDaughter = daughter->GetLogicalVolume()->IsAncestor(aVolume);
if (isDaughter) { break;
}
if (isDaughter) { break; }
}
}
return isDaughter;
@@ -678,8 +681,7 @@ G4bool G4LogicalVolume::ChangeDaughtersType(EVolume aType)
//
void G4LogicalVolume::SetVisAttributes (const G4VisAttributes& VA)
{
if (G4Threading::IsWorkerThread()) { return;
}
if (G4Threading::IsWorkerThread()) { return; }
fVisAttributes = std::make_shared<const G4VisAttributes>(VA);
}
@@ -689,7 +691,6 @@ void G4LogicalVolume::SetVisAttributes (const G4VisAttributes& VA)
//
void G4LogicalVolume::SetVisAttributes (const G4VisAttributes* pVA)
{
if (G4Threading::IsWorkerThread()) { return;
}
if (G4Threading::IsWorkerThread()) { return; }
fVisAttributes = std::shared_ptr<const G4VisAttributes>(pVA,[](const G4VisAttributes*){});
}
@@ -25,7 +25,7 @@
//
// G4LogicalVolumeStore implementation
//
// 10.07.95, P.Kent, G.Cosmo
// Authors: Gabriele Cosmo & Paul Kent (CERN), 10.07.1995 - Initial version
// --------------------------------------------------------------------
#include "G4Types.hh"
@@ -25,8 +25,7 @@
//
// G4NavigationHistory Implementation
//
// Author: P.Kent, August 96
//
// Author: Paul Kent (CERN), 25.07.1996 - Initial version.
// ----------------------------------------------------------------------
#include "G4ios.hh"
@@ -27,7 +27,7 @@
//
// Implementation for singleton container
//
// 07.05.14 G.Cosmo Initial version
// Author: Gabriele Cosmo (CERN), 07.05.2014 - Initial version
// --------------------------------------------------------------------
#include "globals.hh"
@@ -25,7 +25,7 @@
//
// G4NavigationLevel implementation
//
// 30.09.97 J.Apostolakis Initial version
// Author: John Apostolakis (CERN), 30.09.1997 - Initial version
// ----------------------------------------------------------------------
#include "G4NavigationLevel.hh"
@@ -25,7 +25,7 @@
//
// G4NavigationLevelRep implementation
//
// 1 October 1997, J.Apostolakis Initial version
// Author: John Apostolakis (CERN), 01.10.1997- Initial version
// ----------------------------------------------------------------------
#include "G4NavigationLevelRep.hh"
@@ -25,7 +25,7 @@
//
// G4PhysicalVolumeStore implementation
//
// 25.07.95, P.Kent, G.Cosmo
// Authors: Gabriele Cosmo & Paul Kent (CERN), 25.07.1995 - Initial version
// --------------------------------------------------------------------
#include "G4Types.hh"
@@ -25,7 +25,7 @@
//
// Implementation for G4ReflectedSolid class
//
// Author: Vladimir Grichine, 23.07.01 (Vladimir.Grichine@cern.ch)
// Author: Vladimir Grichine (CERN), 23.07.2001 - Created
// --------------------------------------------------------------------
#include "G4ReflectedSolid.hh"
@@ -473,9 +473,9 @@ G4ReflectedSolid::GetPolyhedron () const
if ((fpPolyhedron == nullptr) || fRebuildPolyhedron ||
(fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
fpPolyhedron->GetNumberOfRotationSteps()))
{
fpPolyhedron = CreatePolyhedron();
fRebuildPolyhedron = false;
}
{
fpPolyhedron = CreatePolyhedron();
fRebuildPolyhedron = false;
}
return fpPolyhedron;
}
+2 -2
View File
@@ -23,9 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4Region class implementation
// G4Region implementation
//
// 18.09.02, G.Cosmo - Initial version
// Author: Gabriele Cosmo (CERN), 18.09.2002
// --------------------------------------------------------------------
#include "G4Region.hh"
@@ -25,7 +25,7 @@
//
// G4RegionStore implementation
//
// 18.09.02, G.Cosmo - Initial version
// Author: Gabriele Cosmo (CERN), 18.09.2002
// --------------------------------------------------------------------
#include "G4Region.hh"
@@ -23,16 +23,16 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// class G4SmartVoxelHeader implementation
// G4SmartVoxelHeader implementation
//
// Define G4GEOMETRY_VOXELDEBUG for debugging information on G4cout
//
// 29.04.02 Use 3D voxelisation for non consuming replication - G.C.
// 18.04.01 Migrated to STL vector - G.C.
// 12.02.99 Introduction of new quality/smartless: max for (slices/cand) - S.G.
// 11.02.99 Voxels at lower levels are now built for collapsed slices - S.G.
// 21.07.95 Full implementation, supporting non divided physical volumes - P.K.
// 14.07.95 Initial version - stubb definitions only - P.K.
// 13.07.95 Initial version, stubb definitions only - P.Kent.
// 21.07.95 Full implementation, supporting non divided volumes - P.Kent.
// 11.02.99 Voxels at lower levels now built for collapsed slices - S.Giani.
// 12.02.99 Introduction of new quality/smartless - S.Giani.
// 18.04.01 Migrated to STL vector - G.Cosmo.
// 29.04.02 Use 3D voxelisation for non consuming replication - G.Cosmo.
// --------------------------------------------------------------------
#include "G4SmartVoxelHeader.hh"
@@ -51,7 +51,7 @@
// ***************************************************************************
// Constructor for topmost header, to begin voxel construction at a
// given logical volume.
// Constructs target List of volumes, calls "Build and refine" constructor.
// Constructs target list of volumes, calls "Build and refine" constructor.
// Assumes all daughters represent single volumes (ie. no divisions
// or parametric)
// ***************************************************************************
@@ -82,8 +82,7 @@ G4SmartVoxelHeader::G4SmartVoxelHeader(G4LogicalVolume* pVolume,
}
// ***************************************************************************
// Protected constructor:
// builds and refines voxels between specified limits, considering only
// Builds and refines voxels between specified limits, considering only
// the physical volumes numbered `pCandidates'. `pSlice' is used to set max
// and min equivalent slice nos for the header - they apply to the level
// of the header, not its nodes.
@@ -112,8 +111,7 @@ G4SmartVoxelHeader::G4SmartVoxelHeader(G4LogicalVolume* pVolume,
}
// ***************************************************************************
// Destructor:
// deletes all proxies and underlying objects.
// Destructor: deletes all proxies and underlying objects.
// ***************************************************************************
//
G4SmartVoxelHeader::~G4SmartVoxelHeader()
@@ -370,9 +368,9 @@ void G4SmartVoxelHeader::BuildReplicaVoxels(G4LogicalVolume* pVolume)
}
// ***************************************************************************
// Builds `consumed nodes': nReplicas nodes each containing one replication,
// Builds 'consumed nodes': nReplicas nodes each containing one replication,
// numbered in sequence 0->nReplicas-1
// o Modifies fslices `in place'
// o Modifies fslices 'in place'
// o faxis,fminExtent,fmaxExtent NOT modified.
// ***************************************************************************
//
@@ -418,7 +416,7 @@ void G4SmartVoxelHeader::BuildConsumedNodes(G4int nReplicas)
// ***************************************************************************
// Builds and refines voxels between specified limits, considering only
// the physical volumes numbered `pCandidates'.
// the physical volumes numbered 'pCandidates'.
// o Chooses axis
// o Determines min and max extents (of mother solid) within limits.
// ***************************************************************************
@@ -704,7 +702,7 @@ void G4SmartVoxelHeader::CollectEquivalentHeaders()
// ***************************************************************************
// Builds the nodes corresponding to slices between the specified limits
// and along the specified axis, using candidate volume no.s in the vector
// pCandidates. If the `daughters' are replicated volumes (ie. the logical
// pCandidates. If the 'daughters' are replicated volumes (ie. the logical
// volume has a single replicated/parameterised volume for a daughter)
// the candidate no.s are interpreted as PARAMETERISED volume no.s &
// PARAMETERISATIONs are applied to compute transformations & solid
@@ -776,7 +774,7 @@ G4ProxyVector* G4SmartVoxelHeader::BuildNodes(G4LogicalVolume* pVolume,
pDaughter->GetTranslation());
replicated = true;
}
else
else
{
replicated = false;
}
@@ -23,10 +23,10 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Class G4SmartVoxelNode implementation
// G4SmartVoxelNode implementation
//
// 18.04.01, G.Cosmo - Migrated to STL vector
// 12.07.95, P.Kent - Initial version
// Author: Paul Kent (CERN), 12.07.1995 - Initial version
// Gabriele Cosmo (CERN), 18.04.2001 - Migrated to STL vector
// --------------------------------------------------------------------
#include "G4SmartVoxelNode.hh"
@@ -28,7 +28,7 @@
// Stores information on the performance of the smart voxel algorithm
// for an individual logical volume.
//
// Author: D.C.Williams, UCSC (davidw@scipp.ucsc.edu)
// Author: D.C.Williams (UCSC), 1998
// --------------------------------------------------------------------
#include "G4SmartVoxelStat.hh"
@@ -25,7 +25,7 @@
//
// G4SolidStore implementation
//
// 10.07.95, P.Kent, G.Cosmo
// Authors: Gabriele Cosmo & Paul Kent (CERN), 10.07.1995 - Initial version
// --------------------------------------------------------------------
#include "globals.hh"
@@ -25,7 +25,7 @@
//
// class G4TouchableHistory Implementation
//
// Created: Paul Kent, August 1996
// Author: Paul Kent (CERN), August 1996
// ----------------------------------------------------------------------
#include "G4TouchableHistory.hh"
@@ -51,8 +51,6 @@ G4TouchableHistory::G4TouchableHistory( const G4NavigationHistory& history )
frot = tf.InverseNetRotation();
}
G4TouchableHistory::~G4TouchableHistory() = default;
const G4ThreeVector&
G4TouchableHistory::GetTranslation(G4int depth) const
{
@@ -23,9 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4VCurvedTrajectoryFilter class implementation
// G4VCurvedTrajectoryFilter implementation
//
// First version: Oct 30, 2002 - Jacek Generowicz
// Author: Jacek Generowicz (CERN), 30.10.2002
// --------------------------------------------------------------------
#include "G4VCurvedTrajectoryFilter.hh"
@@ -23,9 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// class G4VNestedParameterisation implementation
// G4VNestedParameterisation implementation
//
// 24.02.05, J.Apostolakis - First created version.
// Author: John Apostolakis (CERN), 24.02.2005 - First created version
// --------------------------------------------------------------------
#include "G4VNestedParameterisation.hh"
@@ -23,9 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// class G4VPVDivisionFactory Implementation file
// G4VPVDivisionFactory Implementation file
//
// Author: Ivana Hrivnacova, 4.5.2004
// Author: Ivana Hrivnacova (IJCLab, Orsay), 04.05.2004
// ------------------------------------------------------------------------
#include "G4VPVDivisionFactory.hh"
@@ -26,7 +26,7 @@
// Default implementations for Parameterisations that do not
// parameterise solid and/or material.
//
// 25.07.96, P.Kent - Initial stub version
// Author: Paul Kent (CERN), 25.07.1996, P.Kent - Initial stub version
// --------------------------------------------------------------------
#include "G4VPVParameterisation.hh"
@@ -25,10 +25,10 @@
//
// class G4VPhysicalVolume Implementation
//
// 15.01.13, G.Cosmo, A.Dotti: Modified for thread-safety for MT
// 28.08.96, P.Kent: Replaced transform by rotmat + vector
// 25.07.96, P.Kent: Modified interface for new `Replica' capable geometry
// 24.07.95, P.Kent: First non-stub version
// 24.07.95, P.Kent (CERN): First non-stub version
// 25.07.96, P.Kent (CERN): Modified interface for 'Replica' capable geometry
// 28.08.96, P.Kent (CERN): Replaced transform by rotmat + vector
// 15.01.13, G.Cosmo, A.Dotti (CERN): Modified for thread-safety for MT
// --------------------------------------------------------------------
#include "G4VPhysicalVolume.hh"
+23 -12
View File
@@ -25,8 +25,10 @@
//
// G4VSolid implementation for solid base class
//
// 10.10.18 E.Tcherniaev, more robust EstimateSurfaceArea() based on distance
// 30.06.95 P.Kent, Created.
// Author: Paul Kent (CERN), 30.06.1995 - Initial version
// John Allison (Manchester Univ.), 27.03.1996 - Added methods for vis
// Paul Kent (CERN), 26.07.1996 - Added replication mechanism
// Evgueni Tcherniaev (CERN), 10.10.2018 - EstimateSurfaceArea() rewrite
// --------------------------------------------------------------------
#include "G4VSolid.hh"
@@ -67,7 +69,6 @@ G4VSolid::G4VSolid(const G4String& name)
//////////////////////////////////////////////////////////////////////////
//
// Copy constructor
//
G4VSolid::G4VSolid(const G4VSolid& rhs)
: kCarTolerance(rhs.kCarTolerance), fshapeName(rhs.fshapeName)
@@ -81,7 +82,7 @@ G4VSolid::G4VSolid(const G4VSolid& rhs)
//
// Fake default constructor - sets only member data and allocates memory
// for usage restricted to object persistency.
//
G4VSolid::G4VSolid( __void__& )
: fshapeName("")
{
@@ -118,8 +119,6 @@ G4VSolid& G4VSolid::operator = (const G4VSolid& rhs)
return *this;
}
//////////////////////////////////////////////////////////////////////////
//
// Set solid name and notify store of the change
@@ -166,30 +165,42 @@ G4ThreeVector G4VSolid::GetPointOnSurface() const
// of the solid. For non-Boolean solids the return value is one.
G4int G4VSolid::GetNumOfConstituents() const
{ return 1; }
{
return 1;
}
//////////////////////////////////////////////////////////////////////////
//
// Returns true if the solid has only planar faces, false otherwise.
G4bool G4VSolid::IsFaceted() const
{ return false; }
{
return false;
}
//////////////////////////////////////////////////////////////////////////
//
// Dummy implementations ...
const G4VSolid* G4VSolid::GetConstituentSolid(G4int) const
{ return nullptr; }
{
return nullptr;
}
G4VSolid* G4VSolid::GetConstituentSolid(G4int)
{ return nullptr; }
{
return nullptr;
}
const G4DisplacedSolid* G4VSolid::GetDisplacedSolidPtr() const
{ return nullptr; }
{
return nullptr;
}
G4DisplacedSolid* G4VSolid::GetDisplacedSolidPtr()
{ return nullptr; }
{
return nullptr;
}
////////////////////////////////////////////////////////////////
//
+22 -22
View File
@@ -25,7 +25,7 @@
//
// Class G4VoxelLimits implementation
//
// 13.07.95, P.Kent - Initial version
// Author: Paul Kent (CERN), 13.07.1995 - Initial version.
// --------------------------------------------------------------------
#include "G4VoxelLimits.hh"
@@ -245,32 +245,32 @@ std::ostream& operator << (std::ostream& os, const G4VoxelLimits& pLim)
{
os << "{";
if (pLim.IsXLimited())
{
os << "(" << pLim.GetMinXExtent()
<< "," << pLim.GetMaxXExtent() << ") ";
}
{
os << "(" << pLim.GetMinXExtent()
<< "," << pLim.GetMaxXExtent() << ") ";
}
else
{
os << "(-,-) ";
}
{
os << "(-,-) ";
}
if (pLim.IsYLimited())
{
os << "(" << pLim.GetMinYExtent()
<< "," << pLim.GetMaxYExtent() << ") ";
}
{
os << "(" << pLim.GetMinYExtent()
<< "," << pLim.GetMaxYExtent() << ") ";
}
else
{
os << "(-,-) ";
}
{
os << "(-,-) ";
}
if (pLim.IsZLimited())
{
os << "(" << pLim.GetMinZExtent()
<< "," << pLim.GetMaxZExtent() << ")";
}
{
os << "(" << pLim.GetMinZExtent()
<< "," << pLim.GetMaxZExtent() << ")";
}
else
{
os << "(-,-)";
}
{
os << "(-,-)";
}
os << "}";
return os;
}
@@ -0,0 +1,640 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4VoxelisationHelper implementation
//
// Author: John Apostolakis (CERN), 10.02.2025
// --------------------------------------------------------------------
#include "G4VoxelisationHelper.hh"
#include "voxeldefs.hh"
#include "G4LogicalVolume.hh"
#include "G4LogicalVolumeStore.hh"
#include "G4SmartVoxelHeader.hh"
#include "G4Threading.hh"
#include "G4Timer.hh"
G4VoxelisationHelper::G4VoxelisationHelper()
{
fWallClockTimer = new G4Timer;
ResetListOfVolumesToOptimise();
}
G4VoxelisationHelper::~G4VoxelisationHelper()
{
delete fWallClockTimer;
}
// ***************************************************************************
// Setup up state to enable parallel optimisation by workers.
// ***************************************************************************
//
// Method's Old Name: ConfigureParallelOptimisation
//
void G4VoxelisationHelper::ReSetParallelOptimisation(G4bool verbose)
{
if(verbose)
{
G4cout << "** G4VoxelisationHelper::ReSetParallelOptimisation() called. "
<< " All the work (of voxel optimisation) WAS LEFT to the threads/tasks !"
<< G4endl << " Clearing the state for this work." << G4endl;
}
// fParallelVoxelOptimisationRequested = true;
fParallelVoxelOptimisationUnderway = false;
fParallelVoxelOptimisationFinished = false;
// Keep values of options / verbosity for use in threads
fVerboseParallel = verbose;
// New effort -- reset all 'sums' & totals: total time, number of threads reporting
fSumVoxelTime = 0.0;
fNumberThreadsReporting = 0;
fTotalNumberVolumesOptimised = 0; // Number of volumes done
fWallClockStarted = false; // Will need to restart it!
fLogVolumeIterator = fVolumesToOptimise.cbegin();
// Reset the iterator -- else to be sure that work is done correctly
}
// ***************************************************************************
// Creates a list of logical volumes which will be optimised
// if allOpts=true it lists all voxels
// otherwise it lists only the voxels of replicated volumes.
// This list will be used subsequently to build their voxels.
//
// Note: this method is NOT thread safe!
// It expects to be called only once in each (re)initalisation
// i.e. either by master thread or a selected thread.
// ***************************************************************************
//
void
G4VoxelisationHelper::CreateListOfVolumesToOptimise(G4bool allOpts, G4bool verbose)
{
// Prepare the work - must be called only in one thread !!
G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance();
if( !fVolumesToOptimise.empty() )
{
ResetListOfVolumesToOptimise();
}
for (auto & n : *Store)
{
G4LogicalVolume* volume=n;
if ( ( (volume->IsToOptimise())
&& (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) )
|| ( (volume->GetNoDaughters()==1)
&& (volume->GetDaughter(0)->IsReplicated())
&& (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) )
{
fVolumesToOptimise.push_back(volume);
// For safety, must check (later) if there are any existing voxels and
// delete before replacement:
// All 'clients' of this code must do the following:
// delete volume->GetVoxelHeader();
// volume->SetVoxelHeader(nullptr);
#ifdef G4GEOMETRY_VOXELDEBUG
G4cout << "- Booking logical volume with " << volume->GetNoDaughters()
<< " daughters and name = '" << volume->GetName() << "' "
<< " -- for optimisation (ie voxels will be built for it). " << G4endl;
#endif
}
else
{
#ifdef G4GEOMETRY_VOXELDEBUG
G4cout << "- Skipping logical volume with " << volume->GetNoDaughters()
<< " daughters and name = '" << volume->GetName() << "' " << G4endl;
#endif
}
}
if(verbose)
G4cout << "** G4VoxelisationHelper::PrepareOptimisationWork: "
<< " Number of volumes for voxelisation = "
<< fVolumesToOptimise.size() << G4endl;
fLogVolumeIterator = fVolumesToOptimise.cbegin();
}
// ***************************************************************************
// Build voxel optimisation in parallel -- prepare the work for threads/tasks
// ***************************************************************************
//
void G4VoxelisationHelper::PrepareParallelOptimisation(G4bool allOpts, G4bool verbose)
{
if( verbose )
{
G4cout << "** G4VoxelisationHelper::PrepareParallelOptimisation() called."
<< " LEAVING all the work (of voxel optimisation) to the threads/tasks !"
<< G4endl;
}
CreateListOfVolumesToOptimise(allOpts, verbose);
ReSetParallelOptimisation(verbose);
}
// ***************************************************************************
// Data structures / mutexes for parallel optimisation
// ***************************************************************************
//
namespace
{
// Mutex to obtain a volume to optimise
G4Mutex obtainVolumeMutex = G4MUTEX_INITIALIZER;
// Mutex to lock saving of voxel statistics
G4Mutex voxelStatsMutex = G4MUTEX_INITIALIZER;
// Mutex to provide Statistics Results
G4Mutex statResultsMutex = G4MUTEX_INITIALIZER;
// Mutex to start wall clock (global) timer
G4Mutex wallClockTimerMutex = G4MUTEX_INITIALIZER;
// Mutex to write debug output
G4Mutex outputDbgMutex = G4MUTEX_INITIALIZER;
}
// ***************************************************************************
// Method for a thread/task to contribute dynamically to Optimisation
// ***************************************************************************
//
void G4VoxelisationHelper::UndertakeOptimisation()
{
G4bool verbose = fVerboseParallel;
G4LogicalVolume* logVolume = nullptr;
// Use a mutex to protect parallel writes, but may be better to use atomic,
// or do away with this entirely since it's not practically used?
{
G4AutoLock uo_lock(&statResultsMutex);
fParallelVoxelOptimisationUnderway = true;
}
// Start timer - if not already done
if( ( !fWallClockStarted ) && verbose )
{
G4AutoLock startTimeLock(wallClockTimerMutex);
if( !fWallClockStarted )
{
fWallClockTimer->Start();
fWallClockStarted= true;
}
}
G4Timer fetimer;
unsigned int numVolumesOptimised = 0;
while( (logVolume = ObtainVolumeToOptimise()) != nullptr )
{
if (verbose) fetimer.Start();
G4SmartVoxelHeader* head = logVolume->GetVoxelHeader();
delete head;
logVolume->SetVoxelHeader(nullptr);
head = new G4SmartVoxelHeader(logVolume);
// *********************************
logVolume->SetVoxelHeader(head);
if (head != nullptr)
{
++numVolumesOptimised;
}
else
{
G4ExceptionDescription message;
message << "VoxelHeader allocation error." << G4endl
<< "Allocation of new VoxelHeader" << G4endl
<< "for logical volume " << logVolume->GetName() << " failed.";
G4Exception("G4VoxelisationHelper::BuildOptimisationsParallel()",
"GeomMgt0003", FatalException, message);
}
if(verbose)
{
fetimer.Stop();
auto feRealElapsed = fetimer.GetRealElapsed();
// Must use 'real' elapsed time -- cannot trust user/system time
// (it accounts for all threads)
G4AutoLock lock(voxelStatsMutex);
fGlobVoxelStats.emplace_back( logVolume, head,
0.0, // Cannot estimate system time
feRealElapsed ); // Use real time instead of user time
fSumVoxelTime += feRealElapsed;
}
}
G4bool allDone = false;
G4int myCount= -1;
myCount = ReportWorkerIsDoneOptimising(numVolumesOptimised);
allDone = IsParallelOptimisationFinished();
if( allDone && (myCount == G4Threading::GetNumberOfRunningWorkerThreads()) )
{
G4int badVolumes = CheckOptimisation(); // Check all voxels are created!
if( badVolumes > 0 )
{
G4ExceptionDescription errmsg;
errmsg <<" Expected that all voxelisation work is done, "
<< "but found that voxels headers are missing in "
<< badVolumes << " volumes.";
G4Exception("G4VoxelisationHelper::UndertakeOptimisation()",
"GeomMng002", FatalException, errmsg);
}
// Create report
if( verbose )
{
fWallClockTimer->Stop();
std::ostream& report_stream = std::cout; // G4cout; does not work!
report_stream << G4endl
<< "G4VoxelisationHelper::UndertakeOptimisation"
<< " -- Timing for Voxel Optimisation" << G4endl;
report_stream << " - Elapsed time (real) = " << std::setprecision(4)
<< fWallClockTimer->GetRealElapsed() << "s (wall clock)"
<< ", user " << fWallClockTimer->GetUserElapsed() << "s"
<< ", system " << fWallClockTimer->GetSystemElapsed() << "s."
<< G4endl;
report_stream << " - Sum voxel time (real) = " << fSumVoxelTime
<< "s.";
report_stream << std::setprecision(6) << G4endl << G4endl;
ReportVoxelStats( fGlobVoxelStats, fSumVoxelTime, report_stream );
report_stream.flush();
}
}
else
{
WaitForVoxelisationFinish(false);
}
}
// ***************************************************************************
// Obtain a logical volume from the list of volumes to optimise
// Must be thread-safe: its role is to be called in parallel by threads/tasks!
// Critical method for parallel optimisation - must be correct and fast.
// ***************************************************************************
//
G4LogicalVolume* G4VoxelisationHelper::ObtainVolumeToOptimise()
{
G4LogicalVolume* logVolume = nullptr;
G4AutoLock lock(obtainVolumeMutex);
if( fLogVolumeIterator != fVolumesToOptimise.cend() )
{
logVolume = *fLogVolumeIterator;
++fLogVolumeIterator;
}
return logVolume;
}
// ***************************************************************************
// Thread-safe method to clear the list of volumes to Optimise.
// ***************************************************************************
//
void G4VoxelisationHelper::ResetListOfVolumesToOptimise()
{
G4AutoLock lock(obtainVolumeMutex);
std::vector<G4LogicalVolume*>().swap(fVolumesToOptimise);
// Swapping with an empty vector in order to empty it
// without calling destructors of logical volumes.
// Must not call clear: i.e. fVolumesToOptimise.clear();
assert(fVolumesToOptimise.empty());
fLogVolumeIterator = fVolumesToOptimise.cbegin();
fGlobVoxelStats.clear();
// Reset also the statistics of volumes -- to avoid double recording.
}
// ***************************************************************************
// Report that current thread/task is done optimising.
// A thread call this method to reports that is is done (finished), and how
// many volumes it optimised. The method:
// - increments the count of workers that have finished, and return it;
// - keeps count of number of volumes optimised;
// - if all works is done (ie all workers have reported) it will result
// in the 'Finished' state.
// ***************************************************************************
//
G4int
G4VoxelisationHelper::ReportWorkerIsDoneOptimising(unsigned int numVolumesOptimised)
{
// Check that all are done and, if so, signal that optimisation is finished
G4int orderReporting;
G4AutoLock lock(statResultsMutex);
orderReporting = ++fNumberThreadsReporting;
fTotalNumberVolumesOptimised += numVolumesOptimised;
if( fVerboseParallel )
std::cout << "G4GeometryManager: the " << orderReporting << " worker has finished. "
<< " Total volumes voxelised = " << fTotalNumberVolumesOptimised
<< " out of " << fVolumesToOptimise.size() << G4endl;
if (fNumberThreadsReporting == G4Threading::GetNumberOfRunningWorkerThreads()
|| fTotalNumberVolumesOptimised == fVolumesToOptimise.size()
)
{
const auto TotalThreads = G4Threading::GetNumberOfRunningWorkerThreads();
auto tid= G4Threading::G4GetThreadId();
// -- Some Checks
if( fTotalNumberVolumesOptimised != fVolumesToOptimise.size() )
{
G4ExceptionDescription errmsg;
errmsg << " [thread " << tid << " ] "
<< " WARNING: Number of volumes 'voxelised' = " << fTotalNumberVolumesOptimised
<< " is not equal to the total number requested " << fVolumesToOptimise.size() << " !! " << G4endl;
G4Exception("G4GeometryManager::ReportWorkerIsDoneOptimising", "G4GeomMgr0999",
FatalException, errmsg);
}
if( fNumberThreadsReporting > TotalThreads )
{
G4ExceptionDescription errmsg;
errmsg << " [thread " << tid << " ] "
<< " WARNING: Number of threads 'reporting' = " << fNumberThreadsReporting
<< " exceeds the total number of threads " << TotalThreads << " !! " << G4endl
<< " *Missed* calling the method ConfigureParallelOptimisation() to reset. ";
G4Exception("G4GeometryManager::ReportWorkerIsDoneOptimising", "G4GeomMgr0999",
JustWarning, errmsg);
}
else
{
if( fTotalNumberVolumesOptimised == fVolumesToOptimise.size()
&& ( fNumberThreadsReporting < TotalThreads ) )
{
G4ExceptionDescription errmsg;
errmsg << " [thread " << tid << " ] "
<< " WARNING: All volumes optimised, yet only "
<< fNumberThreadsReporting << " threads reported out of " << TotalThreads;
G4Exception("G4GeometryManager::ReportWorkerIsDoneOptimising", "G4GeomMgr099",
JustWarning, errmsg);
}
} // -- End of Checks
// Report the end
if( fNumberThreadsReporting <= G4Threading::GetNumberOfRunningWorkerThreads() )
{
// Close the work, and (if verbosity is on) report statistics
RecordOptimisationIsFinished(fVerboseParallel);
}
}
return orderReporting;
}
// ***************************************************************************
// Inform that all work for parallel optimisation is finished.
// ***************************************************************************
//
void G4VoxelisationHelper::RecordOptimisationIsFinished(G4bool verbose)
{
if(verbose) // G4cout does not work!
{
std::cout << "** G4VoxelisationHelper: All voxel optimisation work is completed!"
<< G4endl;
std::cout << " Total number of volumes optimised = "
<< fTotalNumberVolumesOptimised
<< " of " << fVolumesToOptimise.size() << " expected\n";
std::cout << " Number of workers reporting = "
<< fNumberThreadsReporting
<< " of " << G4Threading::GetNumberOfRunningWorkerThreads()
<< " expected\n";
}
assert ( fTotalNumberVolumesOptimised == fVolumesToOptimise.size() );
fParallelVoxelOptimisationFinished = true;
// fParallelVoxelOptimisationRequested = false; // Maintain request for next one!
fParallelVoxelOptimisationUnderway = false; // It's no longer underway!
}
// ***************************************************************************
// Ensure that all the work of voxelisation is done.
// Can be called in GeometryManager methods or externally.
// ***************************************************************************
//
void G4VoxelisationHelper::WaitForVoxelisationFinish(G4bool verbose)
{
// Must wait until all workers are done ...
using namespace std::chrono_literals;
unsigned int trials = 0;
auto tid = G4Threading::G4GetThreadId();
std::ostream& out_stream = std::cout; // G4cout; does not work!
while( ! IsParallelOptimisationFinished() )
{
// Each thread must wait until all are done ...
std::this_thread::sleep_for(250ms);
++trials;
}
if( verbose )
{
G4AutoLock lock(outputDbgMutex);
out_stream << G4endl
<< "** UndertakeOptimisation done on tid= " << tid
<< " after waiting for " << trials << " trials." << G4endl;
out_stream.flush();
}
}
// ***************************************************************************
// Report about Voxel(isation) of a logical volume.
// ***************************************************************************
//
void
G4VoxelisationHelper::ReportVoxelInfo(G4LogicalVolume* logVolume, std::ostream& os)
{
G4SmartVoxelHeader* head = logVolume->GetVoxelHeader();
if( head != nullptr )
{
os << "** Created optimisations for logical-volume '"
<< std::setw(50) << logVolume->GetName() << "'" << G4endl
<< "- Result VoxelInfo - START: " << " ptr= " << head << G4endl
<< *head
<< "- Result VoxelInfo - END. " << G4endl;
}
else
{
os << "** No optimisation for log-vol " << logVolume->GetName() << G4endl;
}
os << "*** Report Voxel Info: END " << G4endl;
}
// ***************************************************************************
// Reports statistics on voxel optimisation when closing geometry.
// ***************************************************************************
//
void
G4VoxelisationHelper::ReportVoxelStats( std::vector<G4SmartVoxelStat> & stats,
G4double totalCpuTime,
std::ostream &os )
{
os << "--------------------------------------------------------------------------------"
<< G4endl;
os << "G4VoxelisationHelper::ReportVoxelStats -- Voxel Statistics"
<< G4endl << G4endl;
//
// Get total memory use
//
G4int i, nStat = (G4int)stats.size();
G4long totalMemory = 0;
for( i=0; i<nStat; ++i ) { totalMemory += stats[i].GetMemoryUse(); }
os << " Total memory consumed for geometry optimisation: "
<< totalMemory/1024 << " kByte" << G4endl;
os << " Total CPU time elapsed for geometry optimisation: "
<< std::setprecision(4) << totalCpuTime << " seconds"
<< std::setprecision(6) << G4endl;
//
// First list: sort by total CPU time
//
std::sort( stats.begin(), stats.end(),
[](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
{
return a.GetTotalTime() > b.GetTotalTime();
} );
const G4int maxPrint = 20;
G4int nPrint = std::min ( nStat, maxPrint );
if (nPrint != 0)
{
os << "\n Voxelisation: top CPU users:" << G4endl;
os << " Percent Total CPU System CPU Memory Volume\n"
<< " ------- ---------- ---------- -------- ----------"
<< G4endl;
}
for(i=0; i<nPrint; ++i)
{
G4double total = stats[i].GetTotalTime();
G4double system = stats[i].GetSysTime();
G4double perc = 0.0;
if (system < 0) { system = 0.0; }
if ((total < 0) || (totalCpuTime < CLHEP::perMillion))
{ total = 0; }
else
{ perc = total*100/totalCpuTime; }
os << std::setprecision(2)
<< std::setiosflags(std::ios::fixed|std::ios::right)
<< std::setw(11) << perc
<< std::setw(13) << total
<< std::setw(13) << system
<< std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
<< "k " << std::setiosflags(std::ios::left)
<< stats[i].GetVolume()->GetName()
<< std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
<< std::setprecision(6)
<< G4endl;
}
//
// Second list: sort by memory use
//
std::sort( stats.begin(), stats.end(),
[](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
{
return a.GetMemoryUse() > b.GetMemoryUse();
} );
if (nPrint != 0)
{
os << "\n Voxelisation: top memory users:" << G4endl;
os << " Percent Memory Heads Nodes Pointers Total CPU Volume\n"
<< " ------- -------- ------ ------ -------- ---------- ----------"
<< G4endl;
}
for(i=0; i<nPrint; ++i)
{
G4long memory = stats[i].GetMemoryUse();
G4double totTime = stats[i].GetTotalTime();
if (totTime < 0) { totTime = 0.0; }
os << std::setprecision(2)
<< std::setiosflags(std::ios::fixed|std::ios::right)
<< std::setw(11) << G4double(memory*100)/G4double(totalMemory)
<< std::setw(11) << memory/1024 << "k "
<< std::setw( 9) << stats[i].GetNumberHeads()
<< std::setw( 9) << stats[i].GetNumberNodes()
<< std::setw(11) << stats[i].GetNumberPointers()
<< std::setw(13) << totTime << " "
<< std::setiosflags(std::ios::left)
<< stats[i].GetVolume()->GetName()
<< std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
<< std::setprecision(6)
<< G4endl;
}
os << "--------------------------------------------------------------------------------"
<< G4endl << G4endl;
}
G4bool G4VoxelisationHelper::IsParallelOptimisationFinished()
{
G4AutoLock lock(&statResultsMutex);
return fParallelVoxelOptimisationFinished;
}
// ***************************************************************************
// Ensure that all logical volumes in list have a voxel-header.
// ***************************************************************************
//
G4int G4VoxelisationHelper::CheckOptimisation()
{
unsigned int numErrors = 0;
for ( const auto& logical : fVolumesToOptimise )
{
if( logical->GetVoxelHeader() == nullptr ) { ++numErrors; }
}
return numErrors;
}