// This code implementation is the intellectual property of // the GEANT4 collaboration. // // By copying, distributing or modifying the Program (or any work // based on the Program) you indicate your acceptance of this statement, // and all its terms. // // $Id: G4Navigator.cc,v 1.7.6.1.2.4 1999/12/14 07:07:52 gunter Exp $ // GEANT4 tag $Name: geant4-02-00 $ // // // class G4Navigator Implementation Paul Kent July 95/96 #include "G4Navigator.hh" #include "G4ios.hh" #include "g4std/iomanip" G4Navigator::G4Navigator() : fWasLimitedByGeometry(false), fTopPhysical(0), fVerbose(0) { ResetStackAndState(); } G4Navigator::~G4Navigator() {;} // Set the world (`topmost') volume void G4Navigator::SetWorldVolume(G4VPhysicalVolume* pWorld) { // Setup the volume pWorld->Setup(0); // No mother since world volume if (!(pWorld->GetTranslation()==G4ThreeVector(0,0,0))) { G4Exception ("G4Navigator::SetWorldVolume - Must be centred on origin"); } const G4RotationMatrix* rm=pWorld->GetRotation(); if (rm&&(!rm->isIdentity())) { G4Exception ("G4Navigator::SetWorldVolume - Must not be rotated"); } fTopPhysical=pWorld; fHistory.SetFirstEntry(pWorld); } // define DEBUG_HIST 1 // Locate the point in the hierarchy return 0 if outside // // ( The direction is required only if we are on an edge shared by // two or more surfaces. ) // G4VPhysicalVolume* G4Navigator::LocateGlobalPointAndSetup(const G4ThreeVector& globalPoint, const G4ThreeVector* pGlobalDirection, const G4bool relativeSearch) { G4bool notKnownContained=true,noResult; G4VPhysicalVolume *targetPhysical; G4LogicalVolume *targetLogical; G4VSolid *targetSolid; G4ThreeVector localPoint; EInside insideCode; #ifdef DEBUG_HIST G4cerr << "Upon entering LocateGlobalPointAndSetup " << G4endl; G4cerr << " History = " << G4endl << fHistory << G4endl << G4endl; #endif #ifdef G4VERBOSE if( fVerbose > 0 ) { G4cout << "*** G4Navigator::LocateGlobalPointAndSetup: ***" << G4endl; G4cout.precision(8); G4cout << " I was called with the following arguments: " << G4endl << " Globalpoint = " << globalPoint << G4endl << " relativeSearch = " << relativeSearch << G4endl; // << " = " << << G4endl G4cout << " Upon entering my state is: " << G4endl; PrintState(); } #endif if (!relativeSearch) { ResetStackAndState(); } else { if (fWasLimitedByGeometry) { fWasLimitedByGeometry=false; fEnteredDaughter=fEntering; // Remember fExitedMother= fExiting; // Remember if (fExiting) { if (fHistory.GetDepth()) { fBlockedPhysicalVolume=fHistory.GetTopVolume(); fBlockedReplicaNo=fHistory.GetTopReplicaNo(); fHistory.BackLevel(); } else { // Have exited world volume return 0; } // A fix for the case where a volume is "entered" at an edge // and a coincident surface exists outside it. // - This stops it from exiting further volumes and cycling // - However ReplicaNavigator treats this case itself if( fLocatedOnEdge && (VolumeType(fBlockedPhysicalVolume) != kReplica )) // ( fLastStepWasZero ) { fExiting= false; } } else if (fEntering) { G4VPhysicalVolume *curPhysical=fHistory.GetTopVolume(); switch (VolumeType(fBlockedPhysicalVolume)) { case kNormal: fBlockedPhysicalVolume->Setup(curPhysical); fHistory.NewLevel(fBlockedPhysicalVolume); break; case kReplica: freplicaNav.ComputeTransformation(fBlockedReplicaNo, fBlockedPhysicalVolume); fBlockedPhysicalVolume->Setup(curPhysical); fHistory.NewLevel(fBlockedPhysicalVolume, kReplica, fBlockedReplicaNo); fBlockedPhysicalVolume->SetCopyNo(fBlockedReplicaNo); break; case kParameterised: G4VSolid *pSolid; // G4VSolid *pSolid=fBlockedPhysicalVolume-> // GetLogicalVolume()-> GetSolid(); G4VPVParameterisation *pParam=fBlockedPhysicalVolume-> GetParameterisation(); pSolid= pParam->ComputeSolid(fBlockedReplicaNo, fBlockedPhysicalVolume); pSolid->ComputeDimensions(pParam, fBlockedReplicaNo, fBlockedPhysicalVolume); pParam->ComputeTransformation(fBlockedReplicaNo, fBlockedPhysicalVolume); fBlockedPhysicalVolume->Setup(curPhysical); fHistory.NewLevel(fBlockedPhysicalVolume, kParameterised, fBlockedReplicaNo); fBlockedPhysicalVolume->SetCopyNo(fBlockedReplicaNo); // Set the correct solid and material in Logical Volume G4LogicalVolume *pLogical; pLogical= fBlockedPhysicalVolume->GetLogicalVolume(); pLogical->SetSolid( pSolid ); pLogical->SetMaterial( pParam->ComputeMaterial(fBlockedReplicaNo, fBlockedPhysicalVolume)); break; } fEntering=false; fBlockedPhysicalVolume=0; localPoint=fHistory.GetTopTransform().TransformPoint(globalPoint); notKnownContained=false; } } else { fBlockedPhysicalVolume=0; fEntering=false; fEnteredDaughter=false; // Full Step was not taken, did not enter fExiting=false; fExitedMother=false; // Full Step was not taken, did not exit } } // // Search from top of history up through geometry until // containing volume found: // // If on // o OUTSIDE - Back up level, not/no longer exiting volumes // o SURFACE and EXITING - Back up level, setting new blocking no.s // else // o containing volume found // while (notKnownContained) { if (fHistory.GetTopVolumeType()!=kReplica) { targetSolid=fHistory.GetTopVolume()->GetLogicalVolume()->GetSolid(); localPoint=fHistory.GetTopTransform().TransformPoint(globalPoint); insideCode=targetSolid->Inside(localPoint); } else { insideCode=freplicaNav.BackLocate(fHistory,globalPoint,localPoint,fExiting,notKnownContained); // !CARE! if notKnownContained returns false then the point is within // the containing placement volume of the replica(s). If insidecode // will result in the history being backed up one level, then the // local point returned is the point in the system of this new level } if (insideCode==kOutside) { if (fHistory.GetDepth()) { fBlockedPhysicalVolume=fHistory.GetTopVolume(); fBlockedReplicaNo=fHistory.GetTopReplicaNo(); fHistory.BackLevel(); fExiting=false; } else { // Have exited world volume return 0; } } else if (insideCode==kSurface&&fExiting) { if (fHistory.GetDepth()) { fBlockedPhysicalVolume=fHistory.GetTopVolume(); fBlockedReplicaNo=fHistory.GetTopReplicaNo(); fHistory.BackLevel(); // Still on surface but exited volume not necessarily convex fValidExitNormal=false; } else { // Have exited world volume return 0; } } else { notKnownContained=false; } } // // Search downwards until deepest containing volume found, // blocking fBlockedPhysicalVolume/BlockedReplicaNum // // 3 Cases: // // o Parameterised daughters // =>Must be one G4PVParameterised daughter & voxels // o Positioned daughters & voxels // o Positioned daughters & no voxels noResult=true; // noResult should be renamed to // something like enteredLevel, as that is its meaning. do { // Determine `type' of current mother volume targetPhysical=fHistory.GetTopVolume(); targetLogical=targetPhysical->GetLogicalVolume(); switch(CharacteriseDaughters(targetLogical)) { case kNormal: if (targetLogical->GetVoxelHeader()) { noResult=fvoxelNav.LevelLocate(fHistory, fBlockedPhysicalVolume, fBlockedReplicaNo, globalPoint, pGlobalDirection, fLocatedOnEdge, localPoint); } else { noResult=fnormalNav.LevelLocate(fHistory, fBlockedPhysicalVolume, fBlockedReplicaNo, globalPoint, pGlobalDirection, fLocatedOnEdge, localPoint); } break; case kReplica: noResult=freplicaNav.LevelLocate(fHistory, fBlockedPhysicalVolume, fBlockedReplicaNo, globalPoint, pGlobalDirection, fLocatedOnEdge, localPoint); break; case kParameterised: noResult=fparamNav.LevelLocate(fHistory, fBlockedPhysicalVolume, fBlockedReplicaNo, globalPoint, pGlobalDirection, fLocatedOnEdge, localPoint); break; } // LevelLocate returns true if it finds a daughter volume // in which globalPoint is inside (or on the surface). if (noResult) { // The blocked volume is no longer valid - it was for another level fBlockedPhysicalVolume= 0; fBlockedReplicaNo= -1; } } while (noResult); fLastLocatedPointLocal=localPoint; #ifdef G4VERBOSE if( fVerbose > 0 ) PrintState(); if( fVerbose > 1 ) { G4cout.precision(6); G4String curPhysVol_Name("None"); if (targetPhysical!=0) curPhysVol_Name= targetPhysical->GetName(); G4cout << " Return value = new volume = " << curPhysVol_Name << G4endl; } #endif #ifdef DEBUG_HIST G4cerr << "Upon exiting LocateGlobalPointAndSetup " << G4endl; G4cerr << " History = " << G4endl << fHistory << G4endl << G4endl; #endif return targetPhysical; } // Compute the next geometric Step: Intersections with current // mother and `daughter' volumes. // // NOTE: // // Flags on entry: // // fValidExitNormal - Normal of exited volume is valid (convex, not a // coincident boundary) // fExitNormal - Surface normal of exited volume // fExiting - True if have exited solid // // fBlockedPhysicalVolume - Ptr to exited volume (or 0) // fBlockedReplicaNo - Replication no of exited volume // fLastStepWasZero - True if last Step size was zero. // // Flags on exit: // fValidExitNormal - True if surface normal of exited volume is valid // fExitNormal - Surface normal of exited volume rotated to mothers // reference system // fExiting - True if exiting mother // fEntering - True if entering `daughter' volume (or replica) // fBlockedPhysicalVolume - Ptr to candidate (entered) volume // fBlockedReplicaNo - Replication no of candidate (entered) volume // fLastStepWasZero - True if this Step size was zero. G4double G4Navigator::ComputeStep(const G4ThreeVector &pGlobalpoint, const G4ThreeVector &pDirection, const G4double pCurrentProposedStepLength, G4double &pNewSafety) { G4double Step; G4ThreeVector localDirection=ComputeLocalAxis(pDirection); G4VPhysicalVolume *motherPhysical=fHistory.GetTopVolume(); G4LogicalVolume *motherLogical=motherPhysical->GetLogicalVolume(); #ifdef G4VERBOSE G4std::cout.precision(8); if( fVerbose > 1 ) { G4cout << "*** G4Navigator::ComputeStep: ***" << G4endl; G4std::cout.precision(8); G4cout << " I was called with the following arguments: " << G4endl << " Globalpoint = " << G4std::setw(25) << pGlobalpoint << G4endl << " Direction = " << G4std::setw(25) << pDirection << G4endl << " ProposedStepLength= " << pCurrentProposedStepLength << G4endl; // << " = " << << G4endl } if( fVerbose > 2 ) { // G4std::cout.precision(3); G4cout << " Upon entering my state is: " << G4endl; PrintState(); } #endif static G4double fAccuracyForWarning= kCarTolerance, fAccuracyForException= 1000*kCarTolerance; G4ThreeVector newLocalPoint =ComputeLocalPoint(pGlobalpoint); if( newLocalPoint != fLastLocatedPointLocal ) { // Check whether the relocation is within safety // G4ThreeVector oldLocalPoint= fLastLocatedPointLocal; G4double moveLenSq= (newLocalPoint-oldLocalPoint).mag2(); if (moveLenSq >= kCarTolerance*kCarTolerance){ // // The following checks only make sense if the move is larger // than the tolerance. // G4ThreeVector OriginalGlobalpoint; OriginalGlobalpoint = fHistory.GetTopTransform().Inverse() .TransformPoint(fLastLocatedPointLocal); G4double shiftOriginSafSq= (fPreviousSftOrigin-pGlobalpoint).mag2(); // Check that the starting point of this step is // within the isotropic safety sphere of the last point // to a accuracy/precision given by // fAccuracyForWarning // If so give warning. If it fails by more than // fAccuracyForException // exit with error. if( shiftOriginSafSq >= sqr(fPreviousSafety) ){ G4double shiftOrigin=sqrt(shiftOriginSafSq); G4double diffShiftSaf= shiftOrigin - fPreviousSafety; G4bool isError; if( diffShiftSaf > fAccuracyForWarning ){ isError = ( diffShiftSaf >= fAccuracyForException ); G4cerr.precision(10); if ( isError ) G4cerr << "Accuracy ERROR found in G4Navigator::ComputeStep: " << G4endl; else G4cerr << "Warning G4Navigator::ComputeStep found slightly inaccurate position:" << G4endl; G4cerr << " The Step's starting point has moved " << sqrt(moveLenSq)/mm << " mm " << G4endl << " since the last call to a Locate method." << G4endl; G4cerr << " This has resulted in moving " << shiftOrigin/mm << " mm " << " from the last point at which the safety " << " was calculated " << G4endl; G4cerr << " which is more than the computed safety= " << fPreviousSafety/mm << " mm at that point." << G4endl; G4cerr << " This difference is " << diffShiftSaf /mm << " mm." << G4endl; #ifdef G4VERBOSE static G4int warnNow= 0; if( ((++warnNow % 100) == 1) ) { // || (warnNow < 4) ){ G4cerr << " This problem can be due to either " << G4endl; G4cerr << " - a process that has proposed a displacement" << " larger than the current safety , or" << G4endl; G4cerr << " - inaccuracy in the computation of the safety" << G4endl; G4cerr << " - if you are using a magnetic field, a known conflict about the safety exists in this case." << G4endl; G4cerr << " We suggest that you " << G4endl << " - find i) what particle is being tracked, and " << " ii) through what part of your geometry " << G4endl << " for example by reruning this event with " << G4endl << " /tracking/verbose 1 " << G4endl << " - check which processes you declare for this particle" << " (and look at non-standard ones) " << G4endl << " - if possible create a detailed logfile " << " of this event using:" << G4endl << " /tracking/verbose 6 " << G4endl; } // G4cerr << " - ." << G4endl; #endif } #ifdef DEBUG else { G4cerr << " Warning in G4Navigator::ComputeStep: " << G4endl << "The Step's starting point has moved " << sqrt(moveLenSq) << " which has taken it to the limit of the current safety. " << G4endl; } #endif } G4double safetyPlus = fPreviousSafety+ fAccuracyForException; assert( shiftOriginSafSq <= sqr(safetyPlus) ); // Relocate the point within the same volume // LocateGlobalPointWithinVolume( pGlobalpoint ); } } if (fHistory.GetTopVolumeType()!=kReplica) { switch(CharacteriseDaughters(motherLogical)) { case kNormal: if (motherLogical->GetVoxelHeader()) { Step=fvoxelNav.ComputeStep(fLastLocatedPointLocal, localDirection, pCurrentProposedStepLength, pNewSafety, fHistory, fValidExitNormal, fExitNormal, fExiting, fEntering, &fBlockedPhysicalVolume, fBlockedReplicaNo); } else { Step=fnormalNav.ComputeStep(fLastLocatedPointLocal, localDirection, pCurrentProposedStepLength, pNewSafety, fHistory, fValidExitNormal, fExitNormal, fExiting, fEntering, &fBlockedPhysicalVolume, fBlockedReplicaNo); } break; case kParameterised: Step=fparamNav.ComputeStep(fLastLocatedPointLocal, localDirection, pCurrentProposedStepLength, pNewSafety, fHistory, fValidExitNormal, fExitNormal, fExiting, fEntering, &fBlockedPhysicalVolume, fBlockedReplicaNo); break; case kReplica: G4Exception("Logic Error in G4Navigator::ComputeStep()"); break; } } else { // In the case of a replica, // it must handles the exiting edge/corner problem by itself G4bool exitingReplica= fExitedMother; Step=freplicaNav.ComputeStep(pGlobalpoint, pDirection, fLastLocatedPointLocal, localDirection, pCurrentProposedStepLength, pNewSafety, fHistory, fValidExitNormal, fExitNormal, exitingReplica, fEntering, &fBlockedPhysicalVolume, fBlockedReplicaNo); // still ok to set it ?? fExiting= exitingReplica; } if( (Step == pCurrentProposedStepLength) && (!fExiting) && (!fEntering) ) { // This is Step is not really limited by the geometry. // The Navigator is obliged to return "infinity" Step = kInfinity; } // Remember last safety origin & value. fPreviousSftOrigin= pGlobalpoint; fPreviousSafety= pNewSafety; fLocatedOnEdge= fLastStepWasZero && (Step==0); // Edge if two consecutive // steps are zero, because // at least two candidate volumes must have been checked fLastStepWasZero= (Step==0); fEnteredDaughter=fEntering; // I expect to enter a volume in this Step fExitedMother=fExiting; if(fExiting && !fValidExitNormal) { // We must calculate the normal anyway (in order to have it if requested) G4ThreeVector FinalPoint= fLastLocatedPointLocal + localDirection*Step; fExitNormal= motherLogical->GetSolid()->SurfaceNormal(FinalPoint); } #ifdef G4VERBOSE if( fVerbose > 1 ) { G4cout << " Upon exiting my state is: " << G4endl; PrintState(); } #endif return Step; } G4VPhysicalVolume* G4Navigator::LocateGlobalPointAndSetup(const G4ThreeVector &p, const G4TouchableHistory &h) { fHistory=*h.GetHistory(); SetupHierarchy(); return LocateGlobalPointAndSetup(p, 0); } G4ThreeVector G4Navigator::NetTranslation() const { G4AffineTransform tf(fHistory.GetTopTransform().Inverse()); return tf.NetTranslation(); } G4RotationMatrix G4Navigator::NetRotation() const { G4AffineTransform tf(fHistory.GetTopTransform().Inverse()); return tf.NetRotation(); } G4GRSVolume* G4Navigator::CreateGRSVolume() const { G4AffineTransform tf(fHistory.GetTopTransform().Inverse()); return new G4GRSVolume(fHistory.GetTopVolume(), tf.NetRotation(), tf.NetTranslation()); } G4GRSSolid* G4Navigator::CreateGRSSolid() const { G4AffineTransform tf(fHistory.GetTopTransform().Inverse()); return new G4GRSSolid(fHistory.GetTopVolume()->GetLogicalVolume()->GetSolid(), tf.NetRotation(), tf.NetTranslation()); } G4TouchableHistory* G4Navigator::CreateTouchableHistory() const { return new G4TouchableHistory(fHistory); } // Renavigate & reset hierarchy described by current history // o Reset volumes // o Recompute transforms and/or solids of replicated/parameterised vols void G4Navigator::SetupHierarchy() { G4int i; const G4int cdepth=fHistory.GetDepth(); G4VPhysicalVolume *mother,*current; G4VSolid *pSolid; G4VPVParameterisation *pParam; mother=fHistory.GetVolume(0); for (i=1;i<=cdepth;i++) { current=fHistory.GetVolume(i); switch (fHistory.GetVolumeType(i)) { case kNormal: break; case kReplica: freplicaNav.ComputeTransformation(fHistory.GetReplicaNo(i), current); break; case kParameterised: G4int replicaNo; // pSolid=current->GetLogicalVolume()->GetSolid(); pParam=current->GetParameterisation(); replicaNo= fHistory.GetReplicaNo(i); pSolid= pParam->ComputeSolid(replicaNo, current); // Set up dimensions & transform in solid/physical volume pSolid->ComputeDimensions(pParam, replicaNo, current); pParam->ComputeTransformation(replicaNo, current); // Set up the correct solid and material in Logical Volume G4LogicalVolume *pLogical; pLogical= current->GetLogicalVolume(); pLogical->SetSolid( pSolid ); pLogical->SetMaterial( pParam->ComputeMaterial(replicaNo, current)); break; } current->Setup(mother); mother=current; } } G4std::ostream& operator << (G4std::ostream &os,const G4Navigator &n) { os << "Current History: " << G4endl << n.fHistory; return os; } // Return global to local transformation const G4AffineTransform G4Navigator::GetLocalToGlobalTransform() const { G4AffineTransform tempTransform; tempTransform= fHistory.GetTopTransform().Inverse(); return tempTransform; } // Obtain the Normal vector to a surface (in local coordinates) // pointing out of previous volume and into current volume // G4ThreeVector G4Navigator::GetLocalExitNormal(G4bool* valid) { G4ThreeVector ExitNormal(0.,0.,0.); if( fExitedMother ){ ExitNormal=fExitNormal; *valid = true; }else if (EnteredDaughterVolume()) { ExitNormal= -(fHistory.GetTopVolume()->GetLogicalVolume() ->GetSolid()->SurfaceNormal(fLastLocatedPointLocal)); *valid = true; }else{ // We are not at a boundary. // ExitNormal remains (0,0,0) *valid = false; } return ExitNormal; } // It assumes that it assumes that it will be // i) called at the Point in the same volume as the EndPoint of the ComputeStep. // ii) after (or at the end of) ComputeStep OR after the relocation. G4double G4Navigator::ComputeSafety(const G4ThreeVector &pGlobalpoint, const G4double pMaxLength) // A sort of MaximumLength ... ? { G4double newSafety=0.0; #ifdef G4VERBOSE if( fVerbose > 0 ) { G4cout << "*** G4Navigator::ComputeSafety: ***" << G4endl; G4cout.precision(8); G4cout << " I was called with the following arguments: " << G4endl << " Globalpoint = " << pGlobalpoint << G4endl; // cout << " pMaxLength = " << pMaxLength << G4endl; G4cout << " Upon entering my state is: " << G4endl; PrintState(); } #endif // Pseudo-relocate to this point (updates voxel information only). LocateGlobalPointWithinVolume( pGlobalpoint ); if( ! (fEnteredDaughter || fExitedMother ) ) { G4VPhysicalVolume *motherPhysical=fHistory.GetTopVolume(); G4LogicalVolume *motherLogical=motherPhysical->GetLogicalVolume(); G4ThreeVector localPoint= ComputeLocalPoint(pGlobalpoint); if (fHistory.GetTopVolumeType()!=kReplica) { switch(CharacteriseDaughters(motherLogical)) { case kNormal: if (motherLogical->GetVoxelHeader()) { newSafety=fvoxelNav.ComputeSafety(localPoint, fHistory, pMaxLength); } else { newSafety=fnormalNav.ComputeSafety(localPoint, fHistory, pMaxLength); } break; case kParameterised: newSafety=fparamNav.ComputeSafety(localPoint, fHistory, pMaxLength); break; case kReplica: G4Exception("Logic Error in G4Navigator::ComputeSafety()"); break; } } else { newSafety=freplicaNav.ComputeSafety(pGlobalpoint, localPoint, fHistory, pMaxLength); } } // Remember last safety origin & value. fPreviousSftOrigin= pGlobalpoint; fPreviousSafety= newSafety; #ifdef G4VERBOSE if( fVerbose > 1 ) { G4std::cout.precision(8); G4cout << " Upon exiting my state is: " << G4endl; PrintState(); G4cout << " and I return a value of Safety = " << newSafety << G4endl; } #endif return newSafety; } G4bool G4Navigator::EnteredDaughterVolume() { return fEnteredDaughter; } // G4bool G4Navigator::ExitedVolume() // { // return fExitedCurrent; // } void G4Navigator::PrintState() { if( fVerbose >= 4 ) { G4cout.precision(3); G4cout << " Upon exiting my state is: " << G4endl; G4cout << " ValidExitNormal= " << fValidExitNormal << G4endl << " ExitNormal = " << fExitNormal << G4endl << " Exiting = " << fExiting << G4endl << " Entering = " << fEntering << G4endl << " BlockedPhysicalVolume= " ; if (fBlockedPhysicalVolume==0 ) G4cout << "None"; else G4cout << fBlockedPhysicalVolume->GetName(); G4cout << G4endl << " BlockedReplicaNo = " << fBlockedReplicaNo << G4endl << " LastStepWasZero = " << fLastStepWasZero << G4endl << G4endl; } if( ( 1 < fVerbose) && (fVerbose < 4) ) { G4cout.precision(3); G4cout << G4std::setw(18) << " ExitNormal " << " " << G4std::setw( 5) << " Valid " << " " << G4std::setw( 9) << " Exiting " << " " << G4std::setw( 9) << " Entering" << " " << G4std::setw(15) << " Blocked:Volume " << " " << G4std::setw( 9) << " ReplicaNo" << " " << G4std::setw( 8) << " LastStepZero " << " " << G4endl; G4cout << G4std::setw(18) << fExitNormal << " " << G4std::setw( 5) << fValidExitNormal << " " << G4std::setw( 9) << fExiting << " " << G4std::setw( 9) << fEntering << " "; if (fBlockedPhysicalVolume==0 ) G4cout << G4std::setw(15) << "None"; else G4cout << G4std::setw(15)<< fBlockedPhysicalVolume->GetName(); G4cout << G4std::setw( 9) << fBlockedReplicaNo << " " << G4std::setw( 8) << fLastStepWasZero << " " << G4endl; } if( fVerbose > 2 ) { G4cout.precision(8); G4cout << " Current Localpoint = " << fLastLocatedPointLocal << G4endl; G4cout << " PreviousSftOrigin = " << fPreviousSftOrigin << G4endl; G4cout << " PreviousSafety = " << fPreviousSafety << G4endl; } } void G4Navigator::LocateGlobalPointWithinVolume(const G4ThreeVector& pGlobalpoint) { // The new implementation of LocateGlobalPointWithinVolume // // -> the state information of this Navigator and its subNavigators // is updated in order to start the next step at pGlobalpoint // -> no check is performed whether pGlobalpoint is inside the // original volume (this must be the case). // // Note: a direction could be added to the arguments, to aid in // future optional checking (via the Old code below). // [ This would be done only in verbose mode ] fLastLocatedPointLocal =ComputeLocalPoint(pGlobalpoint); // For the case of Voxel (or Parameterised) volume the respective // Navigator must be messaged to update its voxel information etc.o // Update the state of the Sub Navigators // - in particular any voxel information they store/cache //. G4VPhysicalVolume* motherPhysical=fHistory.GetTopVolume(); G4LogicalVolume* motherLogical= motherPhysical->GetLogicalVolume(); G4SmartVoxelHeader* pVoxelHeader= motherLogical->GetVoxelHeader(); G4ThreeVector localPoint= ComputeLocalPoint(pGlobalpoint); if (fHistory.GetTopVolumeType()!=kReplica) { switch(CharacteriseDaughters(motherLogical)) { case kNormal: if (pVoxelHeader) { fvoxelNav.VoxelLocate( pVoxelHeader, localPoint ); } // else { fnormalNav. nothing !? } break; case kParameterised: // Resets state & returns voxel node fparamNav.VoxelLocate( pVoxelHeader, localPoint ); break; case kReplica: G4Exception("Logic Error in G4Navigator::LocateGlobalPointWithinVolume()"); break; } } #if 0 else { // There is no state stored in G4ReplicaNavigation // freplicaNav.VoxelLocate( pVoxelHeader, localPoint ); } #endif #ifdef OLD_LOCATE // An alternative implementation using LocateGlobalPointAndSetup. // It can also be used to check the method's assumptions. // G4VPhysicalVolume *pOldVol, *pNewVol; pOldVol= fHistory.GetTopVolume(); pNewVol= LocateGlobalPointAndSetup(pGlobalpoint, 0); // , G4ThreeVector(1.,0.,0.)); if( pOldVol != pNewVol ){ // This is abnormal behaviour. G4cerr << " ERROR in G4Navigator::LocateGlobalPointWithinVolume " << G4endl; G4cerr << " A volume change has occured - this is not expected & illegal" << G4endl; G4cerr << " Old volume name = " << pOldVol->GetName() << G4endl; G4cerr << " New volume name = " << pNewVol->GetName() << G4endl; G4VPhysicalVolume *pNewVol2; pNewVol2= LocateGlobalPointAndSetup(pGlobalpoint, 0); //, G4ThreeVector(1.,0.,0.)); G4cerr << " Tried again & found volume= " << pNewVol2->GetName() << G4endl; } // Check that the new volume located is same as the old one. assert( pOldVol == pNewVol ); #endif } G4int G4Navigator::GetVerboseLevel() { return fVerbose; } void G4Navigator::SetVerboseLevel(G4int level) { fVerbose=level; }