G4SafetyHelper.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 // $Id$
00027 // GEANT4 tag $ Name:  $
00028 // 
00029 // class G4SafetyHelper Implementation
00030 //
00031 // Original author: John Apostolakis, 2006
00032 //
00033 // --------------------------------------------------------------------
00034 
00035 #include "G4SafetyHelper.hh"
00036 #include "G4PathFinder.hh"
00037 #include "G4TransportationManager.hh"
00038 #include "G4Navigator.hh"
00039 
00040 #include "globals.hh"
00041 
00042 G4SafetyHelper::G4SafetyHelper()
00043  : fUseParallelGeometries(false),     // By default, one geometry only
00044    fFirstCall(true),
00045    fVerbose(0), 
00046    fLastSafetyPosition(0.0,0.0,0.0),
00047    fLastSafety(0.0),
00048    fRecomputeFactor(0.0)
00049 {
00050   fpPathFinder= 0; //  Cannot initialise this yet - a loop results
00051 
00052   // Initialization of the Navigator pointer is postponed, and must
00053   // be undertaken by another class calling InitialiseHelper()
00054   //
00055   fpMassNavigator= 0;  
00056   fMassNavigatorId= -1; 
00057 }
00058 
00059 void G4SafetyHelper::InitialiseNavigator()
00060 {
00061   fpPathFinder= G4PathFinder::GetInstance();
00062  
00063   G4TransportationManager* pTransportMgr= 
00064     G4TransportationManager::GetTransportationManager();
00065 
00066   fpMassNavigator = pTransportMgr->GetNavigatorForTracking(); 
00067 
00068   // Check
00069   //
00070   G4VPhysicalVolume* worldPV = fpMassNavigator->GetWorldVolume(); 
00071   if( worldPV == 0 )
00072   { 
00073     G4Exception("G4SafetyHelper::InitialiseNavigator",
00074                 "InvalidNavigatorWorld", FatalException, 
00075                 "Found that existing tracking Navigator has NULL world"); 
00076   }
00077 
00078   fMassNavigatorId = pTransportMgr->ActivateNavigator( fpMassNavigator ); 
00079 }
00080 
00081 void G4SafetyHelper::InitialiseHelper()
00082 {
00083   fLastSafetyPosition = G4ThreeVector(0.0,0.0,0.0);
00084   fLastSafety         = 0.0;
00085   if (fFirstCall) { InitialiseNavigator(); }
00086   fFirstCall = false;
00087 }
00088 
00089 G4SafetyHelper::~G4SafetyHelper()
00090 {
00091 }
00092 
00093 G4double   
00094 G4SafetyHelper::CheckNextStep(const G4ThreeVector &position, 
00095                               const G4ThreeVector &direction,
00096                               const G4double currentMaxStep,
00097                                     G4double& newSafety )
00098 {  
00099   // Distance in the Mass geometry
00100   //
00101   G4double linstep = fpMassNavigator->CheckNextStep( position,
00102                                                      direction,
00103                                                      currentMaxStep,
00104                                                      newSafety);
00105   fLastSafetyPosition = position;
00106   fLastSafety         = newSafety;
00107 
00108   // TO-DO: Can replace this with a call to PathFinder 
00109   //        giving id of Mass Geometry --> this avoid doing the work twice
00110 
00111   return linstep;
00112 }
00113 
00114 G4double G4SafetyHelper::ComputeSafety( const G4ThreeVector& position, G4double maxLength )
00115 {
00116   G4double newSafety;
00117 
00118   // Only recompute (calling Navigator/PathFinder) if 'position'
00119   // is  *not* the safety location and has moved 'significantly'
00120   //
00121   G4double moveLengthSq = (position-fLastSafetyPosition).mag2();
00122   G4double safeDistance = fRecomputeFactor*fLastSafety; 
00123   if(   (moveLengthSq > 0.0 )
00124      && (moveLengthSq >= safeDistance*safeDistance))    
00125   {
00126     fLastSafetyPosition = position;
00127  
00128     if( !fUseParallelGeometries )
00129     {
00130       // Safety for mass geometry
00131       fLastSafety = fpMassNavigator->ComputeSafety(position, maxLength, true);
00132     }
00133     else
00134     {
00135       // Safety for all geometries
00136       fLastSafety = fpPathFinder->ComputeSafety(position); 
00137     } 
00138     newSafety = fLastSafety;
00139   }
00140   else
00141   {
00142     // return last value if position is not significantly changed
00143     //
00144     G4double moveLength = 0;
00145     if( moveLengthSq > 0.0 )
00146     {
00147       moveLength= std::sqrt(moveLengthSq); 
00148     }
00149     newSafety = fLastSafety-moveLength;
00150   } 
00151   return newSafety;
00152 }
00153 
00154 void G4SafetyHelper::ReLocateWithinVolume( const G4ThreeVector &newPosition )
00155 {
00156 #ifdef G4VERBOSE
00157   if( fVerbose > 0 ) { 
00158     // There is an opportunity - and need - to check whether the proposed move is safe
00159     G4ThreeVector moveVec= newPosition - fLastSafetyPosition;
00160     if( moveVec.mag2() > sqr(fLastSafety) )
00161     {
00162       // A problem exists - we are proposing to move outside 'Safety Sphere'
00163       G4ExceptionDescription ed;
00164       ed << " Safety Sphere:  Radius = " << fLastSafety;
00165       ed << " Center   = " << fLastSafetyPosition << G4endl;
00166       ed << " New Location :  Move   = " << moveVec.mag2();
00167       ed << " Position = " << newPosition << G4endl;
00168       G4Exception("G4SafetyHelper::ReLocateWithinVolume", "GeomNav999", JustWarning,
00169                  "Unsafe Move> Asked to relocate beyond 'Safety sphere'.");
00170     }
00171   }
00172 #endif
00173    
00174   if( !fUseParallelGeometries )
00175   {
00176     fpMassNavigator->LocateGlobalPointWithinVolume( newPosition ); 
00177   }
00178   else
00179   {
00180     fpPathFinder->ReLocate( newPosition ); 
00181   }
00182 }
00183 
00184 void  G4SafetyHelper::Locate( const G4ThreeVector& newPosition, 
00185                               const G4ThreeVector& newDirection)
00186 {
00187   if( !fUseParallelGeometries)
00188   {
00189     fpMassNavigator->LocateGlobalPointAndSetup(newPosition, &newDirection,
00190                                                true, false); 
00191   }
00192   else
00193   {
00194     fpPathFinder->Locate( newPosition, newDirection ); 
00195   }
00196 }

Generated on Mon May 27 17:49:47 2013 for Geant4 by  doxygen 1.4.7