// // ******************************************************************** // * 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. * // ******************************************************************** // // // $Id: G4GeometryManager.cc,v 1.24 2010/07/16 15:52:57 gcosmo Exp $ // GEANT4 tag $Name: geommng-V09-03-05 $ // // class G4GeometryManager // // Implementation // // Author: // 26.07.95 P.Kent Initial version, including optimisation Build // -------------------------------------------------------------------- #include #include "G4Timer.hh" #include "G4GeometryManager.hh" #ifdef G4GEOMETRY_VOXELDEBUG #include "G4ios.hh" #endif // Needed for building optimisations // #include "G4LogicalVolumeStore.hh" #include "G4VPhysicalVolume.hh" #include "G4SmartVoxelHeader.hh" #include "voxeldefs.hh" // Needed for setting the extent for tolerance value // #include "G4GeometryTolerance.hh" #include "G4SolidStore.hh" #include "G4VSolid.hh" // *************************************************************************** // Static class variable: ptr to single instance of class // *************************************************************************** // G4GeometryManager* G4GeometryManager::fgInstance = 0; // *************************************************************************** // Constructor. Set the geometry to be open // *************************************************************************** // G4GeometryManager::G4GeometryManager() : fIsClosed(false) { } // *************************************************************************** // Closes geometry - performs sanity checks and optionally builds optimisation // for placed volumes (always built for replicas & parameterised). // NOTE: Currently no sanity checks are performed. // Applies to just a specific subtree if a physical volume is specified. // *************************************************************************** // G4bool G4GeometryManager::CloseGeometry(G4bool pOptimise, G4bool verbose, G4VPhysicalVolume* pVolume) { if (!fIsClosed) { if (pVolume) { BuildOptimisations(pOptimise, pVolume); } else { BuildOptimisations(pOptimise, verbose); } fIsClosed=true; } return true; } // *************************************************************************** // Opens the geometry and removes optimisations (optionally, related to just // the specified logical-volume). // Applies to just a specific subtree if a physical volume is specified. // *************************************************************************** // void G4GeometryManager::OpenGeometry(G4VPhysicalVolume* pVolume) { if (fIsClosed) { if (pVolume) { DeleteOptimisations(pVolume); } else { DeleteOptimisations(); } fIsClosed=false; } } // *************************************************************************** // Returns status of geometry // *************************************************************************** // G4bool G4GeometryManager::IsGeometryClosed() { return fIsClosed; } // *************************************************************************** // Returns the instance of the singleton. // Creates it in case it's called for the first time. // *************************************************************************** // G4GeometryManager* G4GeometryManager::GetInstance() { static G4GeometryManager worldManager; if (!fgInstance) { fgInstance = &worldManager; } return fgInstance; } // *************************************************************************** // Creates optimisation info. Builds all voxels if allOpts=true // otherwise it builds voxels only for replicated volumes. // *************************************************************************** // void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4bool verbose) { G4Timer timer; G4Timer allTimer; std::vector stats; if (verbose) { allTimer.Start(); } G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance(); G4LogicalVolume* volume; G4SmartVoxelHeader* head; for (size_t n=0; nsize(); n++) { if (verbose) timer.Start(); volume=(*Store)[n]; // For safety, check if there are any existing voxels and // delete before replacement // head = volume->GetVoxelHeader(); delete head; volume->SetVoxelHeader(0); if ( ( (volume->IsToOptimise()) && (volume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) ) || ( (volume->GetNoDaughters()==1) && (volume->GetDaughter(0)->IsReplicated()==true) && (volume->GetDaughter(0)->GetRegularStructureId()!=1) ) ) { #ifdef G4GEOMETRY_VOXELDEBUG G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl << " Examining logical volume name = " << volume->GetName() << G4endl; #endif head = new G4SmartVoxelHeader(volume); if (head) { volume->SetVoxelHeader(head); } else { G4cerr << "ERROR - Allocation of new VoxelHeader" << G4endl << " for volume " << volume->GetName() << " failed." << G4endl; G4Exception("G4GeometryManager::BuildOptimisations()", "FatalError", FatalException, "VoxelHeader allocation error."); } if (verbose) { timer.Stop(); stats.push_back( G4SmartVoxelStat( volume, head, timer.GetSystemElapsed(), timer.GetUserElapsed() ) ); } } else { // Don't create voxels for this node #ifdef G4GEOMETRY_VOXELDEBUG G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl << " Skipping logical volume name = " << volume->GetName() << G4endl; #endif } } if (verbose) { allTimer.Stop(); ReportVoxelStats( stats, allTimer.GetSystemElapsed() + allTimer.GetUserElapsed() ); } } // *************************************************************************** // Creates optimisation info for the specified volumes subtree. // *************************************************************************** // void G4GeometryManager::BuildOptimisations(G4bool allOpts, G4VPhysicalVolume* pVolume) { if (!pVolume) { return; } // Retrieve the mother logical volume, if not NULL, // otherwise apply global optimisation for the world volume // G4LogicalVolume* tVolume = pVolume->GetMotherLogical(); if (!tVolume) { return BuildOptimisations(allOpts, false); } G4SmartVoxelHeader* head = tVolume->GetVoxelHeader(); delete head; tVolume->SetVoxelHeader(0); if ( ( (tVolume->IsToOptimise()) && (tVolume->GetNoDaughters()>=kMinVoxelVolumesLevel1&&allOpts) ) || ( (tVolume->GetNoDaughters()==1) && (tVolume->GetDaughter(0)->IsReplicated()==true) ) ) { head = new G4SmartVoxelHeader(tVolume); if (head) { tVolume->SetVoxelHeader(head); } else { G4cerr << "ERROR - Allocation of new VoxelHeader" << G4endl << " for volume " << tVolume->GetName() << " failed." << G4endl; G4Exception("G4GeometryManager::BuildOptimisations()", "FatalError", FatalException, "VoxelHeader allocation error."); } } else { // Don't create voxels for this node #ifdef G4GEOMETRY_VOXELDEBUG G4cout << "**** G4GeometryManager::BuildOptimisations" << G4endl << " Skipping logical volume name = " << tVolume->GetName() << G4endl; #endif } // Scan recursively the associated logical volume tree // tVolume = pVolume->GetLogicalVolume(); if (tVolume->GetNoDaughters()) { BuildOptimisations(allOpts, tVolume->GetDaughter(0)); } } // *************************************************************************** // Removes all optimisation info. // Loops over all logical volumes, deleting non-null voxels pointers, // *************************************************************************** // void G4GeometryManager::DeleteOptimisations() { G4LogicalVolume* tVolume = 0; G4LogicalVolumeStore* Store = G4LogicalVolumeStore::GetInstance(); for (size_t n=0; nsize(); n++) { tVolume=(*Store)[n]; delete tVolume->GetVoxelHeader(); tVolume->SetVoxelHeader(0); } } // *************************************************************************** // Removes optimisation info for the specified subtree. // Scans recursively all daughter volumes, deleting non-null voxels pointers. // *************************************************************************** // void G4GeometryManager::DeleteOptimisations(G4VPhysicalVolume* pVolume) { if (!pVolume) { return; } // Retrieve the mother logical volume, if not NULL, // otherwise global deletion to world volume. // G4LogicalVolume* tVolume = pVolume->GetMotherLogical(); if (!tVolume) { return DeleteOptimisations(); } delete tVolume->GetVoxelHeader(); tVolume->SetVoxelHeader(0); // Scan recursively the associated logical volume tree // tVolume = pVolume->GetLogicalVolume(); if (tVolume->GetNoDaughters()) { DeleteOptimisations(tVolume->GetDaughter(0)); } } // *************************************************************************** // Sets the maximum extent of the world volume. The operation is allowed only // if NO solids have been created already. // *************************************************************************** // void G4GeometryManager::SetWorldMaximumExtent(G4double extent) { if (G4SolidStore::GetInstance()->size()) { // Sanity check to assure that extent is fixed BEFORE creating // any geometry object (solids in this case) // G4Exception("G4GeometryManager::SetMaximumExtent()", "NotApplicable", FatalException, "Extent can be set only BEFORE creating any geometry object!"); } G4GeometryTolerance::GetInstance()->SetSurfaceTolerance(extent); } // *************************************************************************** // Reports statistics on voxel optimisation when closing geometry. // *************************************************************************** // void G4GeometryManager::ReportVoxelStats( std::vector & stats, G4double totalCpuTime ) { G4cout << "G4GeometryManager::ReportVoxelStats -- Voxel Statistics" << G4endl << G4endl; // // Get total memory use // G4int i, nStat = stats.size(); G4long totalMemory = 0; for( i=0;i 10 ? 10 : nStat; if (nPrint) { G4cout << "\n Voxelisation: top CPU users:" << G4endl; G4cout << " Percent Total CPU System CPU Memory Volume\n" << " ------- ---------- ---------- -------- ----------" << G4endl; // 12345678901.234567890123.234567890123.234567890123k . } for(i=0;iGetName() << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield) << std::setprecision(6) << G4endl; } // // Second list: sort by memory use // std::sort( stats.begin(), stats.end(), G4SmartVoxelStat::ByMemory() ); if (nPrint) { G4cout << "\n Voxelisation: top memory users:" << G4endl; G4cout << " Percent Memory Heads Nodes Pointers Total CPU Volume\n" << " ------- -------- ------ ------ -------- ---------- ----------" << G4endl; // 12345678901.2345678901k .23456789.23456789.2345678901.234567890123. . } for(i=0;iGetName() << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield) << std::setprecision(6) << G4endl; } }