Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/magneticfield/src/G4ChordFinder.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/magneticfield/src/G4ChordFinder.cc (Version 11.3.0) and /geometry/magneticfield/src/G4ChordFinder.cc (Version 10.4.p2)


  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 // G4ChordFinder implementation                << 
 27 //                                                 26 //
 28 // Author: J.Apostolakis - Design and implemen <<  27 // $Id: G4ChordFinder.cc 107508 2017-11-20 08:23:14Z gcosmo $
                                                   >>  28 //
                                                   >>  29 //
                                                   >>  30 // 25.02.97 - John Apostolakis - Design and implementation 
 29 // -------------------------------------------     31 // -------------------------------------------------------------------
 30                                                    32 
 31 #include <iomanip>                                 33 #include <iomanip>
 32                                                    34 
 33 #include "G4ChordFinder.hh"                        35 #include "G4ChordFinder.hh"
 34 #include "G4SystemOfUnits.hh"                      36 #include "G4SystemOfUnits.hh"
 35 #include "G4MagneticField.hh"                      37 #include "G4MagneticField.hh"
 36 #include "G4Mag_UsualEqRhs.hh"                     38 #include "G4Mag_UsualEqRhs.hh"
 37 #include "G4MagIntegratorDriver.hh"                39 #include "G4MagIntegratorDriver.hh"
 38 // #include "G4ClassicalRK4.hh"                    40 // #include "G4ClassicalRK4.hh"
 39 // #include "G4CashKarpRKF45.hh"                   41 // #include "G4CashKarpRKF45.hh"
 40 // #include "G4NystromRK4.hh"                  << 
 41 // #include "G4BogackiShampine23.hh"               42 // #include "G4BogackiShampine23.hh"
 42 // #include "G4BogackiShampine45.hh"               43 // #include "G4BogackiShampine45.hh"
 43                                                << 
 44 #include "G4DormandPrince745.hh"                   44 #include "G4DormandPrince745.hh"
 45                                                    45 
 46 // New templated stepper(s) -- avoid virtual c <<  46 // New FSAL type driver / steppers -----
 47 #include "G4TDormandPrince45.hh"               << 
 48                                                << 
 49 // FSAL type driver / steppers -----           << 
 50 #include "G4FSALIntegrationDriver.hh"              47 #include "G4FSALIntegrationDriver.hh"
 51 #include "G4VFSALIntegrationStepper.hh"            48 #include "G4VFSALIntegrationStepper.hh"
 52 #include "G4RK547FEq1.hh"                          49 #include "G4RK547FEq1.hh"
 53 // #include "G4RK547FEq2.hh"                       50 // #include "G4RK547FEq2.hh"
 54 // #include "G4RK547FEq3.hh"                       51 // #include "G4RK547FEq3.hh"
 55 // #include "G4FSALBogackiShampine45.hh"       <<  52 // #include "G4NystromRK4.hh"
 56 // #include "G4FSALDormandPrince745.hh"        << 
 57                                                    53 
 58 // Templated type drivers -----                <<  54 // New FSAL type driver / steppers -----
 59 #include "G4IntegrationDriver.hh"                  55 #include "G4IntegrationDriver.hh"
 60 #include "G4InterpolationDriver.hh"            <<  56 #include "G4FSALBogackiShampine45.hh"
 61                                                <<  57 // #include "G4FSALDormandPrince745.hh"
 62 #include "G4HelixHeum.hh"                      << 
 63 #include "G4BFieldIntegrationDriver.hh"        << 
 64                                                << 
 65 #include "G4QSSDriverCreator.hh"               << 
 66                                                << 
 67 #include "G4CachedMagneticField.hh"            << 
 68                                                    58 
 69 #include <cassert>                             << 
 70 #include <memory>                              << 
 71                                                    59 
 72 G4bool G4ChordFinder::gVerboseCtor = false;    << 
 73 // ...........................................     60 // ..........................................................................
 74                                                    61 
 75 G4ChordFinder::G4ChordFinder(G4VIntegrationDri     62 G4ChordFinder::G4ChordFinder(G4VIntegrationDriver* pIntegrationDriver)
 76   : fDefaultDeltaChord(0.25 * mm), fIntgrDrive <<  63   : fDefaultDeltaChord( 0.25 * mm ),      // Parameters
                                                   >>  64     fDeltaChord( fDefaultDeltaChord ),    //   Internal parameters
                                                   >>  65     fFirstFraction(0.999), fFractionLast(1.00),  fFractionNextEstimate(0.98), 
                                                   >>  66     fMultipleRadius(15.0), 
                                                   >>  67     fStatsVerbose(0),
                                                   >>  68     fRegularStepperOwned(nullptr),                    // Dependent objects 
                                                   >>  69     fEquation(0),      
                                                   >>  70     fTotalNoTrials_FNC(0), fNoCalls_FNC(0), fmaxTrials_FNC(0)
 77 {                                                  71 {
 78   // Simple constructor -- it does not create      72   // Simple constructor -- it does not create equation
 79   if( gVerboseCtor )                           <<  73   fIntgrDriver= pIntegrationDriver;
 80   {                                            <<  74 
 81     G4cout << "G4ChordFinder: Simple construct <<  75   fLastStepEstimate_Unconstrained = DBL_MAX;          // Should move q, p to
 82   }                                            <<  76 
 83                                                <<  77   SetFractions_Last_Next( fFractionLast, fFractionNextEstimate);  
 84   fDeltaChord = fDefaultDeltaChord;       // P <<  78     // check the values and set the other parameters
                                                   >>  79 
                                                   >>  80   // G4cout << "G4ChordFinder 1st Constructor called - (driver given). " << G4endl;
 85 }                                                  81 }
 86                                                    82 
                                                   >>  83 
 87 // ...........................................     84 // ..........................................................................
 88                                                    85 
 89 G4ChordFinder::G4ChordFinder( G4MagneticField*     86 G4ChordFinder::G4ChordFinder( G4MagneticField*        theMagField,
 90                               G4double         <<  87                               G4double                stepMinimum, 
 91                               G4MagIntegratorS <<  88                               G4MagIntegratorStepper* pItsStepper,     // nullptr is default
 92                               G4int            <<  89                               // G4bool      useHigherEfficiencyStepper,  // false by default
 93   : fDefaultDeltaChord(0.25 * mm)              <<  90                               G4bool                  useFSALstepper ) // false by default
                                                   >>  91   : fDefaultDeltaChord( 0.25 * mm ),     // Constants 
                                                   >>  92     fDeltaChord( fDefaultDeltaChord ),   // Parameters
                                                   >>  93     fFirstFraction(0.999), fFractionLast(1.00),  fFractionNextEstimate(0.98), 
                                                   >>  94     fMultipleRadius(15.0), 
                                                   >>  95     fStatsVerbose(0),
                                                   >>  96     // fRegularStepperOwned(nullptr),                    // Dependent objects     
                                                   >>  97     fEquation(0), 
                                                   >>  98     fTotalNoTrials_FNC(0), fNoCalls_FNC(0), fmaxTrials_FNC(0)  // State - stats
 94 {                                                  99 {
 95   // Construct the Chord Finder                << 100   //  Construct the Chord Finder
 96   // by creating in inverse order the Driver,  << 101   //  by creating in inverse order the  Driver, the Stepper and EqRhs ...
 97   constexpr G4int nVar6 = 6;   // Components i << 
 98                                                << 
 99   fDeltaChord = fDefaultDeltaChord;       // P << 
100                                                << 
101   G4cout << " G4ChordFinder: stepperDriverId:  << 
102                                                << 
103   G4bool useFSALstepper     = (stepperDriverId << 
104   G4bool useTemplatedStepper= (stepperDriverId << 
105   G4bool useRegularStepper  = (stepperDriverId << 
106   G4bool useBfieldDriver    = (stepperDriverId << 
107   G4bool useG4QSSDriver     = (stepperDriverId << 
108                                                << 
109   if( stepperDriverId == kQss3DriverType)      << 
110   {                                            << 
111     stepperDriverId = kQss2DriverType;         << 
112     G4cout << " G4ChordFinder: QSS 3 is curren << 
113   }                                            << 
114                                                   102 
115   using EquationType = G4Mag_UsualEqRhs;       << 103   using NewFsalStepperType = G4RK547FEq1; // or 2 or 3
116                                                << 104   const char* NewFSALStepperName = "G4RK574FEq1> FSAL 4th/5th order 7-stage 'Equilibrium-type' #1.";
117   using TemplatedStepperType =                 << 105 //  using OldFsalStepperType = G4FSALBogackiShampine45;
118          G4TDormandPrince45<EquationType,nVar6 << 106 //  const char* OldFSALStepperName = "FSAL BogackiShampine 45 (Embedded 5th/4th Order, 7-stage)";
119   const char* TemplatedStepperName =           << 107           // = G4FSALDormandPrince745; // = "FSAL Dormand Prince 745 stepper";   
120       "G4TDormandPrince745 (templated Dormand- << 
121                                                << 
122   using RegularStepperType =                      108   using RegularStepperType =
123          G4DormandPrince745; // 5th order embe << 109          G4DormandPrince745; // Famous DOPRI5 (MatLab) 5th order embedded method. High efficiency.
124          // G4ClassicalRK4;        // The old     110          // G4ClassicalRK4;        // The old default
125          // G4CashKarpRKF45;       // First em    111          // G4CashKarpRKF45;       // First embedded method in G4
126          // G4BogackiShampine45;   // High eff    112          // G4BogackiShampine45;   // High efficiency 5th order embedded method
127          // G4NystromRK4;          // Nystrom  << 113          // G4NystromRK4(pEquation, 0.1*millimeter ); // *clhep::millimeter );
128          // G4RK547FEq1;  // or 2 or 3            114          // G4RK547FEq1;  // or 2 or 3 
129   const char* RegularStepperName =             << 115   const char* RegularStepperName = "G4DormandPrince745 (aka DOPRI5): 5th/4th Order 7-stage embedded stepper";
130       "G4DormandPrince745 (aka DOPRI5): 5th/4t << 
131       // "BogackiShampine 45 (Embedded 5th/4th    116       // "BogackiShampine 45 (Embedded 5th/4th Order, 7-stage)";
132       // "Nystrom stepper 4th order";          << 
133                                                   117 
134   using NewFsalStepperType = G4DormandPrince74 << 118   // Configurable
135                                                << 119   G4bool forceFSALstepper= false; //  Choice - true to enable !!
136   const char* NewFSALStepperName =             << 120   // G4bool useNewFSALtype= true;
137       "G4RK574FEq1> FSAL 4th/5th order 7-stage << 121   // G4bool forceHigherEffiencyStepper = false;
138                                                << 122   G4bool report = false;  // Report type of stepper used
139 #ifdef G4DEBUG_FIELD                           << 123 
140   static G4bool verboseDebug = true;           << 124   bool recallFSALflag  = useFSALstepper;
141   if( verboseDebug )                           << 125   useFSALstepper   = forceFSALstepper || useFSALstepper;
142   {                                            << 126 
                                                   >> 127   if( report ) {
143      G4cout << "G4ChordFinder 2nd Constructor     128      G4cout << "G4ChordFinder 2nd Constructor called. " << G4endl;
144      G4cout << " Arguments: " << G4endl        << 129      G4cout << " Parameters: " << G4endl;
145             << " - min step = " << stepMinimum << 130      G4cout << "    useFSAL stepper= " << useFSALstepper
146             << " - stepper ptr provided : "    << 131             << " (request = " << recallFSALflag 
147             << ( pItsStepper==nullptr ? " no   << 132             << " force FSAL = " << forceFSALstepper << " )" << G4endl;
148      if( pItsStepper==nullptr )                << 
149         G4cout << " - stepper/driver Id = " << << 
150                << "  useFSAL = " << useFSALste << 
151                << "  , useTemplated = " << use << 
152                << "  , useRegular = " << useRe << 
153                << "  , useFSAL = " << useFSALs << 
154                << G4endl;                      << 
155   }                                               133   }
156 #endif                                         << 
157                                                   134 
158   // useHigherStepper = forceHigherEffiencySte    135   // useHigherStepper = forceHigherEffiencyStepper || useHigherStepper;
159                                                << 136   
160   auto  pEquation = new G4Mag_UsualEqRhs(theMa << 137   G4Mag_EqRhs *pEquation = new G4Mag_UsualEqRhs(theMagField);
161   fEquation = pEquation;                          138   fEquation = pEquation;                            
162                                                << 139   fLastStepEstimate_Unconstrained = DBL_MAX;          // Should move q, p to
163   // G4MagIntegratorStepper* regularStepper =  << 140                                                      //    G4FieldTrack ??
164   // G4VFSALIntegrationStepper* fsalStepper =  << 141   SetFractions_Last_Next( fFractionLast, fFractionNextEstimate);  
165   // G4MagIntegratorStepper* oldFSALStepper =  << 142     // check the values and set the other parameters
                                                   >> 143 
                                                   >> 144   // G4MagIntegratorStepper*    regularStepper = nullptr;
                                                   >> 145   // G4VFSALIntegrationStepper*    fsalSepper  = nullptr; // for new-type FSAL steppers only
                                                   >> 146   // NewFsalStepperType*           fsalStepper =nullptr;
                                                   >> 147   // G4MagIntegratorStepper*    oldFSALStepper =nullptr;
166                                                   148 
167   G4bool errorInStepperCreation = false;          149   G4bool errorInStepperCreation = false;
168                                                   150 
169   std::ostringstream message;  // In case of f    151   std::ostringstream message;  // In case of failure, load with description !
                                                   >> 152   message << "G4ChordFinder 2nd Constructor called. " << G4endl;
170                                                   153 
171   if( pItsStepper != nullptr )                    154   if( pItsStepper != nullptr )
172   {                                               155   {
173      if( gVerboseCtor )                        << 156      // Type is not known - so must use old class
174      {                                         << 157      fIntgrDriver = new G4MagInt_Driver(stepMinimum, pItsStepper, 
175        G4cout << " G4ChordFinder: Creating G4I << 158                                         pItsStepper->GetNumberOfVariables() );
176               << " stepMinimum = " << stepMini << 159   }
177               << " numVar= " << pItsStepper->G << 160   else if ( !useFSALstepper )
178      }                                         << 161   {
179                                                << 162      // RegularStepperType* regularStepper =nullptr;  // To check the exception
180      // Stepper type is not known - so must us << 163      auto regularStepper =new RegularStepperType(pEquation);
181       if(pItsStepper->isQSS())                 << 164      //                   *** ******************
182       {                                        << 
183          // fIntgrDriver = pItsStepper->build_ << 
184          G4Exception("G4ChordFinder::G4ChordFi << 
185                       "GeomField1001", FatalEx << 
186                       "Cannot provide  QSS ste << 
187       }                                        << 
188       else                                     << 
189       {                                        << 
190          fIntgrDriver = new G4IntegrationDrive << 
191                                   pItsStepper, << 
192          // Stepper type is not known - so mus << 
193          // Non-interpolating driver used by d << 
194          // WAS:  fIntgrDriver = pItsStepper-> << 
195       }                                        << 
196      // -- Older:                              << 
197      // G4cout << " G4ChordFinder: Creating G4 << 
198      // Type is not known - so must use old cl << 
199      // fIntgrDriver = new G4MagInt_Driver( st << 
200      //                                 pItsSt << 
201   }                                            << 
202   else if ( useTemplatedStepper )              << 
203   {                                            << 
204      if( gVerboseCtor )                        << 
205      {                                         << 
206         G4cout << " G4ChordFinder: Creating Te << 
207                << TemplatedStepperName << G4en << 
208      }                                         << 
209      // RegularStepperType* regularStepper = n << 
210      auto templatedStepper = new TemplatedStep << 
211      //                    *** *************** << 
212      //                                           165      //
213      // Alternative - for G4NystromRK4:           166      // Alternative - for G4NystromRK4:
214      // = new G4NystromRK4(pEquation, 0.1*mm ) << 167      // = new G4NystromRK4(pEquation, 0.1*millimeter ); // *clhep::millimeter );
215      fRegularStepperOwned = templatedStepper;  << 
216      if( templatedStepper == nullptr )         << 
217      {                                         << 
218         message << "Templated Stepper instanti << 
219         message << "G4ChordFinder: Attempted t << 
220                 << TemplatedStepperName << " t << 
221         errorInStepperCreation = true;         << 
222      }                                         << 
223      else                                      << 
224      {                                         << 
225         fIntgrDriver = new G4IntegrationDriver << 
226            stepMinimum, templatedStepper, nVar << 
227         if( gVerboseCtor )                     << 
228         {                                      << 
229            G4cout << " G4ChordFinder: Using G4 << 
230         }                                      << 
231      }                                         << 
232                                                << 
233   }                                            << 
234   else if ( useRegularStepper   )  // Plain st << 
235   {                                            << 
236      auto regularStepper = new RegularStepperT << 
237      //                    *** *************** << 
238      fRegularStepperOwned = regularStepper;       168      fRegularStepperOwned = regularStepper;
239                                                   169 
240      if( gVerboseCtor )                        << 
241      {                                         << 
242         G4cout << " G4ChordFinder: Creating Dr << 
243      }                                         << 
244                                                << 
245      if( regularStepper == nullptr )              170      if( regularStepper == nullptr )
246      {                                            171      {
247         message << "Regular Stepper instantiat << 172         message << "  ERROR> 'Regular' RK Stepper instantiation FAILED." << G4endl;        
248         message << "G4ChordFinder: Attempted t    173         message << "G4ChordFinder: Attempted to instantiate "
249                 << RegularStepperName << " typ    174                 << RegularStepperName << " type stepper " << G4endl;
250         errorInStepperCreation = true;            175         errorInStepperCreation = true;
251      }                                            176      }
252      else                                         177      else
253      {                                            178      {
254         auto dp5= dynamic_cast<G4DormandPrince << 179         fIntgrDriver =
255         if( dp5 != nullptr )                   << 180            new G4MagInt_Driver(stepMinimum,
256         {                                      << 181                                regularStepper,
257            fIntgrDriver = new G4InterpolationD << 182                                regularStepper->GetNumberOfVariables() );
258                                   stepMinimum, << 183            //  ====  Create the old type of driver
259            if( gVerboseCtor )                  << 
260            {                                   << 
261               G4cout << " Using InterpolationD << 
262            }                                   << 
263         }                                      << 
264         else                                   << 
265         {                                      << 
266            fIntgrDriver = new G4IntegrationDri << 
267                                   stepMinimum, << 
268            if( gVerboseCtor )                  << 
269            {                                   << 
270               G4cout << " Using IntegrationDri << 
271            }                                   << 
272         }                                      << 
273      }                                         << 
274   }                                            << 
275   else if ( useBfieldDriver )                  << 
276   {                                            << 
277      auto regularStepper = new G4DormandPrince << 
278      //                    *** *************** << 
279      //                                        << 
280      fRegularStepperOwned = regularStepper;    << 
281                                                << 
282      {                                         << 
283         using SmallStepDriver = G4Interpolatio << 
284         using LargeStepDriver = G4IntegrationD << 
285                                                   184 
286         fLongStepper = std::make_unique<G4Heli << 185            // Alternative: 
287                                                << 186            // new G4IntegrationDriver<RegularStepperType>(stepMinimum,
288         fIntgrDriver = new G4BFieldIntegration << 187            //  ====  Create the driver which knows the class type
289           std::make_unique<SmallStepDriver>(st << 
290               regularStepper, regularStepper-> << 
291           std::make_unique<LargeStepDriver>(st << 
292               fLongStepper.get(), regularStepp << 
293                                                   188         
294         if( fIntgrDriver == nullptr)           << 189         if( (fIntgrDriver==nullptr) || report ) {        
295         {                                      << 190            message << "G4ChordFinder: Using G4IntegrationDriver with "
296            message << "Using G4BFieldIntegrati << 
297                    << RegularStepperName << "     191                    << RegularStepperName << " type stepper " << G4endl;
298            message << "Driver instantiation FA << 
299            G4Exception("G4ChordFinder::G4Chord << 
300                        "GeomField1001", JustWa << 
301         }                                         192         }
302      }                                         << 193         if(fIntgrDriver==nullptr) {
303   }                                            << 194            message << "  ERROR> 'Regular' RK Driver instantiation FAILED." << G4endl;
304   else if( useG4QSSDriver )                    << 195         }
305   {                                            << 
306      if( stepperDriverId == kQss2DriverType )  << 
307      {                                         << 
308        auto qssStepper2 = G4QSSDriverCreator:: << 
309        if( gVerboseCtor )                      << 
310        {                                       << 
311          G4cout << "-- Created QSS-2 stepper"  << 
312        }                                       << 
313        fIntgrDriver = G4QSSDriverCreator::Crea << 
314      }                                         << 
315      else                                      << 
316      {                                         << 
317        auto qssStepper3 = G4QSSDriverCreator:: << 
318        if( gVerboseCtor )                      << 
319        {                                       << 
320          G4cout << "-- Created QSS-3 stepper"  << 
321        }                                       << 
322        fIntgrDriver = G4QSSDriverCreator::Crea << 
323      }                                         << 
324      if( gVerboseCtor )                        << 
325      {                                         << 
326        G4cout << "-- G4ChordFinder: Using QSS  << 
327      }                                            196      }
328   }                                               197   }
329   else                                            198   else
330   {                                               199   {
331      auto fsalStepper=  new NewFsalStepperType    200      auto fsalStepper=  new NewFsalStepperType(pEquation);
332      //                 *** ****************** << 201      //                     ******************
333      fNewFSALStepperOwned = fsalStepper;          202      fNewFSALStepperOwned = fsalStepper;
                                                   >> 203      // delete fsalStepper;
                                                   >> 204      // /*NewFsalStepperType* */ fsalStepper =nullptr;  // To check the exception
334                                                   205 
335      if( fsalStepper == nullptr )                 206      if( fsalStepper == nullptr )
336      {                                            207      {
337         message << "Stepper instantiation FAIL << 208         message << "  ERROR> 'FSAL' RK Stepper instantiation FAILED." << G4endl;        
338         message << "Attempted to instantiate " << 209         message << "G4ChordFinder: Attempted to instantiate "
339                 << NewFSALStepperName << " typ    210                 << NewFSALStepperName << " type stepper " << G4endl;
340         G4Exception("G4ChordFinder::G4ChordFin << 
341                     "GeomField1001", JustWarni << 
342         errorInStepperCreation = true;            211         errorInStepperCreation = true;
343      }                                            212      }
344      else                                         213      else
345      {                                            214      {
346         fIntgrDriver = new                        215         fIntgrDriver = new
347            G4FSALIntegrationDriver<NewFsalStep << 216            G4FSALIntegrationDriver<NewFsalStepperType>(stepMinimum,
348                                           fsal << 217                                                        fsalStepper,
                                                   >> 218                                                        fsalStepper->GetNumberOfVariables() );
349            //  ====  Create the driver which k    219            //  ====  Create the driver which knows the class type
350                                                   220         
351         if( fIntgrDriver == nullptr )          << 221         if( (fIntgrDriver==nullptr) || report ) {
352         {                                      << 222            message << "G4ChordFinder: Using G4FSALIntegrationDriver with stepper type: " << G4endl
353            message << "Using G4FSALIntegration << 223                    << NewFSALStepperName << " (new-FSAL type stepper.) " << G4endl;
354                    << NewFSALStepperName << G4 << 224         }
355            message << "Integration Driver inst << 225         if(fIntgrDriver==nullptr) {
356            G4Exception("G4ChordFinder::G4Chord << 226            message << "  ERROR> FSAL Integration Driver instantiation FAILED." << G4endl;
357                        "GeomField1001", JustWa << 
358         }                                         227         }
359      }                                            228      }
360   }                                               229   }
361                                                   230 
362   // -- Main work is now done                     231   // -- Main work is now done
363                                                   232   
364   //    Now check that no error occured, and r    233   //    Now check that no error occured, and report it if one did.
365                                                   234   
366   // To test failure to create driver             235   // To test failure to create driver
367   // delete fIntgrDriver;                         236   // delete fIntgrDriver;
368   // fIntgrDriver = nullptr;                   << 237   // fIntgrDriver= nullptr;
369                                                   238 
370   // Detect and report Error conditions           239   // Detect and report Error conditions
371   //                                           << 
372   if( errorInStepperCreation || (fIntgrDriver     240   if( errorInStepperCreation || (fIntgrDriver == nullptr ))
373   {                                               241   {
374      std::ostringstream errmsg;                   242      std::ostringstream errmsg;
375                                                   243      
376      if( errorInStepperCreation )                 244      if( errorInStepperCreation )
377      {                                            245      {
378         errmsg  << "ERROR> Failure to create S    246         errmsg  << "ERROR> Failure to create Stepper object." << G4endl
379                 << "       -------------------    247                 << "       --------------------------------" << G4endl;
380      }                                            248      }
381      if (fIntgrDriver == nullptr )                249      if (fIntgrDriver == nullptr )
382      {                                            250      {
383         errmsg  << "ERROR> Failure to create I << 251         errmsg  << "ERROR> Failure to create Integration-Driver object." << G4endl
384                 << G4endl                      << 252                 << "       -------------------------------------------" << G4endl;
385                 << "       ------------------- << 
386                 << G4endl;                     << 
387      }                                            253      }
388      const std::string BoolName[2]= { "False",    254      const std::string BoolName[2]= { "False", "True" }; 
389      errmsg << "  Configuration:  (constructor    255      errmsg << "  Configuration:  (constructor arguments) " << G4endl        
390             << "    provided Stepper = " << pI    256             << "    provided Stepper = " << pItsStepper << G4endl
391             << " stepper/driver Id = " << step << 257             << "    use FSAL stepper = " << BoolName[useFSALstepper]
392             << "   useTemplated = " << BoolNam << 258                                // ( useFSALstepper    ? "True" : "False" )
393             << "   useRegular = " << BoolName[ << 259             << " (request = " << BoolName[recallFSALflag]
394             << "   useFSAL = " << BoolName[use << 260             << " force FSAL = " << BoolName[forceFSALstepper] << " )"  << G4endl;
395             << "   using combo BField Driver = << 261 //          << "     use new FSAL stp = " << ( useNewFSALstepper ? "True" : "False" ) << G4endl;
396                    BoolName[ ! (useFSALstepper << 
397                                || useRegularSt << 
398             << G4endl;                         << 
399      errmsg << message.str();                     262      errmsg << message.str(); 
400      errmsg << "Aborting.";                       263      errmsg << "Aborting.";
401      G4Exception("G4ChordFinder::G4ChordFinder << 264      G4Exception("G4ChordFinder::G4ChordFinder() - constructor 2", "GeomField0003",
402                  "GeomField0003", FatalExcepti << 265                   FatalException, errmsg);     
                                                   >> 266   }
                                                   >> 267   else if ( report )
                                                   >> 268   {
                                                   >> 269      G4cout << message.str();
403   }                                               270   }
404                                                   271 
405   assert(    ( pItsStepper != nullptr )        << 272   assert(    ( pItsStepper    != nullptr ) 
406           || ( fRegularStepperOwned != nullptr    273           || ( fRegularStepperOwned != nullptr )
407           || ( fNewFSALStepperOwned != nullptr << 274           || ( fNewFSALStepperOwned  != nullptr )
408           || useG4QSSDriver                    << 275  //       || ( fOldFSALStepperOwned  != nullptr )
409      );                                           276      );
410   assert( fIntgrDriver != nullptr );              277   assert( fIntgrDriver != nullptr );
                                                   >> 278 
411 }                                                 279 }
412                                                   280 
                                                   >> 281 
413 // ...........................................    282 // ......................................................................
414                                                   283 
415 G4ChordFinder::~G4ChordFinder()                   284 G4ChordFinder::~G4ChordFinder()
416 {                                                 285 {
417   delete fEquation;                            << 286   delete   fEquation; // fIntgrDriver->pIntStepper->theEquation_Rhs;
418   delete fRegularStepperOwned;                 << 287   delete   fRegularStepperOwned;
419   delete fNewFSALStepperOwned;                 << 288   delete   fNewFSALStepperOwned;
420   delete fCachedField;                         << 289   // delete   fOldFSALStepperOwned;       
421   delete fIntgrDriver;                         << 290   delete   fIntgrDriver; 
                                                   >> 291 
                                                   >> 292   if( fStatsVerbose ) { PrintStatistics(); }
                                                   >> 293 }
                                                   >> 294 
                                                   >> 295 
                                                   >> 296 // ......................................................................
                                                   >> 297 
                                                   >> 298 void   
                                                   >> 299 G4ChordFinder::SetFractions_Last_Next( G4double fractLast, G4double fractNext )
                                                   >> 300 { 
                                                   >> 301   // Use -1.0 as request for Default.
                                                   >> 302   if( fractLast == -1.0 )   fractLast = 1.0;   // 0.9;
                                                   >> 303   if( fractNext == -1.0 )   fractNext = 0.98;  // 0.9; 
                                                   >> 304 
                                                   >> 305   // fFirstFraction  = 0.999; // Orig 0.999 A safe value, range: ~ 0.95 - 0.999
                                                   >> 306   // fMultipleRadius = 15.0;  // For later use, range: ~  2 - 20 
                                                   >> 307 
                                                   >> 308   if( fStatsVerbose )
                                                   >> 309   { 
                                                   >> 310     G4cout << " ChordFnd> Trying to set fractions: "
                                                   >> 311            << " first " << fFirstFraction
                                                   >> 312            << " last " <<  fractLast
                                                   >> 313            << " next " <<  fractNext
                                                   >> 314            << " and multiple " << fMultipleRadius
                                                   >> 315            << G4endl;
                                                   >> 316   } 
                                                   >> 317 
                                                   >> 318   if( (fractLast > 0.0) && (fractLast <=1.0) ) 
                                                   >> 319   {
                                                   >> 320     fFractionLast= fractLast;
                                                   >> 321   }
                                                   >> 322   else
                                                   >> 323   {
                                                   >> 324     G4cerr << "G4ChordFinder::SetFractions_Last_Next: Invalid "
                                                   >> 325            << " fraction Last = " << fractLast
                                                   >> 326            << " must be  0 <  fractionLast <= 1 " << G4endl;
                                                   >> 327   }
                                                   >> 328   if( (fractNext > 0.0) && (fractNext <1.0) )
                                                   >> 329   {
                                                   >> 330     fFractionNextEstimate = fractNext;
                                                   >> 331   }
                                                   >> 332   else
                                                   >> 333   {
                                                   >> 334     G4cerr << "G4ChordFinder:: SetFractions_Last_Next: Invalid "
                                                   >> 335            << " fraction Next = " << fractNext
                                                   >> 336            << " must be  0 <  fractionNext < 1 " << G4endl;
                                                   >> 337   }
422 }                                                 338 }
423                                                   339 
                                                   >> 340 
                                                   >> 341 // ......................................................................
                                                   >> 342 
                                                   >> 343 G4double 
                                                   >> 344 G4ChordFinder::AdvanceChordLimited( G4FieldTrack& yCurrent,
                                                   >> 345                                     G4double      stepMax,
                                                   >> 346                                     G4double      epsStep,
                                                   >> 347                                     const G4ThreeVector& latestSafetyOrigin,
                                                   >> 348                                     G4double       latestSafetyRadius )
                                                   >> 349 {
                                                   >> 350   G4double stepPossible;
                                                   >> 351   G4double dyErr;
                                                   >> 352   G4FieldTrack yEnd( yCurrent);
                                                   >> 353   G4double  startCurveLen= yCurrent.GetCurveLength();
                                                   >> 354   G4double nextStep;
                                                   >> 355   //            *************
                                                   >> 356   stepPossible= FindNextChord(yCurrent, stepMax, yEnd, dyErr, epsStep,
                                                   >> 357                               &nextStep, latestSafetyOrigin, latestSafetyRadius
                                                   >> 358                              );
                                                   >> 359   //            *************
                                                   >> 360 
                                                   >> 361   G4bool good_advance;
                                                   >> 362 
                                                   >> 363   if ( dyErr < epsStep * stepPossible )
                                                   >> 364   {
                                                   >> 365      // Accept this accuracy.
                                                   >> 366 
                                                   >> 367      yCurrent = yEnd;
                                                   >> 368      good_advance = true; 
                                                   >> 369   }
                                                   >> 370   else
                                                   >> 371   {  
                                                   >> 372      // Advance more accurately to "end of chord"
                                                   >> 373      //                           ***************
                                                   >> 374      good_advance = fIntgrDriver->AccurateAdvance(yCurrent, stepPossible,
                                                   >> 375                                                   epsStep, nextStep);
                                                   >> 376      if ( ! good_advance )
                                                   >> 377      { 
                                                   >> 378        // In this case the driver could not do the full distance
                                                   >> 379        stepPossible= yCurrent.GetCurveLength()-startCurveLen;
                                                   >> 380      }
                                                   >> 381   }
                                                   >> 382   return stepPossible;
                                                   >> 383 }
                                                   >> 384 
                                                   >> 385 
                                                   >> 386 // ............................................................................
                                                   >> 387 
                                                   >> 388 G4double
                                                   >> 389 G4ChordFinder::FindNextChord( const  G4FieldTrack& yStart,
                                                   >> 390                                      G4double     stepMax,
                                                   >> 391                                      G4FieldTrack&   yEnd, // Endpoint
                                                   >> 392                                      G4double&   dyErrPos, // Error of endpoint
                                                   >> 393                                      G4double    epsStep,
                                                   >> 394                                      G4double*  pStepForAccuracy, 
                                                   >> 395                               const  G4ThreeVector, //  latestSafetyOrigin,
                                                   >> 396                                      G4double       //  latestSafetyRadius 
                                                   >> 397                                         )
                                                   >> 398 {
                                                   >> 399   // Returns Length of Step taken
                                                   >> 400 
                                                   >> 401   // G4cout << ">G4ChordFinder::FindNextChord called." << G4endl;
                                                   >> 402    
                                                   >> 403   G4FieldTrack yCurrent=  yStart;  
                                                   >> 404   G4double    stepTrial, stepForAccuracy;
                                                   >> 405   G4double    dydx[G4FieldTrack::ncompSVEC]; 
                                                   >> 406 
                                                   >> 407   //  1.)  Try to "leap" to end of interval
                                                   >> 408   //  2.)  Evaluate if resulting chord gives d_chord that is good enough.
                                                   >> 409   // 2a.)  If d_chord is not good enough, find one that is.
                                                   >> 410   
                                                   >> 411   G4bool    validEndPoint= false;
                                                   >> 412   G4double  dChordStep, lastStepLength; //  stepOfLastGoodChord;
                                                   >> 413 
                                                   >> 414   fIntgrDriver-> GetDerivatives( yCurrent, dydx );
                                                   >> 415 
                                                   >> 416   unsigned int        noTrials=0;
                                                   >> 417   const unsigned int  maxTrials= 75; // Avoid endless loop for bad convergence 
                                                   >> 418 
                                                   >> 419   const G4double safetyFactor= fFirstFraction; //  0.975 or 0.99 ? was 0.999
                                                   >> 420 
                                                   >> 421   stepTrial = std::min( stepMax, safetyFactor*fLastStepEstimate_Unconstrained );
                                                   >> 422 
                                                   >> 423   G4double newStepEst_Uncons= 0.0; 
                                                   >> 424   G4double stepForChord;
                                                   >> 425   do
                                                   >> 426   { 
                                                   >> 427      yCurrent = yStart;    // Always start from initial point  
                                                   >> 428      //            ************
                                                   >> 429      fIntgrDriver->QuickAdvance( yCurrent, dydx, stepTrial, 
                                                   >> 430                                  dChordStep, dyErrPos);
                                                   >> 431      //            ************
                                                   >> 432      
                                                   >> 433      //  We check whether the criterion is met here.
                                                   >> 434      validEndPoint = AcceptableMissDist(dChordStep);
                                                   >> 435 
                                                   >> 436      lastStepLength = stepTrial; 
                                                   >> 437 
                                                   >> 438      // This method estimates to step size for a good chord.
                                                   >> 439      stepForChord = NewStep(stepTrial, dChordStep, newStepEst_Uncons );
                                                   >> 440 
                                                   >> 441      if( ! validEndPoint )
                                                   >> 442      {
                                                   >> 443         if( stepTrial<=0.0 )
                                                   >> 444         {
                                                   >> 445           stepTrial = stepForChord;
                                                   >> 446         }
                                                   >> 447         else if (stepForChord <= stepTrial)
                                                   >> 448         {
                                                   >> 449           // Reduce by a fraction, possibly up to 20% 
                                                   >> 450           stepTrial = std::min( stepForChord, fFractionLast * stepTrial);
                                                   >> 451         }
                                                   >> 452         else
                                                   >> 453         {
                                                   >> 454           stepTrial *= 0.1;
                                                   >> 455         }
                                                   >> 456      }
                                                   >> 457      noTrials++; 
                                                   >> 458   }
                                                   >> 459   while( (! validEndPoint) && (noTrials < maxTrials) );
                                                   >> 460   // Loop checking, 07.10.2016, J. Apostolakis
                                                   >> 461 
                                                   >> 462   if( noTrials >= maxTrials )
                                                   >> 463   {
                                                   >> 464       std::ostringstream message;
                                                   >> 465       message << "Exceeded maximum number of trials= " << maxTrials << G4endl
                                                   >> 466               << "Current sagita dist= " << dChordStep << G4endl
                                                   >> 467               << "Step sizes (actual and proposed): " << G4endl
                                                   >> 468               << "Last trial =         " << lastStepLength  << G4endl
                                                   >> 469               << "Next trial =         " << stepTrial  << G4endl
                                                   >> 470               << "Proposed for chord = " << stepForChord  << G4endl              
                                                   >> 471               ;
                                                   >> 472       G4Exception("G4ChordFinder::FindNextChord()", "GeomField0003",
                                                   >> 473                   JustWarning, message);
                                                   >> 474   }
                                                   >> 475 
                                                   >> 476   if( newStepEst_Uncons > 0.0  )
                                                   >> 477   {
                                                   >> 478      fLastStepEstimate_Unconstrained= newStepEst_Uncons;
                                                   >> 479   }
                                                   >> 480 
                                                   >> 481   AccumulateStatistics( noTrials );
                                                   >> 482 
                                                   >> 483   if( pStepForAccuracy )
                                                   >> 484   { 
                                                   >> 485      // Calculate the step size required for accuracy, if it is needed
                                                   >> 486      //
                                                   >> 487      G4double dyErr_relative = dyErrPos/(epsStep*lastStepLength);
                                                   >> 488      if( dyErr_relative > 1.0 )
                                                   >> 489      {
                                                   >> 490         stepForAccuracy = fIntgrDriver->ComputeNewStepSize( dyErr_relative,
                                                   >> 491                                                             lastStepLength );
                                                   >> 492      }
                                                   >> 493      else
                                                   >> 494      {
                                                   >> 495         stepForAccuracy = 0.0;   // Convention to show step was ok 
                                                   >> 496      }
                                                   >> 497      *pStepForAccuracy = stepForAccuracy;
                                                   >> 498   }
                                                   >> 499 
                                                   >> 500 #ifdef  TEST_CHORD_PRINT
                                                   >> 501   static int dbg=0;
                                                   >> 502   if( dbg )
                                                   >> 503   {
                                                   >> 504     G4cout << "ChordF/FindNextChord:  NoTrials= " << noTrials 
                                                   >> 505            << " StepForGoodChord=" << std::setw(10) << stepTrial << G4endl;
                                                   >> 506   }
                                                   >> 507 #endif
                                                   >> 508   yEnd=  yCurrent;  
                                                   >> 509   return stepTrial; 
                                                   >> 510 }
                                                   >> 511 
                                                   >> 512 
                                                   >> 513 // ...........................................................................
                                                   >> 514 
                                                   >> 515 G4double G4ChordFinder::NewStep(G4double  stepTrialOld, 
                                                   >> 516                                 G4double  dChordStep, // Curr. dchord achieved
                                                   >> 517                                 G4double& stepEstimate_Unconstrained )  
                                                   >> 518 {
                                                   >> 519   // Is called to estimate the next step size, even for successful steps,
                                                   >> 520   // in order to predict an accurate 'chord-sensitive' first step
                                                   >> 521   // which is likely to assist in more performant 'stepping'.
                                                   >> 522 
                                                   >> 523   G4double stepTrial;
                                                   >> 524 
                                                   >> 525 #if 1
                                                   >> 526 
                                                   >> 527   if (dChordStep > 0.0)
                                                   >> 528   {
                                                   >> 529     stepEstimate_Unconstrained =
                                                   >> 530                  stepTrialOld*std::sqrt( fDeltaChord / dChordStep );
                                                   >> 531     stepTrial =  fFractionNextEstimate * stepEstimate_Unconstrained;
                                                   >> 532   }
                                                   >> 533   else
                                                   >> 534   {
                                                   >> 535     // Should not update the Unconstrained Step estimate: incorrect!
                                                   >> 536     stepTrial =  stepTrialOld * 2.; 
                                                   >> 537   }
                                                   >> 538 
                                                   >> 539   if( stepTrial <= 0.001 * stepTrialOld)
                                                   >> 540   {
                                                   >> 541      if ( dChordStep > 1000.0 * fDeltaChord )
                                                   >> 542      {
                                                   >> 543         stepTrial= stepTrialOld * 0.03;   
                                                   >> 544      }
                                                   >> 545      else
                                                   >> 546      {
                                                   >> 547         if ( dChordStep > 100. * fDeltaChord )
                                                   >> 548         {
                                                   >> 549           stepTrial= stepTrialOld * 0.1;   
                                                   >> 550         }
                                                   >> 551         else   // Try halving the length until dChordStep OK
                                                   >> 552         {
                                                   >> 553           stepTrial= stepTrialOld * 0.5;   
                                                   >> 554         }
                                                   >> 555      }
                                                   >> 556   }
                                                   >> 557   else if (stepTrial > 1000.0 * stepTrialOld)
                                                   >> 558   {
                                                   >> 559      stepTrial= 1000.0 * stepTrialOld;
                                                   >> 560   }
                                                   >> 561 
                                                   >> 562   if( stepTrial == 0.0 )
                                                   >> 563   {
                                                   >> 564      stepTrial= 0.000001;
                                                   >> 565   }
                                                   >> 566 
                                                   >> 567 #else
                                                   >> 568 
                                                   >> 569   if ( dChordStep > 1000. * fDeltaChord )
                                                   >> 570   {
                                                   >> 571         stepTrial= stepTrialOld * 0.03;   
                                                   >> 572   }
                                                   >> 573   else
                                                   >> 574   {
                                                   >> 575      if ( dChordStep > 100. * fDeltaChord )
                                                   >> 576      {
                                                   >> 577         stepTrial= stepTrialOld * 0.1;   
                                                   >> 578      }
                                                   >> 579      else  // Keep halving the length until dChordStep OK
                                                   >> 580      {
                                                   >> 581         stepTrial= stepTrialOld * 0.5;   
                                                   >> 582      }
                                                   >> 583   }
                                                   >> 584 
                                                   >> 585 #endif 
                                                   >> 586 
                                                   >> 587   // A more sophisticated chord-finder could figure out a better
                                                   >> 588   // stepTrial, from dChordStep and the required d_geometry
                                                   >> 589   //   e.g.
                                                   >> 590   //      Calculate R, r_helix (eg at orig point)
                                                   >> 591   //      if( stepTrial < 2 pi  R )
                                                   >> 592   //          stepTrial = R arc_cos( 1 - fDeltaChord / r_helix )
                                                   >> 593   //      else    
                                                   >> 594   //          ??
                                                   >> 595 
                                                   >> 596   return stepTrial;
                                                   >> 597 }
                                                   >> 598 
                                                   >> 599 
424 // ...........................................    600 // ...........................................................................
425                                                   601 
426 G4FieldTrack                                      602 G4FieldTrack
427 G4ChordFinder::ApproxCurvePointS( const G4Fiel    603 G4ChordFinder::ApproxCurvePointS( const G4FieldTrack&  CurveA_PointVelocity, 
428                                   const G4Fiel    604                                   const G4FieldTrack&  CurveB_PointVelocity, 
429                                   const G4Fiel    605                                   const G4FieldTrack&  ApproxCurveV,
430                                   const G4Thre    606                                   const G4ThreeVector& CurrentE_Point,
431                                   const G4Thre    607                                   const G4ThreeVector& CurrentF_Point,
432                                   const G4Thre    608                                   const G4ThreeVector& PointG,
433                                         G4bool << 609                                        G4bool first, G4double eps_step)
434 {                                                 610 {
435   // ApproxCurvePointS is 2nd implementation o    611   // ApproxCurvePointS is 2nd implementation of ApproxCurvePoint.
436   // Use Brent Algorithm (or InvParabolic) whe    612   // Use Brent Algorithm (or InvParabolic) when possible.
437   // Given a starting curve point A (CurveA_Po    613   // Given a starting curve point A (CurveA_PointVelocity), curve point B
438   // (CurveB_PointVelocity), a point E which i    614   // (CurveB_PointVelocity), a point E which is (generally) not on the curve
439   // and  a point F which is on the curve (fir    615   // and  a point F which is on the curve (first approximation), find new
440   // point S on the curve closer to point E.      616   // point S on the curve closer to point E. 
441   // While advancing towards S utilise 'eps_st    617   // While advancing towards S utilise 'eps_step' as a measure of the
442   // relative accuracy of each Step.              618   // relative accuracy of each Step.
443                                                   619 
444   G4FieldTrack EndPoint(CurveA_PointVelocity);    620   G4FieldTrack EndPoint(CurveA_PointVelocity);
445   if(!first) { EndPoint = ApproxCurveV; }      << 621   if(!first){EndPoint= ApproxCurveV;}
446                                                   622 
447   G4ThreeVector Point_A,Point_B;                  623   G4ThreeVector Point_A,Point_B;
448   Point_A=CurveA_PointVelocity.GetPosition();     624   Point_A=CurveA_PointVelocity.GetPosition();
449   Point_B=CurveB_PointVelocity.GetPosition();     625   Point_B=CurveB_PointVelocity.GetPosition();
450                                                   626 
451   G4double xa,xb,xc,ya,yb,yc;                     627   G4double xa,xb,xc,ya,yb,yc;
452                                                   628  
453   // InverseParabolic. AF Intersects (First Pa    629   // InverseParabolic. AF Intersects (First Part of Curve) 
454                                                   630 
455   if(first)                                       631   if(first)
456   {                                               632   {
457     xa=0.;                                        633     xa=0.;
458     ya=(PointG-Point_A).mag();                    634     ya=(PointG-Point_A).mag();
459     xb=(Point_A-CurrentF_Point).mag();            635     xb=(Point_A-CurrentF_Point).mag();
460     yb=-(PointG-CurrentF_Point).mag();            636     yb=-(PointG-CurrentF_Point).mag();
461     xc=(Point_A-Point_B).mag();                   637     xc=(Point_A-Point_B).mag();
462     yc=-(CurrentE_Point-Point_B).mag();           638     yc=-(CurrentE_Point-Point_B).mag();
463   }                                               639   }    
464   else                                            640   else
465   {                                               641   {
466     xa=0.;                                        642     xa=0.;
467     ya=(Point_A-CurrentE_Point).mag();            643     ya=(Point_A-CurrentE_Point).mag();
468     xb=(Point_A-CurrentF_Point).mag();            644     xb=(Point_A-CurrentF_Point).mag();
469     yb=(PointG-CurrentF_Point).mag();             645     yb=(PointG-CurrentF_Point).mag();
470     xc=(Point_A-Point_B).mag();                   646     xc=(Point_A-Point_B).mag();
471     yc=-(Point_B-PointG).mag();                   647     yc=-(Point_B-PointG).mag();
472     if(xb==0.)                                    648     if(xb==0.)
473     {                                             649     {
474       EndPoint = ApproxCurvePointV(CurveA_Poin << 650       EndPoint=
475                                    CurrentE_Po << 651       ApproxCurvePointV(CurveA_PointVelocity, CurveB_PointVelocity,
                                                   >> 652                         CurrentE_Point, eps_step);
476       return EndPoint;                            653       return EndPoint;
477     }                                             654     }
478   }                                               655   }
479                                                   656 
480   const G4double tolerance = 1.e-12;           << 657   const G4double tolerance= 1.e-12;
481   if(std::abs(ya)<=tolerance||std::abs(yc)<=to    658   if(std::abs(ya)<=tolerance||std::abs(yc)<=tolerance)
482   {                                               659   {
483     ; // What to do for the moment: return the    660     ; // What to do for the moment: return the same point as at start
484       // then PropagatorInField will take care    661       // then PropagatorInField will take care
485   }                                               662   }
486   else                                            663   else
487   {                                               664   {
488     G4double test_step = InvParabolic(xa,ya,xb    665     G4double test_step = InvParabolic(xa,ya,xb,yb,xc,yc);
489     G4double curve;                               666     G4double curve;
490     if(first)                                     667     if(first)
491     {                                             668     {
492       curve=std::abs(EndPoint.GetCurveLength()    669       curve=std::abs(EndPoint.GetCurveLength()
493                     -ApproxCurveV.GetCurveLeng    670                     -ApproxCurveV.GetCurveLength());
494     }                                             671     }
495     else                                          672     else
496     {                                             673     {
497       test_step = test_step - xb;              << 674       test_step=(test_step-xb);
498       curve=std::abs(EndPoint.GetCurveLength()    675       curve=std::abs(EndPoint.GetCurveLength()
499                     -CurveB_PointVelocity.GetC    676                     -CurveB_PointVelocity.GetCurveLength());
500       xb = (CurrentF_Point-Point_B).mag();     << 677       xb=(CurrentF_Point-Point_B).mag();
501     }                                             678     }
502                                                   679       
503     if(test_step<=0)    { test_step=0.1*xb; }     680     if(test_step<=0)    { test_step=0.1*xb; }
504     if(test_step>=xb)   { test_step=0.5*xb; }     681     if(test_step>=xb)   { test_step=0.5*xb; }
505     if(test_step>=curve){ test_step=0.5*curve;    682     if(test_step>=curve){ test_step=0.5*curve; } 
506                                                   683 
507     if(curve*(1.+eps_step)<xb) // Similar to R    684     if(curve*(1.+eps_step)<xb) // Similar to ReEstimate Step from
508     {                          // G4VIntersect    685     {                          // G4VIntersectionLocator
509       test_step=0.5*curve;                        686       test_step=0.5*curve;
510     }                                             687     }
511                                                   688 
512     fIntgrDriver->AccurateAdvance(EndPoint,tes    689     fIntgrDriver->AccurateAdvance(EndPoint,test_step, eps_step);
513                                                   690       
514 #ifdef G4DEBUG_FIELD                              691 #ifdef G4DEBUG_FIELD
515     // Printing Brent and Linear Approximation    692     // Printing Brent and Linear Approximation
516     //                                            693     //
517     G4cout << "G4ChordFinder::ApproxCurvePoint    694     G4cout << "G4ChordFinder::ApproxCurvePointS() - test-step ShF = "
518            << test_step << "  EndPoint = " <<     695            << test_step << "  EndPoint = " << EndPoint << G4endl;
519                                                   696 
520     //  Test Track                                697     //  Test Track
521     //                                            698     //
522     G4FieldTrack TestTrack( CurveA_PointVeloci    699     G4FieldTrack TestTrack( CurveA_PointVelocity);
523     TestTrack = ApproxCurvePointV( CurveA_Poin    700     TestTrack = ApproxCurvePointV( CurveA_PointVelocity, 
524                                    CurveB_Poin    701                                    CurveB_PointVelocity, 
525                                    CurrentE_Po    702                                    CurrentE_Point, eps_step );
526     G4cout.precision(14);                         703     G4cout.precision(14);
527     G4cout << "G4ChordFinder::BrentApprox = "     704     G4cout << "G4ChordFinder::BrentApprox = " << EndPoint  << G4endl;
528     G4cout << "G4ChordFinder::LinearApprox= "     705     G4cout << "G4ChordFinder::LinearApprox= " << TestTrack << G4endl; 
529 #endif                                            706 #endif
530   }                                               707   }
531   return EndPoint;                                708   return EndPoint;
532 }                                                 709 }
533                                                   710 
534                                                   711 
535 // ...........................................    712 // ...........................................................................
536                                                   713 
537 G4FieldTrack G4ChordFinder::                      714 G4FieldTrack G4ChordFinder::
538 ApproxCurvePointV( const G4FieldTrack& CurveA_    715 ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity, 
539                    const G4FieldTrack& CurveB_    716                    const G4FieldTrack& CurveB_PointVelocity, 
540                    const G4ThreeVector& Curren    717                    const G4ThreeVector& CurrentE_Point,
541                          G4double eps_step)       718                          G4double eps_step)
542 {                                                 719 {
543   // If r=|AE|/|AB|, and s=true path lenght (A    720   // If r=|AE|/|AB|, and s=true path lenght (AB)
544   // return the point that is r*s along the cu    721   // return the point that is r*s along the curve!
545                                                   722  
546   G4FieldTrack   Current_PointVelocity = Curve    723   G4FieldTrack   Current_PointVelocity = CurveA_PointVelocity; 
547                                                   724 
548   G4ThreeVector  CurveA_Point= CurveA_PointVel    725   G4ThreeVector  CurveA_Point= CurveA_PointVelocity.GetPosition();
549   G4ThreeVector  CurveB_Point= CurveB_PointVel    726   G4ThreeVector  CurveB_Point= CurveB_PointVelocity.GetPosition();
550                                                   727 
551   G4ThreeVector  ChordAB_Vector= CurveB_Point     728   G4ThreeVector  ChordAB_Vector= CurveB_Point   - CurveA_Point;
552   G4ThreeVector  ChordAE_Vector= CurrentE_Poin    729   G4ThreeVector  ChordAE_Vector= CurrentE_Point - CurveA_Point;
553                                                   730 
554   G4double       ABdist= ChordAB_Vector.mag();    731   G4double       ABdist= ChordAB_Vector.mag();
555   G4double  curve_length;  //  A curve length     732   G4double  curve_length;  //  A curve length  of AB
556   G4double  AE_fraction;                          733   G4double  AE_fraction; 
557                                                   734   
558   curve_length= CurveB_PointVelocity.GetCurveL    735   curve_length= CurveB_PointVelocity.GetCurveLength()
559               - CurveA_PointVelocity.GetCurveL    736               - CurveA_PointVelocity.GetCurveLength();  
560                                                   737  
561   G4double integrationInaccuracyLimit= std::ma << 738   G4double  integrationInaccuracyLimit= std::max( perMillion, 0.5*eps_step ); 
562   if( curve_length < ABdist * (1. - integratio    739   if( curve_length < ABdist * (1. - integrationInaccuracyLimit) )
563   {                                               740   { 
564 #ifdef G4DEBUG_FIELD                              741 #ifdef G4DEBUG_FIELD
565     G4cerr << " Warning in G4ChordFinder::Appr    742     G4cerr << " Warning in G4ChordFinder::ApproxCurvePoint: "
566            << G4endl                              743            << G4endl
567            << " The two points are further apa    744            << " The two points are further apart than the curve length "
568            << G4endl                              745            << G4endl
569            << " Dist = "         << ABdist        746            << " Dist = "         << ABdist
570            << " curve length = " << curve_leng    747            << " curve length = " << curve_length 
571            << " relativeDiff = " << (curve_len    748            << " relativeDiff = " << (curve_length-ABdist)/ABdist 
572            << G4endl;                             749            << G4endl;
573     if( curve_length < ABdist * (1. - 10*eps_s    750     if( curve_length < ABdist * (1. - 10*eps_step) )
574     {                                             751     {
575       std::ostringstream message;                 752       std::ostringstream message;
576       message << "Unphysical curve length." <<    753       message << "Unphysical curve length." << G4endl
577               << "The size of the above differ    754               << "The size of the above difference exceeds allowed limits."
578               << G4endl                           755               << G4endl
579               << "Aborting.";                     756               << "Aborting.";
580       G4Exception("G4ChordFinder::ApproxCurveP    757       G4Exception("G4ChordFinder::ApproxCurvePointV()", "GeomField0003",
581                   FatalException, message);       758                   FatalException, message);
582     }                                             759     }
583 #endif                                            760 #endif
584     // Take default corrective action: adjust     761     // Take default corrective action: adjust the maximum curve length. 
585     // NOTE: this case only happens for relati    762     // NOTE: this case only happens for relatively straight paths.
586     // curve_length = ABdist;                     763     // curve_length = ABdist; 
587   }                                               764   }
588                                                   765 
589   G4double new_st_length;                      << 766   G4double  new_st_length; 
590                                                   767 
591   if ( ABdist > 0.0 )                             768   if ( ABdist > 0.0 )
592   {                                               769   {
593      AE_fraction = ChordAE_Vector.mag() / ABdi    770      AE_fraction = ChordAE_Vector.mag() / ABdist;
594   }                                               771   }
595   else                                            772   else
596   {                                               773   {
597      AE_fraction = 0.5;                           774      AE_fraction = 0.5;                         // Guess .. ?; 
598 #ifdef G4DEBUG_FIELD                              775 #ifdef G4DEBUG_FIELD
599      G4cout << "Warning in G4ChordFinder::Appr    776      G4cout << "Warning in G4ChordFinder::ApproxCurvePointV():"
600             << " A and B are the same point!"     777             << " A and B are the same point!" << G4endl
601             << " Chord AB length = " << ChordA    778             << " Chord AB length = " << ChordAE_Vector.mag() << G4endl
602             << G4endl;                            779             << G4endl;
603 #endif                                            780 #endif
604   }                                               781   }
605                                                   782   
606   if( (AE_fraction> 1.0 + perMillion) || (AE_f    783   if( (AE_fraction> 1.0 + perMillion) || (AE_fraction< 0.) )
607   {                                               784   {
608 #ifdef G4DEBUG_FIELD                              785 #ifdef G4DEBUG_FIELD
609     G4cerr << " G4ChordFinder::ApproxCurvePoin    786     G4cerr << " G4ChordFinder::ApproxCurvePointV() - Warning:"
610            << " Anomalous condition:AE > AB or    787            << " Anomalous condition:AE > AB or AE/AB <= 0 " << G4endl
611            << "   AE_fraction = " <<  AE_fract    788            << "   AE_fraction = " <<  AE_fraction << G4endl
612            << "   Chord AE length = " << Chord    789            << "   Chord AE length = " << ChordAE_Vector.mag() << G4endl
613            << "   Chord AB length = " << ABdis    790            << "   Chord AB length = " << ABdist << G4endl << G4endl;
614     G4cerr << " OK if this condition occurs af    791     G4cerr << " OK if this condition occurs after a recalculation of 'B'"
615            << G4endl << " Otherwise it is an e    792            << G4endl << " Otherwise it is an error. " << G4endl ; 
616 #endif                                            793 #endif
617      // This course can now result if B has be    794      // This course can now result if B has been re-evaluated, 
618      // without E being recomputed (1 July 99)    795      // without E being recomputed (1 July 99).
619      // In this case this is not a "real error    796      // In this case this is not a "real error" - but it is undesired
620      // and we cope with it by a default corre    797      // and we cope with it by a default corrective action ...
621      //                                           798      //
622      AE_fraction = 0.5;                           799      AE_fraction = 0.5;                         // Default value
623   }                                               800   }
624                                                   801 
625   new_st_length = AE_fraction * curve_length;  << 802   new_st_length= AE_fraction * curve_length; 
626                                                   803 
627   if ( AE_fraction > 0.0 )                        804   if ( AE_fraction > 0.0 )
628   {                                               805   { 
629      fIntgrDriver->AccurateAdvance(Current_Poi    806      fIntgrDriver->AccurateAdvance(Current_PointVelocity, 
630                                    new_st_leng    807                                    new_st_length, eps_step );
631      //                                           808      //
632      // In this case it does not matter if it     809      // In this case it does not matter if it cannot advance the full distance
633   }                                               810   }
634                                                   811 
635   // If there was a memory of the step_length     812   // If there was a memory of the step_length actually required at the start 
636   // of the integration Step, this could be re    813   // of the integration Step, this could be re-used ...
637                                                   814 
638   G4cout.precision(14);                           815   G4cout.precision(14);
639                                                   816 
640   return Current_PointVelocity;                   817   return Current_PointVelocity;
641 }                                                 818 }
642                                                   819 
643 // ........................................... << 
644                                                   820 
645 std::ostream& operator<<( std::ostream& os, co << 821 // ......................................................................
                                                   >> 822 
                                                   >> 823 void
                                                   >> 824 G4ChordFinder::PrintStatistics()
646 {                                                 825 {
647    // Dumping the state of G4ChordFinder       << 826   // Print Statistics
648    os << "State of G4ChordFinder : " << std::e << 827 
649    os << "   delta_chord   = " <<  cf.fDeltaCh << 828   G4cout << "G4ChordFinder statistics report: " << G4endl;
650    os << "   Default d_c   = " <<  cf.fDefault << 829   G4cout 
                                                   >> 830     << "  No trials: " << fTotalNoTrials_FNC
                                                   >> 831     << "  No Calls: "  << fNoCalls_FNC
                                                   >> 832     << "  Max-trial: " <<  fmaxTrials_FNC
                                                   >> 833     << G4endl; 
                                                   >> 834   G4cout 
                                                   >> 835     << "  Parameters: " 
                                                   >> 836     << "  fFirstFraction "  << fFirstFraction
                                                   >> 837     << "  fFractionLast "   << fFractionLast
                                                   >> 838     << "  fFractionNextEstimate " << fFractionNextEstimate
                                                   >> 839     << G4endl; 
                                                   >> 840 }
                                                   >> 841 
651                                                   842 
652    os << "   stats-verbose = " <<  cf.fStatsVe << 843 // ...........................................................................
653                                                   844 
654    return os;                                  << 845 void G4ChordFinder::TestChordPrint( G4int    noTrials, 
                                                   >> 846                                     G4int    lastStepTrial, 
                                                   >> 847                                     G4double dChordStep, 
                                                   >> 848                                     G4double nextStepTrial )
                                                   >> 849 {
                                                   >> 850      G4int oldprec= G4cout.precision(5);
                                                   >> 851      G4cout << " ChF/fnc: notrial " << std::setw( 3) << noTrials 
                                                   >> 852             << " this_step= "       << std::setw(10) << lastStepTrial;
                                                   >> 853      if( std::fabs( (dChordStep / fDeltaChord) - 1.0 ) < 0.001 )
                                                   >> 854      {
                                                   >> 855        G4cout.precision(8);
                                                   >> 856      }
                                                   >> 857      else
                                                   >> 858      {
                                                   >> 859        G4cout.precision(6);
                                                   >> 860      }
                                                   >> 861      G4cout << " dChordStep=  " << std::setw(12) << dChordStep;
                                                   >> 862      if( dChordStep > fDeltaChord ) { G4cout << " d+"; }
                                                   >> 863      else                           { G4cout << " d-"; }
                                                   >> 864      G4cout.precision(5);
                                                   >> 865      G4cout <<  " new_step= "       << std::setw(10)
                                                   >> 866             << fLastStepEstimate_Unconstrained
                                                   >> 867             << " new_step_constr= " << std::setw(10)
                                                   >> 868             << lastStepTrial << G4endl;
                                                   >> 869      G4cout << " nextStepTrial = " << std::setw(10) << nextStepTrial << G4endl;
                                                   >> 870      G4cout.precision(oldprec);
655 }                                                 871 }
656                                                   872