// // ******************************************************************** // * 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: G4MultiNavigator.cc,v 1.11 2010/09/06 09:49:15 gcosmo Exp $ // GEANT4 tag $ Name: $ // // class G4PathFinder Implementation // // Author: John Apostolakis, November 2006 // -------------------------------------------------------------------- #include "G4MultiNavigator.hh" class G4FieldManager; #include "G4Navigator.hh" #include "G4PropagatorInField.hh" #include "G4TransportationManager.hh" #include // ******************************************************************** // Constructor // ******************************************************************** // G4MultiNavigator::G4MultiNavigator() : G4Navigator(), fLastMassWorld(0) { fNoActiveNavigators= 0; G4ThreeVector Big3Vector( kInfinity, kInfinity, kInfinity ); fLastLocatedPosition = Big3Vector; fSafetyLocation = Big3Vector; fPreStepLocation = Big3Vector; fMinSafety_PreStepPt= -1.0; fMinSafety_atSafLocation= -1.0; fMinSafety= -kInfinity; fTrueMinStep= fMinStep= -kInfinity; for(register int num=0; num< fMaxNav; ++num ) { fpNavigator[num] = 0; fLimitTruth[num] = false; fLimitedStep[num] = kUndefLimited; fCurrentStepSize[num] = fNewSafety[num] = -1.0; fLocatedVolume[num] = 0; } pTransportManager= G4TransportationManager::GetTransportationManager(); G4Navigator* massNav= pTransportManager->GetNavigatorForTracking(); if( massNav ) { G4VPhysicalVolume* pWorld= massNav->GetWorldVolume(); if( pWorld ) { SetWorldVolume( pWorld ); fLastMassWorld = pWorld; } } } G4MultiNavigator::~G4MultiNavigator() { } G4double G4MultiNavigator::ComputeStep(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double proposedStepLength, G4double &pNewSafety) { G4double safety= 0.0, step=0.0; G4double minSafety= kInfinity, minStep= kInfinity; #ifdef G4DEBUG_NAVIGATION if( fVerbose > 2 ) { G4cout << " G4MultiNavigator::ComputeStep : entered " << G4endl; G4cout << " Input position= " << pGlobalPoint << " direction= " << pDirection << G4endl; G4cout << " Requested step= " << proposedStepLength << G4endl; } #endif std::vector::iterator pNavigatorIter; pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator(); G4ThreeVector initialPosition = pGlobalPoint; G4ThreeVector initialDirection= pDirection; for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num ) { safety= kInfinity; step= (*pNavigatorIter)->ComputeStep( initialPosition, initialDirection, proposedStepLength, safety ); if( safety < minSafety ){ minSafety = safety; } if( step < minStep ) { minStep= step; } fCurrentStepSize[num] = step; fNewSafety[num]= safety; // This is currently the safety from the last sub-step #ifdef G4DEBUG_NAVIGATION if( fVerbose > 2 ) { G4cout << "G4MultiNavigator::ComputeStep : Navigator [" << num << "] -- step size " << step << " safety= " << safety << G4endl; } #endif } // Save safety value, related position // fPreStepLocation = initialPosition; fMinSafety_PreStepPt = minSafety; fMinStep = minStep; if( fMinStep == kInfinity ) { fTrueMinStep = proposedStepLength; // Use this below for endpoint !! } else { fTrueMinStep = minStep; } #ifdef G4DEBUG_NAVIGATION if( fVerbose > 1 ) { G4ThreeVector endPosition = initialPosition+fTrueMinStep*initialDirection; G4int oldPrec = G4cout.precision(8); G4cout << "G4MultiNavigator::ComputeStep : " << " initialPosition = " << initialPosition << " and endPosition = " << endPosition << G4endl; G4cout.precision( oldPrec ); } #endif pNewSafety = minSafety; this->WhichLimited(); #ifdef G4DEBUG_NAVIGATION if( fVerbose > 2 ) { G4cout << " G4MultiNavigator::ComputeStep : exits returning " << minStep << G4endl; } #endif return minStep; // must return kInfinity if do not limit step } // ---------------------------------------------------------------------- G4double G4MultiNavigator::ObtainFinalStep( G4int navigatorId, G4double &pNewSafety, // for this geometry G4double &minStep, ELimited &limitedStep) { if( navigatorId > fNoActiveNavigators ) { G4cerr << "ERROR - G4MultiNavigator::ObtainFinalStep()" << " Navigator Id = " << navigatorId << " No Active = " << fNoActiveNavigators << " . " << G4endl; G4Exception("G4MultiNavigator::ObtainFinalStep()", "InvalidSetup", FatalException, "Bad Navigator Id" ); } // Prepare the information to return // pNewSafety = fNewSafety[ navigatorId ]; limitedStep = fLimitedStep[ navigatorId ]; minStep= fMinStep; #ifdef G4DEBUG_NAVIGATION if( fVerbose > 1 ) { G4cout << " G4MultiNavigator::ComputeStep returns " << fCurrentStepSize[ navigatorId ] << " for Navigator " << navigatorId << " Limited step = " << limitedStep << " Safety(mm) = " << pNewSafety / mm << G4endl; } #endif return fCurrentStepSize[ navigatorId ]; } // ---------------------------------------------------------------------- void G4MultiNavigator::PrepareNewTrack( const G4ThreeVector position, const G4ThreeVector direction ) { #ifdef G4DEBUG_NAVIGATION if( fVerbose > 1 ) { G4cout << " Entered G4MultiNavigator::PrepareNewTrack() " << G4endl; } #endif G4MultiNavigator::PrepareNavigators(); LocateGlobalPointAndSetup( position, &direction, false, false ); // // The first location for each Navigator must be non-relative // or else call ResetStackAndState() for each Navigator // Use direction to get correct side of boundary (ignore dir= false) } // ---------------------------------------------------------------------- void G4MultiNavigator::PrepareNavigators() { // Key purposes: // - Check and cache set of active navigators // - Reset state for new track #ifdef G4DEBUG_NAVIGATION if( fVerbose > 1 ) { G4cout << " Entered G4MultiNavigator::PrepareNavigators() " << G4endl; } #endif // Message the transportation-manager to find active navigators std::vector::iterator pNavigatorIter; fNoActiveNavigators= pTransportManager-> GetNoActiveNavigators(); if( fNoActiveNavigators > fMaxNav ) { G4cerr << "ERROR - G4MultiNavigator::PrepareNavigators()" << " Too many active Navigators (worlds): " << fNoActiveNavigators << G4endl << " which is more than the number allowed: " << fMaxNav << " !" << G4endl; G4Exception("G4MultiNavigator::PrepareNavigators()", "InvalidSetup", FatalException, "Too many active Navigators / worlds !"); } pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator(); for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num ) { fpNavigator[num] = *pNavigatorIter; fLimitTruth[num] = false; fLimitedStep[num] = kDoNot; fCurrentStepSize[num] = 0.0; fLocatedVolume[num] = 0; } fWasLimitedByGeometry = false; // Check the world volume of the mass navigator // in case a call to SetWorldVolume() changed it G4VPhysicalVolume* massWorld = GetWorldVolume(); if( (massWorld != fLastMassWorld) && (massWorld!=0) ) { // Pass along change to Mass Navigator fpNavigator[0] -> SetWorldVolume( massWorld ); #ifdef G4DEBUG_NAVIGATION if( fVerbose > 0 ) { G4cout << " G4MultiNavigator::PrepareNavigators() changed world volume " << " for mass geometry to " << massWorld->GetName() << G4endl; } #endif fLastMassWorld = massWorld; } } // ---------------------------------------------------------------------- G4VPhysicalVolume* G4MultiNavigator::LocateGlobalPointAndSetup(const G4ThreeVector& position, const G4ThreeVector* pDirection, const G4bool pRelativeSearch, const G4bool ignoreDirection ) { // Locate the point in each geometry G4ThreeVector direction(0.0, 0.0, 0.0); G4bool relative = pRelativeSearch; std::vector::iterator pNavIter = pTransportManager->GetActiveNavigatorsIterator(); if( pDirection ) { direction = *pDirection; } #ifdef G4DEBUG_NAVIGATION if( fVerbose > 2 ) { G4cout << " Entered G4MultiNavigator::LocateGlobalPointAndSetup() " << G4endl; G4cout << " Locating at position: " << position << ", with direction: " << direction << G4endl << " Relative: " << relative << ", ignore direction: " << ignoreDirection << G4endl; G4cout << " Number of active navigators: " << fNoActiveNavigators << G4endl; } #endif for ( register int num=0; num< fNoActiveNavigators ; ++pNavIter,++num ) { if( fWasLimitedByGeometry && fLimitTruth[num] ) { (*pNavIter)->SetGeometricallyLimitedStep(); } G4VPhysicalVolume *pLocated = (*pNavIter)->LocateGlobalPointAndSetup( position, &direction, relative, ignoreDirection ); // Set the state related to the location // fLocatedVolume[num] = pLocated; // Clear state related to the step // fLimitedStep[num] = kDoNot; fCurrentStepSize[num] = 0.0; fLimitTruth[ num ] = false; // Always clear on locating (see Navigator) #ifdef G4DEBUG_NAVIGATION if( fVerbose > 2 ) { G4cout << " Located in world: " << num << ", at: " << position << G4endl << " Used geomLimStp: " << fLimitTruth[num] << ", found in volume: " << pLocated << G4endl; G4cout << " Name = '" ; if( pLocated ) { G4cout << pLocated->GetName() << "'"; G4cout << " - CopyNo= " << pLocated->GetCopyNo(); } else { G4cout << "Null' Id: Not-Set "; } G4cout << G4endl; } #endif } fWasLimitedByGeometry = false; // Clear on locating G4VPhysicalVolume* volMassLocated= fLocatedVolume[0]; return volMassLocated; } // ---------------------------------------------------------------------- void G4MultiNavigator::LocateGlobalPointWithinVolume(const G4ThreeVector& position) { // Relocate the point in each geometry std::vector::iterator pNavIter = pTransportManager->GetActiveNavigatorsIterator(); #ifdef G4DEBUG_NAVIGATION if( fVerbose > 2 ) { G4cout << " Entered G4MultiNavigator::ReLocate() " << G4endl << " Re-locating at position: " << position << G4endl; } #endif for ( register int num=0; num< fNoActiveNavigators ; ++pNavIter,++num ) { // ... none limited the step (*pNavIter)->LocateGlobalPointWithinVolume( position ); // Clear state related to the step // fLimitedStep[num] = kDoNot; fCurrentStepSize[num] = 0.0; fLimitTruth[ num ] = false; // Always clear on locating (see Navigator) } fWasLimitedByGeometry = false; // Clear on locating fLastLocatedPosition = position; } // ---------------------------------------------------------------------- G4double G4MultiNavigator::ComputeSafety( const G4ThreeVector& position, const G4double maxDistance, const G4bool state) { // Recompute safety for the relevant point G4double minSafety = kInfinity, safety = kInfinity; std::vector::iterator pNavigatorIter; pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator(); for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num ) { safety = (*pNavigatorIter)->ComputeSafety( position, maxDistance, state); if( safety < minSafety ) { minSafety = safety; } } fSafetyLocation = position; fMinSafety_atSafLocation = minSafety; #ifdef G4DEBUG_NAVIGATION if( fVerbose > 1 ) { G4cout << " G4MultiNavigator::ComputeSafety - returns: " << minSafety << ", at location: " << position << G4endl; } #endif return minSafety; } // ----------------------------------------------------------------------- G4TouchableHistoryHandle G4MultiNavigator::CreateTouchableHistoryHandle() const { G4Exception( "G4MultiNavigator::CreateTouchableHistoryHandle()", "215-TouchableFromWrongNavigator", FatalException, "Getting a touchable from G4MultiNavigator is not defined."); G4TouchableHistory* touchHist; touchHist= fpNavigator[0] -> CreateTouchableHistory(); G4VPhysicalVolume* locatedVolume= fLocatedVolume[0]; if( locatedVolume == 0 ) { // Workaround to ensure that the touchable is fixed !! // TODO: fix // touchHist->UpdateYourself( locatedVolume, touchHist->GetHistory() ); } return G4TouchableHistoryHandle(touchHist); } // ----------------------------------------------------------------------- void G4MultiNavigator::WhichLimited() { // Flag which processes limited the step G4int last=-1; const G4int IdTransport= 0; // Id of Mass Navigator !! G4int noLimited=0; ELimited shared= kSharedOther; #ifdef G4DEBUG_NAVIGATION if( fVerbose > 2 ) { G4cout << " Entered G4MultiNavigator::WhichLimited() " << G4endl; } #endif // Assume that [IdTransport] is Mass / Transport // G4bool transportLimited = (fCurrentStepSize[IdTransport] == fMinStep) && ( fMinStep!= kInfinity); if( transportLimited ) { shared= kSharedTransport; } for ( register int num= 0; num < fNoActiveNavigators; num++ ) { G4bool limitedStep; G4double step= fCurrentStepSize[num]; limitedStep = ( step == fMinStep ) && ( step != kInfinity); fLimitTruth[ num ] = limitedStep; if( limitedStep ) { noLimited++; fLimitedStep[num] = shared; last= num; } else { fLimitedStep[num] = kDoNot; } } if( (last > -1) && (noLimited == 1 ) ) { fLimitedStep[ last ] = kUnique; } } // ----------------------------------------------------------------------- void G4MultiNavigator::PrintLimited() { // Report results -- for checking static G4String StrDoNot("DoNot"), StrUnique("Unique"), StrUndefined("Undefined"), StrSharedTransport("SharedTransport"), StrSharedOther("SharedOther"); G4cout << "### G4MultiNavigator::PrintLimited() reports: " << G4endl; G4cout << " Minimum step (true): " << fTrueMinStep << ", reported min: " << fMinStep << G4endl; #ifdef G4DEBUG_NAVIGATION if(fVerbose>=2) { G4cout << std::setw(5) << " NavId" << " " << std::setw(12) << " step-size " << " " << std::setw(12) << " raw-size " << " " << std::setw(12) << " pre-safety " << " " << std::setw(15) << " Limited / flag" << " " << std::setw(15) << " World " << " " << G4endl; } #endif for ( register int num= 0; num < fNoActiveNavigators; num++ ) { G4double rawStep = fCurrentStepSize[num]; G4double stepLen = fCurrentStepSize[num]; if( stepLen > fTrueMinStep ) { stepLen = fTrueMinStep; // did not limit (went as far as asked) } G4int oldPrec= G4cout.precision(9); G4cout << std::setw(5) << num << " " << std::setw(12) << stepLen << " " << std::setw(12) << rawStep << " " << std::setw(12) << fNewSafety[num] << " " << std::setw(5) << (fLimitTruth[num] ? "YES" : " NO") << " "; G4String limitedStr; switch ( fLimitedStep[num] ) { case kDoNot : limitedStr= StrDoNot; break; case kUnique : limitedStr = StrUnique; break; case kSharedTransport: limitedStr= StrSharedTransport; break; case kSharedOther : limitedStr = StrSharedOther; break; default : limitedStr = StrUndefined; break; } G4cout << " " << std::setw(15) << limitedStr << " "; G4cout.precision(oldPrec); G4Navigator *pNav= fpNavigator[ num ]; G4String WorldName( "Not-Set" ); if (pNav) { G4VPhysicalVolume *pWorld= pNav->GetWorldVolume(); if( pWorld ) { WorldName = pWorld->GetName(); } } G4cout << " " << WorldName ; G4cout << G4endl; } } // ----------------------------------------------------------------------- void G4MultiNavigator::ResetState() { fWasLimitedByGeometry= false; G4Exception("G4MultiNavigator::ResetState()", "217-NotImplemented", FatalException, "Cannot call ResetState() for navigators of G4MultiNavigator."); std::vector::iterator pNavigatorIter; pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator(); for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num ) { // (*pNavigatorIter)->ResetState(); // KEEP THIS comment !!! } } // ----------------------------------------------------------------------- void G4MultiNavigator::SetupHierarchy() { G4Exception( "G4MultiNavigator::SetupHierarchy()", "217-NotImplemented", FatalException, "Cannot call SetupHierarchy() for navigators of G4MultiNavigator."); } // ----------------------------------------------------------------------- void G4MultiNavigator::CheckMassWorld() { G4VPhysicalVolume* navTrackWorld= pTransportManager->GetNavigatorForTracking()->GetWorldVolume(); if( navTrackWorld != fLastMassWorld ) { G4Exception( "G4MultiNavigator::CheckMassWorld()", "220-InvalidSetup", FatalException, "Mass world pointer has been changed." ); } } // ----------------------------------------------------------------------- G4VPhysicalVolume* G4MultiNavigator::ResetHierarchyAndLocate(const G4ThreeVector &point, const G4ThreeVector &direction, const G4TouchableHistory &MassHistory) { // Reset geometry for all -- and use the touchable for the mass history G4VPhysicalVolume* massVolume=0; G4Navigator* pMassNavigator= fpNavigator[0]; if( pMassNavigator ) { massVolume= pMassNavigator->ResetHierarchyAndLocate( point, direction, MassHistory); } else { G4Exception("G4MultiNavigator::ResetHierarchyAndLocate()", "218-TooEarlyToReset", FatalException, "Cannot reset hierarchy before navigators are initialised."); } std::vector::iterator pNavIter= pTransportManager->GetActiveNavigatorsIterator(); for ( register int num=0; num< fNoActiveNavigators ; ++pNavIter,++num ) { G4bool relativeSearch, ignoreDirection; (*pNavIter)-> LocateGlobalPointAndSetup( point, &direction, relativeSearch=false, ignoreDirection=false); } return massVolume; }