Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/navigation/src/G4Navigator.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /geometry/navigation/src/G4Navigator.cc (Version 11.3.0) and /geometry/navigation/src/G4Navigator.cc (Version 11.2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 // 
 26 // G4Navigator class Implementation                26 // G4Navigator class Implementation
 27 //                                                 27 //
 28 // Original author: Paul Kent, July 95/96          28 // Original author: Paul Kent, July 95/96
 29 // Responsible 1996-present: John Apostolakis,     29 // Responsible 1996-present: John Apostolakis, Gabriele Cosmo
 30 // Additional revisions by: Pedro Arce, Vladim     30 // Additional revisions by: Pedro Arce, Vladimir Grichine
 31 // -------------------------------------------     31 // --------------------------------------------------------------------
 32                                                    32 
 33 #include <iomanip>                                 33 #include <iomanip>
 34                                                    34 
 35 #include "G4Navigator.hh"                          35 #include "G4Navigator.hh"
 36 #include "G4ios.hh"                                36 #include "G4ios.hh"
 37 #include "G4SystemOfUnits.hh"                      37 #include "G4SystemOfUnits.hh"
 38 #include "G4GeometryTolerance.hh"                  38 #include "G4GeometryTolerance.hh"
 39 #include "G4VPhysicalVolume.hh"                    39 #include "G4VPhysicalVolume.hh"
 40                                                    40 
 41 #include "G4VoxelSafety.hh"                        41 #include "G4VoxelSafety.hh"
 42 #include "G4SafetyCalculator.hh"                   42 #include "G4SafetyCalculator.hh"
 43                                                    43 
 44 // Constant determining how precise normals sh     44 // Constant determining how precise normals should be (how close to unit
 45 // vectors). If exceeded, warnings will be iss     45 // vectors). If exceeded, warnings will be issued.
 46 // Can be CLHEP::perMillion (its old default)      46 // Can be CLHEP::perMillion (its old default) for geometry checking.
 47 //                                                 47 //
 48 static const G4double kToleranceNormalCheck =      48 static const G4double kToleranceNormalCheck = CLHEP::perThousand;
 49                                                    49 
 50 // *******************************************     50 // ********************************************************************
 51 // Constructor                                     51 // Constructor
 52 // *******************************************     52 // ********************************************************************
 53 //                                                 53 //
 54 G4Navigator::G4Navigator()                         54 G4Navigator::G4Navigator()
 55 {                                                  55 {
 56   ResetStackAndState();                            56   ResetStackAndState();
 57     // Initialises also all                        57     // Initialises also all 
 58     // - exit / entry flags                        58     // - exit / entry flags
 59     // - flags & variables for exit normals        59     // - flags & variables for exit normals
 60     // - zero step counters                        60     // - zero step counters
 61     // - blocked volume                            61     // - blocked volume 
 62                                                    62 
 63   if( fVerbose > 2 )                               63   if( fVerbose > 2 )
 64   {                                                64   {
 65     G4cout << " G4Navigator parameters: Action     65     G4cout << " G4Navigator parameters: Action Threshold (No Zero Steps) = "
 66            << fActionThreshold_NoZeroSteps         66            << fActionThreshold_NoZeroSteps
 67            << "  Abandon Threshold (No Zero St     67            << "  Abandon Threshold (No Zero Steps) = "
 68            << fAbandonThreshold_NoZeroSteps <<     68            << fAbandonThreshold_NoZeroSteps << G4endl;
 69   }                                                69   }
 70   kCarTolerance = G4GeometryTolerance::GetInst     70   kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
 71   fMinStep = 0.05*kCarTolerance;                   71   fMinStep = 0.05*kCarTolerance;
 72   fSqTol = sqr(kCarTolerance);                     72   fSqTol = sqr(kCarTolerance);
 73                                                    73 
 74   fregularNav.SetNormalNavigation( &fnormalNav     74   fregularNav.SetNormalNavigation( &fnormalNav );
 75                                                    75 
 76   fStepEndPoint = G4ThreeVector( kInfinity, kI     76   fStepEndPoint = G4ThreeVector( kInfinity, kInfinity, kInfinity ); 
 77   fLastStepEndPointLocal = G4ThreeVector( kInf     77   fLastStepEndPointLocal = G4ThreeVector( kInfinity, kInfinity, kInfinity ); 
 78                                                    78 
 79   fpVoxelSafety = new G4VoxelSafety();             79   fpVoxelSafety = new G4VoxelSafety();
 80   fpvoxelNav    = new G4VoxelNavigation();         80   fpvoxelNav    = new G4VoxelNavigation();
 81   fpSafetyCalculator = new G4SafetyCalculator(     81   fpSafetyCalculator = new G4SafetyCalculator( *this, fHistory );
 82   fpSafetyCalculator->SetExternalNavigation(fp     82   fpSafetyCalculator->SetExternalNavigation(fpExternalNav);
 83 }                                                  83 }
 84                                                    84 
 85 // *******************************************     85 // ********************************************************************
 86 // Destructor                                      86 // Destructor
 87 // *******************************************     87 // ********************************************************************
 88 //                                                 88 //
 89 G4Navigator::~G4Navigator()                        89 G4Navigator::~G4Navigator()
 90 {                                                  90 {
 91   delete fpVoxelSafety;                            91   delete fpVoxelSafety;
 92   delete fpExternalNav;                            92   delete fpExternalNav;
 93   delete fpvoxelNav;                               93   delete fpvoxelNav;
 94   delete fpSafetyCalculator;                       94   delete fpSafetyCalculator;
 95 }                                                  95 }
 96                                                    96 
 97 // *******************************************     97 // ********************************************************************
 98 // ResetHierarchyAndLocate                         98 // ResetHierarchyAndLocate
 99 // *******************************************     99 // ********************************************************************
100 //                                                100 //
101 G4VPhysicalVolume*                                101 G4VPhysicalVolume*
102 G4Navigator::ResetHierarchyAndLocate(const G4T    102 G4Navigator::ResetHierarchyAndLocate(const G4ThreeVector& p,
103                                      const G4T    103                                      const G4ThreeVector& direction,
104                                      const G4T    104                                      const G4TouchableHistory& h)
105 {                                                 105 {
106   ResetState();                                   106   ResetState();
107   fHistory = *h.GetHistory();                     107   fHistory = *h.GetHistory();
108   SetupHierarchy();                               108   SetupHierarchy();
109   fLastTriedStepComputation = false;  // Redun    109   fLastTriedStepComputation = false;  // Redundant, but best
110   return LocateGlobalPointAndSetup(p, &directi    110   return LocateGlobalPointAndSetup(p, &direction, true, false);
111 }                                                 111 }
112                                                   112 
113 // *******************************************    113 // ********************************************************************
114 // LocateGlobalPointAndSetup                      114 // LocateGlobalPointAndSetup
115 //                                                115 //
116 // Locate the point in the hierarchy return 0     116 // Locate the point in the hierarchy return 0 if outside
117 // The direction is required                      117 // The direction is required 
118 //    - if on an edge shared by more than two     118 //    - if on an edge shared by more than two surfaces 
119 //      (to resolve likely looping in tracking    119 //      (to resolve likely looping in tracking)
120 //    - at initial location of a particle         120 //    - at initial location of a particle
121 //      (to resolve potential ambiguity at bou    121 //      (to resolve potential ambiguity at boundary)
122 //                                                122 // 
123 // Flags on exit: (comments to be completed)      123 // Flags on exit: (comments to be completed)
124 // fEntering         - True if entering `daugh    124 // fEntering         - True if entering `daughter' volume (or replica)
125 //                     whether daughter of las    125 //                     whether daughter of last mother directly 
126 //                     or daughter of that vol    126 //                     or daughter of that volume's ancestor.
127 // fExiting          - True if exited 'mother'    127 // fExiting          - True if exited 'mother' volume
128 //                     (always ? - how about i    128 //                     (always ? - how about if going back down ? - tbc)
129 // *******************************************    129 // ********************************************************************
130 //                                                130 //
131 G4VPhysicalVolume*                                131 G4VPhysicalVolume* 
132 G4Navigator::LocateGlobalPointAndSetup( const     132 G4Navigator::LocateGlobalPointAndSetup( const G4ThreeVector& globalPoint,
133                                         const     133                                         const G4ThreeVector* pGlobalDirection,
134                                         const     134                                         const G4bool relativeSearch,
135                                         const     135                                         const G4bool ignoreDirection )
136 {                                                 136 {
137   G4bool notKnownContained = true, noResult;      137   G4bool notKnownContained = true, noResult;
138   G4VPhysicalVolume *targetPhysical;              138   G4VPhysicalVolume *targetPhysical;
139   G4LogicalVolume *targetLogical;                 139   G4LogicalVolume *targetLogical;
140   G4VSolid *targetSolid = nullptr;                140   G4VSolid *targetSolid = nullptr;
141   G4ThreeVector localPoint, globalDirection;      141   G4ThreeVector localPoint, globalDirection;
142   EInside insideCode;                             142   EInside insideCode;
143                                                   143 
144   G4bool considerDirection = (pGlobalDirection    144   G4bool considerDirection = (pGlobalDirection != nullptr) && ((!ignoreDirection) || fLocatedOnEdge);
145                                                   145 
146   fLastTriedStepComputation = false;              146   fLastTriedStepComputation = false;   
147   fChangedGrandMotherRefFrame = false;  // For    147   fChangedGrandMotherRefFrame = false;  // For local exit normal
148                                                   148    
149   if( considerDirection )                         149   if( considerDirection )
150   {                                               150   {
151     globalDirection=*pGlobalDirection;            151     globalDirection=*pGlobalDirection;
152   }                                               152   }
153                                                   153 
154 #ifdef G4VERBOSE                                  154 #ifdef G4VERBOSE
155   if( fVerbose > 2 )                              155   if( fVerbose > 2 )
156   {                                               156   {
157     G4long oldcoutPrec = G4cout.precision(8);     157     G4long oldcoutPrec = G4cout.precision(8);
158     G4cout << "*** G4Navigator::LocateGlobalPo    158     G4cout << "*** G4Navigator::LocateGlobalPointAndSetup: ***" << G4endl; 
159     G4cout << "    Called with arguments: " <<    159     G4cout << "    Called with arguments: " << G4endl
160            << "        Globalpoint = " << glob    160            << "        Globalpoint = " << globalPoint << G4endl
161            << "        RelativeSearch = " << r    161            << "        RelativeSearch = " << relativeSearch  << G4endl;
162     if( fVerbose >= 4 )                           162     if( fVerbose >= 4 )
163     {                                             163     {
164       G4cout << "    ----- Upon entering:" <<     164       G4cout << "    ----- Upon entering:" << G4endl;
165       PrintState();                               165       PrintState();
166     }                                             166     }
167     G4cout.precision(oldcoutPrec);                167     G4cout.precision(oldcoutPrec);
168   }                                               168   }
169 #endif                                            169 #endif
170                                                   170 
171   G4int noLevelsExited = 0;                       171   G4int noLevelsExited = 0;
172                                                   172 
173   if ( !relativeSearch )                          173   if ( !relativeSearch )
174   {                                               174   {
175     ResetStackAndState();                         175     ResetStackAndState();
176   }                                               176   }
177   else                                            177   else
178   {                                               178   {
179     if ( fWasLimitedByGeometry )                  179     if ( fWasLimitedByGeometry )
180     {                                             180     {
181       fWasLimitedByGeometry = false;              181       fWasLimitedByGeometry = false;
182       fEnteredDaughter = fEntering;   // Remem    182       fEnteredDaughter = fEntering;   // Remember
183       fExitedMother = fExiting;       // Remem    183       fExitedMother = fExiting;       // Remember
184       if ( fExiting )                             184       if ( fExiting )
185       {                                           185       {
186         ++noLevelsExited;  // count this first    186         ++noLevelsExited;  // count this first level entered too
187                                                   187 
188         if ( fHistory.GetDepth() != 0 )           188         if ( fHistory.GetDepth() != 0 )
189         {                                         189         {
190           fBlockedPhysicalVolume = fHistory.Ge    190           fBlockedPhysicalVolume = fHistory.GetTopVolume();
191           fBlockedReplicaNo = fHistory.GetTopR    191           fBlockedReplicaNo = fHistory.GetTopReplicaNo();
192           fHistory.BackLevel();                   192           fHistory.BackLevel();
193         }                                         193         }
194         else                                      194         else
195         {                                         195         {
196           fLastLocatedPointLocal = localPoint;    196           fLastLocatedPointLocal = localPoint;
197           fLocatedOutsideWorld = true;            197           fLocatedOutsideWorld = true;
198           fBlockedPhysicalVolume = nullptr;       198           fBlockedPhysicalVolume = nullptr;   // to be sure
199           fBlockedReplicaNo = -1;                 199           fBlockedReplicaNo = -1;
200           fEntering = false;            // No     200           fEntering = false;            // No longer 
201           fEnteredDaughter = false;               201           fEnteredDaughter = false; 
202           fExitedMother = true;      // ??        202           fExitedMother = true;      // ??
203                                                   203           
204           return nullptr;           // Have ex    204           return nullptr;           // Have exited world volume
205         }                                         205         }
206         // A fix for the case where a volume i    206         // A fix for the case where a volume is "entered" at an edge
207         // and a coincident surface exists out    207         // and a coincident surface exists outside it.
208         //  - This stops it from exiting furth    208         //  - This stops it from exiting further volumes and cycling
209         //  - However ReplicaNavigator treats     209         //  - However ReplicaNavigator treats this case itself
210         //                                        210         //
211         // assert( fBlockedPhysicalVolume!=0 )    211         // assert( fBlockedPhysicalVolume!=0 );
212                                                   212 
213         // Expect to be on edge => on surface     213         // Expect to be on edge => on surface
214         //                                        214         //
215         if ( fLocatedOnEdge && (VolumeType(fBl    215         if ( fLocatedOnEdge && (VolumeType(fBlockedPhysicalVolume)!=kReplica ))
216         {                                         216         { 
217           fExiting = false;                       217           fExiting = false;
218           // Consider effect on Exit Normal !?    218           // Consider effect on Exit Normal !?
219         }                                         219         }
220       }                                           220       }
221       else                                        221       else
222         if ( fEntering )                          222         if ( fEntering )
223         {                                         223         {
224           switch (VolumeType(fBlockedPhysicalV    224           switch (VolumeType(fBlockedPhysicalVolume))
225           {                                       225           {
226             case kNormal:                         226             case kNormal:
227               fHistory.NewLevel(fBlockedPhysic    227               fHistory.NewLevel(fBlockedPhysicalVolume, kNormal,
228                                 fBlockedPhysic    228                                 fBlockedPhysicalVolume->GetCopyNo());
229               break;                              229               break;
230             case kReplica:                        230             case kReplica:
231               freplicaNav.ComputeTransformatio    231               freplicaNav.ComputeTransformation(fBlockedReplicaNo,
232                                                   232                                                 fBlockedPhysicalVolume);
233               fHistory.NewLevel(fBlockedPhysic    233               fHistory.NewLevel(fBlockedPhysicalVolume, kReplica,
234                                 fBlockedReplic    234                                 fBlockedReplicaNo);
235               fBlockedPhysicalVolume->SetCopyN    235               fBlockedPhysicalVolume->SetCopyNo(fBlockedReplicaNo);
236               break;                              236               break;
237             case kParameterised:                  237             case kParameterised:
238               if( fBlockedPhysicalVolume->GetR    238               if( fBlockedPhysicalVolume->GetRegularStructureId() == 0 )
239               {                                   239               {
240                 G4VSolid *pSolid;                 240                 G4VSolid *pSolid;
241                 G4VPVParameterisation *pParam;    241                 G4VPVParameterisation *pParam;
242                 G4TouchableHistory parentTouch    242                 G4TouchableHistory parentTouchable( fHistory );
243                 pParam = fBlockedPhysicalVolum    243                 pParam = fBlockedPhysicalVolume->GetParameterisation();
244                 pSolid = pParam->ComputeSolid(    244                 pSolid = pParam->ComputeSolid(fBlockedReplicaNo,
245                                                   245                                               fBlockedPhysicalVolume);
246                 pSolid->ComputeDimensions(pPar    246                 pSolid->ComputeDimensions(pParam, fBlockedReplicaNo,
247                                           fBlo    247                                           fBlockedPhysicalVolume);
248                 pParam->ComputeTransformation(    248                 pParam->ComputeTransformation(fBlockedReplicaNo,
249                                                   249                                               fBlockedPhysicalVolume);
250                 fHistory.NewLevel(fBlockedPhys    250                 fHistory.NewLevel(fBlockedPhysicalVolume, kParameterised,
251                                   fBlockedRepl    251                                   fBlockedReplicaNo);
252                 fBlockedPhysicalVolume->SetCop    252                 fBlockedPhysicalVolume->SetCopyNo(fBlockedReplicaNo);
253                 //                                253                 //
254                 // Set the correct solid and m    254                 // Set the correct solid and material in Logical Volume
255                 //                                255                 //
256                 G4LogicalVolume *pLogical;        256                 G4LogicalVolume *pLogical;
257                 pLogical = fBlockedPhysicalVol    257                 pLogical = fBlockedPhysicalVolume->GetLogicalVolume();
258                 pLogical->SetSolid( pSolid );     258                 pLogical->SetSolid( pSolid );
259                 pLogical->UpdateMaterial(pPara    259                 pLogical->UpdateMaterial(pParam ->
260                   ComputeMaterial(fBlockedRepl    260                   ComputeMaterial(fBlockedReplicaNo,
261                                   fBlockedPhys    261                                   fBlockedPhysicalVolume, 
262                                   &parentTouch    262                                   &parentTouchable));
263               }                                   263               }
264               break;                              264               break;
265             case kExternal:                       265             case kExternal:
266               G4Exception("G4Navigator::Locate    266               G4Exception("G4Navigator::LocateGlobalPointAndSetup()",
267                           "GeomNav0001", Fatal    267                           "GeomNav0001", FatalException,
268                           "Extra levels not ap    268                           "Extra levels not applicable for external volumes.");
269               break;                              269               break;
270           }                                       270           }
271           fEntering = false;                      271           fEntering = false;
272           fBlockedPhysicalVolume = nullptr;       272           fBlockedPhysicalVolume = nullptr;
273           localPoint = fHistory.GetTopTransfor    273           localPoint = fHistory.GetTopTransform().TransformPoint(globalPoint);
274           notKnownContained = false;              274           notKnownContained = false;
275         }                                         275         }
276     }                                             276     }
277     else                                          277     else
278     {                                             278     {
279       fBlockedPhysicalVolume = nullptr;           279       fBlockedPhysicalVolume = nullptr;
280       fEntering = false;                          280       fEntering = false;
281       fEnteredDaughter = false;  // Full Step     281       fEnteredDaughter = false;  // Full Step was not taken, did not enter
282       fExiting = false;                           282       fExiting = false;
283       fExitedMother = false;     // Full Step     283       fExitedMother = false;     // Full Step was not taken, did not exit
284     }                                             284     }
285   }                                               285   }
286   //                                              286   //
287   // Search from top of history up through geo    287   // Search from top of history up through geometry until
288   // containing volume found:                     288   // containing volume found:
289   // If on                                        289   // If on 
290   // o OUTSIDE - Back up level, not/no longer     290   // o OUTSIDE - Back up level, not/no longer exiting volumes
291   // o SURFACE and EXITING - Back up level, se    291   // o SURFACE and EXITING - Back up level, setting new blocking no.s
292   // else                                         292   // else
293   // o containing volume found                    293   // o containing volume found
294   //                                              294   //
295                                                   295 
296   while (notKnownContained)  // Loop checking,    296   while (notKnownContained)  // Loop checking, 07.10.2016, J.Apostolakis
297   {                                               297   {
298     EVolume topVolumeType = fHistory.GetTopVol    298     EVolume topVolumeType = fHistory.GetTopVolumeType(); 
299     if (topVolumeType!=kReplica && topVolumeTy    299     if (topVolumeType!=kReplica && topVolumeType!=kExternal)
300     {                                             300     {
301       targetSolid = fHistory.GetTopVolume()->G    301       targetSolid = fHistory.GetTopVolume()->GetLogicalVolume()->GetSolid();
302       localPoint = fHistory.GetTopTransform().    302       localPoint = fHistory.GetTopTransform().TransformPoint(globalPoint);
303       insideCode = targetSolid->Inside(localPo    303       insideCode = targetSolid->Inside(localPoint);
304 #ifdef G4VERBOSE                                  304 #ifdef G4VERBOSE
305       if(( fVerbose == 1 ) && ( fCheck ))         305       if(( fVerbose == 1 ) && ( fCheck ))
306       {                                           306       {
307         G4String solidResponse = "-kInside-";     307         G4String solidResponse = "-kInside-";
308         if (insideCode == kOutside)               308         if (insideCode == kOutside)
309         {                                         309         {
310           solidResponse = "-kOutside-";           310           solidResponse = "-kOutside-";
311         }                                         311         }
312         else if (insideCode == kSurface)          312         else if (insideCode == kSurface)
313         {                                         313         {
314           solidResponse = "-kSurface-";           314           solidResponse = "-kSurface-";
315         }                                         315         }
316         G4cout << "*** G4Navigator::LocateGlob    316         G4cout << "*** G4Navigator::LocateGlobalPointAndSetup(): ***" << G4endl
317                << "    Invoked Inside() for so    317                << "    Invoked Inside() for solid: " << targetSolid->GetName()
318                << ". Solid replied: " << solid    318                << ". Solid replied: " << solidResponse << G4endl
319                << "    For local point p: " <<    319                << "    For local point p: " << localPoint << G4endl;
320       }                                           320       }
321 #endif                                            321 #endif
322     }                                             322     }
323     else                                          323     else
324     {                                             324     {
325        if( topVolumeType == kReplica )            325        if( topVolumeType == kReplica )
326        {                                          326        {
327           insideCode = freplicaNav.BackLocate(    327           insideCode = freplicaNav.BackLocate(fHistory, globalPoint, localPoint,
328                                                   328                                               fExiting, notKnownContained);
329           // !CARE! if notKnownContained retur    329           // !CARE! if notKnownContained returns false then the point is within
330           // the containing placement volume o    330           // the containing placement volume of the replica(s). If insidecode
331           // will result in the history being     331           // will result in the history being backed up one level, then the
332           // local point returned is the point    332           // local point returned is the point in the system of this new level
333        }                                          333        }
334        else                                       334        else
335        {                                          335        {
336           targetSolid = fHistory.GetTopVolume(    336           targetSolid = fHistory.GetTopVolume()->GetLogicalVolume()->GetSolid();
337           localPoint = fHistory.GetTopTransfor    337           localPoint = fHistory.GetTopTransform().TransformPoint(globalPoint);
338           G4ThreeVector localDirection =          338           G4ThreeVector localDirection =
339              fHistory.GetTopTransform().Transf    339              fHistory.GetTopTransform().TransformAxis(globalDirection);
340           insideCode = fpExternalNav->Inside(t    340           insideCode = fpExternalNav->Inside(targetSolid, localPoint, localDirection);
341        }                                          341        }
342     }                                             342     }
343                                                   343 
344     // Point is inside current volume, break o    344     // Point is inside current volume, break out of the loop
345     if ( insideCode == kInside ) { break; }       345     if ( insideCode == kInside ) { break; }
346                                                   346 
347     // Point is outside current volume, move u    347     // Point is outside current volume, move up a level in the hierarchy
348     if ( insideCode == kOutside )                 348     if ( insideCode == kOutside )
349     {                                             349     {
350       ++noLevelsExited;                           350       ++noLevelsExited;
351                                                   351 
352       // Exiting world volume                     352       // Exiting world volume
353       if ( fHistory.GetDepth() == 0 )             353       if ( fHistory.GetDepth() == 0 )
354       {                                           354       {
355         fLocatedOutsideWorld = true;              355         fLocatedOutsideWorld = true;
356         fLastLocatedPointLocal = localPoint;      356         fLastLocatedPointLocal = localPoint;
357         return nullptr;                           357         return nullptr;
358       }                                           358       }
359                                                   359 
360       fBlockedPhysicalVolume = fHistory.GetTop    360       fBlockedPhysicalVolume = fHistory.GetTopVolume();
361       fBlockedReplicaNo = fHistory.GetTopRepli    361       fBlockedReplicaNo = fHistory.GetTopReplicaNo();
362       fHistory.BackLevel();                       362       fHistory.BackLevel();
363       fExiting = false;                           363       fExiting = false;
364                                                   364 
365       if( noLevelsExited > 1 )                    365       if( noLevelsExited > 1 )
366       {                                           366       {
367         // The first transformation was done b    367         // The first transformation was done by the sub-navigator
368         //                                        368         //
369         if(const auto *mRot = fBlockedPhysical    369         if(const auto *mRot = fBlockedPhysicalVolume->GetRotation())
370         {                                         370         {
371           fGrandMotherExitNormal *= (*mRot).in    371           fGrandMotherExitNormal *= (*mRot).inverse();
372           fChangedGrandMotherRefFrame = true;     372           fChangedGrandMotherRefFrame = true;
373         }                                         373         }
374       }                                           374       }
375       continue;                                   375       continue;
376     }                                             376     }
377                                                   377 
378     // Point is on the surface of a volume        378     // Point is on the surface of a volume
379     G4bool isExiting = fExiting;                  379     G4bool isExiting = fExiting;
380     if( (!fExiting) && considerDirection )        380     if( (!fExiting) && considerDirection )
381     {                                             381     {
382       // Figure out whether we are exiting thi    382       // Figure out whether we are exiting this level's volume
383       // by using the direction                   383       // by using the direction
384       //                                          384       //
385       G4bool directionExiting = false;            385       G4bool directionExiting = false;
386       G4ThreeVector localDirection =              386       G4ThreeVector localDirection =
387         fHistory.GetTopTransform().TransformAx    387         fHistory.GetTopTransform().TransformAxis(globalDirection);
388                                                   388 
389       // Make sure localPoint in correct refer    389       // Make sure localPoint in correct reference frame
390       //     ( Was it already correct ? How ?     390       //     ( Was it already correct ? How ? )
391       //                                          391       //
392       localPoint= fHistory.GetTopTransform().T    392       localPoint= fHistory.GetTopTransform().TransformPoint(globalPoint);
393       if ( fHistory.GetTopVolumeType() != kRep    393       if ( fHistory.GetTopVolumeType() != kReplica )
394       {                                           394       {
395         G4ThreeVector normal = targetSolid->Su    395         G4ThreeVector normal = targetSolid->SurfaceNormal(localPoint);
396         directionExiting = normal.dot(localDir    396         directionExiting = normal.dot(localDirection) > 0.0;
397         isExiting = isExiting || directionExit    397         isExiting = isExiting || directionExiting;
398       }                                           398       }
399     }                                             399     }
400                                                   400 
401     // Point is on a surface, but no longer ex    401     // Point is on a surface, but no longer exiting, break out of the loop
402     if ( !isExiting ) { break; }                  402     if ( !isExiting ) { break; }
403                                                   403 
404     ++noLevelsExited;                             404     ++noLevelsExited;
405                                                   405 
406     // Point is on the outer surface, leaving     406     // Point is on the outer surface, leaving world volume
407     if ( fHistory.GetDepth() == 0 )               407     if ( fHistory.GetDepth() == 0 )
408     {                                             408     {
409       fLocatedOutsideWorld = true;                409       fLocatedOutsideWorld = true;
410       fLastLocatedPointLocal = localPoint;        410       fLastLocatedPointLocal = localPoint;
411       return nullptr;                             411       return nullptr;
412     }                                             412     }
413                                                   413 
414     // Point is still on a surface, but exited    414     // Point is still on a surface, but exited a volume not necessarily convex
415     fValidExitNormal = false;                     415     fValidExitNormal = false;
416     fBlockedPhysicalVolume = fHistory.GetTopVo    416     fBlockedPhysicalVolume = fHistory.GetTopVolume();
417     fBlockedReplicaNo = fHistory.GetTopReplica    417     fBlockedReplicaNo = fHistory.GetTopReplicaNo();
418     fHistory.BackLevel();                         418     fHistory.BackLevel();
419                                                   419 
420     if( noLevelsExited > 1 )                      420     if( noLevelsExited > 1 )
421     {                                             421     {
422       // The first transformation was done by     422       // The first transformation was done by the sub-navigator
423       //                                          423       //
424       const G4RotationMatrix* mRot =              424       const G4RotationMatrix* mRot =
425         fBlockedPhysicalVolume->GetRotation();    425         fBlockedPhysicalVolume->GetRotation();
426       if( mRot != nullptr )                       426       if( mRot != nullptr )
427       {                                           427       {
428         fGrandMotherExitNormal *= (*mRot).inve    428         fGrandMotherExitNormal *= (*mRot).inverse();
429         fChangedGrandMotherRefFrame = true;       429         fChangedGrandMotherRefFrame = true;
430       }                                           430       }
431     }                                             431     }
432   }  // END while (notKnownContained)             432   }  // END while (notKnownContained)
433   //                                              433   //
434   // Search downwards until deepest containing    434   // Search downwards until deepest containing volume found,
435   // blocking fBlockedPhysicalVolume/BlockedRe    435   // blocking fBlockedPhysicalVolume/BlockedReplicaNum
436   //                                              436   //
437   // 3 Cases:                                     437   // 3 Cases:
438   //                                              438   //
439   // o Parameterised daughters                    439   // o Parameterised daughters
440   //   =>Must be one G4PVParameterised daughte    440   //   =>Must be one G4PVParameterised daughter & voxels
441   // o Positioned daughters & voxels              441   // o Positioned daughters & voxels
442   // o Positioned daughters & no voxels           442   // o Positioned daughters & no voxels
443                                                   443 
444   noResult = true;  // noResult should be rena    444   noResult = true;  // noResult should be renamed to
445                     // something like enteredL    445                     // something like enteredLevel, as that is its meaning.
446   do                                              446   do
447   {                                               447   {
448     // Determine `type' of current mother volu    448     // Determine `type' of current mother volume
449     //                                            449     //
450     targetPhysical = fHistory.GetTopVolume();     450     targetPhysical = fHistory.GetTopVolume();
451     if (targetPhysical == nullptr) { break; }     451     if (targetPhysical == nullptr) { break; }
452     targetLogical = targetPhysical->GetLogical    452     targetLogical = targetPhysical->GetLogicalVolume();
453     switch( CharacteriseDaughters(targetLogica    453     switch( CharacteriseDaughters(targetLogical) )
454     {                                             454     {
455       case kNormal:                               455       case kNormal:
456         if ( targetLogical->GetVoxelHeader() !    456         if ( targetLogical->GetVoxelHeader() != nullptr )  // use optimised navigation
457         {                                         457         {
458           noResult = GetVoxelNavigator().Level    458           noResult = GetVoxelNavigator().LevelLocate(fHistory,
459                                            fBl    459                                            fBlockedPhysicalVolume,
460                                            fBl    460                                            fBlockedReplicaNo,
461                                            glo    461                                            globalPoint,
462                                            pGl    462                                            pGlobalDirection,
463                                            con    463                                            considerDirection,
464                                            loc    464                                            localPoint);
465         }                                         465         }
466         else                       // do not u    466         else                       // do not use optimised navigation
467         {                                         467         {
468           noResult = fnormalNav.LevelLocate(fH    468           noResult = fnormalNav.LevelLocate(fHistory,
469                                             fB    469                                             fBlockedPhysicalVolume,
470                                             fB    470                                             fBlockedReplicaNo,
471                                             gl    471                                             globalPoint,
472                                             pG    472                                             pGlobalDirection,
473                                             co    473                                             considerDirection,
474                                             lo    474                                             localPoint);
475         }                                         475         }
476         break;                                    476         break;
477       case kReplica:                              477       case kReplica:
478         noResult = freplicaNav.LevelLocate(fHi    478         noResult = freplicaNav.LevelLocate(fHistory,
479                                            fBl    479                                            fBlockedPhysicalVolume,
480                                            fBl    480                                            fBlockedReplicaNo,
481                                            glo    481                                            globalPoint,
482                                            pGl    482                                            pGlobalDirection,
483                                            con    483                                            considerDirection,
484                                            loc    484                                            localPoint);
485         break;                                    485         break;
486       case kParameterised:                        486       case kParameterised:
487         if( GetDaughtersRegularStructureId(tar    487         if( GetDaughtersRegularStructureId(targetLogical) != 1 )
488         {                                         488         {
489           noResult = fparamNav.LevelLocate(fHi    489           noResult = fparamNav.LevelLocate(fHistory,
490                                            fBl    490                                            fBlockedPhysicalVolume,
491                                            fBl    491                                            fBlockedReplicaNo,
492                                            glo    492                                            globalPoint,
493                                            pGl    493                                            pGlobalDirection,
494                                            con    494                                            considerDirection,
495                                            loc    495                                            localPoint);
496         }                                         496         }
497         else  // Regular structure                497         else  // Regular structure
498         {                                         498         {
499           noResult = fregularNav.LevelLocate(f    499           noResult = fregularNav.LevelLocate(fHistory,
500                                              f    500                                              fBlockedPhysicalVolume,
501                                              f    501                                              fBlockedReplicaNo,
502                                              g    502                                              globalPoint,
503                                              p    503                                              pGlobalDirection,
504                                              c    504                                              considerDirection,
505                                              l    505                                              localPoint);
506         }                                         506         }
507         break;                                    507         break;
508       case kExternal:                             508       case kExternal:
509         noResult = fpExternalNav->LevelLocate(    509         noResult = fpExternalNav->LevelLocate(fHistory,
510                                                   510                                               fBlockedPhysicalVolume,
511                                                   511                                               fBlockedReplicaNo,
512                                                   512                                               globalPoint,
513                                                   513                                               pGlobalDirection,
514                                                   514                                               considerDirection,
515                                                   515                                               localPoint);
516         break;                                    516         break;
517     }                                             517     }
518                                                   518 
519     // LevelLocate returns true if it finds a     519     // LevelLocate returns true if it finds a daughter volume 
520     // in which globalPoint is inside (or on t    520     // in which globalPoint is inside (or on the surface).
521                                                   521 
522     if ( noResult )                               522     if ( noResult )
523     {                                             523     {
524       // Entering a daughter after ascending      524       // Entering a daughter after ascending
525       //                                          525       //
526       // The blocked volume is no longer valid    526       // The blocked volume is no longer valid - it was for another level
527       //                                          527       //
528       fBlockedPhysicalVolume = nullptr;           528       fBlockedPhysicalVolume = nullptr;
529       fBlockedReplicaNo = -1;                     529       fBlockedReplicaNo = -1;
530                                                   530 
531       // fEntering should be false -- else blo    531       // fEntering should be false -- else blockedVolume is assumed good.
532       // fEnteredDaughter is used for ExitNorm    532       // fEnteredDaughter is used for ExitNormal
533       //                                          533       //
534       fEntering = false;                          534       fEntering = false;
535       fEnteredDaughter = true;                    535       fEnteredDaughter = true;
536                                                   536 
537       if( fExitedMother )                         537       if( fExitedMother )
538       {                                           538       {
539         G4VPhysicalVolume* enteredPhysical = f    539         G4VPhysicalVolume* enteredPhysical = fHistory.GetTopVolume();
540         const G4RotationMatrix* mRot = entered    540         const G4RotationMatrix* mRot = enteredPhysical->GetRotation();
541         if( mRot != nullptr )                     541         if( mRot != nullptr )
542         {                                         542         { 
543           // Go deeper, i.e. move 'down' in th    543           // Go deeper, i.e. move 'down' in the hierarchy
544           // Apply direct rotation, not invers    544           // Apply direct rotation, not inverse
545           //                                      545           //
546           fGrandMotherExitNormal *= (*mRot);      546           fGrandMotherExitNormal *= (*mRot);
547           fChangedGrandMotherRefFrame= true;      547           fChangedGrandMotherRefFrame= true;
548         }                                         548         }
549       }                                           549       }
550                                                   550 
551 #ifdef G4DEBUG_NAVIGATION                         551 #ifdef G4DEBUG_NAVIGATION
552       if( fVerbose > 2 )                          552       if( fVerbose > 2 )
553       {                                           553       { 
554          G4VPhysicalVolume* enteredPhysical =     554          G4VPhysicalVolume* enteredPhysical = fHistory.GetTopVolume();
555          G4cout << "*** G4Navigator::LocateGlo    555          G4cout << "*** G4Navigator::LocateGlobalPointAndSetup() ***" << G4endl;
556          G4cout << "    Entering volume: " <<     556          G4cout << "    Entering volume: " << enteredPhysical->GetName()
557                 << G4endl;                        557                 << G4endl;
558       }                                           558       }
559 #endif                                            559 #endif
560     }                                             560     }
561   } while (noResult);  // Loop checking, 07.10    561   } while (noResult);  // Loop checking, 07.10.2016, J.Apostolakis
562                                                   562 
563   fLastLocatedPointLocal = localPoint;            563   fLastLocatedPointLocal = localPoint;
564                                                   564 
565 #ifdef G4VERBOSE                                  565 #ifdef G4VERBOSE
566   if( fVerbose >= 4 )                             566   if( fVerbose >= 4 )
567   {                                               567   {
568     G4long oldcoutPrec = G4cout.precision(8);     568     G4long oldcoutPrec = G4cout.precision(8);
569     G4String curPhysVol_Name("None");             569     G4String curPhysVol_Name("None");
570     if (targetPhysical != nullptr)  { curPhysV    570     if (targetPhysical != nullptr)  { curPhysVol_Name = targetPhysical->GetName(); }
571     G4cout << "    Return value = new volume =    571     G4cout << "    Return value = new volume = " << curPhysVol_Name << G4endl;
572     G4cout << "    ----- Upon exiting:" << G4e    572     G4cout << "    ----- Upon exiting:" << G4endl;
573     PrintState();                                 573     PrintState();
574     if( fVerbose >= 5 )                           574     if( fVerbose >= 5 )
575     {                                             575     {
576       G4cout << "Upon exiting LocateGlobalPoin    576       G4cout << "Upon exiting LocateGlobalPointAndSetup():" << G4endl;
577       G4cout << "    History = " << G4endl <<     577       G4cout << "    History = " << G4endl << fHistory << G4endl << G4endl;
578     }                                             578     }
579     G4cout.precision(oldcoutPrec);                579     G4cout.precision(oldcoutPrec);
580   }                                               580   }
581 #endif                                            581 #endif
582                                                   582 
583   fLocatedOutsideWorld = false;                   583   fLocatedOutsideWorld = false;
584                                                   584 
585   return targetPhysical;                          585   return targetPhysical;
586 }                                                 586 }
587                                                   587 
588 // *******************************************    588 // ********************************************************************
589 // LocateGlobalPointWithinVolume                  589 // LocateGlobalPointWithinVolume
590 //                                                590 //
591 // -> the state information of this Navigator     591 // -> the state information of this Navigator and its subNavigators
592 //    is updated in order to start the next st    592 //    is updated in order to start the next step at pGlobalpoint
593 // -> no check is performed whether pGlobalpoi    593 // -> no check is performed whether pGlobalpoint is inside the 
594 //    original volume (this must be the case).    594 //    original volume (this must be the case).
595 //                                                595 //
596 // Note: a direction could be added to the arg    596 // Note: a direction could be added to the arguments, to aid in future
597 //       optional checking (via the old code b    597 //       optional checking (via the old code below, flagged by OLD_LOCATE). 
598 //       [ This would be done only in verbose     598 //       [ This would be done only in verbose mode ]
599 // *******************************************    599 // ********************************************************************
600 //                                                600 //
601 void                                              601 void
602 G4Navigator::LocateGlobalPointWithinVolume(con    602 G4Navigator::LocateGlobalPointWithinVolume(const G4ThreeVector& pGlobalpoint)
603 {                                                 603 {
604 #ifdef G4DEBUG_NAVIGATION                         604 #ifdef G4DEBUG_NAVIGATION
605    assert( !fWasLimitedByGeometry );              605    assert( !fWasLimitedByGeometry );   
606    // Check: Either step was not limited by a     606    // Check: Either step was not limited by a boundary or 
607    //          else the full step is no longer    607    //          else the full step is no longer being taken
608 #endif                                            608 #endif
609                                                   609   
610    fLastLocatedPointLocal = ComputeLocalPoint(    610    fLastLocatedPointLocal = ComputeLocalPoint(pGlobalpoint);
611    fLastTriedStepComputation = false;             611    fLastTriedStepComputation = false;
612    fChangedGrandMotherRefFrame = false;  //  F    612    fChangedGrandMotherRefFrame = false;  //  Frame for Exit Normal
613                                                   613 
614    // For the case of Voxel (or Parameterised)    614    // For the case of Voxel (or Parameterised) volume the respective 
615    // Navigator must be messaged to update its    615    // Navigator must be messaged to update its voxel information etc
616                                                   616 
617    // Update the state of the Sub Navigators      617    // Update the state of the Sub Navigators 
618    // - in particular any voxel information th    618    // - in particular any voxel information they store/cache
619    //                                             619    //
620    G4VPhysicalVolume*  motherPhysical = fHisto    620    G4VPhysicalVolume*  motherPhysical = fHistory.GetTopVolume();
621    G4LogicalVolume*    motherLogical  = mother    621    G4LogicalVolume*    motherLogical  = motherPhysical->GetLogicalVolume();
622                                                   622 
623    switch( CharacteriseDaughters(motherLogical    623    switch( CharacteriseDaughters(motherLogical) )
624    {                                              624    {
625        case kNormal:                              625        case kNormal:
626          GetVoxelNavigator().RelocateWithinVol    626          GetVoxelNavigator().RelocateWithinVolume( motherPhysical, fLastLocatedPointLocal );
627          break;                                   627          break;
628        case kParameterised:                       628        case kParameterised:
629          fparamNav.RelocateWithinVolume( mothe    629          fparamNav.RelocateWithinVolume( motherPhysical, fLastLocatedPointLocal );
630          break;                                   630          break;
631        case kReplica:                             631        case kReplica:
632          // Nothing to do                         632          // Nothing to do
633          break;                                   633          break;
634        case kExternal:                            634        case kExternal:
635          fpExternalNav->RelocateWithinVolume(     635          fpExternalNav->RelocateWithinVolume( motherPhysical,
636                                                   636                                               fLastLocatedPointLocal );
637          break;                                   637          break;
638    }                                              638    }
639                                                   639 
640    // Reset the state variables                   640    // Reset the state variables 
641    //   - which would have been affected          641    //   - which would have been affected
642    //     by the 'equivalent' call to LocateGl    642    //     by the 'equivalent' call to LocateGlobalPointAndSetup
643    //   - who's values have been invalidated b    643    //   - who's values have been invalidated by the 'move'.
644    //                                             644    //
645    fBlockedPhysicalVolume = nullptr;              645    fBlockedPhysicalVolume = nullptr; 
646    fBlockedReplicaNo = -1;                        646    fBlockedReplicaNo = -1;
647    fEntering = false;                             647    fEntering = false;
648    fEnteredDaughter = false;  // Boundary not     648    fEnteredDaughter = false;  // Boundary not encountered, did not enter
649    fExiting = false;                              649    fExiting = false;
650    fExitedMother = false;     // Boundary not     650    fExitedMother = false;     // Boundary not encountered, did not exit
651 }                                                 651 }
652                                                   652 
653 // *******************************************    653 // ********************************************************************
654 // SetSavedState                                  654 // SetSavedState
655 //                                                655 //
656 // Save the state, in case this is a parasitic    656 // Save the state, in case this is a parasitic call
657 // Save fValidExitNormal, fExitNormal, fExitin    657 // Save fValidExitNormal, fExitNormal, fExiting, fEntering, 
658 //      fBlockedPhysicalVolume, fBlockedReplic    658 //      fBlockedPhysicalVolume, fBlockedReplicaNo, fLastStepWasZero; 
659 // *******************************************    659 // ********************************************************************
660 //                                                660 //
661 void G4Navigator::SetSavedState()                 661 void G4Navigator::SetSavedState()
662 {                                                 662 {
663   // Note: the state of dependent objects is n    663   // Note: the state of dependent objects is not currently saved.
664   //   ( This means that the full state is cha    664   //   ( This means that the full state is changed by calls between
665   //     SetSavedState() and RestoreSavedState    665   //     SetSavedState() and RestoreSavedState(); 
666                                                   666   
667   fSaveState.sExitNormal = fExitNormal;           667   fSaveState.sExitNormal = fExitNormal;
668   fSaveState.sValidExitNormal = fValidExitNorm    668   fSaveState.sValidExitNormal = fValidExitNormal;
669   fSaveState.sExiting = fExiting;                 669   fSaveState.sExiting = fExiting;
670   fSaveState.sEntering = fEntering;               670   fSaveState.sEntering = fEntering;
671                                                   671 
672   fSaveState.spBlockedPhysicalVolume = fBlocke    672   fSaveState.spBlockedPhysicalVolume = fBlockedPhysicalVolume;
673   fSaveState.sBlockedReplicaNo = fBlockedRepli    673   fSaveState.sBlockedReplicaNo = fBlockedReplicaNo;
674                                                   674 
675   fSaveState.sLastStepWasZero = static_cast<G4    675   fSaveState.sLastStepWasZero = static_cast<G4int>(fLastStepWasZero);
676                                                   676   
677   fSaveState.sLocatedOutsideWorld = fLocatedOu    677   fSaveState.sLocatedOutsideWorld = fLocatedOutsideWorld;
678   fSaveState.sLastLocatedPointLocal = fLastLoc    678   fSaveState.sLastLocatedPointLocal = fLastLocatedPointLocal;
679   fSaveState.sEnteredDaughter = fEnteredDaught    679   fSaveState.sEnteredDaughter = fEnteredDaughter;
680   fSaveState.sExitedMother = fExitedMother;       680   fSaveState.sExitedMother = fExitedMother;
681   fSaveState.sWasLimitedByGeometry = fWasLimit    681   fSaveState.sWasLimitedByGeometry = fWasLimitedByGeometry;
682                                                   682 
683   // Even the safety sphere - if you want to c    683   // Even the safety sphere - if you want to change it do it explicitly!
684   //                                              684   //
685   fSaveState.sPreviousSftOrigin = fPreviousSft    685   fSaveState.sPreviousSftOrigin = fPreviousSftOrigin;
686   fSaveState.sPreviousSafety = fPreviousSafety    686   fSaveState.sPreviousSafety = fPreviousSafety;
687 }                                                 687 }
688                                                   688 
689 // *******************************************    689 // ********************************************************************
690 // RestoreSavedState                              690 // RestoreSavedState
691 //                                                691 //
692 // Restore the state (in Compute Step), in cas    692 // Restore the state (in Compute Step), in case this is a parasitic call
693 // *******************************************    693 // ********************************************************************
694 //                                                694 //
695 void G4Navigator::RestoreSavedState()             695 void G4Navigator::RestoreSavedState()
696 {                                                 696 {
697   fExitNormal = fSaveState.sExitNormal;           697   fExitNormal = fSaveState.sExitNormal;
698   fValidExitNormal = fSaveState.sValidExitNorm    698   fValidExitNormal = fSaveState.sValidExitNormal;
699   fExiting = fSaveState.sExiting;                 699   fExiting = fSaveState.sExiting;
700   fEntering = fSaveState.sEntering;               700   fEntering = fSaveState.sEntering;
701                                                   701 
702   fBlockedPhysicalVolume = fSaveState.spBlocke    702   fBlockedPhysicalVolume = fSaveState.spBlockedPhysicalVolume;
703   fBlockedReplicaNo = fSaveState.sBlockedRepli    703   fBlockedReplicaNo = fSaveState.sBlockedReplicaNo; 
704                                                   704 
705   fLastStepWasZero = (fSaveState.sLastStepWasZ    705   fLastStepWasZero = (fSaveState.sLastStepWasZero != 0);
706                                                   706   
707   fLocatedOutsideWorld = fSaveState.sLocatedOu    707   fLocatedOutsideWorld = fSaveState.sLocatedOutsideWorld;
708   fLastLocatedPointLocal = fSaveState.sLastLoc    708   fLastLocatedPointLocal = fSaveState.sLastLocatedPointLocal;
709   fEnteredDaughter = fSaveState.sEnteredDaught    709   fEnteredDaughter = fSaveState.sEnteredDaughter;
710   fExitedMother = fSaveState.sExitedMother;       710   fExitedMother = fSaveState.sExitedMother;
711   fWasLimitedByGeometry = fSaveState.sWasLimit    711   fWasLimitedByGeometry = fSaveState.sWasLimitedByGeometry;
712                                                   712   
713   // The 'expected' behaviour is to restore th    713   // The 'expected' behaviour is to restore these too (fix 2014.05.26)
714   fPreviousSftOrigin = fSaveState.sPreviousSft    714   fPreviousSftOrigin = fSaveState.sPreviousSftOrigin;
715   fPreviousSafety = fSaveState.sPreviousSafety    715   fPreviousSafety = fSaveState.sPreviousSafety;
716 }                                                 716 }
717                                                   717 
718 // *******************************************    718 // ********************************************************************
719 // ComputeStep                                    719 // ComputeStep
720 //                                                720 //
721 // Computes the next geometric Step: intersect    721 // Computes the next geometric Step: intersections with current
722 // mother and `daughter' volumes.                 722 // mother and `daughter' volumes.
723 //                                                723 //
724 // NOTE:                                          724 // NOTE:
725 //                                                725 //
726 // Flags on entry:                                726 // Flags on entry:
727 // --------------                                 727 // --------------
728 // fValidExitNormal  - Normal of exited volume    728 // fValidExitNormal  - Normal of exited volume is valid (convex, not a 
729 //                     coincident boundary)       729 //                     coincident boundary)
730 // fExitNormal       - Surface normal of exite    730 // fExitNormal       - Surface normal of exited volume
731 // fExiting          - True if have exited sol    731 // fExiting          - True if have exited solid
732 //                                                732 //
733 // fBlockedPhysicalVolume - Ptr to exited volu    733 // fBlockedPhysicalVolume - Ptr to exited volume (or 0)
734 // fBlockedReplicaNo - Replication no of exite    734 // fBlockedReplicaNo - Replication no of exited volume
735 // fLastStepWasZero  - True if last Step size     735 // fLastStepWasZero  - True if last Step size was almost zero.
736 //                                                736 //
737 // Flags on exit:                                 737 // Flags on exit:
738 // -------------                                  738 // -------------
739 // fValidExitNormal  - True if surface normal     739 // fValidExitNormal  - True if surface normal of exited volume is valid
740 // fExitNormal       - Surface normal of exite    740 // fExitNormal       - Surface normal of exited volume rotated to mothers
741 //                    reference system            741 //                    reference system
742 // fExiting          - True if exiting mother     742 // fExiting          - True if exiting mother
743 // fEntering         - True if entering `daugh    743 // fEntering         - True if entering `daughter' volume (or replica)
744 // fBlockedPhysicalVolume - Ptr to candidate (    744 // fBlockedPhysicalVolume - Ptr to candidate (entered) volume
745 // fBlockedReplicaNo - Replication no of candi    745 // fBlockedReplicaNo - Replication no of candidate (entered) volume
746 // fLastStepWasZero  - True if this Step size     746 // fLastStepWasZero  - True if this Step size was almost zero.
747 // *******************************************    747 // ********************************************************************
748 //                                                748 //
749 G4double G4Navigator::ComputeStep( const G4Thr    749 G4double G4Navigator::ComputeStep( const G4ThreeVector& pGlobalpoint,
750                                    const G4Thr    750                                    const G4ThreeVector& pDirection,
751                                    const G4dou    751                                    const G4double pCurrentProposedStepLength,
752                                          G4dou    752                                          G4double& pNewSafety)
753 {                                                 753 {
754 #ifdef G4DEBUG_NAVIGATION                         754 #ifdef G4DEBUG_NAVIGATION
755   static G4ThreadLocal G4int sNavCScalls = 0;     755   static G4ThreadLocal G4int sNavCScalls = 0;
756   ++sNavCScalls;                                  756   ++sNavCScalls;
757 #endif                                            757 #endif
758                                                   758 
759   G4ThreeVector localDirection = ComputeLocalA    759   G4ThreeVector localDirection = ComputeLocalAxis(pDirection);
760   G4double Step = kInfinity;                      760   G4double Step = kInfinity;
761   G4VPhysicalVolume  *motherPhysical = fHistor    761   G4VPhysicalVolume  *motherPhysical = fHistory.GetTopVolume();
762   G4LogicalVolume *motherLogical = motherPhysi    762   G4LogicalVolume *motherLogical = motherPhysical->GetLogicalVolume();
763                                                   763 
764   // All state relating to exiting normals mus    764   // All state relating to exiting normals must be reset
765   //                                              765   //
766   fExitNormalGlobalFrame = G4ThreeVector( 0.,     766   fExitNormalGlobalFrame = G4ThreeVector( 0., 0., 0.);
767     // Reset value - to erase its memory          767     // Reset value - to erase its memory
768   fChangedGrandMotherRefFrame = false;            768   fChangedGrandMotherRefFrame = false;
769     // Reset - used for local exit normal         769     // Reset - used for local exit normal
770   fGrandMotherExitNormal = G4ThreeVector( 0.,     770   fGrandMotherExitNormal = G4ThreeVector( 0., 0., 0.); 
771   fCalculatedExitNormal = false;                  771   fCalculatedExitNormal = false;
772     // Reset for new step                         772     // Reset for new step
773                                                   773 
774 #ifdef G4VERBOSE                                  774 #ifdef G4VERBOSE
775   if( fVerbose > 0 )                              775   if( fVerbose > 0 )
776   {                                               776   {
777     G4cout << "*** G4Navigator::ComputeStep: *    777     G4cout << "*** G4Navigator::ComputeStep: ***" << G4endl; 
778     G4cout << "    Volume = " << motherPhysica    778     G4cout << "    Volume = " << motherPhysical->GetName() 
779            << " - Proposed step length = " <<     779            << " - Proposed step length = " << pCurrentProposedStepLength
780            << G4endl;                             780            << G4endl; 
781 #ifdef G4DEBUG_NAVIGATION                         781 #ifdef G4DEBUG_NAVIGATION
782     if( fVerbose >= 2 )                           782     if( fVerbose >= 2 )
783     {                                             783     {
784       G4cout << "  Called with the arguments:     784       G4cout << "  Called with the arguments: " << G4endl
785              << "  Globalpoint = " << std::set    785              << "  Globalpoint = " << std::setw(25) << pGlobalpoint << G4endl
786              << "  Direction   = " << std::set    786              << "  Direction   = " << std::setw(25) << pDirection << G4endl;
787       if( fVerbose >= 4 )                         787       if( fVerbose >= 4 )
788       {                                           788       {
789         G4cout << "  ---- Upon entering : Stat    789         G4cout << "  ---- Upon entering : State" << G4endl;
790         PrintState();                             790         PrintState();
791       }                                           791       }
792     }                                             792     }
793 #endif                                            793 #endif
794   }                                               794   }
795 #endif                                            795 #endif
796                                                   796 
797   G4ThreeVector newLocalPoint = ComputeLocalPo    797   G4ThreeVector newLocalPoint = ComputeLocalPoint(pGlobalpoint);
798                                                   798 
799   if( newLocalPoint != fLastLocatedPointLocal     799   if( newLocalPoint != fLastLocatedPointLocal )
800   {                                               800   {
801     // Check whether the relocation is within     801     // Check whether the relocation is within safety
802     //                                            802     //
803     G4ThreeVector oldLocalPoint = fLastLocated    803     G4ThreeVector oldLocalPoint = fLastLocatedPointLocal;
804     G4double moveLenSq = (newLocalPoint-oldLoc    804     G4double moveLenSq = (newLocalPoint-oldLocalPoint).mag2();
805                                                   805 
806     if ( moveLenSq >= fSqTol )                    806     if ( moveLenSq >= fSqTol )
807     {                                             807     {
808 #ifdef G4VERBOSE                                  808 #ifdef G4VERBOSE
809       ComputeStepLog(pGlobalpoint, moveLenSq);    809       ComputeStepLog(pGlobalpoint, moveLenSq);
810 #endif                                            810 #endif
811       // Relocate the point within the same vo    811       // Relocate the point within the same volume
812       //                                          812       //
813       LocateGlobalPointWithinVolume( pGlobalpo    813       LocateGlobalPointWithinVolume( pGlobalpoint );
814     }                                             814     }
815   }                                               815   }
816   if ( fHistory.GetTopVolumeType()!=kReplica )    816   if ( fHistory.GetTopVolumeType()!=kReplica )
817   {                                               817   {
818     switch( CharacteriseDaughters(motherLogica    818     switch( CharacteriseDaughters(motherLogical) )
819     {                                             819     {
820       case kNormal:                               820       case kNormal:
821         if ( motherLogical->GetVoxelHeader() !    821         if ( motherLogical->GetVoxelHeader() != nullptr )
822         {                                         822         {
823           Step = GetVoxelNavigator().ComputeSt    823           Step = GetVoxelNavigator().ComputeStep(fLastLocatedPointLocal,
824                                        localDi    824                                        localDirection,
825                                        pCurren    825                                        pCurrentProposedStepLength,
826                                        pNewSaf    826                                        pNewSafety,
827                                        fHistor    827                                        fHistory,
828                                        fValidE    828                                        fValidExitNormal,
829                                        fExitNo    829                                        fExitNormal,
830                                        fExitin    830                                        fExiting,
831                                        fEnteri    831                                        fEntering,
832                                        &fBlock    832                                        &fBlockedPhysicalVolume,
833                                        fBlocke    833                                        fBlockedReplicaNo);
834                                                   834       
835         }                                         835         }
836         else                                      836         else
837         {                                         837         {
838           if( motherPhysical->GetRegularStruct    838           if( motherPhysical->GetRegularStructureId() == 0 )
839           {                                       839           {
840             Step = fnormalNav.ComputeStep(fLas    840             Step = fnormalNav.ComputeStep(fLastLocatedPointLocal,
841                                           loca    841                                           localDirection,
842                                           pCur    842                                           pCurrentProposedStepLength,
843                                           pNew    843                                           pNewSafety,
844                                           fHis    844                                           fHistory,
845                                           fVal    845                                           fValidExitNormal,
846                                           fExi    846                                           fExitNormal,
847                                           fExi    847                                           fExiting,
848                                           fEnt    848                                           fEntering,
849                                           &fBl    849                                           &fBlockedPhysicalVolume,
850                                           fBlo    850                                           fBlockedReplicaNo);
851           }                                       851           }
852           else  // Regular (non-voxelised) str    852           else  // Regular (non-voxelised) structure
853           {                                       853           {
854             LocateGlobalPointAndSetup( pGlobal    854             LocateGlobalPointAndSetup( pGlobalpoint, &pDirection, true, true );
855             //                                    855             //
856             // if physical process limits the     856             // if physical process limits the step, the voxel will not be the
857             // one given by ComputeStepSkippin    857             // one given by ComputeStepSkippingEqualMaterials() and the local
858             // point will be wrongly calculate    858             // point will be wrongly calculated.
859                                                   859 
860             // There is a problem: when msc li    860             // There is a problem: when msc limits the step and the point is
861             // assigned wrongly to phantom in     861             // assigned wrongly to phantom in previous step (while it is out
862             // of the container volume). Then     862             // of the container volume). Then LocateGlobalPointAndSetup() has
863             // reset the history topvolume to     863             // reset the history topvolume to world.
864             //                                    864             //
865             if(fHistory.GetTopVolume()->GetReg    865             if(fHistory.GetTopVolume()->GetRegularStructureId() == 0 )
866             {                                     866             { 
867               G4Exception("G4Navigator::Comput    867               G4Exception("G4Navigator::ComputeStep()",
868                           "GeomNav1001", JustW    868                           "GeomNav1001", JustWarning,
869                 "Point is relocated in voxels,    869                 "Point is relocated in voxels, while it should be outside!");
870               Step = fnormalNav.ComputeStep(fL    870               Step = fnormalNav.ComputeStep(fLastLocatedPointLocal,
871                                             lo    871                                             localDirection,
872                                             pC    872                                             pCurrentProposedStepLength,
873                                             pN    873                                             pNewSafety,
874                                             fH    874                                             fHistory,
875                                             fV    875                                             fValidExitNormal,
876                                             fE    876                                             fExitNormal,
877                                             fE    877                                             fExiting,
878                                             fE    878                                             fEntering,
879                                             &f    879                                             &fBlockedPhysicalVolume,
880                                             fB    880                                             fBlockedReplicaNo);
881             }                                     881             }
882             else                                  882             else
883             {                                     883             {
884               Step = fregularNav.                 884               Step = fregularNav.
885                    ComputeStepSkippingEqualMat    885                    ComputeStepSkippingEqualMaterials(fLastLocatedPointLocal,
886                                                   886                                                      localDirection,
887                                                   887                                                      pCurrentProposedStepLength,
888                                                   888                                                      pNewSafety,
889                                                   889                                                      fHistory,
890                                                   890                                                      fValidExitNormal,
891                                                   891                                                      fExitNormal,
892                                                   892                                                      fExiting,
893                                                   893                                                      fEntering,
894                                                   894                                                      &fBlockedPhysicalVolume,
895                                                   895                                                      fBlockedReplicaNo,
896                                                   896                                                      motherPhysical);
897             }                                     897             }
898           }                                       898           }
899         }                                         899         }
900         break;                                    900         break;
901       case kParameterised:                        901       case kParameterised:
902         if( GetDaughtersRegularStructureId(mot    902         if( GetDaughtersRegularStructureId(motherLogical) != 1 )
903         {                                         903         {
904           Step = fparamNav.ComputeStep(fLastLo    904           Step = fparamNav.ComputeStep(fLastLocatedPointLocal,
905                                        localDi    905                                        localDirection,
906                                        pCurren    906                                        pCurrentProposedStepLength,
907                                        pNewSaf    907                                        pNewSafety,
908                                        fHistor    908                                        fHistory,
909                                        fValidE    909                                        fValidExitNormal,
910                                        fExitNo    910                                        fExitNormal,
911                                        fExitin    911                                        fExiting,
912                                        fEnteri    912                                        fEntering,
913                                        &fBlock    913                                        &fBlockedPhysicalVolume,
914                                        fBlocke    914                                        fBlockedReplicaNo);
915         }                                         915         }
916         else  // Regular structure                916         else  // Regular structure
917         {                                         917         {
918           Step = fregularNav.ComputeStep(fLast    918           Step = fregularNav.ComputeStep(fLastLocatedPointLocal,
919                                          local    919                                          localDirection,
920                                          pCurr    920                                          pCurrentProposedStepLength,
921                                          pNewS    921                                          pNewSafety,
922                                          fHist    922                                          fHistory,
923                                          fVali    923                                          fValidExitNormal,
924                                          fExit    924                                          fExitNormal,
925                                          fExit    925                                          fExiting,
926                                          fEnte    926                                          fEntering,
927                                          &fBlo    927                                          &fBlockedPhysicalVolume,
928                                          fBloc    928                                          fBlockedReplicaNo);
929         }                                         929         }
930         break;                                    930         break;
931       case kReplica:                              931       case kReplica:
932         G4Exception("G4Navigator::ComputeStep(    932         G4Exception("G4Navigator::ComputeStep()", "GeomNav0001",
933                     FatalException, "Not appli    933                     FatalException, "Not applicable for replicated volumes.");
934         break;                                    934         break;
935       case kExternal:                             935       case kExternal:
936         Step = fpExternalNav->ComputeStep(fLas    936         Step = fpExternalNav->ComputeStep(fLastLocatedPointLocal,
937                                           loca    937                                           localDirection,
938                                           pCur    938                                           pCurrentProposedStepLength,
939                                           pNew    939                                           pNewSafety,
940                                           fHis    940                                           fHistory,
941                                           fVal    941                                           fValidExitNormal,
942                                           fExi    942                                           fExitNormal,
943                                           fExi    943                                           fExiting,
944                                           fEnt    944                                           fEntering,
945                                           &fBl    945                                           &fBlockedPhysicalVolume,
946                                           fBlo    946                                           fBlockedReplicaNo);
947         break;                                    947         break;
948     }                                             948     }
949   }                                               949   }
950   else                                            950   else
951   {                                               951   {
952     // In the case of a replica, it must handl    952     // In the case of a replica, it must handle the exiting
953     // edge/corner problem by itself              953     // edge/corner problem by itself
954     //                                            954     //
955     fExiting = fExitedMother;                     955     fExiting = fExitedMother;
956     Step = freplicaNav.ComputeStep(pGlobalpoin    956     Step = freplicaNav.ComputeStep(pGlobalpoint,
957                                    pDirection,    957                                    pDirection,
958                                    fLastLocate    958                                    fLastLocatedPointLocal,
959                                    localDirect    959                                    localDirection,
960                                    pCurrentPro    960                                    pCurrentProposedStepLength,
961                                    pNewSafety,    961                                    pNewSafety,
962                                    fHistory,      962                                    fHistory,
963                                    fValidExitN    963                                    fValidExitNormal,
964                                    fCalculated    964                                    fCalculatedExitNormal,
965                                    fExitNormal    965                                    fExitNormal,
966                                    fExiting,      966                                    fExiting,
967                                    fEntering,     967                                    fEntering,
968                                    &fBlockedPh    968                                    &fBlockedPhysicalVolume,
969                                    fBlockedRep    969                                    fBlockedReplicaNo);
970   }                                               970   }
971                                                   971 
972   // Remember last safety origin & value.         972   // Remember last safety origin & value.
973   //                                              973   //
974   fPreviousSftOrigin = pGlobalpoint;              974   fPreviousSftOrigin = pGlobalpoint;
975   fPreviousSafety = pNewSafety;                   975   fPreviousSafety = pNewSafety; 
976                                                   976 
977   // Count zero steps - one can occur due to c    977   // Count zero steps - one can occur due to changing momentum at a boundary
978   //                  - one, two (or a few) ca    978   //                  - one, two (or a few) can occur at common edges between
979   //                    volumes                   979   //                    volumes
980   //                  - more than two is likel    980   //                  - more than two is likely a problem in the geometry
981   //                    description or the Nav    981   //                    description or the Navigation 
982                                                   982 
983   // Rule of thumb: likely at an Edge if two c    983   // Rule of thumb: likely at an Edge if two consecutive steps are zero,
984   //                because at least two candi    984   //                because at least two candidate volumes must have been
985   //                checked                       985   //                checked
986   //                                              986   //
987   fLocatedOnEdge   = fLastStepWasZero && (Step    987   fLocatedOnEdge   = fLastStepWasZero && (Step==0.0);
988   fLastStepWasZero = (Step<fMinStep);             988   fLastStepWasZero = (Step<fMinStep);
989   if (fPushed)  { fPushed = fLastStepWasZero;     989   if (fPushed)  { fPushed = fLastStepWasZero; }
990                                                   990 
991   // Handle large number of consecutive zero s    991   // Handle large number of consecutive zero steps
992   //                                              992   //
993   if ( fLastStepWasZero )                         993   if ( fLastStepWasZero )
994   {                                               994   {
995     ++fNumberZeroSteps;                           995     ++fNumberZeroSteps;
996                                                   996     
997     G4bool act     = fNumberZeroSteps >= fActi    997     G4bool act     = fNumberZeroSteps >= fActionThreshold_NoZeroSteps;
998     G4bool actAndReport = false;                  998     G4bool actAndReport = false;
999     G4bool abandon = fNumberZeroSteps >= fAban    999     G4bool abandon = fNumberZeroSteps >= fAbandonThreshold_NoZeroSteps;
1000     G4bool inform  = false;                      1000     G4bool inform  = false;
1001 #ifdef G4VERBOSE                                 1001 #ifdef G4VERBOSE
1002     actAndReport = act && (!fPushed) && fWarn    1002     actAndReport = act && (!fPushed) && fWarnPush;
1003 #endif                                           1003 #endif
1004 #ifdef G4DEBUG_NAVIGATION                        1004 #ifdef G4DEBUG_NAVIGATION
1005     inform = fNumberZeroSteps > 1;               1005     inform = fNumberZeroSteps > 1;
1006 #endif                                           1006 #endif
1007                                                  1007     
1008     if ( act || inform )                         1008     if ( act || inform )
1009     {                                            1009     {
1010       if( act && !abandon )                      1010       if( act && !abandon )
1011       {                                          1011       {
1012         // Act to recover this stuck track. P    1012         // Act to recover this stuck track. Pushing it along original direction
1013         //                                       1013         //
1014         Step += 100*kCarTolerance;               1014         Step += 100*kCarTolerance;
1015         fPushed = true;                          1015         fPushed = true;
1016       }                                          1016       }
1017                                                  1017 
1018       if( actAndReport || abandon || inform )    1018       if( actAndReport || abandon || inform )
1019       {                                          1019       {
1020         std::ostringstream message;              1020         std::ostringstream message;
1021                                                  1021          
1022         message.precision(16);                   1022         message.precision(16);      
1023         message << "Stuck Track: potential ge    1023         message << "Stuck Track: potential geometry or navigation problem."
1024                 << G4endl;                       1024                 << G4endl;
1025         message << "  Track stuck, not moving    1025         message << "  Track stuck, not moving for " 
1026                 << fNumberZeroSteps << " step    1026                 << fNumberZeroSteps << " steps."  << G4endl
1027                 << "  Current  phys volume: '    1027                 << "  Current  phys volume: '" << motherPhysical->GetName()
1028                 << "'" << G4endl                 1028                 << "'" << G4endl
1029                 << "   - at position : " << p    1029                 << "   - at position : " << pGlobalpoint << G4endl
1030                 << "     in direction: " << p    1030                 << "     in direction: " << pDirection   << G4endl
1031                 << "    (local position: " <<    1031                 << "    (local position: " << newLocalPoint << ")" << G4endl
1032                 << "    (local direction: " <    1032                 << "    (local direction: " << localDirection << ")." << G4endl
1033                 << "  Previous phys volume: '    1033                 << "  Previous phys volume: '"
1034                 << ( fLastMotherPhys != nullp << 1034                 << ( fLastMotherPhys != nullptr ? fLastMotherPhys->GetName() : "" )
1035                 << "'" << G4endl << G4endl;      1035                 << "'" << G4endl << G4endl;
1036         if( actAndReport || abandon )            1036         if( actAndReport || abandon )
1037         {                                        1037         {
1038            message << "  Likely geometry over    1038            message << "  Likely geometry overlap - else navigation problem !"
1039                    << G4endl;                    1039                    << G4endl;
1040         }                                        1040         }
1041         if( abandon ) // i.e. fNumberZeroStep    1041         if( abandon ) // i.e. fNumberZeroSteps >= fAbandonThreshold_NoZeroSteps
1042         {                                        1042         {
1043           // Must kill this stuck track          1043           // Must kill this stuck track
1044 #ifdef G4VERBOSE                                 1044 #ifdef G4VERBOSE
1045           if ( fWarnPush ) { CheckOverlapsIte    1045           if ( fWarnPush ) { CheckOverlapsIterative(motherPhysical); }
1046 #endif                                           1046 #endif
1047           message << " Track *abandoned* due     1047           message << " Track *abandoned* due to excessive number of Zero steps."
1048                   << " Event aborted. " << G4    1048                   << " Event aborted. " << G4endl << G4endl;
1049           G4Exception("G4Navigator::ComputeSt    1049           G4Exception("G4Navigator::ComputeStep()", "GeomNav0003",
1050                       EventMustBeAborted, mes    1050                       EventMustBeAborted, message);
1051         }                                        1051         }
1052         else                                     1052         else
1053         {                                        1053         {
1054 #ifdef G4VERBOSE                                 1054 #ifdef G4VERBOSE
1055           if ( actAndReport )  // (!fPushed =    1055           if ( actAndReport )  // (!fPushed => !wasPushed) && (fWarnPush))
1056           {                                      1056           {
1057              message << "   *** Trying to get    1057              message << "   *** Trying to get *unstuck* using a push"
1058                      << " - expanding step to    1058                      << " - expanding step to " << Step << " (mm) ..."
1059                      << "       Potential ove    1059                      << "       Potential overlap in geometry !" << G4endl;
1060              G4Exception("G4Navigator::Comput    1060              G4Exception("G4Navigator::ComputeStep()", "GeomNav1002",
1061                          JustWarning, message    1061                          JustWarning, message); 
1062           }                                      1062           }
1063 #endif                                           1063 #endif
1064 #ifdef G4DEBUG_NAVIGATION                        1064 #ifdef G4DEBUG_NAVIGATION      
1065           else                                   1065           else
1066           {                                      1066           {
1067             if( fNumberZeroSteps > 1 )           1067             if( fNumberZeroSteps > 1 )
1068             {                                    1068             {
1069                message << ", nav-comp-step ca    1069                message << ", nav-comp-step calls # " << sNavCScalls
1070                        << ", Step= " << Step     1070                        << ", Step= " << Step << G4endl;
1071                G4cout << message.str();          1071                G4cout << message.str();
1072             }                                    1072             }
1073           }                                      1073           }
1074 #endif                                           1074 #endif
1075         } // end of else if ( abandon )          1075         } // end of else if ( abandon )
1076       } // end of if( actAndReport || abandon    1076       } // end of if( actAndReport || abandon || inform )
1077     } // end of if ( act || inform )             1077     } // end of if ( act || inform )
1078   }                                              1078   }
1079   else                                           1079   else
1080   {                                              1080   {
1081     if (!fPushed)  { fNumberZeroSteps = 0; }     1081     if (!fPushed)  { fNumberZeroSteps = 0; }
1082   }                                              1082   }
1083   fLastMotherPhys = motherPhysical;              1083   fLastMotherPhys = motherPhysical;
1084                                                  1084 
1085   fEnteredDaughter = fEntering;   // I expect    1085   fEnteredDaughter = fEntering;   // I expect to enter a volume in this Step
1086   fExitedMother = fExiting;                      1086   fExitedMother = fExiting;
1087                                                  1087 
1088   fStepEndPoint = pGlobalpoint                   1088   fStepEndPoint = pGlobalpoint
1089                 + std::min(Step,pCurrentPropo    1089                 + std::min(Step,pCurrentProposedStepLength) * pDirection;
1090   fLastStepEndPointLocal = fLastLocatedPointL    1090   fLastStepEndPointLocal = fLastLocatedPointLocal + Step * localDirection; 
1091                                                  1091 
1092   if( fExiting )                                 1092   if( fExiting )
1093   {                                              1093   {
1094 #ifdef G4DEBUG_NAVIGATION                        1094 #ifdef G4DEBUG_NAVIGATION
1095     if( fVerbose > 2 )                           1095     if( fVerbose > 2 )
1096     {                                            1096     { 
1097       G4cout << " At G4Nav CompStep End - if(    1097       G4cout << " At G4Nav CompStep End - if(exiting) - fExiting= " << fExiting
1098              << " fValidExitNormal = " << fVa    1098              << " fValidExitNormal = " << fValidExitNormal  << G4endl;
1099       G4cout << " fExitNormal= " << fExitNorm    1099       G4cout << " fExitNormal= " << fExitNormal << G4endl;
1100     }                                            1100     }
1101 #endif                                           1101 #endif
1102                                                  1102 
1103     if ( fValidExitNormal || fCalculatedExitN    1103     if ( fValidExitNormal || fCalculatedExitNormal )
1104     {                                            1104     {
1105       // Convention: fExitNormal is in the 'g    1105       // Convention: fExitNormal is in the 'grand-mother' coordinate system
1106       fGrandMotherExitNormal = fExitNormal;      1106       fGrandMotherExitNormal = fExitNormal;
1107     }                                            1107     }
1108     else                                         1108     else
1109     {                                            1109     {  
1110       // We must calculate the normal anyway     1110       // We must calculate the normal anyway (in order to have it if requested)
1111       //                                         1111       //
1112       G4ThreeVector finalLocalPoint = fLastLo    1112       G4ThreeVector finalLocalPoint = fLastLocatedPointLocal
1113                                     + localDi    1113                                     + localDirection*Step;
1114                                                  1114 
1115       if (  fHistory.GetTopVolumeType() != kR    1115       if (  fHistory.GetTopVolumeType() != kReplica )
1116       {                                          1116       {
1117         // Find normal in the 'mother' coordi    1117         // Find normal in the 'mother' coordinate system
1118         //                                       1118         //
1119         G4ThreeVector exitNormalMotherFrame=     1119         G4ThreeVector exitNormalMotherFrame=
1120            motherLogical->GetSolid()->Surface    1120            motherLogical->GetSolid()->SurfaceNormal(finalLocalPoint);
1121                                                  1121         
1122         // Transform it to the 'grand-mother'    1122         // Transform it to the 'grand-mother' coordinate system
1123         //                                       1123         //
1124         const G4RotationMatrix* mRot = mother    1124         const G4RotationMatrix* mRot = motherPhysical->GetRotation();
1125         if( mRot != nullptr )                    1125         if( mRot != nullptr )
1126         {                                        1126         {
1127           fChangedGrandMotherRefFrame = true;    1127           fChangedGrandMotherRefFrame = true;           
1128           fGrandMotherExitNormal = (*mRot).in    1128           fGrandMotherExitNormal = (*mRot).inverse() * exitNormalMotherFrame;
1129         }                                        1129         }
1130         else                                     1130         else
1131         {                                        1131         {
1132           fGrandMotherExitNormal = exitNormal    1132           fGrandMotherExitNormal = exitNormalMotherFrame;
1133         }                                        1133         }
1134                                                  1134 
1135         // Do not set fValidExitNormal -- thi    1135         // Do not set fValidExitNormal -- this signifies
1136         // that the solid is convex!             1136         // that the solid is convex!
1137       }                                          1137       }
1138       else                                       1138       else
1139       {                                          1139       {
1140         fCalculatedExitNormal = false;           1140         fCalculatedExitNormal = false;
1141         //                                       1141         //
1142         // Nothing can be done at this stage     1142         // Nothing can be done at this stage currently - to solve this
1143         // Replica Navigation must have calcu    1143         // Replica Navigation must have calculated the normal for this case
1144         // already.                              1144         // already.
1145         // Cases: mother is not convex, and e    1145         // Cases: mother is not convex, and exit is at previous replica level
1146                                                  1146 
1147 #ifdef G4DEBUG_NAVIGATION                        1147 #ifdef G4DEBUG_NAVIGATION
1148         G4ExceptionDescription desc;             1148         G4ExceptionDescription desc;
1149                                                  1149 
1150         desc << "Problem in ComputeStep:  Rep    1150         desc << "Problem in ComputeStep:  Replica Navigation did not provide"
1151              << " valid exit Normal. " << G4e    1151              << " valid exit Normal. " << G4endl;
1152         desc << " Do not know how calculate i    1152         desc << " Do not know how calculate it in this case." << G4endl;
1153         desc << "  Location    = " << finalLo    1153         desc << "  Location    = " << finalLocalPoint << G4endl;
1154         desc << "  Volume name = " << motherP    1154         desc << "  Volume name = " << motherPhysical->GetName()
1155              << "  copy/replica No = " << mot    1155              << "  copy/replica No = " << motherPhysical->GetCopyNo() << G4endl;
1156         G4Exception("G4Navigator::ComputeStep    1156         G4Exception("G4Navigator::ComputeStep()", "GeomNav0003",
1157                     JustWarning, desc, "Norma    1157                     JustWarning, desc, "Normal not available for exiting.");
1158 #endif                                           1158 #endif
1159       }                                          1159       }
1160     }                                            1160     }
1161                                                  1161 
1162     if ( fHistory.GetTopVolumeType() != kRepl    1162     if ( fHistory.GetTopVolumeType() != kReplica )
1163     {                                            1163     {
1164       fCalculatedExitNormal = true;              1164       fCalculatedExitNormal = true;
1165     }                                            1165     }
1166                                                  1166 
1167     // Now transform it to the global referen    1167     // Now transform it to the global reference frame !!
1168     //                                           1168     //
1169     if( fValidExitNormal || fCalculatedExitNo    1169     if( fValidExitNormal || fCalculatedExitNormal )
1170     {                                            1170     {
1171       auto  depth = (G4int)fHistory.GetDepth(    1171       auto  depth = (G4int)fHistory.GetDepth();
1172       if( depth > 0 )                            1172       if( depth > 0 )
1173       {                                          1173       {
1174         fExitNormalGlobalFrame = fHistory.Get    1174         fExitNormalGlobalFrame = fHistory.GetTransform(depth-1)
1175                                 .InverseTrans    1175                                 .InverseTransformAxis( fGrandMotherExitNormal );
1176       }                                          1176       }
1177       else                                       1177       else
1178       {                                          1178       {
1179         fExitNormalGlobalFrame = fGrandMother    1179         fExitNormalGlobalFrame = fGrandMotherExitNormal;
1180       }                                          1180       }
1181     }                                            1181     }
1182     else                                         1182     else
1183     {                                            1183     {
1184       fExitNormalGlobalFrame = G4ThreeVector(    1184       fExitNormalGlobalFrame = G4ThreeVector( 0., 0., 0.);
1185     }                                            1185     }
1186   }                                              1186   }
1187                                                  1187 
1188   if( (Step == pCurrentProposedStepLength) &&    1188   if( (Step == pCurrentProposedStepLength) && (!fExiting) && (!fEntering) )
1189   {                                              1189   {
1190     // This if Step is not really limited by     1190     // This if Step is not really limited by the geometry.
1191     // The Navigator is obliged to return "in    1191     // The Navigator is obliged to return "infinity"
1192     //                                           1192     //
1193     Step = kInfinity;                            1193     Step = kInfinity;
1194   }                                              1194   }
1195                                                  1195 
1196 #ifdef G4VERBOSE                                 1196 #ifdef G4VERBOSE
1197   if( fVerbose > 1 )                             1197   if( fVerbose > 1 )
1198   {                                              1198   {
1199     if( fVerbose >= 4 )                          1199     if( fVerbose >= 4 )
1200     {                                            1200     {
1201       G4cout << "    ----- Upon exiting :" <<    1201       G4cout << "    ----- Upon exiting :" << G4endl;
1202       PrintState();                              1202       PrintState();
1203     }                                            1203     }
1204     G4cout << "  Returned step= " << Step;       1204     G4cout << "  Returned step= " << Step;
1205     if( fVerbose > 5 )  { G4cout << G4endl; }    1205     if( fVerbose > 5 )  { G4cout << G4endl; }
1206     if( Step == kInfinity )                      1206     if( Step == kInfinity )
1207     {                                            1207     {
1208        G4cout << " Requested step= " << pCurr    1208        G4cout << " Requested step= " << pCurrentProposedStepLength ;
1209        if( fVerbose > 5)  { G4cout << G4endl;    1209        if( fVerbose > 5)  { G4cout << G4endl; }
1210     }                                            1210     }
1211     G4cout << "  Safety = " << pNewSafety <<     1211     G4cout << "  Safety = " << pNewSafety << G4endl;
1212   }                                              1212   }
1213 #endif                                           1213 #endif
1214                                                  1214 
1215   fLastTriedStepComputation = true;              1215   fLastTriedStepComputation = true;
1216                                                  1216 
1217   return Step;                                   1217   return Step;
1218 }                                                1218 }
1219                                                  1219 
1220 // ******************************************    1220 // ********************************************************************
1221 // CheckNextStep                                 1221 // CheckNextStep
1222 //                                               1222 //
1223 // Compute the step without altering the navi    1223 // Compute the step without altering the navigator state
1224 // ******************************************    1224 // ********************************************************************
1225 //                                               1225 //
1226 G4double G4Navigator::CheckNextStep( const G4    1226 G4double G4Navigator::CheckNextStep( const G4ThreeVector& pGlobalpoint,
1227                                      const G4    1227                                      const G4ThreeVector& pDirection,
1228                                      const G4    1228                                      const G4double pCurrentProposedStepLength,
1229                                            G4    1229                                            G4double& pNewSafety)
1230 {                                                1230 {
1231   G4double step;                                 1231   G4double step;
1232                                                  1232 
1233   // Save the state, for this parasitic call     1233   // Save the state, for this parasitic call
1234   //                                             1234   //
1235   SetSavedState();                               1235   SetSavedState();
1236                                                  1236 
1237   step = ComputeStep ( pGlobalpoint,             1237   step = ComputeStep ( pGlobalpoint, 
1238                        pDirection,               1238                        pDirection,
1239                        pCurrentProposedStepLe    1239                        pCurrentProposedStepLength, 
1240                        pNewSafety );             1240                        pNewSafety ); 
1241                                                  1241 
1242   // It is a parasitic call, so attempt to re    1242   // It is a parasitic call, so attempt to restore the key parts of the state
1243   //                                             1243   //
1244   RestoreSavedState();                           1244   RestoreSavedState(); 
1245   // NOTE: the state of the current subnaviga    1245   // NOTE: the state of the current subnavigator is NOT restored.
1246   // ***> TODO: restore subnavigator state       1246   // ***> TODO: restore subnavigator state
1247   //            if( last_located)       Need     1247   //            if( last_located)       Need Position of last location
1248   //            if( last_computed step) Need     1248   //            if( last_computed step) Need Endposition of last step
1249                                                  1249   
1250   return step;                                   1250   return step; 
1251 }                                                1251 }
1252                                                  1252 
1253 // ******************************************    1253 // ********************************************************************
1254 // ResetState                                    1254 // ResetState
1255 //                                               1255 //
1256 // Resets stack and minimum of navigator stat    1256 // Resets stack and minimum of navigator state `machine'
1257 // ******************************************    1257 // ********************************************************************
1258 //                                               1258 //
1259 void G4Navigator::ResetState()                   1259 void G4Navigator::ResetState()
1260 {                                                1260 {
1261   fWasLimitedByGeometry  = false;                1261   fWasLimitedByGeometry  = false;
1262   fEntering              = false;                1262   fEntering              = false;
1263   fExiting               = false;                1263   fExiting               = false;
1264   fLocatedOnEdge         = false;                1264   fLocatedOnEdge         = false;
1265   fLastStepWasZero       = false;                1265   fLastStepWasZero       = false;
1266   fEnteredDaughter       = false;                1266   fEnteredDaughter       = false;
1267   fExitedMother          = false;                1267   fExitedMother          = false;
1268   fPushed                = false;                1268   fPushed                = false;
1269                                                  1269 
1270   fValidExitNormal       = false;                1270   fValidExitNormal       = false;
1271   fChangedGrandMotherRefFrame = false;           1271   fChangedGrandMotherRefFrame = false;
1272   fCalculatedExitNormal  = false;                1272   fCalculatedExitNormal  = false;
1273                                                  1273 
1274   fExitNormal            = G4ThreeVector(0,0,    1274   fExitNormal            = G4ThreeVector(0,0,0);
1275   fGrandMotherExitNormal = G4ThreeVector(0,0,    1275   fGrandMotherExitNormal = G4ThreeVector(0,0,0);
1276   fExitNormalGlobalFrame = G4ThreeVector(0,0,    1276   fExitNormalGlobalFrame = G4ThreeVector(0,0,0);
1277                                                  1277 
1278   fPreviousSftOrigin     = G4ThreeVector(0,0,    1278   fPreviousSftOrigin     = G4ThreeVector(0,0,0);
1279   fPreviousSafety        = 0.0;                  1279   fPreviousSafety        = 0.0; 
1280                                                  1280 
1281   fNumberZeroSteps       = 0;                    1281   fNumberZeroSteps       = 0;
1282                                                  1282 
1283   fBlockedPhysicalVolume = nullptr;              1283   fBlockedPhysicalVolume = nullptr;
1284   fBlockedReplicaNo      = -1;                   1284   fBlockedReplicaNo      = -1;
1285                                                  1285 
1286   fLastLocatedPointLocal = G4ThreeVector( kIn    1286   fLastLocatedPointLocal = G4ThreeVector( kInfinity, -kInfinity, 0.0 ); 
1287   fLocatedOutsideWorld   = false;                1287   fLocatedOutsideWorld   = false;
1288                                                  1288 
1289   fLastMotherPhys = nullptr;                     1289   fLastMotherPhys = nullptr;
1290 }                                                1290 }
1291                                                  1291 
1292 // ******************************************    1292 // ********************************************************************
1293 // SetupHierarchy                                1293 // SetupHierarchy
1294 //                                               1294 //
1295 // Renavigates & resets hierarchy described b    1295 // Renavigates & resets hierarchy described by current history
1296 // o Reset volumes                               1296 // o Reset volumes
1297 // o Recompute transforms and/or solids of re    1297 // o Recompute transforms and/or solids of replicated/parameterised volumes
1298 // ******************************************    1298 // ********************************************************************
1299 //                                               1299 //
1300 void G4Navigator::SetupHierarchy()               1300 void G4Navigator::SetupHierarchy()
1301 {                                                1301 {
1302   const auto  depth = (G4int)fHistory.GetDept    1302   const auto  depth = (G4int)fHistory.GetDepth();
1303   for ( auto i = 1; i <= depth; ++i )            1303   for ( auto i = 1; i <= depth; ++i )
1304   {                                              1304   {
1305     switch ( fHistory.GetVolumeType(i) )         1305     switch ( fHistory.GetVolumeType(i) )
1306     {                                            1306     {
1307       case kNormal:                              1307       case kNormal:
1308       case kExternal:                            1308       case kExternal:
1309         break;                                   1309         break;
1310       case kReplica:                             1310       case kReplica:
1311         freplicaNav.ComputeTransformation(fHi    1311         freplicaNav.ComputeTransformation(fHistory.GetReplicaNo(i), fHistory.GetVolume(i));
1312         break;                                   1312         break;
1313       case kParameterised:                       1313       case kParameterised:
1314         G4VPhysicalVolume* current = fHistory    1314         G4VPhysicalVolume* current = fHistory.GetVolume(i);
1315         G4int replicaNo = fHistory.GetReplica    1315         G4int replicaNo = fHistory.GetReplicaNo(i);
1316         G4VPVParameterisation* pParam = curre    1316         G4VPVParameterisation* pParam = current->GetParameterisation();
1317         G4VSolid* pSolid = pParam->ComputeSol    1317         G4VSolid* pSolid = pParam->ComputeSolid(replicaNo, current);
1318                                                  1318 
1319         // Set up dimensions & transform in s    1319         // Set up dimensions & transform in solid/physical volume
1320         //                                       1320         //
1321         pSolid->ComputeDimensions(pParam, rep    1321         pSolid->ComputeDimensions(pParam, replicaNo, current);
1322         pParam->ComputeTransformation(replica    1322         pParam->ComputeTransformation(replicaNo, current);
1323                                                  1323 
1324         G4TouchableHistory* pTouchable = null    1324         G4TouchableHistory* pTouchable = nullptr;
1325         if( pParam->IsNested() )                 1325         if( pParam->IsNested() )
1326         {                                        1326         {
1327           pTouchable= new G4TouchableHistory(    1327           pTouchable= new G4TouchableHistory( fHistory );
1328           pTouchable->MoveUpHistory(); // Mov    1328           pTouchable->MoveUpHistory(); // Move up to the parent level
1329             // Adequate only if Nested at the    1329             // Adequate only if Nested at the Branch level (last)
1330             // To extend to other cases:         1330             // To extend to other cases:
1331             // pTouchable->MoveUpHistory(cdep    1331             // pTouchable->MoveUpHistory(cdepth-i-1);
1332             // Move to the parent level of *C    1332             // Move to the parent level of *Current* level
1333             // Could replace this line and co    1333             // Could replace this line and constructor with a revised
1334             // c-tor for History(levels to dr    1334             // c-tor for History(levels to drop)
1335         }                                        1335         }
1336         // Set up the correct solid and mater    1336         // Set up the correct solid and material in Logical Volume
1337         //                                       1337         //
1338         G4LogicalVolume* pLogical = current->    1338         G4LogicalVolume* pLogical = current->GetLogicalVolume();
1339         pLogical->SetSolid( pSolid );            1339         pLogical->SetSolid( pSolid );
1340         pLogical->UpdateMaterial( pParam ->      1340         pLogical->UpdateMaterial( pParam ->
1341           ComputeMaterial(replicaNo, current,    1341           ComputeMaterial(replicaNo, current, pTouchable) );
1342         delete pTouchable;                       1342         delete pTouchable;
1343         break;                                   1343         break;
1344     }                                            1344     }
1345   }                                              1345   }
1346 }                                                1346 }
1347                                                  1347 
1348 // ******************************************    1348 // ********************************************************************
1349 // GetLocalExitNormal                            1349 // GetLocalExitNormal
1350 //                                               1350 //
1351 // Obtains the Normal vector to a surface (in    1351 // Obtains the Normal vector to a surface (in local coordinates)
1352 // pointing out of previous volume and into c    1352 // pointing out of previous volume and into current volume
1353 // ******************************************    1353 // ********************************************************************
1354 //                                               1354 //
1355 G4ThreeVector G4Navigator::GetLocalExitNormal    1355 G4ThreeVector G4Navigator::GetLocalExitNormal( G4bool* valid )
1356 {                                                1356 {
1357   G4ThreeVector    ExitNormal(0.,0.,0.);         1357   G4ThreeVector    ExitNormal(0.,0.,0.);
1358   G4VSolid* currentSolid = nullptr;              1358   G4VSolid* currentSolid = nullptr;
1359   G4LogicalVolume* candidateLogical;             1359   G4LogicalVolume* candidateLogical;
1360                                                  1360 
1361   if ( fLastTriedStepComputation )               1361   if ( fLastTriedStepComputation ) 
1362   {                                              1362   {
1363     // use fLastLocatedPointLocal and next ca    1363     // use fLastLocatedPointLocal and next candidate volume
1364     //                                           1364     //
1365     G4ThreeVector nextSolidExitNormal(0.,0.,0    1365     G4ThreeVector nextSolidExitNormal(0.,0.,0.);
1366                                                  1366 
1367     if( fEntering && (fBlockedPhysicalVolume!    1367     if( fEntering && (fBlockedPhysicalVolume!=nullptr) ) 
1368     {                                            1368     { 
1369       candidateLogical = fBlockedPhysicalVolu    1369       candidateLogical = fBlockedPhysicalVolume->GetLogicalVolume();
1370       if( candidateLogical != nullptr )          1370       if( candidateLogical != nullptr ) 
1371       {                                          1371       {
1372         // fLastStepEndPointLocal is in the c    1372         // fLastStepEndPointLocal is in the coordinates of the mother
1373         // we need it in the daughter's coord    1373         // we need it in the daughter's coordinate system.
1374                                                  1374 
1375         // The following code should also wor    1375         // The following code should also work in case of Replica
1376         {                                        1376         {
1377           // First transform fLastLocatedPoin    1377           // First transform fLastLocatedPointLocal to the new daughter
1378           // coordinates                         1378           // coordinates
1379           //                                     1379           //
1380           G4AffineTransform MotherToDaughterT    1380           G4AffineTransform MotherToDaughterTransform=
1381             GetMotherToDaughterTransform( fBl    1381             GetMotherToDaughterTransform( fBlockedPhysicalVolume, 
1382                                           fBl    1382                                           fBlockedReplicaNo,
1383                                           Vol    1383                                           VolumeType(fBlockedPhysicalVolume) ); 
1384           G4ThreeVector daughterPointOwnLocal    1384           G4ThreeVector daughterPointOwnLocal =
1385             MotherToDaughterTransform.Transfo    1385             MotherToDaughterTransform.TransformPoint( fLastStepEndPointLocal ); 
1386                                                  1386 
1387           // OK if it is a parameterised volu    1387           // OK if it is a parameterised volume
1388           //                                     1388           //
1389           EInside inSideIt;                      1389           EInside inSideIt; 
1390           G4bool onSurface;                      1390           G4bool onSurface;
1391           G4double safety = -1.0;                1391           G4double safety = -1.0; 
1392           currentSolid = candidateLogical->Ge    1392           currentSolid = candidateLogical->GetSolid(); 
1393           inSideIt = currentSolid->Inside(dau    1393           inSideIt = currentSolid->Inside(daughterPointOwnLocal); 
1394           onSurface = (inSideIt == kSurface);    1394           onSurface = (inSideIt == kSurface); 
1395           if( !onSurface )                       1395           if( !onSurface ) 
1396           {                                      1396           {
1397             if( inSideIt == kOutside )           1397             if( inSideIt == kOutside )
1398             {                                    1398             {
1399               safety = (currentSolid->Distanc    1399               safety = (currentSolid->DistanceToIn(daughterPointOwnLocal)); 
1400               onSurface = safety < 100.0 * kC    1400               onSurface = safety < 100.0 * kCarTolerance; 
1401             }                                    1401             }
1402             else if (inSideIt == kInside )       1402             else if (inSideIt == kInside )
1403             {                                    1403             {
1404               safety = (currentSolid->Distanc    1404               safety = (currentSolid->DistanceToOut(daughterPointOwnLocal)); 
1405               onSurface = safety < 100.0 * kC    1405               onSurface = safety < 100.0 * kCarTolerance; 
1406             }                                    1406             }
1407           }                                      1407           }
1408                                                  1408 
1409           if( onSurface )                        1409           if( onSurface ) 
1410           {                                      1410           {
1411             nextSolidExitNormal =                1411             nextSolidExitNormal =
1412               currentSolid->SurfaceNormal(dau    1412               currentSolid->SurfaceNormal(daughterPointOwnLocal);
1413                                                  1413  
1414             // Entering the solid ==> opposit    1414             // Entering the solid ==> opposite
1415             //                                   1415             //
1416             // First flip ( ExitNormal = -nex    1416             // First flip ( ExitNormal = -nextSolidExitNormal; )
1417             //  and then rotate the the norma    1417             //  and then rotate the the normal to the frame of the mother (current volume)
1418             ExitNormal = MotherToDaughterTran    1418             ExitNormal = MotherToDaughterTransform
1419                         .InverseTransformAxis    1419                         .InverseTransformAxis( -nextSolidExitNormal );
1420             fCalculatedExitNormal = true;        1420             fCalculatedExitNormal = true;
1421           }                                      1421           }
1422           else                                   1422           else
1423           {                                      1423           {
1424 #ifdef G4VERBOSE                                 1424 #ifdef G4VERBOSE
1425             if(( fVerbose == 1 ) && ( fCheck     1425             if(( fVerbose == 1 ) && ( fCheck ))
1426             {                                    1426             {
1427               std::ostringstream message;        1427               std::ostringstream message;
1428               message << "Point not on surfac    1428               message << "Point not on surface ! " << G4endl
1429                       << "  Point           =    1429                       << "  Point           = "
1430                       << daughterPointOwnLoca    1430                       << daughterPointOwnLocal << G4endl 
1431                       << "  Physical volume =    1431                       << "  Physical volume = "
1432                       << fBlockedPhysicalVolu    1432                       << fBlockedPhysicalVolume->GetName() << G4endl
1433                       << "  Logical volume  =    1433                       << "  Logical volume  = "
1434                       << candidateLogical->Ge    1434                       << candidateLogical->GetName() << G4endl
1435                       << "  Solid           =    1435                       << "  Solid           = " << currentSolid->GetName() 
1436                       << "  Type            =    1436                       << "  Type            = "
1437                       << currentSolid->GetEnt    1437                       << currentSolid->GetEntityType() << G4endl
1438                       << *currentSolid << G4e    1438                       << *currentSolid << G4endl;
1439               if( inSideIt == kOutside )         1439               if( inSideIt == kOutside )
1440               {                                  1440               { 
1441                 message << "Point is Outside.    1441                 message << "Point is Outside. " << G4endl
1442                         << "  Safety (from ou    1442                         << "  Safety (from outside) = " << safety << G4endl;
1443               }                                  1443               }
1444               else // if( inSideIt == kInside    1444               else // if( inSideIt == kInside ) 
1445               {                                  1445               {
1446                 message << "Point is Inside.     1446                 message << "Point is Inside. " << G4endl
1447                         << "  Safety (from in    1447                         << "  Safety (from inside) = " << safety << G4endl;
1448               }                                  1448               }
1449               G4Exception("G4Navigator::GetLo    1449               G4Exception("G4Navigator::GetLocalExitNormal()", "GeomNav1001",
1450                           JustWarning, messag    1450                           JustWarning, message);
1451             }                                    1451             }
1452 #endif                                           1452 #endif
1453           }                                      1453           }
1454           *valid = onSurface;   //   was =tru    1454           *valid = onSurface;   //   was =true;
1455         }                                        1455         }
1456       }                                          1456       }
1457     }                                            1457     }
1458     else if ( fExiting )                         1458     else if ( fExiting ) 
1459     {                                            1459     {
1460       ExitNormal = fGrandMotherExitNormal;       1460       ExitNormal = fGrandMotherExitNormal;
1461       *valid = true;                             1461       *valid = true;
1462       fCalculatedExitNormal = true;  // Shoul    1462       fCalculatedExitNormal = true;  // Should be true already
1463     }                                            1463     }
1464     else  // i.e.  ( fBlockedPhysicalVolume =    1464     else  // i.e.  ( fBlockedPhysicalVolume == 0 )
1465     {                                            1465     {
1466       *valid = false;                            1466       *valid = false;
1467       G4Exception("G4Navigator::GetLocalExitN    1467       G4Exception("G4Navigator::GetLocalExitNormal()",
1468                   "GeomNav0003", JustWarning,    1468                   "GeomNav0003", JustWarning, 
1469                   "Incorrect call to GetLocal    1469                   "Incorrect call to GetLocalSurfaceNormal." );
1470     }                                            1470     }
1471   }                                              1471   }
1472   else //  ( ! fLastTriedStepComputation ) i.    1472   else //  ( ! fLastTriedStepComputation ) i.e. last call was to Locate
1473   {                                              1473   {
1474     if ( EnteredDaughterVolume() )               1474     if ( EnteredDaughterVolume() )
1475     {                                            1475     {
1476       G4VSolid* daughterSolid = fHistory.GetT    1476       G4VSolid* daughterSolid = fHistory.GetTopVolume()->GetLogicalVolume()
1477                                                  1477                                                        ->GetSolid();
1478       ExitNormal = -(daughterSolid->SurfaceNo    1478       ExitNormal = -(daughterSolid->SurfaceNormal(fLastLocatedPointLocal));
1479       if( std::fabs(ExitNormal.mag2()-1.0 ) >    1479       if( std::fabs(ExitNormal.mag2()-1.0 ) > kToleranceNormalCheck )
1480       {                                          1480       {
1481         G4ExceptionDescription desc;             1481         G4ExceptionDescription desc;
1482         desc << " Parameters of solid: " << *    1482         desc << " Parameters of solid: " << *daughterSolid
1483              << " Point for surface = " << fL    1483              << " Point for surface = " << fLastLocatedPointLocal << std::endl;
1484         G4Exception("G4Navigator::GetLocalExi    1484         G4Exception("G4Navigator::GetLocalExitNormal()",
1485                     "GeomNav0003", FatalExcep    1485                     "GeomNav0003", FatalException, desc,
1486                     "Surface Normal returned     1486                     "Surface Normal returned by Solid is not a Unit Vector." );
1487       }                                          1487       }
1488       fCalculatedExitNormal = true;              1488       fCalculatedExitNormal = true;
1489       *valid = true;                             1489       *valid = true;
1490     }                                            1490     }
1491     else                                         1491     else
1492     {                                            1492     {
1493       if( fExitedMother )                        1493       if( fExitedMother )
1494       {                                          1494       {
1495         ExitNormal = fGrandMotherExitNormal;     1495         ExitNormal = fGrandMotherExitNormal;
1496         *valid = true;                           1496         *valid = true;
1497         fCalculatedExitNormal = true;            1497         fCalculatedExitNormal = true;
1498       }                                          1498       }
1499       else  // We are not at a boundary. Exit    1499       else  // We are not at a boundary. ExitNormal remains (0,0,0)
1500       {                                          1500       { 
1501         *valid = false;                          1501         *valid = false;
1502         fCalculatedExitNormal = false;           1502         fCalculatedExitNormal = false; 
1503         G4ExceptionDescription message;          1503         G4ExceptionDescription message; 
1504         message << "Function called when *NOT    1504         message << "Function called when *NOT* at a Boundary." << G4endl;
1505         message << "Exit Normal not calculate    1505         message << "Exit Normal not calculated." << G4endl;
1506         G4Exception("G4Navigator::GetLocalExi    1506         G4Exception("G4Navigator::GetLocalExitNormal()",
1507                     "GeomNav0003", JustWarnin    1507                     "GeomNav0003", JustWarning, message); 
1508       }                                          1508       }
1509     }                                            1509     }
1510   }                                              1510   }
1511   return ExitNormal;                             1511   return ExitNormal;
1512 }                                                1512 }
1513                                                  1513 
1514 // ******************************************    1514 // ********************************************************************
1515 // GetMotherToDaughterTransform                  1515 // GetMotherToDaughterTransform
1516 //                                               1516 //
1517 // Obtains the mother to daughter affine tran    1517 // Obtains the mother to daughter affine transformation
1518 // ******************************************    1518 // ********************************************************************
1519 //                                               1519 //
1520 G4AffineTransform                                1520 G4AffineTransform
1521 G4Navigator::GetMotherToDaughterTransform( G4    1521 G4Navigator::GetMotherToDaughterTransform( G4VPhysicalVolume* pEnteringPhysVol,
1522                                            G4    1522                                            G4int enteringReplicaNo,
1523                                            EV    1523                                            EVolume enteringVolumeType ) 
1524 {                                                1524 {
1525   switch (enteringVolumeType)                    1525   switch (enteringVolumeType)
1526   {                                              1526   {
1527     case kNormal:  // Nothing is needed to pr    1527     case kNormal:  // Nothing is needed to prepare the transformation
1528       break;       // It is stored already in    1528       break;       // It is stored already in the physical volume (placement)
1529     case kReplica: // Sets the transform in t    1529     case kReplica: // Sets the transform in the Replica - tbc
1530       G4Exception("G4Navigator::GetMotherToDa    1530       G4Exception("G4Navigator::GetMotherToDaughterTransform()",
1531                   "GeomNav0001", FatalExcepti    1531                   "GeomNav0001", FatalException,
1532                   "Method NOT Implemented yet    1532                   "Method NOT Implemented yet for replica volumes.");
1533       break;                                     1533       break;
1534     case kParameterised:                         1534     case kParameterised:
1535       if( pEnteringPhysVol->GetRegularStructu    1535       if( pEnteringPhysVol->GetRegularStructureId() == 0 )
1536       {                                          1536       {
1537         G4VPVParameterisation *pParam =          1537         G4VPVParameterisation *pParam =
1538           pEnteringPhysVol->GetParameterisati    1538           pEnteringPhysVol->GetParameterisation();
1539         G4VSolid* pSolid =                       1539         G4VSolid* pSolid =
1540           pParam->ComputeSolid(enteringReplic    1540           pParam->ComputeSolid(enteringReplicaNo, pEnteringPhysVol);
1541         pSolid->ComputeDimensions(pParam, ent    1541         pSolid->ComputeDimensions(pParam, enteringReplicaNo, pEnteringPhysVol);
1542                                                  1542 
1543         // Sets the transform in the Paramete    1543         // Sets the transform in the Parameterisation
1544         //                                       1544         //
1545         pParam->ComputeTransformation(enterin    1545         pParam->ComputeTransformation(enteringReplicaNo, pEnteringPhysVol);
1546                                                  1546 
1547         // Set the correct solid and material    1547         // Set the correct solid and material in Logical Volume
1548         //                                       1548         //
1549         G4LogicalVolume* pLogical = pEntering    1549         G4LogicalVolume* pLogical = pEnteringPhysVol->GetLogicalVolume();
1550         pLogical->SetSolid( pSolid );            1550         pLogical->SetSolid( pSolid );
1551       }                                          1551       }
1552       break;                                     1552       break;
1553     case kExternal:                              1553     case kExternal:
1554       // Expect that nothing is needed to pre    1554       // Expect that nothing is needed to prepare the transformation.
1555       // It is stored already in the physical    1555       // It is stored already in the physical volume (placement)
1556       break;                                     1556       break;
1557   }                                              1557   }
1558   return G4AffineTransform(pEnteringPhysVol->    1558   return G4AffineTransform(pEnteringPhysVol->GetRotation(), 
1559                            pEnteringPhysVol->    1559                            pEnteringPhysVol->GetTranslation()).Invert(); 
1560 }                                                1560 }
1561                                                  1561 
1562                                                  1562 
1563 // ******************************************    1563 // ********************************************************************
1564 // GetLocalExitNormalAndCheck                    1564 // GetLocalExitNormalAndCheck
1565 //                                               1565 //
1566 // Obtains the Normal vector to a surface (in    1566 // Obtains the Normal vector to a surface (in local coordinates)
1567 // pointing out of previous volume and into c    1567 // pointing out of previous volume and into current volume, and
1568 // checks the current point against expected     1568 // checks the current point against expected 'local' value.
1569 // ******************************************    1569 // ********************************************************************
1570 //                                               1570 //
1571 G4ThreeVector                                    1571 G4ThreeVector
1572 G4Navigator::GetLocalExitNormalAndCheck(         1572 G4Navigator::GetLocalExitNormalAndCheck( 
1573 #ifdef G4DEBUG_NAVIGATION                        1573 #ifdef G4DEBUG_NAVIGATION
1574                            const G4ThreeVecto    1574                            const G4ThreeVector& ExpectedBoundaryPointGlobal,
1575 #else                                            1575 #else
1576                            const G4ThreeVecto    1576                            const G4ThreeVector&,
1577 #endif                                           1577 #endif
1578                                  G4bool* pVal    1578                                  G4bool* pValid)
1579 {                                                1579 {
1580 #ifdef G4DEBUG_NAVIGATION                        1580 #ifdef G4DEBUG_NAVIGATION
1581   // Check Current point against expected 'lo    1581   // Check Current point against expected 'local' value
1582   //                                             1582   //
1583   if ( fLastTriedStepComputation )               1583   if ( fLastTriedStepComputation ) 
1584   {                                              1584   {
1585     G4ThreeVector ExpectedBoundaryPointLocal;    1585     G4ThreeVector ExpectedBoundaryPointLocal;
1586                                                  1586 
1587     const G4AffineTransform& GlobalToLocal =     1587     const G4AffineTransform& GlobalToLocal = GetGlobalToLocalTransform(); 
1588     ExpectedBoundaryPointLocal =                 1588     ExpectedBoundaryPointLocal =
1589       GlobalToLocal.TransformPoint( ExpectedB    1589       GlobalToLocal.TransformPoint( ExpectedBoundaryPointGlobal ); 
1590                                                  1590 
1591     // Add here:  Comparison against expected    1591     // Add here:  Comparison against expected position,
1592     //            i.e. the endpoint of Comput    1592     //            i.e. the endpoint of ComputeStep
1593   }                                              1593   }
1594 #endif                                           1594 #endif
1595                                                  1595   
1596   return GetLocalExitNormal( pValid );           1596   return GetLocalExitNormal( pValid ); 
1597 }                                                1597 }
1598                                                  1598 
1599 // ******************************************    1599 // ********************************************************************
1600 // GetGlobalExitNormal                           1600 // GetGlobalExitNormal
1601 //                                               1601 //
1602 // Obtains the Normal vector to a surface (in    1602 // Obtains the Normal vector to a surface (in global coordinates)
1603 // pointing out of previous volume and into c    1603 // pointing out of previous volume and into current volume
1604 // ******************************************    1604 // ********************************************************************
1605 //                                               1605 //
1606 G4ThreeVector                                    1606 G4ThreeVector 
1607 G4Navigator::GetGlobalExitNormal(const G4Thre    1607 G4Navigator::GetGlobalExitNormal(const G4ThreeVector& IntersectPointGlobal,
1608                                        G4bool    1608                                        G4bool*        pNormalCalculated)
1609 {                                                1609 {
1610   G4bool         validNormal;                    1610   G4bool         validNormal;
1611   G4ThreeVector  localNormal, globalNormal;      1611   G4ThreeVector  localNormal, globalNormal;
1612                                                  1612  
1613   G4bool usingStored = fCalculatedExitNormal     1613   G4bool usingStored = fCalculatedExitNormal && (
1614        ( fLastTriedStepComputation && fExitin    1614        ( fLastTriedStepComputation && fExiting ) // Just calculated it
1615        ||                                        1615        ||                                        // No locate in between
1616        ( !fLastTriedStepComputation              1616        ( !fLastTriedStepComputation
1617           && (IntersectPointGlobal-fStepEndPo    1617           && (IntersectPointGlobal-fStepEndPoint).mag2() < 10.0*fSqTol ) );
1618            // Calculated it 'just' before & t    1618            // Calculated it 'just' before & then called locate
1619            // but it did not move position       1619            // but it did not move position
1620                                                  1620   
1621   if( usingStored )                              1621   if( usingStored )
1622   {                                              1622   {
1623     // This was computed in last call to Comp    1623     // This was computed in last call to ComputeStep
1624     // and only if it arrived at boundary        1624     // and only if it arrived at boundary
1625     //                                           1625     //
1626     globalNormal = fExitNormalGlobalFrame;       1626     globalNormal = fExitNormalGlobalFrame; 
1627     G4double  normMag2 = globalNormal.mag2();    1627     G4double  normMag2 = globalNormal.mag2(); 
1628     if( std::fabs ( normMag2 - 1.0 ) < perTho    1628     if( std::fabs ( normMag2 - 1.0 ) < perThousand ) // was perMillion
1629     {                                            1629     {
1630        *pNormalCalculated = true; // ComputeS    1630        *pNormalCalculated = true; // ComputeStep always computes it if Exiting
1631                                   // (fExitin    1631                                   // (fExiting==true)
1632     }                                            1632     }
1633     else                                         1633     else
1634     {                                            1634     {
1635        G4ExceptionDescription message;           1635        G4ExceptionDescription message;
1636        message.precision(10);                    1636        message.precision(10); 
1637        message << " WARNING> Expected normal-    1637        message << " WARNING> Expected normal-global-frame to be valid, "
1638                << " i.e. a unit vector!" << G    1638                << " i.e. a unit vector!" << G4endl
1639                << "  - but |normal|   = "  <<    1639                << "  - but |normal|   = "  << std::sqrt(normMag2)
1640                << "  - and |normal|^2 = "  <<    1640                << "  - and |normal|^2 = "  << normMag2 << G4endl
1641                << " which differs from 1.0 by    1641                << " which differs from 1.0 by " << normMag2 - 1.0 << G4endl
1642                << "   n = " << fExitNormalGlo    1642                << "   n = " << fExitNormalGlobalFrame << G4endl
1643                << " Global point: " << Inters    1643                << " Global point: " << IntersectPointGlobal << G4endl
1644                << " Volume: " << fHistory.Get    1644                << " Volume: " << fHistory.GetTopVolume()->GetName() << G4endl;
1645 #ifdef G4VERBOSE                                 1645 #ifdef G4VERBOSE
1646        G4LogicalVolume* candLog = fHistory.Ge    1646        G4LogicalVolume* candLog = fHistory.GetTopVolume()->GetLogicalVolume();
1647        if ( candLog != nullptr )                 1647        if ( candLog != nullptr )
1648        {                                         1648        {
1649          message << " Solid: " << candLog->Ge    1649          message << " Solid: " << candLog->GetSolid()->GetName()
1650                  << ", Type: " << candLog->Ge    1650                  << ", Type: " << candLog->GetSolid()->GetEntityType() << G4endl
1651                  << *candLog->GetSolid() << G    1651                  << *candLog->GetSolid() << G4endl;
1652        }                                         1652        }
1653 #endif                                           1653 #endif
1654        message << "==========================    1654        message << "============================================================"
1655                << G4endl;                        1655                << G4endl;
1656        G4int oldVerbose = fVerbose;              1656        G4int oldVerbose = fVerbose; 
1657        fVerbose = 4;                             1657        fVerbose = 4; 
1658        message << "   State of Navigator: " <    1658        message << "   State of Navigator: " << G4endl;
1659        message << *this << G4endl;               1659        message << *this << G4endl;
1660        fVerbose = oldVerbose;                    1660        fVerbose = oldVerbose; 
1661        message << "==========================    1661        message << "============================================================"
1662                << G4endl;                        1662                << G4endl;
1663                                                  1663 
1664        G4Exception("G4Navigator::GetGlobalExi    1664        G4Exception("G4Navigator::GetGlobalExitNormal()",
1665                    "GeomNav0003",JustWarning,    1665                    "GeomNav0003",JustWarning, message,
1666               "Value obtained from stored glo    1666               "Value obtained from stored global-normal is not a unit vector.");
1667                                                  1667 
1668        // (Re)Compute it now -- as either it     1668        // (Re)Compute it now -- as either it was not computed, or it is wrong.
1669        //                                        1669        //
1670        localNormal = GetLocalExitNormalAndChe    1670        localNormal = GetLocalExitNormalAndCheck(IntersectPointGlobal,
1671                                                  1671                                                 &validNormal);
1672        *pNormalCalculated = fCalculatedExitNo    1672        *pNormalCalculated = fCalculatedExitNormal;
1673        globalNormal = fHistory.GetTopTransfor    1673        globalNormal = fHistory.GetTopTransform()
1674                      .InverseTransformAxis(lo    1674                      .InverseTransformAxis(localNormal);
1675     }                                            1675     }
1676   }                                              1676   }
1677   else                                           1677   else
1678   {                                              1678   {
1679     localNormal = GetLocalExitNormalAndCheck(    1679     localNormal = GetLocalExitNormalAndCheck(IntersectPointGlobal,&validNormal);
1680     *pNormalCalculated = fCalculatedExitNorma    1680     *pNormalCalculated = fCalculatedExitNormal;
1681                                                  1681 
1682 #ifdef G4DEBUG_NAVIGATION                        1682 #ifdef G4DEBUG_NAVIGATION
1683     usingStored = false;                         1683     usingStored = false;
1684                                                  1684 
1685     if( (!validNormal) && !fCalculatedExitNor    1685     if( (!validNormal) && !fCalculatedExitNormal )
1686     {                                            1686     {
1687       G4ExceptionDescription edN;                1687       G4ExceptionDescription edN;
1688       edN << "  Calculated = " << fCalculated    1688       edN << "  Calculated = " << fCalculatedExitNormal << G4endl;
1689       edN << "   Entering= "  << fEntering <<    1689       edN << "   Entering= "  << fEntering << G4endl;
1690       G4int oldVerbose = this->GetVerboseLeve    1690       G4int oldVerbose = this->GetVerboseLevel();
1691       this->SetVerboseLevel(4);                  1691       this->SetVerboseLevel(4);
1692       edN << "   State of Navigator: " << G4e    1692       edN << "   State of Navigator: " << G4endl;
1693       edN << *this << G4endl;                    1693       edN << *this << G4endl;
1694       this->SetVerboseLevel( oldVerbose );       1694       this->SetVerboseLevel( oldVerbose );
1695                                                  1695        
1696       G4Exception("G4Navigator::GetGlobalExit    1696       G4Exception("G4Navigator::GetGlobalExitNormal()",
1697                   "GeomNav0003", JustWarning,    1697                   "GeomNav0003", JustWarning, edN,
1698                   "LocalExitNormalAndCheck()     1698                   "LocalExitNormalAndCheck() did not calculate Normal.");
1699      }                                           1699      }
1700 #endif                                           1700 #endif
1701                                                  1701      
1702      G4double localMag2 = localNormal.mag2();    1702      G4double localMag2 = localNormal.mag2();
1703      if( validNormal && (std::fabs(localMag2-    1703      if( validNormal && (std::fabs(localMag2-1.0)) > kToleranceNormalCheck )
1704      {                                           1704      {
1705        G4ExceptionDescription edN;               1705        G4ExceptionDescription edN;
1706        edN.precision(10);                        1706        edN.precision(10); 
1707        edN << "G4Navigator::GetGlobalExitNorm    1707        edN << "G4Navigator::GetGlobalExitNormal: "
1708            << "  Using Local Normal - from ca    1708            << "  Using Local Normal - from call to GetLocalExitNormalAndCheck. "
1709            << G4endl                             1709            << G4endl
1710            << "  Local  Exit Normal : " << "     1710            << "  Local  Exit Normal : " << " || = " << std::sqrt(localMag2) 
1711            << " vec = " << localNormal << G4e    1711            << " vec = " << localNormal << G4endl
1712            << "  Global Exit Normal : " << "     1712            << "  Global Exit Normal : " << " || = " << globalNormal.mag() 
1713            << " vec = " << globalNormal << G4    1713            << " vec = " << globalNormal << G4endl
1714            << "  Global point: " << Intersect    1714            << "  Global point: " << IntersectPointGlobal << G4endl;
1715        edN << "  Calculated It      = " << fC    1715        edN << "  Calculated It      = " << fCalculatedExitNormal << G4endl
1716            << "  Volume: " << fHistory.GetTop    1716            << "  Volume: " << fHistory.GetTopVolume()->GetName() << G4endl;
1717 #ifdef G4VERBOSE                                 1717 #ifdef G4VERBOSE
1718        G4LogicalVolume* candLog = fHistory.Ge    1718        G4LogicalVolume* candLog = fHistory.GetTopVolume()->GetLogicalVolume();
1719        if ( candLog != nullptr )                 1719        if ( candLog != nullptr )
1720        {                                         1720        {
1721          edN << "  Solid: " << candLog->GetSo    1721          edN << "  Solid: " << candLog->GetSolid()->GetName()
1722              << ", Type: " << candLog->GetSol    1722              << ", Type: " << candLog->GetSolid()->GetEntityType() << G4endl
1723              << *candLog->GetSolid();            1723              << *candLog->GetSolid();
1724        }                                         1724        }
1725 #endif                                           1725 #endif
1726        G4Exception("G4Navigator::GetGlobalExi    1726        G4Exception("G4Navigator::GetGlobalExitNormal()",
1727                    "GeomNav0003",JustWarning,    1727                    "GeomNav0003",JustWarning, edN,
1728                    "Value obtained from new l    1728                    "Value obtained from new local *solid* is incorrect.");
1729        localNormal = localNormal.unit(); // S    1729        localNormal = localNormal.unit(); // Should we correct it ??
1730      }                                           1730      }
1731      globalNormal = fHistory.GetTopTransform(    1731      globalNormal = fHistory.GetTopTransform()
1732                    .InverseTransformAxis(loca    1732                    .InverseTransformAxis(localNormal);
1733   }                                              1733   }
1734                                                  1734 
1735 #ifdef G4DEBUG_NAVIGATION                        1735 #ifdef G4DEBUG_NAVIGATION
1736   if( usingStored )                              1736   if( usingStored )
1737   {                                              1737   {
1738     G4ThreeVector globalNormAgn;                 1738     G4ThreeVector globalNormAgn; 
1739                                                  1739 
1740     localNormal = GetLocalExitNormalAndCheck(    1740     localNormal = GetLocalExitNormalAndCheck(IntersectPointGlobal,&validNormal);
1741                                                  1741     
1742     globalNormAgn = fHistory.GetTopTransform(    1742     globalNormAgn = fHistory.GetTopTransform()
1743                    .InverseTransformAxis(loca    1743                    .InverseTransformAxis(localNormal);
1744                                                  1744     
1745     // Check the value computed against fExit    1745     // Check the value computed against fExitNormalGlobalFrame
1746     G4ThreeVector diffNorm = globalNormAgn -     1746     G4ThreeVector diffNorm = globalNormAgn - fExitNormalGlobalFrame;
1747     if( diffNorm.mag2() > kToleranceNormalChe    1747     if( diffNorm.mag2() > kToleranceNormalCheck )
1748     {                                            1748     {
1749       G4ExceptionDescription edDfn;              1749       G4ExceptionDescription edDfn;
1750       edDfn << "Found difference in normals i    1750       edDfn << "Found difference in normals in case of exiting mother "
1751             << "- when Get is called after Co    1751             << "- when Get is called after ComputingStep " << G4endl;
1752       edDfn << "  Magnitude of diff =      "     1752       edDfn << "  Magnitude of diff =      " << diffNorm.mag() << G4endl;
1753       edDfn << "  Normal stored (Global)         1753       edDfn << "  Normal stored (Global)     = " << fExitNormalGlobalFrame
1754             << G4endl;                           1754             << G4endl;
1755       edDfn << "  Global Computed from Local     1755       edDfn << "  Global Computed from Local = " << globalNormAgn << G4endl;
1756       G4Exception("G4Navigator::GetGlobalExit    1756       G4Exception("G4Navigator::GetGlobalExitNormal()", "GeomNav0003",
1757                   JustWarning, edDfn);           1757                   JustWarning, edDfn);
1758     }                                            1758     }
1759   }                                              1759   }
1760 #endif                                           1760 #endif
1761                                                  1761 
1762   // Synchronise stored global exit normal as    1762   // Synchronise stored global exit normal as possibly re-computed here
1763   //                                             1763   //
1764   fExitNormalGlobalFrame = globalNormal;         1764   fExitNormalGlobalFrame = globalNormal;
1765                                                  1765 
1766   return globalNormal;                           1766   return globalNormal;
1767 }                                                1767 }
1768                                                  1768 
1769 // ******************************************    1769 // ********************************************************************
1770 // ComputeSafety                                 1770 // ComputeSafety
1771 //                                               1771 //
1772 // It assumes that it will be                    1772 // It assumes that it will be 
1773 //  i) called at the Point in the same volume    1773 //  i) called at the Point in the same volume as the EndPoint of the
1774 //     ComputeStep.                              1774 //     ComputeStep.
1775 // ii) after (or at the end of) ComputeStep O    1775 // ii) after (or at the end of) ComputeStep OR after the relocation.
1776 // ******************************************    1776 // ********************************************************************
1777 //                                               1777 //
1778 G4double G4Navigator::ComputeSafety( const G4    1778 G4double G4Navigator::ComputeSafety( const G4ThreeVector& pGlobalpoint,
1779                                      const G4    1779                                      const G4double pMaxLength,
1780                                      const G4    1780                                      const G4bool )
1781 {                                                1781 {
1782   G4VPhysicalVolume  *motherPhysical = fHisto    1782   G4VPhysicalVolume  *motherPhysical = fHistory.GetTopVolume();
1783   G4double safety = 0.0;                         1783   G4double safety = 0.0;
1784                                                  1784 
1785   G4double distEndpointSq = (pGlobalpoint-fSt    1785   G4double distEndpointSq = (pGlobalpoint-fStepEndPoint).mag2(); 
1786   G4bool stayedOnEndpoint = distEndpointSq <     1786   G4bool stayedOnEndpoint = distEndpointSq < sqr(kCarTolerance); 
1787   G4bool endpointOnSurface = fEnteredDaughter    1787   G4bool endpointOnSurface = fEnteredDaughter || fExitedMother;
1788                                                  1788 
1789   G4bool onSurface = endpointOnSurface && sta    1789   G4bool onSurface = endpointOnSurface && stayedOnEndpoint;
1790   if( ! onSurface )                              1790   if( ! onSurface )
1791   {                                              1791   {
1792     safety= fpSafetyCalculator->SafetyInCurre    1792     safety= fpSafetyCalculator->SafetyInCurrentVolume(pGlobalpoint, motherPhysical, pMaxLength);
1793     // offload to G4SafetyCalculator - avoids    1793     // offload to G4SafetyCalculator - avoids need to save / reload state
1794                                                  1794 
1795     // Remember last safety origin & value       1795     // Remember last safety origin & value
1796     //                                           1796     //
1797     fPreviousSftOrigin = pGlobalpoint;           1797     fPreviousSftOrigin = pGlobalpoint;
1798     fPreviousSafety =    safety;                 1798     fPreviousSafety =    safety;
1799     // We overwrite the Safety 'sphere' - kee    1799     // We overwrite the Safety 'sphere' - keeping old behaviour
1800   }                                              1800   }
1801                                                  1801 
1802   return safety;                                 1802   return safety;
1803 }                                                1803 }
1804                                                  1804 
1805 // ******************************************    1805 // ********************************************************************
1806 // CreateTouchableHistoryHandle                  1806 // CreateTouchableHistoryHandle
1807 // ******************************************    1807 // ********************************************************************
1808 //                                               1808 //
1809 G4TouchableHandle G4Navigator::CreateTouchabl    1809 G4TouchableHandle G4Navigator::CreateTouchableHistoryHandle() const
1810 {                                                1810 {
1811   return G4TouchableHandle( CreateTouchableHi    1811   return G4TouchableHandle( CreateTouchableHistory() );
1812 }                                                1812 }
1813                                                  1813 
1814 // ******************************************    1814 // ********************************************************************
1815 // PrintState                                    1815 // PrintState
1816 // ******************************************    1816 // ********************************************************************
1817 //                                               1817 //
1818 void  G4Navigator::PrintState() const            1818 void  G4Navigator::PrintState() const
1819 {                                                1819 {
1820   G4long oldcoutPrec = G4cout.precision(4);      1820   G4long oldcoutPrec = G4cout.precision(4);
1821   if( fVerbose >= 4 )                            1821   if( fVerbose >= 4 )
1822   {                                              1822   {
1823     G4cout << "The current state of G4Navigat    1823     G4cout << "The current state of G4Navigator is: " << G4endl;
1824     G4cout << "  ValidExitNormal= " << fValid    1824     G4cout << "  ValidExitNormal= " << fValidExitNormal // << G4endl
1825            << "  ExitNormal     = " << fExitN    1825            << "  ExitNormal     = " << fExitNormal      // << G4endl
1826            << "  Exiting        = " << fExiti    1826            << "  Exiting        = " << fExiting         // << G4endl
1827            << "  Entering       = " << fEnter    1827            << "  Entering       = " << fEntering        // << G4endl
1828            << "  BlockedPhysicalVolume= " ;      1828            << "  BlockedPhysicalVolume= " ;
1829     if (fBlockedPhysicalVolume==nullptr)         1829     if (fBlockedPhysicalVolume==nullptr)
1830     {                                            1830     {
1831       G4cout << "None";                          1831       G4cout << "None";
1832     }                                            1832     }
1833     else                                         1833     else
1834     {                                            1834     {
1835       G4cout << fBlockedPhysicalVolume->GetNa    1835       G4cout << fBlockedPhysicalVolume->GetName();
1836     }                                            1836     }
1837     G4cout << G4endl                             1837     G4cout << G4endl
1838            << "  BlockedReplicaNo     = " <<     1838            << "  BlockedReplicaNo     = " <<  fBlockedReplicaNo   //  << G4endl
1839            << "  LastStepWasZero      = " <<     1839            << "  LastStepWasZero      = " <<  fLastStepWasZero    //  << G4endl
1840            << G4endl;                            1840            << G4endl;   
1841   }                                              1841   }
1842   if( ( 1 < fVerbose) && (fVerbose < 4) )        1842   if( ( 1 < fVerbose) && (fVerbose < 4) )
1843   {                                              1843   {
1844     G4cout << G4endl; // Make sure to line up    1844     G4cout << G4endl; // Make sure to line up
1845     G4cout << std::setw(30) << " ExitNormal "    1845     G4cout << std::setw(30) << " ExitNormal "  << " "
1846            << std::setw( 5) << " Valid "         1846            << std::setw( 5) << " Valid "       << " "     
1847            << std::setw( 9) << " Exiting "       1847            << std::setw( 9) << " Exiting "     << " "      
1848            << std::setw( 9) << " Entering"       1848            << std::setw( 9) << " Entering"     << " " 
1849            << std::setw(15) << " Blocked:Volu    1849            << std::setw(15) << " Blocked:Volume "  << " "   
1850            << std::setw( 9) << " ReplicaNo"      1850            << std::setw( 9) << " ReplicaNo"        << " "  
1851            << std::setw( 8) << " LastStepZero    1851            << std::setw( 8) << " LastStepZero  "   << " "   
1852            << G4endl;                            1852            << G4endl;   
1853     G4cout << "( " << std::setw(7) << fExitNo    1853     G4cout << "( " << std::setw(7) << fExitNormal.x() 
1854            << ", " << std::setw(7) << fExitNo    1854            << ", " << std::setw(7) << fExitNormal.y()
1855            << ", " << std::setw(7) << fExitNo    1855            << ", " << std::setw(7) << fExitNormal.z() << " ) "
1856            << std::setw( 5)  << fValidExitNor    1856            << std::setw( 5)  << fValidExitNormal  << " "   
1857            << std::setw( 9)  << fExiting         1857            << std::setw( 9)  << fExiting          << " "
1858            << std::setw( 9)  << fEntering        1858            << std::setw( 9)  << fEntering         << " ";
1859     if ( fBlockedPhysicalVolume == nullptr )     1859     if ( fBlockedPhysicalVolume == nullptr )
1860     { G4cout << std::setw(15) << "None"; }       1860     { G4cout << std::setw(15) << "None"; }
1861     else                                         1861     else
1862     { G4cout << std::setw(15)<< fBlockedPhysi    1862     { G4cout << std::setw(15)<< fBlockedPhysicalVolume->GetName(); }
1863     G4cout << std::setw( 9)  << fBlockedRepli    1863     G4cout << std::setw( 9)  << fBlockedReplicaNo  << " "
1864            << std::setw( 8)  << fLastStepWasZ    1864            << std::setw( 8)  << fLastStepWasZero   << " "
1865            << G4endl;                            1865            << G4endl;   
1866   }                                              1866   }
1867   if( fVerbose > 2 )                             1867   if( fVerbose > 2 ) 
1868   {                                              1868   {
1869     G4cout.precision(8);                         1869     G4cout.precision(8);
1870     G4cout << " Current Localpoint = " << fLa    1870     G4cout << " Current Localpoint = " << fLastLocatedPointLocal << G4endl;
1871     G4cout << " PreviousSftOrigin  = " << fPr    1871     G4cout << " PreviousSftOrigin  = " << fPreviousSftOrigin << G4endl;
1872     G4cout << " PreviousSafety     = " << fPr    1872     G4cout << " PreviousSafety     = " << fPreviousSafety << G4endl; 
1873   }                                              1873   }
1874   G4cout.precision(oldcoutPrec);                 1874   G4cout.precision(oldcoutPrec);
1875 }                                                1875 }
1876                                                  1876 
1877 // ******************************************    1877 // ********************************************************************
1878 // ComputeStepLog                                1878 // ComputeStepLog
1879 // ******************************************    1879 // ********************************************************************
1880 //                                               1880 //
1881 void G4Navigator::ComputeStepLog(const G4Thre    1881 void G4Navigator::ComputeStepLog(const G4ThreeVector& pGlobalpoint,
1882                                        G4doub    1882                                        G4double moveLenSq) const
1883 {                                                1883 {
1884   //  The following checks only make sense if    1884   //  The following checks only make sense if the move is larger
1885   //  than the tolerance.                        1885   //  than the tolerance.
1886                                                  1886 
1887   const G4double fAccuracyForWarning   = kCar    1887   const G4double fAccuracyForWarning   = kCarTolerance,
1888                  fAccuracyForException = 1000    1888                  fAccuracyForException = 1000*kCarTolerance;
1889                                                  1889 
1890   G4ThreeVector OriginalGlobalpoint = fHistor    1890   G4ThreeVector OriginalGlobalpoint = fHistory.GetTopTransform().
1891                                InverseTransfo    1891                                InverseTransformPoint(fLastLocatedPointLocal); 
1892                                                  1892 
1893   G4double shiftOriginSafSq = (fPreviousSftOr    1893   G4double shiftOriginSafSq = (fPreviousSftOrigin-pGlobalpoint).mag2();
1894                                                  1894 
1895   // Check that the starting point of this st    1895   // Check that the starting point of this step is 
1896   // within the isotropic safety sphere of th    1896   // within the isotropic safety sphere of the last point
1897   // to a accuracy/precision  given by fAccur    1897   // to a accuracy/precision  given by fAccuracyForWarning.
1898   //   If so give warning.                       1898   //   If so give warning.
1899   //   If it fails by more than fAccuracyForE    1899   //   If it fails by more than fAccuracyForException exit with error.
1900   //                                             1900   //
1901   if( shiftOriginSafSq >= sqr(fPreviousSafety    1901   if( shiftOriginSafSq >= sqr(fPreviousSafety) )
1902   {                                              1902   {
1903     G4double shiftOrigin = std::sqrt(shiftOri    1903     G4double shiftOrigin = std::sqrt(shiftOriginSafSq);
1904     G4double diffShiftSaf = shiftOrigin - fPr    1904     G4double diffShiftSaf = shiftOrigin - fPreviousSafety;
1905                                                  1905 
1906     if( diffShiftSaf > fAccuracyForWarning )     1906     if( diffShiftSaf > fAccuracyForWarning )
1907     {                                            1907     {
1908       G4long oldcoutPrec = G4cout.precision(8    1908       G4long oldcoutPrec = G4cout.precision(8);
1909       G4long oldcerrPrec = G4cerr.precision(1    1909       G4long oldcerrPrec = G4cerr.precision(10);
1910       std::ostringstream message, suggestion;    1910       std::ostringstream message, suggestion;
1911       message << "Accuracy error or slightly     1911       message << "Accuracy error or slightly inaccurate position shift."
1912               << G4endl                          1912               << G4endl
1913               << "     The Step's starting po    1913               << "     The Step's starting point has moved " 
1914               << std::sqrt(moveLenSq)/mm << "    1914               << std::sqrt(moveLenSq)/mm << " mm " << G4endl
1915               << "     since the last call to    1915               << "     since the last call to a Locate method." << G4endl
1916               << "     This has resulted in m    1916               << "     This has resulted in moving " 
1917               << shiftOrigin/mm << " mm "        1917               << shiftOrigin/mm << " mm " 
1918               << " from the last point at whi    1918               << " from the last point at which the safety " 
1919               << "     was calculated " << G4    1919               << "     was calculated " << G4endl
1920               << "     which is more than the    1920               << "     which is more than the computed safety= " 
1921               << fPreviousSafety/mm << " mm      1921               << fPreviousSafety/mm << " mm  at that point." << G4endl
1922               << "     This difference is "      1922               << "     This difference is " 
1923               << diffShiftSaf/mm << " mm." <<    1923               << diffShiftSaf/mm << " mm." << G4endl
1924               << "     The tolerated accuracy    1924               << "     The tolerated accuracy is "
1925               << fAccuracyForException/mm <<     1925               << fAccuracyForException/mm << " mm.";
1926                                                  1926 
1927       suggestion << " ";                         1927       suggestion << " ";
1928       static G4ThreadLocal G4int warnNow = 0;    1928       static G4ThreadLocal G4int warnNow = 0;
1929       if( ((++warnNow % 100) == 1) )             1929       if( ((++warnNow % 100) == 1) )
1930       {                                          1930       {
1931         message << G4endl                        1931         message << G4endl
1932                << "  This problem can be due     1932                << "  This problem can be due to either " << G4endl
1933                << "    - a process that has p    1933                << "    - a process that has proposed a displacement"
1934                << " larger than the current s    1934                << " larger than the current safety , or" << G4endl
1935                << "    - inaccuracy in the co    1935                << "    - inaccuracy in the computation of the safety";
1936         suggestion << "We suggest that you "     1936         suggestion << "We suggest that you " << G4endl
1937                    << "   - find i) what part    1937                    << "   - find i) what particle is being tracked, and "
1938                    << " ii) through what part    1938                    << " ii) through what part of your geometry " << G4endl
1939                    << "      for example by r    1939                    << "      for example by re-running this event with "
1940                    << G4endl                     1940                    << G4endl
1941                    << "         /tracking/ver    1941                    << "         /tracking/verbose 1 "  << G4endl
1942                    << "    - check which proc    1942                    << "    - check which processes you declare for"
1943                    << " this particle (and lo    1943                    << " this particle (and look at non-standard ones)"
1944                    << G4endl                     1944                    << G4endl
1945                    << "   - in case, create a    1945                    << "   - in case, create a detailed logfile"
1946                    << " of this event using:"    1946                    << " of this event using:" << G4endl
1947                    << "         /tracking/ver    1947                    << "         /tracking/verbose 6 ";
1948       }                                          1948       }
1949       G4Exception("G4Navigator::ComputeStep()    1949       G4Exception("G4Navigator::ComputeStep()",
1950                   "GeomNav1002", JustWarning,    1950                   "GeomNav1002", JustWarning,
1951                   message, G4String(suggestio    1951                   message, G4String(suggestion.str()));
1952       G4cout.precision(oldcoutPrec);             1952       G4cout.precision(oldcoutPrec);
1953       G4cerr.precision(oldcerrPrec);             1953       G4cerr.precision(oldcerrPrec);
1954     }                                            1954     }
1955 #ifdef G4DEBUG_NAVIGATION                        1955 #ifdef G4DEBUG_NAVIGATION
1956     else                                         1956     else
1957     {                                            1957     {
1958       G4cerr << "WARNING - G4Navigator::Compu    1958       G4cerr << "WARNING - G4Navigator::ComputeStep()" << G4endl
1959              << "          The Step's startin    1959              << "          The Step's starting point has moved "
1960              << std::sqrt(moveLenSq) << "," <    1960              << std::sqrt(moveLenSq) << "," << G4endl
1961              << "          which has taken it    1961              << "          which has taken it to the limit of"
1962              << " the current safety. " << G4    1962              << " the current safety. " << G4endl;
1963     }                                            1963     }
1964 #endif                                           1964 #endif
1965   }                                              1965   }
1966   G4double safetyPlus = fPreviousSafety + fAc    1966   G4double safetyPlus = fPreviousSafety + fAccuracyForException;
1967   if ( shiftOriginSafSq > sqr(safetyPlus) )      1967   if ( shiftOriginSafSq > sqr(safetyPlus) )
1968   {                                              1968   {
1969     std::ostringstream message;                  1969     std::ostringstream message;
1970     message << "May lead to a crash or unreli    1970     message << "May lead to a crash or unreliable results." << G4endl
1971             << "        Position has shifted     1971             << "        Position has shifted considerably without"
1972             << " notifying the navigator !" <    1972             << " notifying the navigator !" << G4endl
1973             << "        Tolerated safety: " <    1973             << "        Tolerated safety: " << safetyPlus << G4endl
1974             << "        Computed shift  : " <    1974             << "        Computed shift  : " << shiftOriginSafSq;
1975     G4Exception("G4Navigator::ComputeStep()",    1975     G4Exception("G4Navigator::ComputeStep()", "GeomNav1002",
1976                 JustWarning, message);           1976                 JustWarning, message);
1977   }                                              1977   }
1978 }                                                1978 }
1979                                                  1979 
1980 // ******************************************    1980 // ********************************************************************
1981 // CheckOverlapsIterative                        1981 // CheckOverlapsIterative
1982 // ******************************************    1982 // ********************************************************************
1983 //                                               1983 //
1984 G4bool G4Navigator::CheckOverlapsIterative(G4    1984 G4bool G4Navigator::CheckOverlapsIterative(G4VPhysicalVolume* vol)
1985 {                                                1985 {
1986   // Check and report overlaps                   1986   // Check and report overlaps
1987   //                                             1987   //
1988   G4bool foundOverlap = false;                   1988   G4bool foundOverlap = false;
1989   G4int  nPoints = 300000,  ntrials = 9, numO    1989   G4int  nPoints = 300000,  ntrials = 9, numOverlaps = 5;
1990   G4double  trialLength = 1.0 * CLHEP::centim    1990   G4double  trialLength = 1.0 * CLHEP::centimeter;
1991   while ( ntrials-- > 0 && !foundOverlap )       1991   while ( ntrials-- > 0 && !foundOverlap )
1992   {                                              1992   {
1993     if ( fVerbose > 1 )                          1993     if ( fVerbose > 1 )
1994     {                                            1994     {
1995        G4cout << " ** Running overlap checks     1995        G4cout << " ** Running overlap checks in volume "
1996               <<  vol->GetName()                 1996               <<  vol->GetName()
1997               << " with length = " << trialLe    1997               << " with length = " << trialLength << G4endl;
1998     }                                            1998     }
1999     foundOverlap = vol->CheckOverlaps(nPoints    1999     foundOverlap = vol->CheckOverlaps(nPoints, trialLength,
2000                                       fVerbos    2000                                       fVerbose != 0, numOverlaps);
2001     trialLength *= 0.1;                          2001     trialLength *= 0.1;
2002     if ( trialLength <= 1.0e-5 ) { numOverlap    2002     if ( trialLength <= 1.0e-5 ) { numOverlaps= 1;}
2003   }                                              2003   }
2004   return foundOverlap;                           2004   return foundOverlap;
2005 }                                                2005 }
2006                                                  2006 
2007 // ******************************************    2007 // ********************************************************************
2008 // Operator <<                                   2008 // Operator <<
2009 // ******************************************    2009 // ********************************************************************
2010 //                                               2010 //
2011 std::ostream& operator << (std::ostream &os,c    2011 std::ostream& operator << (std::ostream &os,const G4Navigator &n)
2012 {                                                2012 {
2013   //  Old version did only the following:        2013   //  Old version did only the following:
2014   // os << "Current History: " << G4endl << n    2014   // os << "Current History: " << G4endl << n.fHistory;
2015   //  Old behaviour is recovered for fVerbose    2015   //  Old behaviour is recovered for fVerbose = 0
2016                                                  2016   
2017   // Adapted from G4Navigator::PrintState() c    2017   // Adapted from G4Navigator::PrintState() const
2018                                                  2018 
2019   G4long oldcoutPrec = os.precision(4);          2019   G4long oldcoutPrec = os.precision(4);
2020   if( n.fVerbose >= 4 )                          2020   if( n.fVerbose >= 4 )
2021   {                                              2021   {
2022     os << "The current state of G4Navigator i    2022     os << "The current state of G4Navigator is: " << G4endl;
2023     os << "  ValidExitNormal= " << n.fValidEx    2023     os << "  ValidExitNormal= " << n.fValidExitNormal << G4endl
2024     << "  ExitNormal     = " << n.fExitNormal    2024     << "  ExitNormal     = " << n.fExitNormal      << G4endl
2025     << "  Exiting        = " << n.fExiting       2025     << "  Exiting        = " << n.fExiting         << G4endl
2026     << "  Entering       = " << n.fEntering      2026     << "  Entering       = " << n.fEntering        << G4endl
2027     << "  BlockedPhysicalVolume= " ;             2027     << "  BlockedPhysicalVolume= " ;
2028     if (n.fBlockedPhysicalVolume==nullptr)       2028     if (n.fBlockedPhysicalVolume==nullptr)
2029     {                                            2029     {
2030       os << "None";                              2030       os << "None";
2031     }                                            2031     }
2032     else                                         2032     else
2033     {                                            2033     {
2034       os << n.fBlockedPhysicalVolume->GetName    2034       os << n.fBlockedPhysicalVolume->GetName();
2035     }                                            2035     }
2036     os << G4endl                                 2036     os << G4endl
2037     << "  BlockedReplicaNo     = " <<  n.fBlo    2037     << "  BlockedReplicaNo     = " <<  n.fBlockedReplicaNo       << G4endl
2038     << "  LastStepWasZero      = " <<   n.fLa    2038     << "  LastStepWasZero      = " <<   n.fLastStepWasZero       << G4endl
2039     << G4endl;                                   2039     << G4endl;
2040   }                                              2040   }
2041   if( ( 1 < n.fVerbose) && (n.fVerbose < 4) )    2041   if( ( 1 < n.fVerbose) && (n.fVerbose < 4) )
2042   {                                              2042   {
2043     os << G4endl; // Make sure to line up        2043     os << G4endl; // Make sure to line up
2044     os << std::setw(30) << " ExitNormal "  <<    2044     os << std::setw(30) << " ExitNormal "  << " "
2045     << std::setw( 5) << " Valid "       << "     2045     << std::setw( 5) << " Valid "       << " "
2046     << std::setw( 9) << " Exiting "     << "     2046     << std::setw( 9) << " Exiting "     << " "
2047     << std::setw( 9) << " Entering"     << "     2047     << std::setw( 9) << " Entering"     << " "
2048     << std::setw(15) << " Blocked:Volume "  <    2048     << std::setw(15) << " Blocked:Volume "  << " "
2049     << std::setw( 9) << " ReplicaNo"        <    2049     << std::setw( 9) << " ReplicaNo"        << " "
2050     << std::setw( 8) << " LastStepZero  "   <    2050     << std::setw( 8) << " LastStepZero  "   << " "
2051     << G4endl;                                   2051     << G4endl;
2052     os << "( " << std::setw(7) << n.fExitNorm    2052     os << "( " << std::setw(7) << n.fExitNormal.x()
2053     << ", " << std::setw(7) << n.fExitNormal.    2053     << ", " << std::setw(7) << n.fExitNormal.y()
2054     << ", " << std::setw(7) << n.fExitNormal.    2054     << ", " << std::setw(7) << n.fExitNormal.z() << " ) "
2055     << std::setw( 5)  << n.fValidExitNormal      2055     << std::setw( 5)  << n.fValidExitNormal  << " "
2056     << std::setw( 9)  << n.fExiting              2056     << std::setw( 9)  << n.fExiting          << " "
2057     << std::setw( 9)  << n.fEntering             2057     << std::setw( 9)  << n.fEntering         << " ";
2058     if ( n.fBlockedPhysicalVolume==nullptr )     2058     if ( n.fBlockedPhysicalVolume==nullptr )
2059       { os << std::setw(15) << "None"; }         2059       { os << std::setw(15) << "None"; }
2060     else                                         2060     else
2061       { os << std::setw(15)<< n.fBlockedPhysi    2061       { os << std::setw(15)<< n.fBlockedPhysicalVolume->GetName(); }
2062     os << std::setw( 9)  << n.fBlockedReplica    2062     os << std::setw( 9)  << n.fBlockedReplicaNo  << " "
2063     << std::setw( 8)  << n.fLastStepWasZero      2063     << std::setw( 8)  << n.fLastStepWasZero   << " "
2064     << G4endl;                                   2064     << G4endl;
2065   }                                              2065   }
2066   if( n.fVerbose > 2 )                           2066   if( n.fVerbose > 2 )
2067   {                                              2067   {
2068     os.precision(8);                             2068     os.precision(8);
2069     os << " Current Localpoint = " << n.fLast    2069     os << " Current Localpoint = " << n.fLastLocatedPointLocal << G4endl;
2070     os << " PreviousSftOrigin  = " << n.fPrev    2070     os << " PreviousSftOrigin  = " << n.fPreviousSftOrigin << G4endl;
2071     os << " PreviousSafety     = " << n.fPrev    2071     os << " PreviousSafety     = " << n.fPreviousSafety << G4endl;
2072   }                                              2072   }
2073   if( n.fVerbose > 3 || n.fVerbose == 0 )        2073   if( n.fVerbose > 3 || n.fVerbose == 0 )
2074   {                                              2074   {
2075     os << "Current History: " << G4endl << n.    2075     os << "Current History: " << G4endl << n.fHistory;
2076   }                                              2076   }
2077                                                  2077     
2078   os.precision(oldcoutPrec);                     2078   os.precision(oldcoutPrec);
2079   return os;                                     2079   return os;
2080 }                                                2080 }
2081                                                  2081 
2082 // ******************************************    2082 // ********************************************************************
2083 // SetVoxelNavigation: alternative navigator     2083 // SetVoxelNavigation: alternative navigator for voxelised geometry
2084 // ******************************************    2084 // ********************************************************************
2085 //                                               2085 //
2086 void G4Navigator::SetVoxelNavigation(G4VoxelN    2086 void G4Navigator::SetVoxelNavigation(G4VoxelNavigation* voxelNav)
2087 {                                                2087 {
2088   delete fpvoxelNav;                             2088   delete fpvoxelNav;
2089   fpvoxelNav = voxelNav;                         2089   fpvoxelNav = voxelNav;
2090 }                                                2090 }
2091                                                  2091 
2092 // ******************************************    2092 // ********************************************************************
2093 // InformLastStep: derived navigators can inf    2093 // InformLastStep: derived navigators can inform of its step
2094 //                 used to update fLastStepWa    2094 //                 used to update fLastStepWasZero
2095 // ******************************************    2095 // ********************************************************************
2096 void  G4Navigator::InformLastStep(G4double la    2096 void  G4Navigator::InformLastStep(G4double lastStep, G4bool entersDaughtVol,
2097                                   G4bool exit    2097                                   G4bool exitsMotherVol)
2098 {                                                2098 {
2099   G4bool zeroStep = ( lastStep == 0.0 );         2099   G4bool zeroStep = ( lastStep == 0.0 );
2100   fLocatedOnEdge   = fLastStepWasZero && zero    2100   fLocatedOnEdge   = fLastStepWasZero && zeroStep;  
2101   fLastStepWasZero = zeroStep;                   2101   fLastStepWasZero = zeroStep;
2102                                                  2102 
2103   fExiting = exitsMotherVol;                     2103   fExiting = exitsMotherVol;
2104   fEntering = entersDaughtVol;                   2104   fEntering = entersDaughtVol;
2105 }                                                2105 }
2106                                                  2106 
2107 // ******************************************    2107 // ********************************************************************
2108 // SetExternalNavigation                         2108 // SetExternalNavigation
2109 // ******************************************    2109 // ********************************************************************
2110 //                                               2110 //
2111 void G4Navigator::SetExternalNavigation(G4VEx    2111 void G4Navigator::SetExternalNavigation(G4VExternalNavigation* externalNav)
2112 {                                                2112 {
2113   fpExternalNav = externalNav;                   2113   fpExternalNav = externalNav;
2114   fpSafetyCalculator->SetExternalNavigation(e    2114   fpSafetyCalculator->SetExternalNavigation(externalNav);
2115 }                                                2115 }
2116                                                  2116