Import Geant4 11.4.0 source tree
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user