Files
geant4/source/geometry/volumes/src/G4Navigator.cc
T
2016-06-08 15:28:20 +02:00

990 lines
29 KiB
C++

// 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 1999/12/07 20:48:43 gunter Exp $
// GEANT4 tag $Name: geant4-01-00 $
//
//
// class G4Navigator Implementation Paul Kent July 95/96
#include "G4Navigator.hh"
#include "G4ios.hh"
#include <iomanip.h>
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 " << endl;
G4cerr << " History = " << endl << fHistory << endl << endl;
#endif
#ifdef G4VERBOSE
if( fVerbose > 0 )
{
G4cout << "*** G4Navigator::LocateGlobalPointAndSetup: ***" << endl;
G4cout.precision(8);
G4cout << " I was called with the following arguments: " << endl
<< " Globalpoint = " << globalPoint << endl
<< " relativeSearch = " << relativeSearch << endl;
// << " = " << << endl
G4cout << " Upon entering my state is: " << endl;
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 << endl;
}
#endif
#ifdef DEBUG_HIST
G4cerr << "Upon exiting LocateGlobalPointAndSetup " << endl;
G4cerr << " History = " << endl << fHistory << endl << endl;
#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
cout.precision(8);
if( fVerbose > 1 )
{
cout << "*** G4Navigator::ComputeStep: ***" << endl;
cout.precision(8);
cout << " I was called with the following arguments: " << endl
<< " Globalpoint = " << setw(25) << pGlobalpoint << endl
<< " Direction = " << setw(25) << pDirection << endl
<< " ProposedStepLength= " << pCurrentProposedStepLength << endl;
// << " = " << << endl
}
if( fVerbose > 2 )
{
// cout.precision(3);
cout << " Upon entering my state is: " << endl;
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: " << endl;
else
G4cerr << "Warning G4Navigator::ComputeStep found slightly inaccurate position:" << endl;
G4cerr << " The Step's starting point has moved "
<< sqrt(moveLenSq)/mm << " mm " << endl
<< " since the last call to a Locate method." << endl;
G4cerr << " This has resulted in moving "
<< shiftOrigin/mm << " mm "
<< " from the last point at which the safety "
<< " was calculated " << endl;
G4cerr << " which is more than the computed safety= "
<< fPreviousSafety/mm << " mm at that point." << endl;
G4cerr << " This difference is "
<< diffShiftSaf /mm << " mm." << endl;
#ifdef G4VERBOSE
static G4int warnNow= 0;
if( ((++warnNow % 100) == 1) ) { // || (warnNow < 4) ){
G4cerr << " This problem can be due to either " << endl;
G4cerr << " - a process that has proposed a displacement"
<< " larger than the current safety , or" << endl;
G4cerr << " - inaccuracy in the computation of the safety" << endl;
G4cerr << " - if you are using a magnetic field, a known conflict about the safety exists in this case."
<< endl;
G4cerr << " We suggest that you " << endl
<< " - find i) what particle is being tracked, and "
<< " ii) through what part of your geometry " << endl
<< " for example by reruning this event with " << endl
<< " /tracking/verbose 1 " << endl
<< " - check which processes you declare for this particle"
<< " (and look at non-standard ones) " << endl
<< " - if possible create a detailed logfile "
<< " of this event using:" << endl
<< " /tracking/verbose 6 "
<< endl;
}
// G4cerr << " - ." << endl;
#endif
}
#ifdef DEBUG
else
{
G4cerr << " Warning in G4Navigator::ComputeStep: " << endl
<< "The Step's starting point has moved " << sqrt(moveLenSq)
<< " which has taken it to the limit of the current safety. "
<< endl;
}
#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 )
{
cout << " Upon exiting my state is: " << endl;
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;
}
}
ostream& operator << (ostream &os,const G4Navigator &n)
{
os << "Current History: " << endl << 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: ***" << endl;
G4cout.precision(8);
G4cout << " I was called with the following arguments: " << endl
<< " Globalpoint = " << pGlobalpoint << endl;
// cout << " pMaxLength = " << pMaxLength << endl;
G4cout << " Upon entering my state is: " << endl;
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 )
{
cout.precision(8);
cout << " Upon exiting my state is: " << endl;
PrintState();
cout << " and I return a value of Safety = " << newSafety << endl;
}
#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: " << endl;
G4cout << " ValidExitNormal= " << fValidExitNormal << endl
<< " ExitNormal = " << fExitNormal << endl
<< " Exiting = " << fExiting << endl
<< " Entering = " << fEntering << endl
<< " BlockedPhysicalVolume= " ;
if (fBlockedPhysicalVolume==0 )
G4cout << "None";
else
G4cout << fBlockedPhysicalVolume->GetName();
G4cout << endl
<< " BlockedReplicaNo = " << fBlockedReplicaNo << endl
<< " LastStepWasZero = " << fLastStepWasZero << endl
<< endl;
}
if( ( 1 < fVerbose) && (fVerbose < 4) )
{
G4cout.precision(3);
G4cout << setw(18) << " ExitNormal " << " "
<< setw( 5) << " Valid " << " "
<< setw( 9) << " Exiting " << " "
<< setw( 9) << " Entering" << " "
<< setw(15) << " Blocked:Volume " << " "
<< setw( 9) << " ReplicaNo" << " "
<< setw( 8) << " LastStepZero " << " "
<< endl;
G4cout << setw(18) << fExitNormal << " "
<< setw( 5) << fValidExitNormal << " "
<< setw( 9) << fExiting << " "
<< setw( 9) << fEntering << " ";
if (fBlockedPhysicalVolume==0 )
G4cout << setw(15) << "None";
else
G4cout << setw(15)<< fBlockedPhysicalVolume->GetName();
G4cout << setw( 9) << fBlockedReplicaNo << " "
<< setw( 8) << fLastStepWasZero << " "
<< endl;
}
if( fVerbose > 2 )
{
G4cout.precision(8);
G4cout << " Current Localpoint = " << fLastLocatedPointLocal << endl;
G4cout << " PreviousSftOrigin = " << fPreviousSftOrigin << endl;
G4cout << " PreviousSafety = " << fPreviousSafety << endl;
}
}
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.
cerr << " ERROR in G4Navigator::LocateGlobalPointWithinVolume " << endl;
cerr << " A volume change has occured - this is not expected & illegal" << endl;
cerr << " Old volume name = " << pOldVol->GetName() << endl;
cerr << " New volume name = " << pNewVol->GetName() << endl;
G4VPhysicalVolume *pNewVol2;
pNewVol2= LocateGlobalPointAndSetup(pGlobalpoint, 0);
//, G4ThreeVector(1.,0.,0.));
cerr << " Tried again & found volume= " << pNewVol2->GetName() << endl;
}
// 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;
}