Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/navigation/src/G4MultiLevelLocator.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/G4MultiLevelLocator.cc (Version 11.3.0) and /geometry/navigation/src/G4MultiLevelLocator.cc (Version 11.1.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 // Class G4MultiLevelLocator implementation        26 // Class G4MultiLevelLocator implementation
 27 //                                                 27 //
 28 // 27.10.08 - Tatiana Nikitina.                    28 // 27.10.08 - Tatiana Nikitina.
 29 // 04.10.11 - John Apostolakis, revised conver     29 // 04.10.11 - John Apostolakis, revised convergence to use Surface Normal
 30 // -------------------------------------------     30 // ---------------------------------------------------------------------------
 31                                                    31 
 32 #include <iomanip>                                 32 #include <iomanip>
 33                                                    33 
 34 #include "G4ios.hh"                                34 #include "G4ios.hh"
 35 #include "G4MultiLevelLocator.hh"                  35 #include "G4MultiLevelLocator.hh"
 36 #include "G4LocatorChangeRecord.hh"                36 #include "G4LocatorChangeRecord.hh"
 37 #include "G4LocatorChangeLogger.hh"                37 #include "G4LocatorChangeLogger.hh"
 38                                                    38 
 39 G4MultiLevelLocator::G4MultiLevelLocator(G4Nav     39 G4MultiLevelLocator::G4MultiLevelLocator(G4Navigator *theNavigator)
 40   : G4VIntersectionLocator(theNavigator)           40   : G4VIntersectionLocator(theNavigator)
 41 {                                                  41 {
 42   // In case of too slow progress in finding I     42   // In case of too slow progress in finding Intersection Point
 43   // intermediates Points on the Track must be     43   // intermediates Points on the Track must be stored.
 44   // Initialise the array of Pointers [max_dep     44   // Initialise the array of Pointers [max_depth+1] to do this  
 45                                                    45   
 46   G4ThreeVector zeroV(0.0,0.0,0.0);                46   G4ThreeVector zeroV(0.0,0.0,0.0);
 47   for (auto & idepth : ptrInterMedFT)          <<  47   for ( auto idepth=0; idepth<max_depth+1; ++idepth )
 48   {                                                48   {
 49     idepth = new G4FieldTrack( zeroV, zeroV, 0 <<  49     ptrInterMedFT[ idepth ] = new G4FieldTrack( zeroV, zeroV, 0., 0., 0., 0.);
 50   }                                                50   }
 51                                                    51 
 52   if (fCheckMode)                                  52   if (fCheckMode)
 53   {                                                53   {
 54     //  Trial values       Loose         Mediu     54     //  Trial values       Loose         Medium      Tight
 55     //  To happen:         Infrequent    Occas     55     //  To happen:         Infrequent    Occasional  Often
 56     SetMaxSteps(150);   //  300             85     56     SetMaxSteps(150);   //  300             85          25
 57     SetWarnSteps(80);   //  250             60     57     SetWarnSteps(80);   //  250             60          15
 58   }                                                58   }  
 59 }                                                  59 }      
 60                                                    60 
 61 G4MultiLevelLocator::~G4MultiLevelLocator()        61 G4MultiLevelLocator::~G4MultiLevelLocator()
 62 {                                                  62 {
 63   for (auto & idepth : ptrInterMedFT)          <<  63   for ( auto idepth=0; idepth<max_depth+1; ++idepth )
 64   {                                                64   {
 65     delete idepth;                             <<  65     delete ptrInterMedFT[idepth];
 66   }                                                66   }
 67 #ifdef G4DEBUG_FIELD                               67 #ifdef G4DEBUG_FIELD
 68   ReportStatistics();                              68   ReportStatistics(); 
 69 #endif                                             69 #endif  
 70 }                                                  70 }
 71                                                    71 
 72                                                    72 
 73 // -------------------------------------------     73 // --------------------------------------------------------------------------
 74 // G4bool G4PropagatorInField::LocateIntersect     74 // G4bool G4PropagatorInField::LocateIntersectionPoint( 
 75 //        const G4FieldTrack&       CurveStart     75 //        const G4FieldTrack&       CurveStartPointVelocity,   // A
 76 //        const G4FieldTrack&       CurveEndPo     76 //        const G4FieldTrack&       CurveEndPointVelocity,     // B
 77 //        const G4ThreeVector&      TrialPoint     77 //        const G4ThreeVector&      TrialPoint,                // E
 78 //              G4FieldTrack&       Intersecte     78 //              G4FieldTrack&       IntersectedOrRecalculated  // Output
 79 //              G4bool&             recalculat     79 //              G4bool&             recalculated )             // Out
 80 // -------------------------------------------     80 // --------------------------------------------------------------------------
 81 //                                                 81 //
 82 // Function that returns the intersection of t     82 // Function that returns the intersection of the true path with the surface
 83 // of the current volume (either the external      83 // of the current volume (either the external one or the inner one with one
 84 // of the daughters:                               84 // of the daughters:
 85 //                                                 85 //
 86 //     A = Initial point                           86 //     A = Initial point
 87 //     B = another point                           87 //     B = another point 
 88 //                                                 88 //
 89 // Both A and B are assumed to be on the true      89 // Both A and B are assumed to be on the true path:
 90 //                                                 90 //
 91 //     E is the first point of intersection of     91 //     E is the first point of intersection of the chord AB with 
 92 //     a volume other than A  (on the surface      92 //     a volume other than A  (on the surface of A or of a daughter)
 93 //                                                 93 //
 94 // Convention of Use :                             94 // Convention of Use :
 95 //     i) If it returns "true", then Intersect     95 //     i) If it returns "true", then IntersectionPointVelocity is set
 96 //       to the approximate intersection point     96 //       to the approximate intersection point.
 97 //    ii) If it returns "false", no intersecti     97 //    ii) If it returns "false", no intersection was found.
 98 //        Potential reasons:                       98 //        Potential reasons:
 99 //        a) no segment found an intersection      99 //        a) no segment found an intersection
100 //        b) too many steps were required - af    100 //        b) too many steps were required - after that it abandoned the effort
101 //           and is returning how far it could    101 //           and is returning how far it could go.  (New - 29 Oct 2015)
102 //           (If so, it must set 'recalculated    102 //           (If so, it must set 'recalculated' to true.) 
103 //        TODO/idea: add a new flag: 'unfinish    103 //        TODO/idea: add a new flag: 'unfinished' to identify these cases.
104 //                                                104 //
105 //        IntersectedOrRecalculated means diff    105 //        IntersectedOrRecalculated means different things:
106 //        a) if it is the same curve lenght al    106 //        a) if it is the same curve lenght along, it is a revision of the
107 //            original enpdoint due to the nee    107 //            original enpdoint due to the need for re-integration.
108 //        b) if it is at a shorter curve lengt    108 //        b) if it is at a shorter curve length, it is 'end of what it could do'
109 //           i.e. as far as it could go, becau    109 //           i.e. as far as it could go, because it took too many steps!
110 //        Note: IntersectedOrRecalculated is v    110 //        Note: IntersectedOrRecalculated is valid only if 'recalculated' is
111 //       'true'.                                  111 //       'true'.
112 // -------------------------------------------    112 // --------------------------------------------------------------------------
113 // NOTE: implementation taken from G4Propagato    113 // NOTE: implementation taken from G4PropagatorInField
114 //                                                114 //
115 G4bool G4MultiLevelLocator::EstimateIntersecti    115 G4bool G4MultiLevelLocator::EstimateIntersectionPoint( 
116          const  G4FieldTrack&       CurveStart    116          const  G4FieldTrack&       CurveStartPointVelocity,       // A
117          const  G4FieldTrack&       CurveEndPo    117          const  G4FieldTrack&       CurveEndPointVelocity,         // B
118          const  G4ThreeVector&      TrialPoint    118          const  G4ThreeVector&      TrialPoint,                    // E
119                 G4FieldTrack&       Intersecte    119                 G4FieldTrack&       IntersectedOrRecalculatedFT,   // Output
120                 G4bool&             recalculat    120                 G4bool&             recalculatedEndPoint,          // Out
121                 G4double&           previousSa    121                 G4double&           previousSafety,                // In/Out
122                 G4ThreeVector&      previousSf    122                 G4ThreeVector&      previousSftOrigin)             // In/Out
123 {                                                 123 {
124   // Find Intersection Point ( A, B, E )  of t    124   // Find Intersection Point ( A, B, E )  of true path AB - start at E.
125   const char* MethodName= "G4MultiLevelLocator    125   const char* MethodName= "G4MultiLevelLocator::EstimateIntersectionPoint()";
126                                                   126   
127   G4bool found_approximate_intersection = fals    127   G4bool found_approximate_intersection = false;
128   G4bool there_is_no_intersection       = fals    128   G4bool there_is_no_intersection       = false;
129                                                   129 
130   G4FieldTrack  CurrentA_PointVelocity = Curve    130   G4FieldTrack  CurrentA_PointVelocity = CurveStartPointVelocity; 
131   G4FieldTrack  CurrentB_PointVelocity = Curve    131   G4FieldTrack  CurrentB_PointVelocity = CurveEndPointVelocity;
132   G4ThreeVector CurrentE_Point = TrialPoint;      132   G4ThreeVector CurrentE_Point = TrialPoint;
133   G4bool        validNormalAtE = false;           133   G4bool        validNormalAtE = false;
134   G4ThreeVector NormalAtEntry;                    134   G4ThreeVector NormalAtEntry;
135                                                   135 
136   G4FieldTrack  ApproxIntersecPointV(CurveEndP    136   G4FieldTrack  ApproxIntersecPointV(CurveEndPointVelocity); // FT-Def-Construct
137   G4bool        validIntersectP= true;   // Is    137   G4bool        validIntersectP= true;   // Is it current ?
138   G4double      NewSafety = 0.0;                  138   G4double      NewSafety = 0.0;
139   G4bool        last_AF_intersection = false;     139   G4bool        last_AF_intersection = false;   
140                                                   140 
141   auto    integrDriver = GetChordFinderFor()->    141   auto    integrDriver = GetChordFinderFor()->GetIntegrationDriver();
142   G4bool  driverReIntegrates = integrDriver->D    142   G4bool  driverReIntegrates = integrDriver->DoesReIntegrate();
143                                                   143   
144   G4bool first_section = true;                    144   G4bool first_section = true;
145   recalculatedEndPoint = false;                   145   recalculatedEndPoint = false; 
146   G4bool restoredFullEndpoint = false;            146   G4bool restoredFullEndpoint = false;
147                                                   147 
148   unsigned int substep_no = 0;                    148   unsigned int substep_no = 0;
149                                                   149 
150   // Statistics for substeps                      150   // Statistics for substeps
151   static G4ThreadLocal unsigned int max_no_see    151   static G4ThreadLocal unsigned int max_no_seen= 0;
152                                                   152 
153 #ifdef G4DEBUG_FIELD                              153 #ifdef G4DEBUG_FIELD
154   unsigned int trigger_substepno_print = 0;       154   unsigned int trigger_substepno_print = 0;
155   const G4double tolerance = 1.0e-8 * CLHEP::m    155   const G4double tolerance = 1.0e-8 * CLHEP::mm;
156   unsigned int biggest_depth = 0;                 156   unsigned int biggest_depth = 0;
157     // using kInitialisingCL = G4LocatorChange    157     // using kInitialisingCL = G4LocatorChangeRecord::kInitialisingCL;
158 #endif                                            158 #endif
159                                                   159 
160   // Log the location, iteration of changes in    160   // Log the location, iteration of changes in A,B 
161   //------------------------------------------    161   //----------------------------------------------
162   static G4ThreadLocal G4LocatorChangeLogger e    162   static G4ThreadLocal G4LocatorChangeLogger endChangeA("StartPointA"),
163     endChangeB("EndPointB"), recApproxPoint("A    163     endChangeB("EndPointB"), recApproxPoint("ApproxPoint"),
164     pointH_logger("Trial points 'E': position,    164     pointH_logger("Trial points 'E': position, normal");
165   unsigned int eventCount = 0;                    165   unsigned int eventCount = 0;
166                                                   166 
167   if (fCheckMode)                                 167   if (fCheckMode)
168   {                                               168   {
169     // Clear previous call's data                 169     // Clear previous call's data
170     endChangeA.clear();                           170     endChangeA.clear();
171     endChangeB.clear();                           171     endChangeB.clear();
172     recApproxPoint.clear();                       172     recApproxPoint.clear();
173     pointH_logger.clear();                        173     pointH_logger.clear();
174                                                   174 
175     // Record the initialisation                  175     // Record the initialisation
176     ++eventCount;                                 176     ++eventCount;
177     endChangeA.AddRecord( G4LocatorChangeRecor    177     endChangeA.AddRecord( G4LocatorChangeRecord::kInitialisingCL, substep_no,
178                           eventCount, CurrentA    178                           eventCount, CurrentA_PointVelocity );
179     endChangeB.AddRecord( G4LocatorChangeRecor    179     endChangeB.AddRecord( G4LocatorChangeRecord::kInitialisingCL, substep_no,
180                           eventCount, CurrentB    180                           eventCount, CurrentB_PointVelocity );
181   }                                               181   }
182                                                   182 
183   //------------------------------------------    183   //--------------------------------------------------------------------------  
184   //  Algorithm for the case if progress in fo    184   //  Algorithm for the case if progress in founding intersection is too slow.
185   //  Process is defined too slow if after N=p    185   //  Process is defined too slow if after N=param_substeps advances on the
186   //  path, it will be only 'fraction_done' of    186   //  path, it will be only 'fraction_done' of the total length.
187   //  In this case the remaining length is div    187   //  In this case the remaining length is divided in two half and 
188   //  the loop is restarted for each half.        188   //  the loop is restarted for each half.  
189   //  If progress is still too slow, the divis    189   //  If progress is still too slow, the division in two halfs continue
190   //  until 'max_depth'.                          190   //  until 'max_depth'.
191   //------------------------------------------    191   //--------------------------------------------------------------------------
192                                                   192 
193   const G4int param_substeps = 5;  // Test val    193   const G4int param_substeps = 5;  // Test value for the maximum number
194                                    // of subst    194                                    // of substeps
195   const G4double fraction_done = 0.3;             195   const G4double fraction_done = 0.3;
196                                                   196 
197   G4bool Second_half = false;    // First half    197   G4bool Second_half = false;    // First half or second half of divided step
198                                                   198 
199   // We need to know this for the 'final_secti    199   // We need to know this for the 'final_section':
200   // real 'final_section' or first half 'final    200   // real 'final_section' or first half 'final_section'
201   // In algorithm it is considered that the 'S    201   // In algorithm it is considered that the 'Second_half' is true
202   // and it becomes false only if we are in th    202   // and it becomes false only if we are in the first-half of level
203   // depthness or if we are in the first secti    203   // depthness or if we are in the first section
204                                                   204 
205   unsigned int depth = 0; // Depth counts subd    205   unsigned int depth = 0; // Depth counts subdivisions of initial step made
206   ++fNumCalls;                                    206   ++fNumCalls;
207                                                   207   
208   NormalAtEntry = GetSurfaceNormal(CurrentE_Po    208   NormalAtEntry = GetSurfaceNormal(CurrentE_Point, validNormalAtE);
209                                                   209 
210   if (fCheckMode)                                 210   if (fCheckMode)
211   {                                               211   {
212     pointH_logger.AddRecord( G4LocatorChangeRe    212     pointH_logger.AddRecord( G4LocatorChangeRecord::kInitialisingCL,
213                              substep_no, event    213                              substep_no, eventCount,
214                              G4FieldTrack( Cur    214                              G4FieldTrack( CurrentE_Point,0.,NormalAtEntry,0.,
215                                            0.,    215                                            0., 1.,G4ThreeVector(0.),0.,0.) );
216   #if (G4DEBUG_FIELD>1)                           216   #if (G4DEBUG_FIELD>1) 
217     G4ThreeVector  StartPosition = CurveStartP    217     G4ThreeVector  StartPosition = CurveStartPointVelocity.GetPosition(); 
218     if( (TrialPoint - StartPosition).mag2() <     218     if( (TrialPoint - StartPosition).mag2() < sqr(tolerance)) 
219     {                                             219     {
220        ReportImmediateHit( MethodName, StartPo    220        ReportImmediateHit( MethodName, StartPosition, TrialPoint,
221                            tolerance, fNumCall    221                            tolerance, fNumCalls); 
222     }                                             222     }
223   #endif                                          223   #endif
224   }                                               224   }
225                                                   225 
226   // Intermediates Points on the Track = Subdi    226   // Intermediates Points on the Track = Subdivided Points must be stored.
227   // Give the initial values to 'InterMedFt'      227   // Give the initial values to 'InterMedFt'
228   // Important is 'ptrInterMedFT[0]', it saves    228   // Important is 'ptrInterMedFT[0]', it saves the 'EndCurvePoint'
229   //                                              229   //
230   *ptrInterMedFT[0] = CurveEndPointVelocity;      230   *ptrInterMedFT[0] = CurveEndPointVelocity;
231   for ( auto idepth=1; idepth<max_depth+1; ++i    231   for ( auto idepth=1; idepth<max_depth+1; ++idepth )
232   {                                               232   {
233     *ptrInterMedFT[idepth] = CurveStartPointVe    233     *ptrInterMedFT[idepth] = CurveStartPointVelocity;
234   }                                               234   }
235                                                   235 
236   // Final_section boolean store                  236   // Final_section boolean store
237   //                                              237   //
238   G4bool fin_section_depth[max_depth];            238   G4bool fin_section_depth[max_depth];
239   for (bool & idepth : fin_section_depth)      << 239   for ( auto idepth=0; idepth<max_depth; ++idepth )
240   {                                               240   {
241     idepth = true;                             << 241     fin_section_depth[idepth] = true;
242   }                                               242   }
243   // 'SubStartPoint' is needed to calculate th    243   // 'SubStartPoint' is needed to calculate the length of the divided step
244   //                                              244   //
245   G4FieldTrack SubStart_PointVelocity = CurveS    245   G4FieldTrack SubStart_PointVelocity = CurveStartPointVelocity;
246                                                   246    
247   do  // Loop checking, 07.10.2016, J.Apostola    247   do  // Loop checking, 07.10.2016, J.Apostolakis
248   {                                               248   {
249     unsigned int substep_no_p = 0;                249     unsigned int substep_no_p = 0;
250     G4bool sub_final_section = false; // the s    250     G4bool sub_final_section = false; // the same as final_section,
251                                       // but f    251                                       // but for 'sub_section'
252     SubStart_PointVelocity = CurrentA_PointVel    252     SubStart_PointVelocity = CurrentA_PointVelocity;
253                                                   253  
254     do // Loop checking, 07.10.2016, J.Apostol    254     do // Loop checking, 07.10.2016, J.Apostolakis
255     { // REPEAT param                             255     { // REPEAT param
256       G4ThreeVector Point_A = CurrentA_PointVe    256       G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();  
257       G4ThreeVector Point_B = CurrentB_PointVe    257       G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
258                                                   258        
259 #ifdef G4DEBUG_FIELD                              259 #ifdef G4DEBUG_FIELD
260       const G4double lenA = CurrentA_PointVelo    260       const G4double lenA = CurrentA_PointVelocity.GetCurveLength() ;
261       const G4double lenB = CurrentB_PointVelo    261       const G4double lenB = CurrentB_PointVelocity.GetCurveLength() ;            
262       G4double curv_lenAB = lenB - lenA;          262       G4double curv_lenAB = lenB - lenA;
263       G4double     distAB = (Point_B - Point_A    263       G4double     distAB = (Point_B - Point_A).mag();
264       if( curv_lenAB < distAB * ( 1. - 10.*fiE    264       if( curv_lenAB < distAB * ( 1. - 10.*fiEpsilonStep ) )
265       {                                           265       {
266         G4cerr << "ERROR> (Start) Point A coin    266         G4cerr << "ERROR> (Start) Point A coincides with or has gone past (end) point B"           
267                << "MLL: iters = " << substep_n    267                << "MLL: iters = " << substep_no << G4endl;
268         G4long op=G4cerr.precision(6);            268         G4long op=G4cerr.precision(6);
269         G4cerr << "       Difference = " << di    269         G4cerr << "       Difference = " << distAB - curv_lenAB
270                << " exceeds limit of relative     270                << " exceeds limit of relative dist (10*epsilon)= " << 10*fiEpsilonStep
271                << "  i.e. limit = " << 10 * fi    271                << "  i.e. limit = " << 10 * fiEpsilonStep * distAB << G4endl;
272         G4cerr.precision(9);                      272         G4cerr.precision(9);        
273         G4cerr << "        Len A, B = " << len    273         G4cerr << "        Len A, B = " << lenA << " " << lenB << G4endl
274                << "        Position A: " << Po    274                << "        Position A: " << Point_A << G4endl
275                << "        Position B: " << Po    275                << "        Position B: " << Point_B << G4endl;
276         G4cerr.precision(op);                     276         G4cerr.precision(op);
277         // G4LocatorChangeRecord::ReportVector    277         // G4LocatorChangeRecord::ReportVector(G4cerr, "endPointB", endChangeB );
278         // G4cerr<<"EndPoints A(start) and B(e    278         // G4cerr<<"EndPoints A(start) and B(end): combined changes " << G4endl;
279         if (fCheckMode)                        << 279         if (fCheckMode) {
280         {                                      << 280            G4LocatorChangeLogger::ReportEndChanges(G4cerr, endChangeA, endChangeB);
281           G4LocatorChangeLogger::ReportEndChan << 
282         }                                         281         }
283       }                                           282       }
284                                                << 283 #endif    
285       if( !validIntersectP )                   << 284       if( !validIntersectP ){
286       {                                        << 
287         G4ExceptionDescription errmsg;            285         G4ExceptionDescription errmsg;
288         errmsg << "Assertion FAILURE - invalid    286         errmsg << "Assertion FAILURE - invalid (stale) Interection point. Substep: "
289                << substep_no << " call: " << f    287                << substep_no << " call: " << fNumCalls << G4endl;
290         if (fCheckMode)                           288         if (fCheckMode)
291         {                                      << 289            G4LocatorChangeRecord::ReportEndChanges(errmsg, endChangeA, endChangeB );
292           G4LocatorChangeRecord::ReportEndChan << 
293         }                                      << 
294         G4Exception("G4MultiLevelLocator::Esti    290         G4Exception("G4MultiLevelLocator::EstimateIntersectionPoint", "GeomNav0004",
295                     JustWarning, errmsg);         291                     JustWarning, errmsg);
296       }                                           292       }
297 #endif                                         << 293       
298                                                << 
299       // F = a point on true AB path close to     294       // F = a point on true AB path close to point E 
300       // (the closest if possible)                295       // (the closest if possible)
301       //                                          296       //
302       ApproxIntersecPointV = GetChordFinderFor    297       ApproxIntersecPointV = GetChordFinderFor()
303                              ->ApproxCurvePoin    298                              ->ApproxCurvePointV( CurrentA_PointVelocity, 
304                                                   299                                                   CurrentB_PointVelocity, 
305                                                   300                                                   CurrentE_Point,
306                                                   301                                                   GetEpsilonStepFor() );
307         // The above method is the key & most     302         // The above method is the key & most intuitive part ...
308                                                   303 
309 #ifdef G4DEBUG_FIELD                              304 #ifdef G4DEBUG_FIELD      
310       recApproxPoint.push_back(G4LocatorChange    305       recApproxPoint.push_back(G4LocatorChangeRecord(G4LocatorChangeRecord::kInvalidCL,
311                                                   306                                                   substep_no, eventCount, ApproxIntersecPointV ) );
312       G4double lenIntsc= ApproxIntersecPointV.    307       G4double lenIntsc= ApproxIntersecPointV.GetCurveLength();
313       G4double checkVsEnd= lenB - lenIntsc;       308       G4double checkVsEnd= lenB - lenIntsc;
314                                                   309 
315       if( lenIntsc > lenB )                       310       if( lenIntsc > lenB ) 
316       {                                           311       {
317         std::ostringstream errmsg;                312         std::ostringstream errmsg;
318         errmsg.precision(17);                     313         errmsg.precision(17);
319         G4double ratio    = checkVsEnd / lenB;    314         G4double ratio    = checkVsEnd / lenB;
320         G4double ratioTol = std::fabs(ratio) /    315         G4double ratioTol = std::fabs(ratio) / tolerance;
321         errmsg << "Intermediate F point is pas    316         errmsg << "Intermediate F point is past end B point" << G4endl
322         << "   l( intersection ) = " << lenInt    317         << "   l( intersection ) = " << lenIntsc << G4endl
323         << "   l( endpoint     ) = " << lenB      318         << "   l( endpoint     ) = " << lenB     << G4endl;
324         errmsg.precision(8);                      319         errmsg.precision(8);
325         errmsg << "   l_end - l_inters  = " <<    320         errmsg << "   l_end - l_inters  = " << checkVsEnd << G4endl
326         << "          / l_end      = " << rati    321         << "          / l_end      = " << ratio << G4endl
327         << "   ratio  / tolerance  = " << rati    322         << "   ratio  / tolerance  = " << ratioTol  << G4endl;
328         if( ratioTol < 1.0 )                      323         if( ratioTol < 1.0 )
329           G4Exception(MethodName, "GeomNav0003    324           G4Exception(MethodName, "GeomNav0003", JustWarning, errmsg );
330         else                                      325         else
331           G4Exception(MethodName, "GeomNav0003    326           G4Exception(MethodName, "GeomNav0003", FatalException, errmsg );
332       }                                           327       }
333 #endif                                            328 #endif
334                                                   329 
335       G4ThreeVector CurrentF_Point= ApproxInte    330       G4ThreeVector CurrentF_Point= ApproxIntersecPointV.GetPosition();
336                                                   331 
337       // First check whether EF is small - the    332       // First check whether EF is small - then F is a good approx. point 
338       // Calculate the length and direction of    333       // Calculate the length and direction of the chord AF
339       //                                          334       //
340       G4ThreeVector  ChordEF_Vector = CurrentF    335       G4ThreeVector  ChordEF_Vector = CurrentF_Point - CurrentE_Point;
341                                                   336 
342       G4ThreeVector  NewMomentumDir = ApproxIn    337       G4ThreeVector  NewMomentumDir = ApproxIntersecPointV.GetMomentumDir(); 
343       G4double       MomDir_dot_Norm = NewMome    338       G4double       MomDir_dot_Norm = NewMomentumDir.dot( NormalAtEntry );
344                                                   339 
345 #ifdef G4DEBUG_FIELD                              340 #ifdef G4DEBUG_FIELD
346       if( fVerboseLevel > 3 )                     341       if( fVerboseLevel > 3 )
347       {                                           342       { 
348          G4ThreeVector  ChordAB           = Po    343          G4ThreeVector  ChordAB           = Point_B - Point_A;
349          G4double       ABchord_length    = Ch    344          G4double       ABchord_length    = ChordAB.mag(); 
350          G4double       MomDir_dot_ABchord;       345          G4double       MomDir_dot_ABchord;
351          MomDir_dot_ABchord = (1.0 / ABchord_l    346          MomDir_dot_ABchord = (1.0 / ABchord_length)
352                             * NewMomentumDir.d    347                             * NewMomentumDir.dot( ChordAB );
353          G4VIntersectionLocator::ReportTrialSt    348          G4VIntersectionLocator::ReportTrialStep( substep_no, ChordAB,
354               ChordEF_Vector, NewMomentumDir,     349               ChordEF_Vector, NewMomentumDir, NormalAtEntry, validNormalAtE ); 
355          G4cout << " dot( MomentumDir, ABchord    350          G4cout << " dot( MomentumDir, ABchord_unit ) = "
356                 << MomDir_dot_ABchord << G4end    351                 << MomDir_dot_ABchord << G4endl;
357       }                                           352       }
358 #endif                                            353 #endif
359       G4bool adequate_angle =                     354       G4bool adequate_angle =
360              ( MomDir_dot_Norm >= 0.0 ) // Can    355              ( MomDir_dot_Norm >= 0.0 ) // Can use ( > -epsilon) instead
361           || (! validNormalAtE );       // Inv    356           || (! validNormalAtE );       // Invalid, cannot use this criterion
362       G4double EF_dist2 = ChordEF_Vector.mag2(    357       G4double EF_dist2 = ChordEF_Vector.mag2();
363       if ( ( EF_dist2 <= sqr(fiDeltaIntersecti    358       if ( ( EF_dist2 <= sqr(fiDeltaIntersection) && ( adequate_angle ) )
364         || ( EF_dist2 <= kCarTolerance*kCarTol    359         || ( EF_dist2 <= kCarTolerance*kCarTolerance ) )
365       {                                           360       { 
366         found_approximate_intersection = true;    361         found_approximate_intersection = true;
367                                                   362 
368         // Create the "point" return value        363         // Create the "point" return value
369         //                                        364         //
370         IntersectedOrRecalculatedFT = ApproxIn    365         IntersectedOrRecalculatedFT = ApproxIntersecPointV;
371         IntersectedOrRecalculatedFT.SetPositio    366         IntersectedOrRecalculatedFT.SetPosition( CurrentE_Point );
372                                                   367 
373         if ( GetAdjustementOfFoundIntersection    368         if ( GetAdjustementOfFoundIntersection() )
374         {                                         369         {
375           // Try to Get Correction of Intersec    370           // Try to Get Correction of IntersectionPoint using SurfaceNormal()
376           //                                      371           //  
377           G4ThreeVector IP;                       372           G4ThreeVector IP;
378           G4ThreeVector MomentumDir=ApproxInte    373           G4ThreeVector MomentumDir=ApproxIntersecPointV.GetMomentumDirection();
379           G4bool goodCorrection = AdjustmentOf    374           G4bool goodCorrection = AdjustmentOfFoundIntersection(Point_A,
380                                     CurrentE_P    375                                     CurrentE_Point, CurrentF_Point, MomentumDir,
381                                     last_AF_in    376                                     last_AF_intersection, IP, NewSafety,
382                                     previousSa    377                                     previousSafety, previousSftOrigin );
383           if ( goodCorrection )                   378           if ( goodCorrection )
384           {                                       379           {
385             IntersectedOrRecalculatedFT = Appr    380             IntersectedOrRecalculatedFT = ApproxIntersecPointV;
386             IntersectedOrRecalculatedFT.SetPos    381             IntersectedOrRecalculatedFT.SetPosition(IP);
387           }                                       382           }
388         }                                         383         }
389         // Note: in order to return a point on    384         // Note: in order to return a point on the boundary, 
390         //       we must return E. But it is F    385         //       we must return E. But it is F on the curve.
391         //       So we must "cheat": we are us    386         //       So we must "cheat": we are using the position at point E
392         //       and the velocity at point F !    387         //       and the velocity at point F !!!
393         //                                        388         //
394         // This must limit the length we can a    389         // This must limit the length we can allow for displacement!
395       }                                           390       }
396       else  // E is NOT close enough to the cu    391       else  // E is NOT close enough to the curve (ie point F)
397       {                                           392       {
398         // Check whether any volumes are encou    393         // Check whether any volumes are encountered by the chord AF
399         // -----------------------------------    394         // ---------------------------------------------------------
400         // First relocate to restore any Voxel    395         // First relocate to restore any Voxel etc information
401         // in the Navigator before calling Com    396         // in the Navigator before calling ComputeStep()
402         //                                        397         //
403         GetNavigatorFor()->LocateGlobalPointWi    398         GetNavigatorFor()->LocateGlobalPointWithinVolume( Point_A );
404                                                   399 
405         G4ThreeVector PointG;   // Candidate i    400         G4ThreeVector PointG;   // Candidate intersection point
406         G4double stepLengthAF;                    401         G4double stepLengthAF; 
407         G4bool Intersects_FB = false;             402         G4bool Intersects_FB = false;
408         G4bool Intersects_AF = IntersectChord(    403         G4bool Intersects_AF = IntersectChord( Point_A,   CurrentF_Point,
409                                                   404                                                NewSafety, previousSafety,
410                                                   405                                                previousSftOrigin,
411                                                   406                                                stepLengthAF,
412                                                   407                                                PointG );
413         last_AF_intersection = Intersects_AF;     408         last_AF_intersection = Intersects_AF;
414         if( Intersects_AF )                       409         if( Intersects_AF )
415         {                                         410         {
416           // G is our new Candidate for the in    411           // G is our new Candidate for the intersection point.
417           // It replaces  "E" and we will see     412           // It replaces  "E" and we will see if it's good enough.
418           CurrentB_PointVelocity = ApproxInter    413           CurrentB_PointVelocity = ApproxIntersecPointV;  // B  <- F
419           CurrentE_Point = PointG;                414           CurrentE_Point = PointG;                        // E  <- G
420                                                   415 
421           validIntersectP = true;    // 'E' ha    416           validIntersectP = true;    // 'E' has been updated.
422                                                   417 
423           G4bool validNormalLast;                 418           G4bool validNormalLast; 
424           NormalAtEntry  = GetSurfaceNormal( P    419           NormalAtEntry  = GetSurfaceNormal( PointG, validNormalLast ); 
425           validNormalAtE = validNormalLast;       420           validNormalAtE = validNormalLast; 
426                                                   421 
427           // As we move point B, must take car    422           // As we move point B, must take care in case the current
428           // AF has no intersection to try cur    423           // AF has no intersection to try current FB!!
429           fin_section_depth[depth] = false;       424           fin_section_depth[depth] = false;
430                                                   425 
431           if (fCheckMode)                         426           if (fCheckMode)
432           {                                       427           {
433             ++eventCount;                         428             ++eventCount;
434             endChangeB.push_back(                 429             endChangeB.push_back(
435               G4LocatorChangeRecord(G4LocatorC    430               G4LocatorChangeRecord(G4LocatorChangeRecord::kIntersectsAF,
436                              substep_no, event    431                              substep_no, eventCount, CurrentB_PointVelocity) );
437           }                                       432           }
438 #ifdef G4VERBOSE                                  433 #ifdef G4VERBOSE
439           if( fVerboseLevel > 3 )                 434           if( fVerboseLevel > 3 )
440           {                                       435           {
441             G4cout << "G4PiF::LI> Investigatin    436             G4cout << "G4PiF::LI> Investigating intermediate point"
442                    << " at s=" << ApproxInters    437                    << " at s=" << ApproxIntersecPointV.GetCurveLength()
443                    << " on way to full s="        438                    << " on way to full s="
444                    << CurveEndPointVelocity.Ge    439                    << CurveEndPointVelocity.GetCurveLength() << G4endl;
445           }                                       440           }
446 #endif                                            441 #endif
447         }                                         442         }
448         else  // not Intersects_AF                443         else  // not Intersects_AF
449         {                                         444         {  
450           // In this case:                        445           // In this case:
451           // There is NO intersection of AF wi    446           // There is NO intersection of AF with a volume boundary.
452           // We must continue the search in th    447           // We must continue the search in the segment FB!
453           //                                      448           //
454           GetNavigatorFor()->LocateGlobalPoint    449           GetNavigatorFor()->LocateGlobalPointWithinVolume( CurrentF_Point );
455                                                   450 
456           G4double stepLengthFB;                  451           G4double stepLengthFB;
457           G4ThreeVector PointH;                   452           G4ThreeVector PointH;
458                                                   453 
459           // Check whether any volumes are enc    454           // Check whether any volumes are encountered by the chord FB
460           // ---------------------------------    455           // ---------------------------------------------------------
461                                                   456 
462           Intersects_FB = IntersectChord( Curr    457           Intersects_FB = IntersectChord( CurrentF_Point, Point_B, 
463                                           NewS    458                                           NewSafety, previousSafety,
464                                           prev    459                                           previousSftOrigin,
465                                           step    460                                           stepLengthFB,
466                                           Poin    461                                           PointH );
467           if( Intersects_FB )                     462           if( Intersects_FB )
468           {                                       463           {
469             // There is an intersection of FB     464             // There is an intersection of FB with a volume boundary
470             // H <- First Intersection of Chor    465             // H <- First Intersection of Chord FB 
471                                                   466 
472             // H is our new Candidate for the     467             // H is our new Candidate for the intersection point.
473             // It replaces  "E" and we will re    468             // It replaces  "E" and we will repeat the test to see if
474             // it is a good enough approximate    469             // it is a good enough approximate point for us.
475                                                   470 
476             // Note that F must be in volume v    471             // Note that F must be in volume volA  (the same as A)
477             // (otherwise AF would meet a volu    472             // (otherwise AF would meet a volume boundary!)
478             //   A    <- F                        473             //   A    <- F 
479             //   E    <- H                        474             //   E    <- H
480             //                                    475             //
481             CurrentA_PointVelocity = ApproxInt    476             CurrentA_PointVelocity = ApproxIntersecPointV;
482             CurrentE_Point = PointH;              477             CurrentE_Point = PointH;
483                                                   478 
484             validIntersectP = true;    // 'E'     479             validIntersectP = true;    // 'E' has been updated.
485                                                   480 
486             G4bool validNormalH;                  481             G4bool validNormalH;
487             NormalAtEntry  = GetSurfaceNormal(    482             NormalAtEntry  = GetSurfaceNormal( PointH, validNormalH ); 
488             validNormalAtE = validNormalH;        483             validNormalAtE = validNormalH;
489                                                   484 
490             if (fCheckMode)                       485             if (fCheckMode)
491             {                                     486             {
492               ++eventCount;                       487               ++eventCount;
493               endChangeA.push_back(               488               endChangeA.push_back( 
494                  G4LocatorChangeRecord(G4Locat    489                  G4LocatorChangeRecord(G4LocatorChangeRecord::kIntersectsFB,
495                              substep_no, event    490                              substep_no, eventCount, CurrentA_PointVelocity) );
496               G4FieldTrack intersectH_pn('0');    491               G4FieldTrack intersectH_pn('0');  // Point and normal
497                                                   492                                                 // nothing else will be valid
498               intersectH_pn.SetPosition( Point    493               intersectH_pn.SetPosition( PointH );
499               intersectH_pn.SetMomentum( Norma    494               intersectH_pn.SetMomentum( NormalAtEntry ); 
500               pointH_logger.AddRecord(G4Locato    495               pointH_logger.AddRecord(G4LocatorChangeRecord::kIntersectsFB,
501                                     substep_no    496                                     substep_no, eventCount, intersectH_pn );
502             }                                     497             }
503           }                                       498           }
504           else  // not Intersects_FB              499           else  // not Intersects_FB
505           {                                       500           {
506             validIntersectP = false;    // Int    501             validIntersectP = false;    // Intersections are now stale
507             if( fin_section_depth[depth] )        502             if( fin_section_depth[depth] )
508             {                                     503             {
509               // If B is the original endpoint    504               // If B is the original endpoint, this means that whatever
510               // volume(s) intersected the ori    505               // volume(s) intersected the original chord, none touch the
511               // smaller chords we have used.     506               // smaller chords we have used.
512               // The value of 'IntersectedOrRe    507               // The value of 'IntersectedOrRecalculatedFT' returned is
513               // likely not valid                 508               // likely not valid 
514                                                   509 
515               // Check on real final_section o    510               // Check on real final_section or SubEndSection
516               //                                  511               //
517               if( ((Second_half)&&(depth==0))     512               if( ((Second_half)&&(depth==0)) || (first_section) )
518               {                                   513               {
519                 there_is_no_intersection = tru    514                 there_is_no_intersection = true;   // real final_section
520               }                                   515               }
521               else                                516               else
522               {                                   517               {
523                 // end of subsection, not real    518                 // end of subsection, not real final section 
524                 // exit from the and go to the    519                 // exit from the and go to the depth-1 level 
525                 substep_no_p = param_substeps+    520                 substep_no_p = param_substeps+2;  // exit from the loop
526                                                   521 
527                 // but 'Second_half' is still     522                 // but 'Second_half' is still true because we need to find
528                 // the 'CurrentE_point' for th    523                 // the 'CurrentE_point' for the next loop
529                 Second_half = true;               524                 Second_half = true; 
530                 sub_final_section = true;         525                 sub_final_section = true;
531               }                                   526               }
532             }                                     527             }
533             else                                  528             else
534             {                                     529             {
535               CurrentA_PointVelocity = Current    530               CurrentA_PointVelocity = CurrentB_PointVelocity;  // Got to B
536               CurrentB_PointVelocity = (depth=    531               CurrentB_PointVelocity = (depth==0) ? CurveEndPointVelocity 
537                                                   532                                                   : *ptrInterMedFT[depth] ;
538               SubStart_PointVelocity = Current    533               SubStart_PointVelocity = CurrentA_PointVelocity;
539               restoredFullEndpoint = true;        534               restoredFullEndpoint = true;
540                                                   535 
541               validIntersectP = false;  // 'E'    536               validIntersectP = false;  // 'E' has NOT been updated.
542                                                   537 
543               if (fCheckMode)                     538               if (fCheckMode)
544               {                                   539               {
545                 ++eventCount;                     540                 ++eventCount;
546                 endChangeA.push_back(             541                 endChangeA.push_back(
547                   G4LocatorChangeRecord(          542                   G4LocatorChangeRecord(
548                     G4LocatorChangeRecord::kNo    543                     G4LocatorChangeRecord::kNoIntersectAForFB,
549                              substep_no, event    544                              substep_no, eventCount, CurrentA_PointVelocity) ); 
550                 endChangeB.push_back(             545                 endChangeB.push_back(
551                   G4LocatorChangeRecord (         546                   G4LocatorChangeRecord (
552                     G4LocatorChangeRecord::kNo    547                     G4LocatorChangeRecord::kNoIntersectAForFB,
553                              substep_no, event    548                              substep_no, eventCount, CurrentB_PointVelocity) );
554               }                                   549               }
555             }                                     550             }
556           } // Endif (Intersects_FB)              551           } // Endif (Intersects_FB)
557         } // Endif (Intersects_AF)                552         } // Endif (Intersects_AF)
558                                                   553 
559         G4int errorEndPt = 0; // Default: no e    554         G4int errorEndPt = 0; // Default: no error (if not calling CheckAnd...
560                                                   555 
561         G4bool recalculatedB= false;              556         G4bool recalculatedB= false;
562         if( driverReIntegrates )                  557         if( driverReIntegrates )
563         {                                         558         {
564           G4FieldTrack RevisedB_FT = CurrentB_    559           G4FieldTrack RevisedB_FT = CurrentB_PointVelocity;
565           recalculatedB= CheckAndReEstimateEnd    560           recalculatedB= CheckAndReEstimateEndpoint(CurrentA_PointVelocity,
566                                                   561                                                     CurrentB_PointVelocity,
567                                                   562                                                     RevisedB_FT,
568                                                   563                                                     errorEndPt );
569           if( recalculatedB )                     564           if( recalculatedB )
570           {                                       565           {
571             CurrentB_PointVelocity = RevisedB_    566             CurrentB_PointVelocity = RevisedB_FT;  // Use it !
572             // Do not invalidate intersection     567             // Do not invalidate intersection F -- it is still roughly OK.
573             //                                    568             //
574             // The best course would be to inv    569             // The best course would be to invalidate (reset validIntersectP)
575             // BUT if we invalidate it, we mus    570             // BUT if we invalidate it, we must re-estimate it somewhere! E.g.
576             //   validIntersectP = false;  //     571             //   validIntersectP = false;  // 'E' has NOT been updated.
577                                                   572  
578             if ( (fin_section_depth[depth])       573             if ( (fin_section_depth[depth])           // real final section
579                &&( first_section || ((Second_h    574                &&( first_section || ((Second_half)&&(depth==0)) ) )
580             {                                     575             {
581               recalculatedEndPoint = true;        576               recalculatedEndPoint = true;
582               IntersectedOrRecalculatedFT = Re    577               IntersectedOrRecalculatedFT = RevisedB_FT;
583               // So that we can return it, if     578               // So that we can return it, if it is the endpoint!
584             }                                     579             }
585             // else                               580             // else
586             //  Move forward the other points     581             //  Move forward the other points 
587             //   - or better flag it, so that     582             //   - or better flag it, so that they are re-computed when next used
588             //     [ Implementation: a counter    583             //     [ Implementation: a counter for # of recomputations
589             //       => avoids extra work]        584             //       => avoids extra work]
590           }                                       585           }
591           if (fCheckMode)                         586           if (fCheckMode)
592           {                                       587           {
593             ++eventCount;                         588             ++eventCount;
594             endChangeB.push_back(                 589             endChangeB.push_back(
595               G4LocatorChangeRecord( G4Locator    590               G4LocatorChangeRecord( G4LocatorChangeRecord::kRecalculatedB,
596                                      substep_n    591                                      substep_no, eventCount, RevisedB_FT ) );
597           }                                       592           }
598         }                                         593         }
599         else                                      594         else
600         {                                         595         {
601           if( CurrentB_PointVelocity.GetCurveL << 596           if( CurrentB_PointVelocity.GetCurveLength() < CurrentA_PointVelocity.GetCurveLength() )
602             < CurrentA_PointVelocity.GetCurveL << 
603           {                                    << 
604             errorEndPt = 2;                       597             errorEndPt = 2;
605           }                                    << 
606         }                                         598         }
607                                                   599 
608         if( errorEndPt > 1 )  // errorEndPt =     600         if( errorEndPt > 1 )  // errorEndPt = 1 is milder, just: len(B)=len(A)
609         {                                         601         {
610           std::ostringstream errmsg;              602           std::ostringstream errmsg;
611                                                   603 
612           ReportReversedPoints(errmsg,            604           ReportReversedPoints(errmsg,
613                                CurveStartPoint    605                                CurveStartPointVelocity, CurveEndPointVelocity,
614                                NewSafety, fiEp    606                                NewSafety, fiEpsilonStep,
615                                CurrentA_PointV    607                                CurrentA_PointVelocity, CurrentB_PointVelocity,
616                                SubStart_PointV    608                                SubStart_PointVelocity, CurrentE_Point,
617                                ApproxIntersecP    609                                ApproxIntersecPointV, substep_no, substep_no_p, depth);
618                                                   610           
619           if (fCheckMode)                      << 611           if (fCheckMode) {
620           {                                    << 
621             G4LocatorChangeRecord::ReportEndCh    612             G4LocatorChangeRecord::ReportEndChanges(errmsg, endChangeA, endChangeB );
622           }                                       613           }
623                                                   614 
624           errmsg << G4endl << " * Location: "     615           errmsg << G4endl << " * Location: " << MethodName
625                  << "- After EndIf(Intersects_    616                  << "- After EndIf(Intersects_AF)" << G4endl;
626           errmsg << " * Bool flags:  Recalcula    617           errmsg << " * Bool flags:  Recalculated = " << recalculatedB
627                  << "   Intersects_AF = " << I    618                  << "   Intersects_AF = " << Intersects_AF
628                  << "   Intersects_FB = " << I    619                  << "   Intersects_FB = " << Intersects_FB << G4endl;
629           errmsg << " * Number of calls to MLL    620           errmsg << " * Number of calls to MLL:EIP= " << fNumCalls << G4endl;
630           G4Exception(MethodName, "GeomNav0003    621           G4Exception(MethodName, "GeomNav0003", FatalException, errmsg);
631         }                                         622         }
632         if( restoredFullEndpoint )                623         if( restoredFullEndpoint )
633         {                                         624         {
634           fin_section_depth[depth] = restoredF    625           fin_section_depth[depth] = restoredFullEndpoint;
635           restoredFullEndpoint = false;           626           restoredFullEndpoint = false;
636         }                                         627         }
637       } // EndIf ( E is close enough to the cu    628       } // EndIf ( E is close enough to the curve, ie point F. )
638         // tests ChordAF_Vector.mag() <= maxim    629         // tests ChordAF_Vector.mag() <= maximum_lateral_displacement 
639                                                   630 
640 #ifdef G4DEBUG_FIELD                              631 #ifdef G4DEBUG_FIELD
641       if( trigger_substepno_print == 0)           632       if( trigger_substepno_print == 0)
642       {                                           633       {
643         trigger_substepno_print= fWarnSteps -     634         trigger_substepno_print= fWarnSteps - 20;
644       }                                           635       }
645                                                   636 
646       if( substep_no >= trigger_substepno_prin    637       if( substep_no >= trigger_substepno_print )
647       {                                           638       {
648         G4cout << "Difficulty in converging in    639         G4cout << "Difficulty in converging in " << MethodName
649                << "    Substep no = " << subst    640                << "    Substep no = " << substep_no << G4endl;
650         if( substep_no == trigger_substepno_pr    641         if( substep_no == trigger_substepno_print )
651         {                                         642         {
652           G4cout << " Start:   ";                 643           G4cout << " Start:   ";
653           printStatus( CurveStartPointVelocity    644           printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
654                        -1.0, NewSafety, 0 );      645                        -1.0, NewSafety, 0 );
655           if( fCheckMode ) {                      646           if( fCheckMode ) {
656             G4LocatorChangeRecord::ReportEndCh    647             G4LocatorChangeRecord::ReportEndChanges(G4cout, endChangeA, endChangeB );
657           } else {                                648           } else {
658             G4cout << " ** For more informatio    649             G4cout << " ** For more information enable 'check mode' in G4MultiLevelLocator "
659                    << "-- (it saves and can ou    650                    << "-- (it saves and can output change records) " << G4endl;
660           }                                       651           }
661         }                                         652         }
662         G4cout << " Point A: ";                   653         G4cout << " Point A: "; 
663         printStatus( CurrentA_PointVelocity, C    654         printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
664                      -1.0, NewSafety, substep_    655                      -1.0, NewSafety, substep_no-1 );
665         G4cout << " Point B: ";                   656         G4cout << " Point B: ";
666         printStatus( CurrentA_PointVelocity, C    657         printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
667                      -1.0, NewSafety, substep_    658                      -1.0, NewSafety, substep_no );
668       }                                           659       }
669 #endif                                            660 #endif
670       ++substep_no;                               661       ++substep_no; 
671       ++substep_no_p;                             662       ++substep_no_p;
672                                                   663 
673     } while (  ( ! found_approximate_intersect    664     } while (  ( ! found_approximate_intersection )
674             && ( ! there_is_no_intersection )     665             && ( ! there_is_no_intersection )     
675             && validIntersectP        // New c    666             && validIntersectP        // New condition:  must refresh intersection !!
676             && ( substep_no_p <= param_substep    667             && ( substep_no_p <= param_substeps) );  // UNTIL found or
677                                                   668                                                      // failed param substep
678                                                   669 
679     if( (!found_approximate_intersection) && (    670     if( (!found_approximate_intersection) && (!there_is_no_intersection) )
680     {                                             671     {
681       G4double did_len = std::abs( CurrentA_Po    672       G4double did_len = std::abs( CurrentA_PointVelocity.GetCurveLength()
682                        - SubStart_PointVelocit    673                        - SubStart_PointVelocity.GetCurveLength()); 
683       G4double all_len = std::abs( CurrentB_Po    674       G4double all_len = std::abs( CurrentB_PointVelocity.GetCurveLength()
684                        - SubStart_PointVelocit    675                        - SubStart_PointVelocity.GetCurveLength());
685                                                   676    
686       G4double distAB = -1;                       677       G4double distAB = -1;
687       //                                          678       //
688       // Is progress is too slow, and is it po    679       // Is progress is too slow, and is it possible to go deeper?
689       // If so, then *halve the step*             680       // If so, then *halve the step*
690       //              ==============              681       //              ==============
691       if(   (did_len < fraction_done*all_len)     682       if(   (did_len < fraction_done*all_len)
692          && (depth<max_depth) && (!sub_final_s    683          && (depth<max_depth) && (!sub_final_section) )
693       {                                           684       {
694 #ifdef G4DEBUG_FIELD                              685 #ifdef G4DEBUG_FIELD         
695         static G4ThreadLocal unsigned int numS    686         static G4ThreadLocal unsigned int numSplits=0;   // For debugging only 
696         biggest_depth = std::max(depth, bigges    687         biggest_depth = std::max(depth, biggest_depth);
697         ++numSplits;                              688         ++numSplits;
698 #endif                                            689 #endif
699         Second_half = false;                      690         Second_half = false;
700         ++depth;                                  691         ++depth;
701         first_section = false;                    692         first_section = false;
702                                                   693 
703         G4double Sub_len = (all_len-did_len)/(    694         G4double Sub_len = (all_len-did_len)/(2.);
704         G4FieldTrack midPoint = CurrentA_Point    695         G4FieldTrack midPoint = CurrentA_PointVelocity;
705         G4bool fullAdvance=                       696         G4bool fullAdvance=              
706            integrDriver->AccurateAdvance(midPo    697            integrDriver->AccurateAdvance(midPoint, Sub_len, fiEpsilonStep);
707                                                   698                          
708         ++fNumAdvanceTrials;                      699         ++fNumAdvanceTrials;
709         if( fullAdvance )  { ++fNumAdvanceFull    700         if( fullAdvance )  { ++fNumAdvanceFull; }
710                                                   701 
711         G4double lenAchieved=                     702         G4double lenAchieved=
712            midPoint.GetCurveLength()-CurrentA_    703            midPoint.GetCurveLength()-CurrentA_PointVelocity.GetCurveLength();
713                                                   704         
714         const G4double adequateFraction = (1.0    705         const G4double adequateFraction = (1.0-CLHEP::perThousand);
715         G4bool goodAdvance = (lenAchieved >= a    706         G4bool goodAdvance = (lenAchieved >= adequateFraction * Sub_len);
716         if ( goodAdvance )  { ++fNumAdvanceGoo    707         if ( goodAdvance )  { ++fNumAdvanceGood; }
717                                                   708 
718 #ifdef G4DEBUG_FIELD                              709 #ifdef G4DEBUG_FIELD
719         else  //  !goodAdvance                    710         else  //  !goodAdvance
720         {                                         711         {
721            G4cout << "MLL> AdvanceChordLimited    712            G4cout << "MLL> AdvanceChordLimited not full at depth=" << depth 
722                   << "  total length achieved     713                   << "  total length achieved = " << lenAchieved << " of "
723                   << Sub_len << "  fraction= "    714                   << Sub_len << "  fraction= ";
724            if (Sub_len != 0.0 ) { G4cout << le    715            if (Sub_len != 0.0 ) { G4cout << lenAchieved / Sub_len; }
725            else                 { G4cout << "D    716            else                 { G4cout << "DivByZero"; }
726            G4cout << "  Good-enough fraction =    717            G4cout << "  Good-enough fraction = " << adequateFraction;
727            G4cout << "  Number of call to mll     718            G4cout << "  Number of call to mll = " << fNumCalls
728                   << "   iteration " << subste    719                   << "   iteration " << substep_no
729                   << "  inner =  " << substep_    720                   << "  inner =  " << substep_no_p << G4endl;
730            G4cout << "  Epsilon of integration    721            G4cout << "  Epsilon of integration = " << fiEpsilonStep << G4endl;
731            G4cout << "  State at start is         722            G4cout << "  State at start is      = " << CurrentA_PointVelocity
732                   << G4endl                       723                   << G4endl
733                   << "        at end (midpoint    724                   << "        at end (midpoint)= " << midPoint << G4endl;
734            G4cout << "  Particle mass = " << m    725            G4cout << "  Particle mass = " << midPoint.GetRestMass() << G4endl;
735                                                   726 
736            G4EquationOfMotion *equation = inte    727            G4EquationOfMotion *equation = integrDriver->GetEquationOfMotion();
737            ReportFieldValue( CurrentA_PointVel    728            ReportFieldValue( CurrentA_PointVelocity, "start", equation );
738            ReportFieldValue( midPoint, "midPoi    729            ReportFieldValue( midPoint, "midPoint", equation );            
739            G4cout << "  Original Start = "        730            G4cout << "  Original Start = "
740                   << CurveStartPointVelocity <    731                   << CurveStartPointVelocity << G4endl;
741            G4cout << "  Original   End = "        732            G4cout << "  Original   End = "
742                   << CurveEndPointVelocity <<     733                   << CurveEndPointVelocity << G4endl;
743            G4cout << "  Original TrialPoint =     734            G4cout << "  Original TrialPoint = "
744                   << TrialPoint << G4endl;        735                   << TrialPoint << G4endl;
745            G4cout << "  (this is STRICT mode)     736            G4cout << "  (this is STRICT mode) "
746                   << "  num Splits= " << numSp    737                   << "  num Splits= " << numSplits;           
747            G4cout << G4endl;                      738            G4cout << G4endl;
748         }                                         739         }
749 #endif                                            740 #endif
750                                                   741 
751         *ptrInterMedFT[depth] =  midPoint;        742         *ptrInterMedFT[depth] =  midPoint;
752         CurrentB_PointVelocity = midPoint;        743         CurrentB_PointVelocity = midPoint; 
753                                                   744 
754         if (fCheckMode)                           745         if (fCheckMode)
755         {                                         746         {
756           ++eventCount;                           747           ++eventCount;
757           endChangeB.push_back(                   748           endChangeB.push_back(
758             G4LocatorChangeRecord( G4LocatorCh    749             G4LocatorChangeRecord( G4LocatorChangeRecord::kInsertingMidPoint,
759                                    substep_no,    750                                    substep_no, eventCount, midPoint) );
760         }                                         751         }        
761                                                   752         
762         // Adjust 'SubStartPoint' to calculate    753         // Adjust 'SubStartPoint' to calculate the 'did_length' in next loop
763         //                                        754         //
764         SubStart_PointVelocity = CurrentA_Poin    755         SubStart_PointVelocity = CurrentA_PointVelocity;
765                                                   756 
766         // Find new trial intersection point n    757         // Find new trial intersection point needed at start of the loop
767         //                                        758         //
768         G4ThreeVector Point_A = CurrentA_Point    759         G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
769         G4ThreeVector Point_B = CurrentB_Point    760         G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();   
770                                                   761 
771         G4ThreeVector PointGe;                    762         G4ThreeVector PointGe;
772         GetNavigatorFor()->LocateGlobalPointWi    763         GetNavigatorFor()->LocateGlobalPointWithinVolume(Point_A);
773         G4bool Intersects_AB = IntersectChord(    764         G4bool Intersects_AB = IntersectChord(Point_A, Point_B,
774                                                   765                                               NewSafety, previousSafety,
775                                                   766                                               previousSftOrigin, distAB,
776                                                   767                                               PointGe);
777         if( Intersects_AB )                       768         if( Intersects_AB )
778         {                                         769         {
779           last_AF_intersection = Intersects_AB    770           last_AF_intersection = Intersects_AB;
780           CurrentE_Point = PointGe;               771           CurrentE_Point = PointGe;
781           fin_section_depth[depth] = true;        772           fin_section_depth[depth] = true;
782                                                   773 
783           validIntersectP = true;  // 'E' has     774           validIntersectP = true;  // 'E' has been updated.
784                                                   775 
785           G4bool validNormalAB;                   776           G4bool validNormalAB; 
786           NormalAtEntry  = GetSurfaceNormal( P    777           NormalAtEntry  = GetSurfaceNormal( PointGe, validNormalAB ); 
787           validNormalAtE = validNormalAB;         778           validNormalAtE = validNormalAB;
788         }                                         779         }
789         else                                      780         else
790         {                                         781         {
791           // No intersection found for first p    782           // No intersection found for first part of curve
792           // (CurrentA,InterMedPoint[depth]).     783           // (CurrentA,InterMedPoint[depth]). Go to the second part
793           //                                      784           //
794           Second_half = true;                     785           Second_half = true;
795                                                   786 
796           validIntersectP=  false;  // No new     787           validIntersectP=  false;  // No new 'E' chord intersection found
797         }                                         788         }
798       } // if did_len                             789       } // if did_len
799                                                   790 
800       G4bool unfinished = Second_half;            791       G4bool unfinished = Second_half;
801       while ( unfinished && (depth>0) )  // Lo    792       while ( unfinished && (depth>0) )  // Loop checking, 07.10.2016, JA
802       {                                           793       {
803         // Second part of curve (InterMed[dept    794         // Second part of curve (InterMed[depth],Intermed[depth-1])) 
804         // On the depth-1 level normally we ar    795         // On the depth-1 level normally we are on the 'second_half'
805                                                   796 
806         //  Find new trial intersection point     797         //  Find new trial intersection point needed at start of the loop
807         //                                        798         //
808         SubStart_PointVelocity = *ptrInterMedF    799         SubStart_PointVelocity = *ptrInterMedFT[depth];
809         CurrentA_PointVelocity = *ptrInterMedF    800         CurrentA_PointVelocity = *ptrInterMedFT[depth];
810         CurrentB_PointVelocity = *ptrInterMedF    801         CurrentB_PointVelocity = *ptrInterMedFT[depth-1];
811                                                   802 
812         if (fCheckMode)                           803         if (fCheckMode)
813         {                                         804         {
814           ++eventCount;                           805           ++eventCount;
815           G4LocatorChangeRecord chngPop_a( G4L    806           G4LocatorChangeRecord chngPop_a( G4LocatorChangeRecord::kLevelPop,
816                               substep_no, even    807                               substep_no, eventCount, CurrentA_PointVelocity);
817           endChangeA.push_back( chngPop_a );      808           endChangeA.push_back( chngPop_a );
818           G4LocatorChangeRecord chngPop_b( G4L    809           G4LocatorChangeRecord chngPop_b( G4LocatorChangeRecord::kLevelPop,
819                               substep_no, even    810                               substep_no, eventCount, CurrentB_PointVelocity);
820           endChangeB.push_back( chngPop_b );      811           endChangeB.push_back( chngPop_b );
821         }                                         812         }
822                                                   813         
823         // Ensure that the new endpoints are n    814         // Ensure that the new endpoints are not further apart in space
824         // than on the curve due to different     815         // than on the curve due to different errors in the integration
825         //                                        816         //
826         G4int  errorEndPt = -1;                   817         G4int  errorEndPt = -1;
827         G4bool recalculatedB= false;              818         G4bool recalculatedB= false;
828         if( driverReIntegrates )                  819         if( driverReIntegrates )
829         {                                         820         {
830           // Ensure that the new endpoints are    821           // Ensure that the new endpoints are not further apart in space
831           // than on the curve due to differen    822           // than on the curve due to different errors in the integration
832           //                                      823           //
833           G4FieldTrack RevisedEndPointFT = Cur    824           G4FieldTrack RevisedEndPointFT = CurrentB_PointVelocity;
834           recalculatedB =                         825           recalculatedB = 
835              CheckAndReEstimateEndpoint( Curre    826              CheckAndReEstimateEndpoint( CurrentA_PointVelocity,  
836                                          Curre    827                                          CurrentB_PointVelocity,
837                                          Revis    828                                          RevisedEndPointFT,
838                                          error    829                                          errorEndPt );
839           if( recalculatedB )                     830           if( recalculatedB )
840           {                                       831           {
841             CurrentB_PointVelocity = RevisedEn    832             CurrentB_PointVelocity = RevisedEndPointFT;  // Use it !
842                                                   833             
843             if ( depth == 1 )                     834             if ( depth == 1 )
844             {                                     835             {
845                recalculatedEndPoint = true;       836                recalculatedEndPoint = true;
846                IntersectedOrRecalculatedFT = R    837                IntersectedOrRecalculatedFT = RevisedEndPointFT;
847                // So that we can return it, if    838                // So that we can return it, if it is the endpoint!
848             }                                     839             }
849           }                                       840           }
850           else                                    841           else
851           {                                       842           {          
852             if( CurrentB_PointVelocity.GetCurv << 843             if( CurrentB_PointVelocity.GetCurveLength() < CurrentA_PointVelocity.GetCurveLength() )
853               < CurrentA_PointVelocity.GetCurv << 
854             {                                  << 
855               errorEndPt = 2;                     844               errorEndPt = 2;
856             }                                  << 
857           }                                       845           }
858                                                   846           
859           if (fCheckMode)                         847           if (fCheckMode)
860           {                                       848           {
861             ++eventCount;                         849             ++eventCount;
862             endChangeB.push_back(                 850             endChangeB.push_back(
863               G4LocatorChangeRecord(G4LocatorC    851               G4LocatorChangeRecord(G4LocatorChangeRecord::kRecalculatedBagn,
864                                     substep_no    852                                     substep_no, eventCount, RevisedEndPointFT));
865           }                                       853           }
866         }                                         854         }
867         if( errorEndPt > 1 )  // errorEndPt =     855         if( errorEndPt > 1 )  // errorEndPt = 1 is milder, just: len(B)=len(A)
868         {                                         856         {
869           std::ostringstream errmsg;              857           std::ostringstream errmsg; 
870           ReportReversedPoints(errmsg,            858           ReportReversedPoints(errmsg, 
871                     CurveStartPointVelocity, C    859                     CurveStartPointVelocity, CurveEndPointVelocity,
872                     NewSafety, fiEpsilonStep,     860                     NewSafety, fiEpsilonStep, 
873                     CurrentA_PointVelocity, Cu    861                     CurrentA_PointVelocity, CurrentB_PointVelocity,
874                     SubStart_PointVelocity, Cu    862                     SubStart_PointVelocity, CurrentE_Point,
875                     ApproxIntersecPointV, subs    863                     ApproxIntersecPointV, substep_no, substep_no_p, depth);
876           errmsg << " * Location:  " << Method    864           errmsg << " * Location:  " << MethodName << "- Second-Half" << G4endl;
877           errmsg << " * Recalculated = " << re    865           errmsg << " * Recalculated = " << recalculatedB << G4endl; // false
878           G4Exception(MethodName, "GeomNav0003    866           G4Exception(MethodName, "GeomNav0003", FatalException, errmsg);
879         }                                         867         }
880                                                   868         
881         G4ThreeVector Point_A = CurrentA_Point    869         G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
882         G4ThreeVector Point_B = CurrentB_Point    870         G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
883         G4ThreeVector PointGi;                    871         G4ThreeVector PointGi;     
884         GetNavigatorFor()->LocateGlobalPointWi    872         GetNavigatorFor()->LocateGlobalPointWithinVolume(Point_A);
885         G4bool Intersects_AB = IntersectChord(    873         G4bool Intersects_AB = IntersectChord(Point_A, Point_B, NewSafety,
886                                                   874                                               previousSafety,
887                                                   875                                               previousSftOrigin, distAB,
888                                                   876                                               PointGi);
889         if( Intersects_AB )                       877         if( Intersects_AB )
890         {                                         878         {
891           last_AF_intersection = Intersects_AB    879           last_AF_intersection = Intersects_AB;
892           CurrentE_Point = PointGi;               880           CurrentE_Point = PointGi;
893                                                   881 
894           validIntersectP = true;  // 'E' has     882           validIntersectP = true;  // 'E' has been updated.
895           NormalAtEntry  = GetSurfaceNormal( P    883           NormalAtEntry  = GetSurfaceNormal( PointGi, validNormalAtE ); 
896         }                                         884         }
897         else                                      885         else
898         {                                         886         {
899           validIntersectP = false;  // No new     887           validIntersectP = false;  // No new 'E' chord intersection found
900           if( depth == 1)                         888           if( depth == 1)
901           {                                       889           {
902             there_is_no_intersection = true;      890             there_is_no_intersection = true;
903           }                                       891           }
904         }                                         892         }
905         depth--;                                  893         depth--;
906         fin_section_depth[depth] = true;          894         fin_section_depth[depth] = true;
907         unfinished = !validIntersectP;            895         unfinished = !validIntersectP;
908       }                                           896       }
909 #ifdef G4DEBUG_FIELD                              897 #ifdef G4DEBUG_FIELD
910       if( ! ( validIntersectP || there_is_no_i    898       if( ! ( validIntersectP || there_is_no_intersection ) )
911       {                                           899       {
912          // What happened ??                      900          // What happened ??
913          G4cout << "MLL - WARNING Potential FA    901          G4cout << "MLL - WARNING Potential FAILURE: Conditions not met!"
914                 << G4endl                         902                 << G4endl
915                 << " Depth = " << depth << G4e    903                 << " Depth = " << depth << G4endl
916                 << " Num Substeps= " << subste    904                 << " Num Substeps= " << substep_no << G4endl;
917          G4cout << " Found intersection= " <<     905          G4cout << " Found intersection= " << found_approximate_intersection
918                 << G4endl;                        906                 << G4endl;
919          G4cout << " Progress report: -- " <<     907          G4cout << " Progress report: -- " << G4endl;
920          ReportProgress(G4cout,                   908          ReportProgress(G4cout, 
921                         CurveStartPointVelocit    909                         CurveStartPointVelocity, CurveEndPointVelocity,
922                         substep_no, CurrentA_P    910                         substep_no, CurrentA_PointVelocity,
923                         CurrentB_PointVelocity    911                         CurrentB_PointVelocity,
924                         NewSafety, depth );       912                         NewSafety, depth ); 
925          G4cout << G4endl;                        913          G4cout << G4endl; 
926       }                                           914       }
927 #endif                                            915 #endif      
928     }  // if(!found_aproximate_intersection)      916     }  // if(!found_aproximate_intersection)
929                                                   917 
930     assert( validIntersectP || there_is_no_int    918     assert( validIntersectP || there_is_no_intersection
931                             || found_approxima    919                             || found_approximate_intersection);
932                                                   920 
933   } while ( ( ! found_approximate_intersection    921   } while ( ( ! found_approximate_intersection )
934             && ( ! there_is_no_intersection )     922             && ( ! there_is_no_intersection )     
935             && ( substep_no <= fMaxSteps) ); /    923             && ( substep_no <= fMaxSteps) ); // UNTIL found or failed
936                                                   924 
937   if( substep_no > max_no_seen )                  925   if( substep_no > max_no_seen )
938   {                                               926   {
939     max_no_seen = substep_no;                     927     max_no_seen = substep_no; 
940 #ifdef G4DEBUG_FIELD                              928 #ifdef G4DEBUG_FIELD
941     if( max_no_seen > fWarnSteps )                929     if( max_no_seen > fWarnSteps )
942     {                                             930     {
943       trigger_substepno_print = max_no_seen-20    931       trigger_substepno_print = max_no_seen-20; // Want to see last 20 steps 
944     }                                             932     } 
945 #endif                                            933 #endif
946   }                                               934   }
947                                                   935 
948   if( !there_is_no_intersection && !found_appr    936   if( !there_is_no_intersection && !found_approximate_intersection )
949   {                                               937   {
950      if( substep_no >= fMaxSteps)                 938      if( substep_no >= fMaxSteps)
951      {                                            939      {
952         // Since we cannot go further (yet), w    940         // Since we cannot go further (yet), we return as far as we have gone
953                                                   941 
954         recalculatedEndPoint = true;              942         recalculatedEndPoint = true;
955         IntersectedOrRecalculatedFT = CurrentA    943         IntersectedOrRecalculatedFT = CurrentA_PointVelocity;
956         found_approximate_intersection = false    944         found_approximate_intersection = false; 
957                                                   945      
958         std::ostringstream message;               946         std::ostringstream message;
959         message << G4endl;                        947         message << G4endl;
960         message << "Convergence is requiring t    948         message << "Convergence is requiring too many substeps: "
961                 << substep_no << "  ( limit =     949                 << substep_no << "  ( limit = "<<  fMaxSteps << ")"
962                 << G4endl                         950                 << G4endl 
963                 << "  Abandoning effort to int    951                 << "  Abandoning effort to intersect. " << G4endl << G4endl;
964         message << "    Number of calls to MLL    952         message << "    Number of calls to MLL: " <<   fNumCalls;
965         message << "  iteration = " << substep    953         message << "  iteration = " << substep_no <<G4endl << G4endl;
966                                                   954         
967         message.precision( 12 );                  955         message.precision( 12 ); 
968         G4double done_len = CurrentA_PointVelo    956         G4double done_len = CurrentA_PointVelocity.GetCurveLength(); 
969         G4double full_len = CurveEndPointVeloc    957         G4double full_len = CurveEndPointVelocity.GetCurveLength();
970         message << "        Undertaken only le    958         message << "        Undertaken only length: " << done_len
971                 << " out of " << full_len << "    959                 << " out of " << full_len << " required." << G4endl
972                 << "        Remaining length =    960                 << "        Remaining length = " << full_len - done_len; 
973                                                   961         
974         message << "     Start and end-point o    962         message << "     Start and end-point of requested Step:" << G4endl;
975         printStatus( CurveStartPointVelocity,     963         printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
976                      -1.0, NewSafety, 0,     m    964                      -1.0, NewSafety, 0,     message, -1 );
977         message << "        Start and end-poin    965         message << "        Start and end-point of current Sub-Step:" << G4endl;
978         printStatus( CurrentA_PointVelocity, C    966         printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
979                      -1.0, NewSafety, substep_    967                      -1.0, NewSafety, substep_no-1, message, -1 );
980         printStatus( CurrentA_PointVelocity, C    968         printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
981                      -1.0, NewSafety, substep_    969                      -1.0, NewSafety, substep_no, message, -1 );
982                                                   970         
983         G4Exception(MethodName, "GeomNav0003",    971         G4Exception(MethodName, "GeomNav0003", JustWarning, message);
984      }                                            972      }
985      else if( substep_no >= fWarnSteps)           973      else if( substep_no >= fWarnSteps)
986      {                                            974      {  
987         std::ostringstream message;               975         std::ostringstream message;
988         message << "Many substeps while trying    976         message << "Many substeps while trying to locate intersection."
989                 << G4endl                         977                 << G4endl
990                 << "          Undertaken lengt    978                 << "          Undertaken length: "  
991                 << CurrentB_PointVelocity.GetC    979                 << CurrentB_PointVelocity.GetCurveLength()
992                 << " - Needed: "  << substep_n    980                 << " - Needed: "  << substep_no << " substeps." << G4endl
993                 << "          Warning number =    981                 << "          Warning number = " << fWarnSteps
994                 << " and maximum substeps = "     982                 << " and maximum substeps = " << fMaxSteps;
995         G4Exception(MethodName, "GeomNav1002",    983         G4Exception(MethodName, "GeomNav1002", JustWarning, message);
996      }                                            984      }
997   }                                               985   }
998                                                   986   
999   return  (!there_is_no_intersection) && found    987   return  (!there_is_no_intersection) && found_approximate_intersection;
1000     //  Success or failure                       988     //  Success or failure
1001 }                                                989 }
1002                                                  990 
1003 void G4MultiLevelLocator::ReportStatistics()     991 void G4MultiLevelLocator::ReportStatistics()
1004 {                                                992 {
1005    G4cout << " Number of calls = " << fNumCal    993    G4cout << " Number of calls = " << fNumCalls << G4endl;
1006    G4cout << " Number of split level ('advanc    994    G4cout << " Number of split level ('advances'):  "
1007           << fNumAdvanceTrials << G4endl;        995           << fNumAdvanceTrials << G4endl;
1008    G4cout << " Number of full advances:          996    G4cout << " Number of full advances:             "
1009           << fNumAdvanceGood << G4endl;          997           << fNumAdvanceGood << G4endl;
1010    G4cout << " Number of good advances:          998    G4cout << " Number of good advances:             "
1011           << fNumAdvanceFull << G4endl;          999           << fNumAdvanceFull << G4endl;
1012 }                                                1000 }
1013                                                  1001 
1014 void G4MultiLevelLocator::ReportFieldValue( c    1002 void G4MultiLevelLocator::ReportFieldValue( const G4FieldTrack& locationPV,
1015                                             c    1003                                             const char* nameLoc,
1016                                             c    1004                                             const G4EquationOfMotion* equation )
1017 {                                                1005 {
1018    enum { maxNumFieldComp = 24 };                1006    enum { maxNumFieldComp = 24 };
1019                                                  1007 
1020    G4ThreeVector position = locationPV.GetPos    1008    G4ThreeVector position = locationPV.GetPosition();   
1021    G4double startPoint[4] = { position.x(), p    1009    G4double startPoint[4] = { position.x(), position.y(), position.z(),
1022                               locationPV.GetL    1010                               locationPV.GetLabTimeOfFlight() };
1023    G4double FieldVec[maxNumFieldComp]; // 24     1011    G4double FieldVec[maxNumFieldComp]; // 24 ;
1024    for (double & i : FieldVec)                << 1012    for (auto i=0; i<maxNumFieldComp; ++i )
1025    {                                             1013    {
1026      i = 0.0;                                 << 1014      FieldVec[i] = 0.0;
1027    }                                             1015    }
1028    equation->GetFieldValue( startPoint, Field    1016    equation->GetFieldValue( startPoint, FieldVec);
1029    G4cout << "  B-field value (" << nameLoc <    1017    G4cout << "  B-field value (" << nameLoc << ")=   "
1030           << FieldVec[0] << " " << FieldVec[1    1018           << FieldVec[0] << " " << FieldVec[1] << " " << FieldVec[2];
1031    G4double Emag2= G4ThreeVector( FieldVec[3]    1019    G4double Emag2= G4ThreeVector( FieldVec[3],
1032                                   FieldVec[4]    1020                                   FieldVec[4],
1033                                   FieldVec[5]    1021                                   FieldVec[5] ).mag2(); 
1034    if( Emag2 > 0.0 )                             1022    if( Emag2 > 0.0 )
1035    {                                             1023    {
1036       G4cout << " Electric = " << FieldVec[3]    1024       G4cout << " Electric = " << FieldVec[3] << " "
1037                                << FieldVec[4]    1025                                << FieldVec[4] << " "
1038                                << FieldVec[5]    1026                                << FieldVec[5]<< G4endl;
1039    }                                             1027    }
1040    return;                                       1028    return;
1041 }                                                1029 }
1042                                                  1030