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 3.2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                    <<   3 // * DISCLAIMER                                                       *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th <<   5 // * The following disclaimer summarizes all the specific disclaimers *
  6 // * the Geant4 Collaboration.  It is provided <<   6 // * of contributors to this software. The specific disclaimers,which *
  7 // * conditions of the Geant4 Software License <<   7 // * govern, are listed with their locations in:                      *
  8 // * LICENSE and available at  http://cern.ch/ <<   8 // *   http://cern.ch/geant4/license                                  *
  9 // * include a list of copyright holders.      << 
 10 // *                                                9 // *                                                                  *
 11 // * Neither the authors of this software syst     10 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     11 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     12 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     13 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  <<  14 // * use.                                                             *
 16 // * for the full disclaimer and the limitatio << 
 17 // *                                               15 // *                                                                  *
 18 // * This  code  implementation is the result  <<  16 // * This  code  implementation is the  intellectual property  of the *
 19 // * technical work of the GEANT4 collaboratio <<  17 // * GEANT4 collaboration.                                            *
 20 // * By using,  copying,  modifying or  distri <<  18 // * By copying,  distributing  or modifying the Program (or any work *
 21 // * any work based  on the software)  you  ag <<  19 // * based  on  the Program)  you indicate  your  acceptance of  this *
 22 // * use  in  resulting  scientific  publicati <<  20 // * statement, and all its terms.                                    *
 23 // * acceptance of all terms of the Geant4 Sof << 
 24 // *******************************************     21 // ********************************************************************
 25 //                                                 22 //
 26 // G4ChordFinder implementation                << 
 27 //                                                 23 //
 28 // Author: J.Apostolakis - Design and implemen <<  24 // $Id: G4ChordFinder.cc,v 1.18.2.1 2001/06/28 19:08:18 gunter Exp $
 29 // ------------------------------------------- <<  25 // GEANT4 tag $Name:  $
 30                                                <<  26 //
 31 #include <iomanip>                             <<  27 //
                                                   >>  28 // 25.02.97 John Apostolakis,  design and implimentation 
                                                   >>  29 // 05.03.97 V. Grichine , style modification
 32                                                    30 
 33 #include "G4ChordFinder.hh"                        31 #include "G4ChordFinder.hh"
 34 #include "G4SystemOfUnits.hh"                  <<  32 #include "G4MagIntegratorDriver.hh"
 35 #include "G4MagneticField.hh"                  << 
 36 #include "G4Mag_UsualEqRhs.hh"                     33 #include "G4Mag_UsualEqRhs.hh"
                                                   >>  34 #include "G4ClassicalRK4.hh"
                                                   >>  35 // #include "G4Field.hh"
                                                   >>  36                                        // #include "G4MagIntegratorStepper.hh"
 37 #include "G4MagIntegratorDriver.hh"                37 #include "G4MagIntegratorDriver.hh"
 38 // #include "G4ClassicalRK4.hh"                <<  38 #include "g4std/iomanip"
 39 // #include "G4CashKarpRKF45.hh"               << 
 40 // #include "G4NystromRK4.hh"                  << 
 41 // #include "G4BogackiShampine23.hh"           << 
 42 // #include "G4BogackiShampine45.hh"           << 
 43                                                    39 
 44 #include "G4DormandPrince745.hh"               <<  40 //  For the moment fDeltaChord is a constant!
 45                                                    41 
 46 // New templated stepper(s) -- avoid virtual c <<  42 const G4double G4ChordFinder::fDefaultDeltaChord  = 3. * mm; 
 47 #include "G4TDormandPrince45.hh"               << 
 48                                                    43 
 49 // FSAL type driver / steppers -----           <<  44 // ..........................................................................
 50 #include "G4FSALIntegrationDriver.hh"          << 
 51 #include "G4VFSALIntegrationStepper.hh"        << 
 52 #include "G4RK547FEq1.hh"                      << 
 53 // #include "G4RK547FEq2.hh"                   << 
 54 // #include "G4RK547FEq3.hh"                   << 
 55 // #include "G4FSALBogackiShampine45.hh"       << 
 56 // #include "G4FSALDormandPrince745.hh"        << 
 57                                                << 
 58 // Templated type drivers -----                << 
 59 #include "G4IntegrationDriver.hh"              << 
 60 #include "G4InterpolationDriver.hh"            << 
 61                                                    45 
 62 #include "G4HelixHeum.hh"                      <<  46 G4ChordFinder::G4ChordFinder( G4MagneticField*        theMagField,
 63 #include "G4BFieldIntegrationDriver.hh"        <<  47                   G4double                stepMinimum, 
                                                   >>  48                   G4MagIntegratorStepper* pItsStepper ) // A default one
                                                   >>  49      : fDeltaChord( fDefaultDeltaChord )
                                                   >>  50 {
                                                   >>  51   //  Construct the Chord Finder
                                                   >>  52   //  by creating in inverse order the  Driver, the Stepper and EqRhs ...
                                                   >>  53   G4Mag_EqRhs *pEquation = new G4Mag_UsualEqRhs(theMagField);
                                                   >>  54   fEquation = pEquation;                            
                                                   >>  55   fLastStepEstimate_Unconstrained = DBL_MAX;          // Should move q, p to
                                                   >>  56                                                       //    G4FieldTrack ??
                                                   >>  57   // --->>  Charge    Q = 0 
                                                   >>  58   // --->>  Momentum  P = 1       NOMINAL VALUES !!!!!!!!!!!!!!!!!!
 64                                                    59 
 65 #include "G4QSSDriverCreator.hh"               <<  60   if( pItsStepper == 0 )
                                                   >>  61   { 
                                                   >>  62      pItsStepper = fDriversStepper = new G4ClassicalRK4(pEquation);
                                                   >>  63      fAllocatedStepper= true;
                                                   >>  64   }
                                                   >>  65   else
                                                   >>  66   {
                                                   >>  67      fAllocatedStepper= false; 
                                                   >>  68   }
                                                   >>  69   fIntgrDriver = new G4MagInt_Driver(stepMinimum, 
                                                   >>  70              pItsStepper, 
                                                   >>  71              pItsStepper->GetNumberOfVariables() );
                                                   >>  72 }
 66                                                    73 
 67 #include "G4CachedMagneticField.hh"            <<  74 // ......................................................................
 68                                                    75 
 69 #include <cassert>                             <<  76 G4ChordFinder::~G4ChordFinder()
 70 #include <memory>                              <<  77 {
                                                   >>  78   delete   fEquation; // fIntgrDriver->pIntStepper->theEquation_Rhs;
                                                   >>  79   if( fAllocatedStepper)
                                                   >>  80   { 
                                                   >>  81      delete fDriversStepper; 
                                                   >>  82   }                                //  fIntgrDriver->pIntStepper;}
                                                   >>  83   delete   fIntgrDriver; 
                                                   >>  84 }
 71                                                    85 
 72 G4bool G4ChordFinder::gVerboseCtor = false;    <<  86 // ......................................................................
 73 // ........................................... << 
 74                                                    87 
 75 G4ChordFinder::G4ChordFinder(G4VIntegrationDri <<  88 G4double 
 76   : fDefaultDeltaChord(0.25 * mm), fIntgrDrive <<  89 G4ChordFinder::AdvanceChordLimited( G4FieldTrack& yCurrent,
                                                   >>  90             G4double      stepMax,
                                                   >>  91             G4double      epsStep )
 77 {                                                  92 {
 78   // Simple constructor -- it does not create  <<  93   G4double stepPossible;
 79   if( gVerboseCtor )                           <<  94   G4double dyErr;
                                                   >>  95   G4FieldTrack yEnd( yCurrent);
                                                   >>  96   G4double  startCurveLen= yCurrent.GetCurveLength();
                                                   >>  97   G4bool dbg= false; 
                                                   >>  98 
                                                   >>  99 #ifdef G4VERBOSE
                                                   >> 100   if( dbg ) 
                                                   >> 101     G4cerr << "Entered AdvanceChordLimited with:\n yCurrent: " << yCurrent
                                                   >> 102      << " and initial Step=stepMax=" <<  stepMax << " mm. " << G4endl;
                                                   >> 103 #endif
                                                   >> 104 
                                                   >> 105   stepPossible= FindNextChord(yCurrent, stepMax, yEnd, dyErr, epsStep);
                                                   >> 106   G4bool good_advance;
                                                   >> 107   if ( dyErr < epsStep * stepPossible )
                                                   >> 108   {
                                                   >> 109      // Accept this accuracy.
                                                   >> 110      yCurrent = yEnd;
                                                   >> 111      good_advance = true; 
                                                   >> 112   }
                                                   >> 113   else
 80   {                                               114   {
 81     G4cout << "G4ChordFinder: Simple construct << 115      // Advance more accurately to "end of chord"
                                                   >> 116      good_advance = fIntgrDriver->AccurateAdvance(yCurrent, stepPossible, epsStep);
                                                   >> 117      #ifdef G4VERBOSE
                                                   >> 118      if (dbg) G4cerr << "Accurate advance to end of chord attemped"
                                                   >> 119            << "with result " << good_advance << G4endl ;
                                                   >> 120      #endif
                                                   >> 121      if ( ! good_advance ){ 
                                                   >> 122        // In this case the driver could not do the full distance
                                                   >> 123        stepPossible= yCurrent.GetCurveLength()-startCurveLen;
                                                   >> 124      }
 82   }                                               125   }
 83                                                << 126 
 84   fDeltaChord = fDefaultDeltaChord;       // P << 127 #ifdef G4VERBOSE
                                                   >> 128   if( dbg ) G4cerr << "Exiting FindNextChord Limited with:\n yCurrent: " 
                                                   >> 129      << yCurrent<< G4endl; 
                                                   >> 130 #endif
                                                   >> 131 
                                                   >> 132   return stepPossible;
 85 }                                                 133 }
 86                                                   134 
 87 // ........................................... << 135 // #define  TEST_CHORD_PRINT  1
 88                                                   136 
 89 G4ChordFinder::G4ChordFinder( G4MagneticField* << 137 // ..............................................................................
 90                               G4double         << 138 
 91                               G4MagIntegratorS << 139 G4double
 92                               G4int            << 140 G4ChordFinder::FindNextChord( const  G4FieldTrack  yStart,
 93   : fDefaultDeltaChord(0.25 * mm)              << 141                         G4double     stepMax,
                                                   >> 142                         G4FieldTrack&   yEnd,      //  Endpoint
                                                   >> 143                         G4double&      dyErr,      //  Error of endpoint 
                                                   >> 144             G4double     epsStep )
                                                   >> 145       
                                                   >> 146 // Returns Length of Step taken
 94 {                                                 147 {
 95   // Construct the Chord Finder                << 148   // G4int       stepRKnumber=0;
 96   // by creating in inverse order the Driver,  << 149   G4FieldTrack yCurrent=  yStart;  
 97   constexpr G4int nVar6 = 6;   // Components i << 150   G4double    stepTrial;
                                                   >> 151   G4double    dydx[G4FieldTrack::ncompSVEC]; 
                                                   >> 152 
                                                   >> 153   //  1.)  Try to "leap" to end of interval
                                                   >> 154   //  2.)  Evaluate if resulting chord gives d_chord that is good enough.
                                                   >> 155   //     2a.)  If d_chord is not good enough, find one that is.
 98                                                   156   
 99   fDeltaChord = fDefaultDeltaChord;       // P << 157   G4bool    validEndPoint= false;
                                                   >> 158   G4double  dChordStep, oldStepTrial, stepOfLastGoodChord;
100                                                   159 
101   G4cout << " G4ChordFinder: stepperDriverId:  << 160   fIntgrDriver-> GetDerivatives( yCurrent, dydx )  ;
102                                                   161 
103   G4bool useFSALstepper     = (stepperDriverId << 162   G4int     noTrials=0;
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                                                   163 
115   using EquationType = G4Mag_UsualEqRhs;       << 164   stepTrial = G4std::min( stepMax, 
116                                                << 165         (1-perThousand)*fLastStepEstimate_Unconstrained );
117   using TemplatedStepperType =                 << 
118          G4TDormandPrince45<EquationType,nVar6 << 
119   const char* TemplatedStepperName =           << 
120       "G4TDormandPrince745 (templated Dormand- << 
121                                                << 
122   using RegularStepperType =                   << 
123          G4DormandPrince745; // 5th order embe << 
124          // G4ClassicalRK4;        // The old  << 
125          // G4CashKarpRKF45;       // First em << 
126          // G4BogackiShampine45;   // High eff << 
127          // G4NystromRK4;          // Nystrom  << 
128          // G4RK547FEq1;  // or 2 or 3         << 
129   const char* RegularStepperName =             << 
130       "G4DormandPrince745 (aka DOPRI5): 5th/4t << 
131       // "BogackiShampine 45 (Embedded 5th/4th << 
132       // "Nystrom stepper 4th order";          << 
133                                                << 
134   using NewFsalStepperType = G4DormandPrince74 << 
135                                                << 
136   const char* NewFSALStepperName =             << 
137       "G4RK574FEq1> FSAL 4th/5th order 7-stage << 
138                                                << 
139 #ifdef G4DEBUG_FIELD                           << 
140   static G4bool verboseDebug = true;           << 
141   if( verboseDebug )                           << 
142   {                                            << 
143      G4cout << "G4ChordFinder 2nd Constructor  << 
144      G4cout << " Arguments: " << G4endl        << 
145             << " - min step = " << stepMinimum << 
146             << " - stepper ptr provided : "    << 
147             << ( pItsStepper==nullptr ? " no   << 
148      if( pItsStepper==nullptr )                << 
149         G4cout << " - stepper/driver Id = " << << 
150                << "  useFSAL = " << useFSALste << 
151                << "  , useTemplated = " << use << 
152                << "  , useRegular = " << useRe << 
153                << "  , useFSAL = " << useFSALs << 
154                << G4endl;                      << 
155   }                                            << 
156 #endif                                         << 
157                                                   166 
158   // useHigherStepper = forceHigherEffiencySte << 167   do
                                                   >> 168   { 
                                                   >> 169      G4double stepForChord; // , stepForAccuracy;
                                                   >> 170  
                                                   >> 171      yCurrent = yStart;    // Always start from initial point
159                                                   172 
160   auto  pEquation = new G4Mag_UsualEqRhs(theMa << 173      fIntgrDriver->QuickAdvance( yCurrent, dydx, stepTrial, dChordStep, dyErr);
161   fEquation = pEquation;                       << 
162                                                   174 
163   // G4MagIntegratorStepper* regularStepper =  << 175      // First debug print
164   // G4VFSALIntegrationStepper* fsalStepper =  << 
165   // G4MagIntegratorStepper* oldFSALStepper =  << 
166                                                   176 
167   G4bool errorInStepperCreation = false;       << 177      // We check whether the criterion is met here.
                                                   >> 178      validEndPoint = AcceptableMissDist(dChordStep); 
                                                   >> 179                       //  && (dyErr < eps) ;
168                                                   180 
169   std::ostringstream message;  // In case of f << 181      oldStepTrial = stepTrial; 
170                                                   182 
171   if( pItsStepper != nullptr )                 << 183      // This method estimates to step size for a good chord.
172   {                                            << 184      stepForChord = NewStep(stepTrial, dChordStep, fLastStepEstimate_Unconstrained );
173      if( gVerboseCtor )                        << 
174      {                                         << 
175        G4cout << " G4ChordFinder: Creating G4I << 
176               << " stepMinimum = " << stepMini << 
177               << " numVar= " << pItsStepper->G << 
178      }                                         << 
179                                                   185 
180      // Stepper type is not known - so must us << 186      if( ! validEndPoint ) {
181       if(pItsStepper->isQSS())                 << 187    stepTrial = stepForChord;
182       {                                        << 188 #if 0
183          // fIntgrDriver = pItsStepper->build_ << 189          // Possible complementary approach:
184          G4Exception("G4ChordFinder::G4ChordFi << 190    //  Get the driver to calculate the new step size, if it is needed
185                       "GeomField1001", FatalEx << 191    stepForAccuracy = fIntgrDriver->ComputeNewStepSize( dyErr/(epsStep*oldStepTrial), 
186                       "Cannot provide  QSS ste << 192                    stepTrial);
187       }                                        << 193    stepTrial = G4std::min(stepForChord, stepForAccuracy);
188       else                                     << 194 #endif
189       {                                        << 195 
190          fIntgrDriver = new G4IntegrationDrive << 196    // if(dbg) G4cerr<<"Dchord too big. Try new hstep="<<stepTrial<<G4endl;
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      //                                        << 
213      // Alternative - for G4NystromRK4:        << 
214      // = new G4NystromRK4(pEquation, 0.1*mm ) << 
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;    << 
239                                                << 
240      if( gVerboseCtor )                        << 
241      {                                         << 
242         G4cout << " G4ChordFinder: Creating Dr << 
243      }                                         << 
244                                                << 
245      if( regularStepper == nullptr )           << 
246      {                                         << 
247         message << "Regular Stepper instantiat << 
248         message << "G4ChordFinder: Attempted t << 
249                 << RegularStepperName << " typ << 
250         errorInStepperCreation = true;         << 
251      }                                         << 
252      else                                      << 
253      {                                         << 
254         auto dp5= dynamic_cast<G4DormandPrince << 
255         if( dp5 != nullptr )                   << 
256         {                                      << 
257            fIntgrDriver = new G4InterpolationD << 
258                                   stepMinimum, << 
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                                                << 
286         fLongStepper = std::make_unique<G4Heli << 
287                                                << 
288         fIntgrDriver = new G4BFieldIntegration << 
289           std::make_unique<SmallStepDriver>(st << 
290               regularStepper, regularStepper-> << 
291           std::make_unique<LargeStepDriver>(st << 
292               fLongStepper.get(), regularStepp << 
293                                                << 
294         if( fIntgrDriver == nullptr)           << 
295         {                                      << 
296            message << "Using G4BFieldIntegrati << 
297                    << RegularStepperName << "  << 
298            message << "Driver instantiation FA << 
299            G4Exception("G4ChordFinder::G4Chord << 
300                        "GeomField1001", JustWa << 
301         }                                      << 
302      }                                         << 
303   }                                            << 
304   else if( useG4QSSDriver )                    << 
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      }                                            197      }
328   }                                            << 198 #ifdef  TEST_CHORD_PRINT
329   else                                         << 199      G4cout.precision(5);
330   {                                            << 200      G4cout << " ChF/fnc: notrial " << G4std::setw( 3) << noTrials 
331      auto fsalStepper=  new NewFsalStepperType << 201             << " this_step= "       << G4std::setw(10) << oldStepTrial;
332      //                 *** ****************** << 202      if( fabs( (dChordStep / fDeltaChord) - 1.0 ) < 0.001 ){
333      fNewFSALStepperOwned = fsalStepper;       << 203        G4cout.precision(8);
334                                                << 204        G4cout << " dChordStep=  "     << G4std::setw(12) << dChordStep;
335      if( fsalStepper == nullptr )              << 205      }else{
336      {                                         << 206        G4cout.precision(6);
337         message << "Stepper instantiation FAIL << 207        G4cout << " dChordStep=  "     << G4std::setw(12) << dChordStep;
338         message << "Attempted to instantiate " << 
339                 << NewFSALStepperName << " typ << 
340         G4Exception("G4ChordFinder::G4ChordFin << 
341                     "GeomField1001", JustWarni << 
342         errorInStepperCreation = true;         << 
343      }                                            208      }
                                                   >> 209      if( dChordStep > fDeltaChord )
                                                   >> 210   G4cout << " d+";
344      else                                         211      else
345      {                                         << 212   G4cout << " d-";
346         fIntgrDriver = new                     << 213      G4cout.precision(5);
347            G4FSALIntegrationDriver<NewFsalStep << 214      G4cout <<  " new_step= "        << G4std::setw(10) << fLastStepEstimate_Unconstrained
348                                           fsal << 215             << " new_step_constr= " << G4std::setw(10) << stepTrial << endl;
349            //  ====  Create the driver which k << 216 #endif
350                                                << 217      noTrials++; 
351         if( fIntgrDriver == nullptr )          << 
352         {                                      << 
353            message << "Using G4FSALIntegration << 
354                    << NewFSALStepperName << G4 << 
355            message << "Integration Driver inst << 
356            G4Exception("G4ChordFinder::G4Chord << 
357                        "GeomField1001", JustWa << 
358         }                                      << 
359      }                                         << 
360   }                                               218   }
                                                   >> 219   while( ! validEndPoint );   // End of do-while  RKD 
361                                                   220 
362   // -- Main work is now done                  << 221   stepOfLastGoodChord = stepTrial;
363                                                << 222 #ifdef  TEST_CHORD_PRINT
364   //    Now check that no error occured, and r << 223   G4cout << "ChordF/FindNextChord:  NoTrials= " << noTrials 
365                                                << 224    << " StepForGoodChord=" << G4std::setw(10) << stepTrial << endl;
366   // To test failure to create driver          << 225 #endif
367   // delete fIntgrDriver;                      << 
368   // fIntgrDriver = nullptr;                   << 
369                                                << 
370   // Detect and report Error conditions        << 
371   //                                           << 
372   if( errorInStepperCreation || (fIntgrDriver  << 
373   {                                            << 
374      std::ostringstream errmsg;                << 
375                                                << 
376      if( errorInStepperCreation )              << 
377      {                                         << 
378         errmsg  << "ERROR> Failure to create S << 
379                 << "       ------------------- << 
380      }                                         << 
381      if (fIntgrDriver == nullptr )             << 
382      {                                         << 
383         errmsg  << "ERROR> Failure to create I << 
384                 << G4endl                      << 
385                 << "       ------------------- << 
386                 << G4endl;                     << 
387      }                                         << 
388      const std::string BoolName[2]= { "False", << 
389      errmsg << "  Configuration:  (constructor << 
390             << "    provided Stepper = " << pI << 
391             << " stepper/driver Id = " << step << 
392             << "   useTemplated = " << BoolNam << 
393             << "   useRegular = " << BoolName[ << 
394             << "   useFSAL = " << BoolName[use << 
395             << "   using combo BField Driver = << 
396                    BoolName[ ! (useFSALstepper << 
397                                || useRegularSt << 
398             << G4endl;                         << 
399      errmsg << message.str();                  << 
400      errmsg << "Aborting.";                    << 
401      G4Exception("G4ChordFinder::G4ChordFinder << 
402                  "GeomField0003", FatalExcepti << 
403   }                                            << 
404                                                << 
405   assert(    ( pItsStepper != nullptr )        << 
406           || ( fRegularStepperOwned != nullptr << 
407           || ( fNewFSALStepperOwned != nullptr << 
408           || useG4QSSDriver                    << 
409      );                                        << 
410   assert( fIntgrDriver != nullptr );           << 
411 }                                              << 
412                                                << 
413 // ........................................... << 
414                                                   226 
415 G4ChordFinder::~G4ChordFinder()                << 227   yEnd=  yCurrent;  
416 {                                              << 228   return stepTrial; 
417   delete fEquation;                            << 
418   delete fRegularStepperOwned;                 << 
419   delete fNewFSALStepperOwned;                 << 
420   delete fCachedField;                         << 
421   delete fIntgrDriver;                         << 
422 }                                                 229 }
423                                                   230 
                                                   >> 231 // ----------------------------------------------------------------------------
                                                   >> 232 #if 0          
                                                   >> 233        // First debug print             //    older OPTIONAL code 
                                                   >> 234 //   #ifdef G4VERBOSE
                                                   >> 235      if( dbg ) {
                                                   >> 236         G4cerr << "Returned from QuickAdvance with: yCur=" << yCurrent <<G4endl;
                                                   >> 237         G4cerr << " dChordStep= "<< dChordStep <<" dyErr=" << dyErr << G4endl; 
                                                   >> 238      }
                                                   >> 239 #endif
                                                   >> 240 // ----------------------------------------------------------------------------
                                                   >> 241 
424 // ...........................................    242 // ...........................................................................
425                                                   243 
426 G4FieldTrack                                   << 244 G4double G4ChordFinder::NewStep(G4double  stepTrialOld, 
427 G4ChordFinder::ApproxCurvePointS( const G4Fiel << 245                     G4double  dChordStep, // Current dchord achieved.
428                                   const G4Fiel << 246                                 G4double& stepEstimate_Unconstrained )  
429                                   const G4Fiel << 247        
430                                   const G4Thre << 
431                                   const G4Thre << 
432                                   const G4Thre << 
433                                         G4bool << 
434 {                                                 248 {
435   // ApproxCurvePointS is 2nd implementation o << 249   G4double stepTrial;
436   // Use Brent Algorithm (or InvParabolic) whe << 250   static G4double lastStepTrial = 1.,  lastDchordStep= 1.;
437   // Given a starting curve point A (CurveA_Po << 
438   // (CurveB_PointVelocity), a point E which i << 
439   // and  a point F which is on the curve (fir << 
440   // point S on the curve closer to point E.   << 
441   // While advancing towards S utilise 'eps_st << 
442   // relative accuracy of each Step.           << 
443                                                << 
444   G4FieldTrack EndPoint(CurveA_PointVelocity); << 
445   if(!first) { EndPoint = ApproxCurveV; }      << 
446                                                << 
447   G4ThreeVector Point_A,Point_B;               << 
448   Point_A=CurveA_PointVelocity.GetPosition();  << 
449   Point_B=CurveB_PointVelocity.GetPosition();  << 
450                                                   251 
451   G4double xa,xb,xc,ya,yb,yc;                  << 252 #if 1 
452                                                << 253   const G4double  threshold = 1.21, multiplier = 0.9;   //  0.9 < 1 / sqrt(1.21)
453   // InverseParabolic. AF Intersects (First Pa << 
454                                                   254 
455   if(first)                                    << 
456   {                                            << 
457     xa=0.;                                     << 
458     ya=(PointG-Point_A).mag();                 << 
459     xb=(Point_A-CurrentF_Point).mag();         << 
460     yb=-(PointG-CurrentF_Point).mag();         << 
461     xc=(Point_A-Point_B).mag();                << 
462     yc=-(CurrentE_Point-Point_B).mag();        << 
463   }                                            << 
464   else                                         << 
465   {                                            << 
466     xa=0.;                                     << 
467     ya=(Point_A-CurrentE_Point).mag();         << 
468     xb=(Point_A-CurrentF_Point).mag();         << 
469     yb=(PointG-CurrentF_Point).mag();          << 
470     xc=(Point_A-Point_B).mag();                << 
471     yc=-(Point_B-PointG).mag();                << 
472     if(xb==0.)                                 << 
473     {                                          << 
474       EndPoint = ApproxCurvePointV(CurveA_Poin << 
475                                    CurrentE_Po << 
476       return EndPoint;                         << 
477     }                                          << 
478   }                                            << 
479                                                   255 
480   const G4double tolerance = 1.e-12;           << 256   stepEstimate_Unconstrained = stepTrialOld * sqrt( fDeltaChord / dChordStep );
481   if(std::abs(ya)<=tolerance||std::abs(yc)<=to << 257   stepTrial =  0.98 * stepEstimate_Unconstrained;
482   {                                            << 258 
483     ; // What to do for the moment: return the << 259   if ( dChordStep < threshold * fDeltaChord ){
484       // then PropagatorInField will take care << 260      stepTrial= stepTrialOld *  multiplier;    
485   }                                               261   }
486   else                                         << 
487   {                                            << 
488     G4double test_step = InvParabolic(xa,ya,xb << 
489     G4double curve;                            << 
490     if(first)                                  << 
491     {                                          << 
492       curve=std::abs(EndPoint.GetCurveLength() << 
493                     -ApproxCurveV.GetCurveLeng << 
494     }                                          << 
495     else                                       << 
496     {                                          << 
497       test_step = test_step - xb;              << 
498       curve=std::abs(EndPoint.GetCurveLength() << 
499                     -CurveB_PointVelocity.GetC << 
500       xb = (CurrentF_Point-Point_B).mag();     << 
501     }                                          << 
502                                                << 
503     if(test_step<=0)    { test_step=0.1*xb; }  << 
504     if(test_step>=xb)   { test_step=0.5*xb; }  << 
505     if(test_step>=curve){ test_step=0.5*curve; << 
506                                                << 
507     if(curve*(1.+eps_step)<xb) // Similar to R << 
508     {                          // G4VIntersect << 
509       test_step=0.5*curve;                     << 
510     }                                          << 
511                                                   262 
512     fIntgrDriver->AccurateAdvance(EndPoint,tes << 263   lastStepTrial = stepTrialOld; 
513                                                << 264   lastDchordStep= dChordStep;
514 #ifdef G4DEBUG_FIELD                           << 265 #else
515     // Printing Brent and Linear Approximation << 266   if ( dChordStep > 1000. * fDeltaChord ){
516     //                                         << 267         stepTrial= stepTrialOld * 0.03;   
517     G4cout << "G4ChordFinder::ApproxCurvePoint << 268   }else{
518            << test_step << "  EndPoint = " <<  << 269      if ( dChordStep > 100. * fDeltaChord ){
519                                                << 270   stepTrial= stepTrialOld * 0.1;   
520     //  Test Track                             << 271      }else{
521     //                                         << 272         // Keep halving the length until dChordStep OK
522     G4FieldTrack TestTrack( CurveA_PointVeloci << 273   stepTrial= stepTrialOld * 0.5;   
523     TestTrack = ApproxCurvePointV( CurveA_Poin << 274      }
524                                    CurveB_Poin << 
525                                    CurrentE_Po << 
526     G4cout.precision(14);                      << 
527     G4cout << "G4ChordFinder::BrentApprox = "  << 
528     G4cout << "G4ChordFinder::LinearApprox= "  << 
529 #endif                                         << 
530   }                                               275   }
531   return EndPoint;                             << 276 #endif 
532 }                                              << 
533                                                   277 
                                                   >> 278   // A more sophisticated chord-finder could figure out a better
                                                   >> 279   //   stepTrial, from dChordStep and the required d_geometry
                                                   >> 280   //   eg
                                                   >> 281   //      Calculate R, r_helix (eg at orig point)
                                                   >> 282   //      if( stepTrial < 2 pi  R )
                                                   >> 283   //          stepTrial = R arc_cos( 1 - fDeltaChord / r_helix )
                                                   >> 284   //      else    
                                                   >> 285   //          ??
534                                                   286 
535 // ........................................... << 287   return stepTrial;
                                                   >> 288 }
536                                                   289 
537 G4FieldTrack G4ChordFinder::                   << 290 //
538 ApproxCurvePointV( const G4FieldTrack& CurveA_ << 291 //   Given a starting curve point A (CurveA_PointVelocity),  a later 
539                    const G4FieldTrack& CurveB_ << 292 //  curve point B (CurveB_PointVelocity) and a point E which is (generally)
540                    const G4ThreeVector& Curren << 293 //  not on the curve, find and return a point F which is on the curve and 
541                          G4double eps_step)    << 294 //  which is close to E. While advancing towards F utilise eps_step 
                                                   >> 295 //  as a measure of the relative accuracy of each Step.
                                                   >> 296   
                                                   >> 297 G4FieldTrack G4ChordFinder::ApproxCurvePointV( 
                                                   >> 298             const G4FieldTrack& CurveA_PointVelocity, 
                                                   >> 299             const G4FieldTrack& CurveB_PointVelocity, 
                                                   >> 300             const G4ThreeVector& CurrentE_Point,
                                                   >> 301                   G4double eps_step)
542 {                                                 302 {
543   // If r=|AE|/|AB|, and s=true path lenght (A << 303   // 1st implementation:
544   // return the point that is r*s along the cu << 304   //    if r=|AE|/|AB|, and s=true path lenght (AB)
545                                                << 305   //    return the point that is r*s along the curve!
546   G4FieldTrack   Current_PointVelocity = Curve << 306 
                                                   >> 307   G4FieldTrack    Current_PointVelocity= CurveA_PointVelocity; 
547                                                   308 
548   G4ThreeVector  CurveA_Point= CurveA_PointVel    309   G4ThreeVector  CurveA_Point= CurveA_PointVelocity.GetPosition();
549   G4ThreeVector  CurveB_Point= CurveB_PointVel    310   G4ThreeVector  CurveB_Point= CurveB_PointVelocity.GetPosition();
550                                                   311 
551   G4ThreeVector  ChordAB_Vector= CurveB_Point     312   G4ThreeVector  ChordAB_Vector= CurveB_Point   - CurveA_Point;
552   G4ThreeVector  ChordAE_Vector= CurrentE_Poin    313   G4ThreeVector  ChordAE_Vector= CurrentE_Point - CurveA_Point;
553                                                   314 
554   G4double       ABdist= ChordAB_Vector.mag();    315   G4double       ABdist= ChordAB_Vector.mag();
555   G4double  curve_length;  //  A curve length     316   G4double  curve_length;  //  A curve length  of AB
556   G4double  AE_fraction;                          317   G4double  AE_fraction; 
557                                                   318   
558   curve_length= CurveB_PointVelocity.GetCurveL << 319   curve_length= 
559               - CurveA_PointVelocity.GetCurveL << 320        CurveB_PointVelocity.GetCurveLength() - CurveA_PointVelocity.GetCurveLength();  
560                                                << 321 
561   G4double integrationInaccuracyLimit= std::ma << 322   // const 
562   if( curve_length < ABdist * (1. - integratio << 323   G4double  integrationInaccuracyLimit= G4std::max( perMillion, 0.5*eps_step ); 
563   {                                            << 324   if( curve_length < ABdist * (1. - integrationInaccuracyLimit) ){ 
564 #ifdef G4DEBUG_FIELD                           << 325 //  #ifdef G4DEBUG
565     G4cerr << " Warning in G4ChordFinder::Appr << 326     G4cerr << " Warning in G4ChordFinder::ApproxCurvePoint: " << G4endl <<
566            << G4endl                           << 327       " The two points are further apart than the curve length " << G4endl <<
567            << " The two points are further apa << 328       " Dist = "         << ABdist  << 
568            << G4endl                           << 329       " curve length = " << curve_length 
569            << " Dist = "         << ABdist     << 330      << " relativeDiff = " << (curve_length-ABdist)/ABdist 
570            << " curve length = " << curve_leng << 331      << G4endl;
571            << " relativeDiff = " << (curve_len << 332 //  #endif
572            << G4endl;                          << 333     if( curve_length < ABdist * (1. - 10*eps_step) ) {
573     if( curve_length < ABdist * (1. - 10*eps_s << 334 //    #ifdef G4DEBUG
574     {                                          << 335       G4cerr << " ERROR: the size of the above difference exceeds allowed limits.  Aborting." 
575       std::ostringstream message;              << 336        << G4endl;
576       message << "Unphysical curve length." << << 337 //    #endif
577               << "The size of the above differ << 338       G4Exception("G4ChordFinder::ApproxCurvePoint> Unphysical curve length.");
578               << G4endl                        << 
579               << "Aborting.";                  << 
580       G4Exception("G4ChordFinder::ApproxCurveP << 
581                   FatalException, message);    << 
582     }                                             339     }
583 #endif                                         << 340     // Take default corrective action: 
584     // Take default corrective action: adjust  << 341     //    -->  adjust the maximum curve length. 
585     // NOTE: this case only happens for relati << 342     //  NOTE: this case only happens for relatively straight paths.
586     // curve_length = ABdist;                  << 343     curve_length = ABdist; 
587   }                                               344   }
588                                                   345 
589   G4double new_st_length;                      << 346   G4double  new_st_length; 
590                                                   347 
591   if ( ABdist > 0.0 )                          << 348   if ( ABdist > 0.0 ){
592   {                                            << 
593      AE_fraction = ChordAE_Vector.mag() / ABdi    349      AE_fraction = ChordAE_Vector.mag() / ABdist;
594   }                                            << 350   }else{
595   else                                         << 351      G4cerr << " Error in G4ChordFinder::ApproxCurvePoint: A and B are the same point\n" <<
596   {                                            << 352       " Chord AB length = " << ChordAE_Vector.mag()  << G4endl << G4endl;
597      AE_fraction = 0.5;                           353      AE_fraction = 0.5;                         // Guess .. ?; 
598 #ifdef G4DEBUG_FIELD                           << 
599      G4cout << "Warning in G4ChordFinder::Appr << 
600             << " A and B are the same point!"  << 
601             << " Chord AB length = " << ChordA << 
602             << G4endl;                         << 
603 #endif                                         << 
604   }                                               354   }
605                                                   355   
606   if( (AE_fraction> 1.0 + perMillion) || (AE_f << 356   if( (AE_fraction> 1.0 + perMillion) || (AE_fraction< 0.) ){
607   {                                            << 357     G4cerr << " G4ChordFinder::ApproxCurvePointV: Warning: Anomalous condition:AE > AB or AE/AB <= 0 " << G4endl <<
608 #ifdef G4DEBUG_FIELD                           << 358       "   AE_fraction = " <<  AE_fraction << G4endl <<
609     G4cerr << " G4ChordFinder::ApproxCurvePoin << 359       "   Chord AE length = " << ChordAE_Vector.mag()  << G4endl << 
610            << " Anomalous condition:AE > AB or << 360       "   Chord AB length = " << ABdist << G4endl << G4endl;
611            << "   AE_fraction = " <<  AE_fract << 361     G4cerr << " OK if this condition occurs after a recalculation of 'B'" << G4endl
612            << "   Chord AE length = " << Chord << 362      << " Otherwise it is an error. " << G4endl ; 
613            << "   Chord AB length = " << ABdis << 
614     G4cerr << " OK if this condition occurs af << 
615            << G4endl << " Otherwise it is an e << 
616 #endif                                         << 
617      // This course can now result if B has be    363      // This course can now result if B has been re-evaluated, 
618      // without E being recomputed (1 July 99) << 364      //   without E being recomputed   (1 July 99)
619      // In this case this is not a "real error << 365      //  In this case this is not a "real error" - but it undesired
620      // and we cope with it by a default corre << 366      //   and we cope with it by a default corrective action ...
621      //                                        << 
622      AE_fraction = 0.5;                           367      AE_fraction = 0.5;                         // Default value
623   }                                               368   }
624                                                   369 
625   new_st_length = AE_fraction * curve_length;  << 370   new_st_length= AE_fraction * curve_length; 
626                                                   371 
627   if ( AE_fraction > 0.0 )                     << 372   G4bool good_advance;
628   {                                            << 373   if ( AE_fraction > 0.0 ) { 
629      fIntgrDriver->AccurateAdvance(Current_Poi << 374      good_advance = 
630                                    new_st_leng << 375       fIntgrDriver->AccurateAdvance(Current_PointVelocity, 
631      //                                        << 376             new_st_length,
                                                   >> 377             eps_step ); // Relative accuracy
632      // In this case it does not matter if it     378      // In this case it does not matter if it cannot advance the full distance
633   }                                               379   }
634                                                   380 
635   // If there was a memory of the step_length  << 381   // If there was a memory of the step_length actually require at the start 
636   // of the integration Step, this could be re    382   // of the integration Step, this could be re-used ...
637                                                   383 
638   G4cout.precision(14);                        << 
639                                                << 
640   return Current_PointVelocity;                   384   return Current_PointVelocity;
641 }                                                 385 }
642                                                   386 
643 // ........................................... << 
644                                                << 
645 std::ostream& operator<<( std::ostream& os, co << 
646 {                                              << 
647    // Dumping the state of G4ChordFinder       << 
648    os << "State of G4ChordFinder : " << std::e << 
649    os << "   delta_chord   = " <<  cf.fDeltaCh << 
650    os << "   Default d_c   = " <<  cf.fDefault << 
651                                                << 
652    os << "   stats-verbose = " <<  cf.fStatsVe << 
653                                                   387 
654    return os;                                  << 
655 }                                              << 
656                                                   388