Geant4 Cross Reference

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


  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 // G4MagInt_Driver implementation                  26 // G4MagInt_Driver implementation
 27 //                                                 27 //
 28 // V.Grichine, 07.10.1996 - Created                28 // V.Grichine, 07.10.1996 - Created
 29 // W.Wander, 28.01.1998 - Added ability for lo     29 // W.Wander, 28.01.1998 - Added ability for low order integrators
 30 // J.Apostolakis, 08.11.2001 - Respect minimum     30 // J.Apostolakis, 08.11.2001 - Respect minimum step in AccurateAdvance
 31 // -------------------------------------------     31 // --------------------------------------------------------------------
 32                                                    32 
 33 #include <iomanip>                                 33 #include <iomanip>
 34                                                    34 
 35 #include "globals.hh"                              35 #include "globals.hh"
 36 #include "G4SystemOfUnits.hh"                      36 #include "G4SystemOfUnits.hh"
 37 #include "G4GeometryTolerance.hh"                  37 #include "G4GeometryTolerance.hh"
 38 #include "G4MagIntegratorDriver.hh"                38 #include "G4MagIntegratorDriver.hh"
 39 #include "G4FieldTrack.hh"                         39 #include "G4FieldTrack.hh"
 40                                                    40 
 41 #ifdef   G4DEBUG_FIELD                             41 #ifdef   G4DEBUG_FIELD
 42 #include "G4DriverReporter.hh"                     42 #include "G4DriverReporter.hh"
 43 #endif                                             43 #endif
 44                                                    44 
 45 // -------------------------------------------     45 // ---------------------------------------------------------
 46                                                    46 
 47 //  Constructor                                    47 //  Constructor
 48 //                                                 48 //
 49 G4MagInt_Driver::G4MagInt_Driver( G4double         49 G4MagInt_Driver::G4MagInt_Driver( G4double                hminimum, 
 50                                   G4MagIntegra     50                                   G4MagIntegratorStepper* pStepper,
 51                                   G4int            51                                   G4int                   numComponents,
 52                                   G4int            52                                   G4int                   statisticsVerbose)
 53   : fNoIntegrationVariables(numComponents),        53   : fNoIntegrationVariables(numComponents), 
 54     fNoVars( std::max( fNoIntegrationVariables     54     fNoVars( std::max( fNoIntegrationVariables, fMinNoVars )),
 55     fStatisticsVerboseLevel(statisticsVerbose)     55     fStatisticsVerboseLevel(statisticsVerbose)
 56 {                                                  56 {  
 57   // In order to accomodate "Laboratory Time",     57   // In order to accomodate "Laboratory Time", which is [7], fMinNoVars=8
 58   // is required. For proper time of flight an     58   // is required. For proper time of flight and spin,  fMinNoVars must be 12
 59                                                    59 
 60   RenewStepperAndAdjust( pStepper );               60   RenewStepperAndAdjust( pStepper );
 61   fMinimumStep = hminimum;                         61   fMinimumStep = hminimum;
 62                                                    62 
 63   fMaxNoSteps = fMaxStepBase / pIntStepper->In     63   fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
 64 #ifdef G4DEBUG_FIELD                               64 #ifdef G4DEBUG_FIELD
 65   fVerboseLevel=2;                                 65   fVerboseLevel=2;
 66 #endif                                             66 #endif
 67                                                    67 
 68   if( (fVerboseLevel > 0) || (fStatisticsVerbo     68   if( (fVerboseLevel > 0) || (fStatisticsVerboseLevel > 1) )
 69   {                                                69   {
 70     G4cout << "MagIntDriver version: Accur-Adv     70     G4cout << "MagIntDriver version: Accur-Adv: "
 71            << "invE_nS, QuickAdv-2sqrt with St     71            << "invE_nS, QuickAdv-2sqrt with Statistics "
 72 #ifdef G4FLD_STATS                                 72 #ifdef G4FLD_STATS
 73            << " enabled "                          73            << " enabled "
 74 #else                                              74 #else
 75            << " disabled "                         75            << " disabled "
 76 #endif                                             76 #endif
 77            << G4endl;                              77            << G4endl;
 78   }                                                78   }
 79 }                                                  79 }
 80                                                    80 
 81 // -------------------------------------------     81 // ---------------------------------------------------------
 82                                                    82 
 83 //  Destructor                                     83 //  Destructor
 84 //                                                 84 //
 85 G4MagInt_Driver::~G4MagInt_Driver()                85 G4MagInt_Driver::~G4MagInt_Driver()
 86 {                                                  86 { 
 87   if( fStatisticsVerboseLevel > 1 )                87   if( fStatisticsVerboseLevel > 1 )
 88   {                                                88   {
 89     PrintStatisticsReport();                       89     PrintStatisticsReport();
 90   }                                                90   }
 91 }                                                  91 }
 92                                                    92 
 93 // -------------------------------------------     93 // ---------------------------------------------------------
 94                                                    94 
 95 G4bool                                             95 G4bool
 96 G4MagInt_Driver::AccurateAdvance(G4FieldTrack&     96 G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
 97                                  G4double          97                                  G4double      hstep,
 98                                  G4double          98                                  G4double      eps,
 99                                  G4double          99                                  G4double      hinitial )
100 {                                                 100 {
101   // Runge-Kutta driver with adaptive stepsize    101   // Runge-Kutta driver with adaptive stepsize control. Integrate starting
102   // values at y_current over hstep x2 with ac    102   // values at y_current over hstep x2 with accuracy eps. 
103   // On output ystart is replaced by values at    103   // On output ystart is replaced by values at the end of the integration 
104   // interval. RightHandSide is the right-hand    104   // interval. RightHandSide is the right-hand side of ODE system. 
105   // The source is similar to odeint routine f    105   // The source is similar to odeint routine from NRC p.721-722 .
106                                                   106 
107   G4int nstp, i;                               << 107   G4int nstp, i, no_warnings = 0;
108   G4double x, hnext, hdid, h;                     108   G4double x, hnext, hdid, h;
109                                                   109 
110 #ifdef G4DEBUG_FIELD                              110 #ifdef G4DEBUG_FIELD
111   G4int no_warnings = 0;                       << 
112   static G4int dbg = 1;                           111   static G4int dbg = 1;
113   static G4int nStpPr = 50;   // For debug pri    112   static G4int nStpPr = 50;   // For debug printing of long integrations
114   G4double ySubStepStart[G4FieldTrack::ncompSV    113   G4double ySubStepStart[G4FieldTrack::ncompSVEC];
115   G4FieldTrack  yFldTrkStart(y_current);          114   G4FieldTrack  yFldTrkStart(y_current);
116 #endif                                            115 #endif
117                                                   116 
118   G4double y[G4FieldTrack::ncompSVEC] = {0., 0 << 117   G4double y[G4FieldTrack::ncompSVEC], dydx[G4FieldTrack::ncompSVEC];
119   G4double dydx[G4FieldTrack::ncompSVEC] = {0. << 118   G4double ystart[G4FieldTrack::ncompSVEC], yEnd[G4FieldTrack::ncompSVEC]; 
120   G4double ystart[G4FieldTrack::ncompSVEC] = { << 
121   G4double yEnd[G4FieldTrack::ncompSVEC] = {0. << 
122   G4double  x1, x2;                               119   G4double  x1, x2;
123   G4bool succeeded = true;                     << 120   G4bool succeeded = true, lastStepSucceeded;
124                                                   121 
125   G4double startCurveLength;                      122   G4double startCurveLength;
126                                                   123 
                                                   >> 124   G4int noFullIntegr = 0, noSmallIntegr = 0;
                                                   >> 125   static G4ThreadLocal G4int  noGoodSteps = 0;  // Bad = chord > curve-len 
127   const G4int nvar = fNoVars;                     126   const G4int nvar = fNoVars;
128                                                   127 
129   G4FieldTrack yStartFT(y_current);               128   G4FieldTrack yStartFT(y_current);
130                                                   129 
131   //  Ensure that hstep > 0                       130   //  Ensure that hstep > 0
132   //                                              131   //
133   if( hstep <= 0.0 )                              132   if( hstep <= 0.0 )
134   {                                               133   { 
135     if( hstep == 0.0 )                            134     if( hstep == 0.0 )
136     {                                             135     {
137       std::ostringstream message;                 136       std::ostringstream message;
138       message << "Proposed step is zero; hstep    137       message << "Proposed step is zero; hstep = " << hstep << " !";
139       G4Exception("G4MagInt_Driver::AccurateAd    138       G4Exception("G4MagInt_Driver::AccurateAdvance()", 
140                   "GeomField1001", JustWarning    139                   "GeomField1001", JustWarning, message);
141       return succeeded;                           140       return succeeded; 
142     }                                             141     }
143                                                << 142     else
144     std::ostringstream message;                << 143     { 
145     message << "Invalid run condition." << G4e << 144       std::ostringstream message;
146             << "Proposed step is negative; hst << 145       message << "Invalid run condition." << G4endl
147             << "Requested step cannot be negat << 146               << "Proposed step is negative; hstep = " << hstep << "." << G4endl
148     G4Exception("G4MagInt_Driver::AccurateAdva << 147               << "Requested step cannot be negative! Aborting event.";
149                 "GeomField0003", EventMustBeAb << 148       G4Exception("G4MagInt_Driver::AccurateAdvance()", 
150     return false;                              << 149                   "GeomField0003", EventMustBeAborted, message);
                                                   >> 150       return false;
                                                   >> 151     }
151   }                                               152   }
152                                                   153 
153   y_current.DumpToArray( ystart );                154   y_current.DumpToArray( ystart );
154                                                   155 
155   startCurveLength= y_current.GetCurveLength()    156   startCurveLength= y_current.GetCurveLength();
156   x1= startCurveLength;                           157   x1= startCurveLength; 
157   x2= x1 + hstep;                                 158   x2= x1 + hstep;
158                                                   159 
159   if ( (hinitial > 0.0) && (hinitial < hstep)     160   if ( (hinitial > 0.0) && (hinitial < hstep)
160     && (hinitial > perMillion * hstep) )          161     && (hinitial > perMillion * hstep) )
161   {                                               162   {
162      h = hinitial;                                163      h = hinitial;
163   }                                               164   }
164   else  //  Initial Step size "h" defaults to     165   else  //  Initial Step size "h" defaults to the full interval
165   {                                               166   {
166      h = hstep;                                   167      h = hstep;
167   }                                               168   }
168                                                   169 
169   x = x1;                                         170   x = x1;
170                                                   171 
171   for ( i=0; i<nvar; ++i)  { y[i] = ystart[i];    172   for ( i=0; i<nvar; ++i)  { y[i] = ystart[i]; }
172                                                   173 
173   G4bool lastStep= false;                         174   G4bool lastStep= false;
174   nstp = 1;                                       175   nstp = 1;
175                                                   176 
176   do                                              177   do
177   {                                               178   {
178     G4ThreeVector StartPos( y[0], y[1], y[2] )    179     G4ThreeVector StartPos( y[0], y[1], y[2] );
179                                                   180 
180 #ifdef G4DEBUG_FIELD                              181 #ifdef G4DEBUG_FIELD
181     G4double xSubStepStart= x;                    182     G4double xSubStepStart= x; 
182     for (i=0; i<nvar; ++i)  { ySubStepStart[i]    183     for (i=0; i<nvar; ++i)  { ySubStepStart[i] = y[i]; }
183     yFldTrkStart.LoadFromArray(y, fNoIntegrati    184     yFldTrkStart.LoadFromArray(y, fNoIntegrationVariables);
184     yFldTrkStart.SetCurveLength(x);               185     yFldTrkStart.SetCurveLength(x);
185 #endif                                            186 #endif
186                                                   187 
187     pIntStepper->RightHandSide( y, dydx );        188     pIntStepper->RightHandSide( y, dydx );
188     ++fNoTotalSteps;                              189     ++fNoTotalSteps;
189                                                   190 
190     // Perform the Integration                    191     // Perform the Integration
191     //                                            192     //      
192     if( h > fMinimumStep )                        193     if( h > fMinimumStep )
193     {                                             194     { 
194       OneGoodStep(y,dydx,x,h,eps,hdid,hnext) ;    195       OneGoodStep(y,dydx,x,h,eps,hdid,hnext) ;
195       //--------------------------------------    196       //--------------------------------------
                                                   >> 197       lastStepSucceeded = (hdid == h);   
196 #ifdef G4DEBUG_FIELD                              198 #ifdef G4DEBUG_FIELD
197       if (dbg>2)                                  199       if (dbg>2)
198       {                                           200       {
199          // PrintStatus( ySubStepStart, xSubSt    201          // PrintStatus( ySubStepStart, xSubStepStart, y, x, h,  nstp); // Only
200         G4DriverReporter::PrintStatus( ySubSte    202         G4DriverReporter::PrintStatus( ySubStepStart, xSubStepStart, y, x, h,  nstp, nvar);
201       }                                           203       }
202 #endif                                            204 #endif
203     }                                             205     }
204     else                                          206     else
205     {                                             207     {
206       G4FieldTrack yFldTrk( G4ThreeVector(0,0,    208       G4FieldTrack yFldTrk( G4ThreeVector(0,0,0), 
207                             G4ThreeVector(0,0,    209                             G4ThreeVector(0,0,0), 0., 0., 0., 0. );
208       G4double dchord_step, dyerr, dyerr_len;     210       G4double dchord_step, dyerr, dyerr_len;   // What to do with these ?
209       yFldTrk.LoadFromArray(y, fNoIntegrationV    211       yFldTrk.LoadFromArray(y, fNoIntegrationVariables); 
210       yFldTrk.SetCurveLength( x );                212       yFldTrk.SetCurveLength( x );
211                                                   213 
212       QuickAdvance( yFldTrk, dydx, h, dchord_s    214       QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
213       //--------------------------------------    215       //-----------------------------------------------------
214                                                   216 
215       yFldTrk.DumpToArray(y);                     217       yFldTrk.DumpToArray(y);    
216                                                   218 
217 #ifdef G4FLD_STATS                                219 #ifdef G4FLD_STATS
218       ++fNoSmallSteps;                            220       ++fNoSmallSteps; 
219       if ( dyerr_len > fDyerr_max )  { fDyerr_    221       if ( dyerr_len > fDyerr_max )  { fDyerr_max = dyerr_len; }
220       fDyerrPos_smTot += dyerr_len;               222       fDyerrPos_smTot += dyerr_len;
221       fSumH_sm += h;  // Length total for 'sma    223       fSumH_sm += h;  // Length total for 'small' steps
222       if (nstp==1)  { ++fNoInitialSmallSteps;     224       if (nstp==1)  { ++fNoInitialSmallSteps; }
223 #endif                                            225 #endif
224 #ifdef G4DEBUG_FIELD                              226 #ifdef G4DEBUG_FIELD
225       if (dbg>1)                                  227       if (dbg>1)
226       {                                           228       {
227         if(fNoSmallSteps<2) { PrintStatus(ySub    229         if(fNoSmallSteps<2) { PrintStatus(ySubStepStart, x1, y, x, h, -nstp); }
228         G4cout << "Another sub-min step, no "     230         G4cout << "Another sub-min step, no " << fNoSmallSteps 
229                << " of " << fNoTotalSteps << "    231                << " of " << fNoTotalSteps << " this time " << nstp << G4endl; 
230         PrintStatus( ySubStepStart, x1, y, x,     232         PrintStatus( ySubStepStart, x1, y, x, h,  nstp);   // Only this
231         G4cout << " dyerr= " << dyerr_len << "    233         G4cout << " dyerr= " << dyerr_len << " relative = " << dyerr_len / h 
232                << " epsilon= " << eps << " hst    234                << " epsilon= " << eps << " hstep= " << hstep 
233                << " h= " << h << " hmin= " <<     235                << " h= " << h << " hmin= " << fMinimumStep << G4endl;
234       }                                           236       }
235 #endif                                            237 #endif        
236       if( h == 0.0 )                              238       if( h == 0.0 )
237       {                                           239       { 
238         G4Exception("G4MagInt_Driver::Accurate    240         G4Exception("G4MagInt_Driver::AccurateAdvance()",
239                     "GeomField0003", FatalExce    241                     "GeomField0003", FatalException,
240                     "Integration Step became Z    242                     "Integration Step became Zero!"); 
241       }                                           243       }
242       dyerr = dyerr_len / h;                      244       dyerr = dyerr_len / h;
243       hdid = h;                                   245       hdid = h;
244       x += hdid;                                  246       x += hdid;
245                                                   247 
246       // Compute suggested new step               248       // Compute suggested new step
247       hnext = ComputeNewStepSize( dyerr/eps, h    249       hnext = ComputeNewStepSize( dyerr/eps, h);
                                                   >> 250 
                                                   >> 251       // .. hnext= ComputeNewStepSize_WithinLimits( dyerr/eps, h);
                                                   >> 252       lastStepSucceeded = (dyerr<= eps);
248     }                                             253     }
249                                                   254 
                                                   >> 255     if (lastStepSucceeded)  { ++noFullIntegr; }
                                                   >> 256     else                    { ++noSmallIntegr; }
                                                   >> 257 
250     G4ThreeVector EndPos( y[0], y[1], y[2] );     258     G4ThreeVector EndPos( y[0], y[1], y[2] );
251                                                   259 
252 #ifdef  G4DEBUG_FIELD                             260 #ifdef  G4DEBUG_FIELD
253     if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))     261     if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
254     {                                             262     {
255       if( nstp==nStpPr )  { G4cout << "***** M    263       if( nstp==nStpPr )  { G4cout << "***** Many steps ****" << G4endl; }
256       G4cout << "MagIntDrv: " ;                   264       G4cout << "MagIntDrv: " ; 
257       G4cout << "hdid="  << std::setw(12) << h    265       G4cout << "hdid="  << std::setw(12) << hdid  << " "
258              << "hnext=" << std::setw(12) << h    266              << "hnext=" << std::setw(12) << hnext << " " 
259              << "hstep=" << std::setw(12) << h    267              << "hstep=" << std::setw(12) << hstep << " (requested) " 
260              << G4endl;                           268              << G4endl;
261       PrintStatus( ystart, x1, y, x, h, (nstp=    269       PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp); 
262     }                                             270     }
263 #endif                                            271 #endif
264                                                   272 
265     // Check the endpoint                         273     // Check the endpoint
266     G4double endPointDist= (EndPos-StartPos).m    274     G4double endPointDist= (EndPos-StartPos).mag(); 
267     if ( endPointDist >= hdid*(1.+perMillion)     275     if ( endPointDist >= hdid*(1.+perMillion) )
268     {                                             276     {
269       ++fNoBadSteps;                              277       ++fNoBadSteps;
270                                                   278 
271       // Issue a warning only for gross differ    279       // Issue a warning only for gross differences -
272       // we understand how small difference oc    280       // we understand how small difference occur.
273       if ( endPointDist >= hdid*(1.+perThousan    281       if ( endPointDist >= hdid*(1.+perThousand) )
274       {                                           282       { 
275 #ifdef G4DEBUG_FIELD                              283 #ifdef G4DEBUG_FIELD
276         if (dbg)                                  284         if (dbg)
277         {                                         285         {
278           WarnEndPointTooFar ( endPointDist, h    286           WarnEndPointTooFar ( endPointDist, hdid, eps, dbg ); 
279           G4cerr << "  Total steps:  bad " <<     287           G4cerr << "  Total steps:  bad " << fNoBadSteps
280                  << " current h= " << hdid <<  << 288                  << " good " << noGoodSteps << " current h= " << hdid
                                                   >> 289                  << G4endl;
281           PrintStatus( ystart, x1, y, x, hstep    290           PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);  
282         }                                         291         }
283         ++no_warnings;                         << 
284 #endif                                            292 #endif
                                                   >> 293         ++no_warnings;
285       }                                           294       }
286     }                                             295     }
                                                   >> 296     else
                                                   >> 297     {
                                                   >> 298       ++noGoodSteps;
                                                   >> 299     } 
                                                   >> 300 // #endif
287                                                   301 
288     //  Avoid numerous small last steps           302     //  Avoid numerous small last steps
289     if( (h < eps * hstep) || (h < fSmallestFra    303     if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) )
290     {                                             304     {
291       // No more integration -- the next step     305       // No more integration -- the next step will not happen
292       lastStep = true;                            306       lastStep = true;  
293     }                                             307     }
294     else                                          308     else
295     {                                             309     {
296       // Check the proposed next stepsize         310       // Check the proposed next stepsize
297       if(std::fabs(hnext) <= Hmin())              311       if(std::fabs(hnext) <= Hmin())
298       {                                           312       {
299 #ifdef  G4DEBUG_FIELD                             313 #ifdef  G4DEBUG_FIELD
300         // If simply a very small interval is     314         // If simply a very small interval is being integrated, do not warn
301         if( (x < x2 * (1-eps) ) &&        // T    315         if( (x < x2 * (1-eps) ) &&        // The last step can be small: OK
302             (std::fabs(hstep) > Hmin()) ) // a    316             (std::fabs(hstep) > Hmin()) ) // and if we are asked, it's OK
303         {                                         317         {
304           if(dbg>0)                               318           if(dbg>0)
305           {                                       319           {
306             WarnSmallStepSize( hnext, hstep, h    320             WarnSmallStepSize( hnext, hstep, h, x-x1, nstp );  
307             PrintStatus( ystart, x1, y, x, hst    321             PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
308           }                                       322           }
309           ++no_warnings;                          323           ++no_warnings;
310         }                                         324         }
311 #endif                                            325 #endif
312         // Make sure that the next step is at     326         // Make sure that the next step is at least Hmin.
313         h = Hmin();                               327         h = Hmin();
314       }                                           328       }
315       else                                        329       else
316       {                                           330       {
317         h = hnext;                                331         h = hnext;
318       }                                           332       }
319                                                   333 
320       //  Ensure that the next step does not o    334       //  Ensure that the next step does not overshoot
321       if ( x+h > x2 )                             335       if ( x+h > x2 )
322       {                // When stepsize oversh    336       {                // When stepsize overshoots, decrease it!
323         h = x2 - x ;   // Must cope with diffi    337         h = x2 - x ;   // Must cope with difficult rounding-error
324       }                // issues if hstep << x    338       }                // issues if hstep << x2
325                                                   339 
326       if ( h == 0.0 )                             340       if ( h == 0.0 )
327       {                                           341       {
328         // Cannot progress - accept this as la    342         // Cannot progress - accept this as last step - by default
329         lastStep = true;                          343         lastStep = true;
330 #ifdef G4DEBUG_FIELD                              344 #ifdef G4DEBUG_FIELD
331         if (dbg>2)                                345         if (dbg>2)
332         {                                         346         {
333           int prec= G4cout.precision(12);         347           int prec= G4cout.precision(12); 
334           G4cout << "Warning: G4MagIntegratorD    348           G4cout << "Warning: G4MagIntegratorDriver::AccurateAdvance"
335                  << G4endl                        349                  << G4endl
336                  << "  Integration step 'h' be    350                  << "  Integration step 'h' became "
337                  << h << " due to roundoff. "     351                  << h << " due to roundoff. " << G4endl
338                  << " Calculated as difference    352                  << " Calculated as difference of x2= "<< x2 << " and x=" << x
339                  << "  Forcing termination of     353                  << "  Forcing termination of advance." << G4endl;
340           G4cout.precision(prec);                 354           G4cout.precision(prec);
341         }                                         355         }          
342 #endif                                            356 #endif
343       }                                           357       }
344     }                                             358     }
345   } while ( ((++nstp)<=fMaxNoSteps) && (x < x2    359   } while ( ((++nstp)<=fMaxNoSteps) && (x < x2) && (!lastStep) );
346   // Loop checking, 07.10.2016, J. Apostolakis    360   // Loop checking, 07.10.2016, J. Apostolakis
347                                                   361 
348      // Have we reached the end ?                 362      // Have we reached the end ?
349      // --> a better test might be x-x2 > an_e    363      // --> a better test might be x-x2 > an_epsilon
350                                                   364 
351   succeeded = (x>=x2);  // If it was a "forced    365   succeeded = (x>=x2);  // If it was a "forced" last step
352                                                   366 
353   for (i=0; i<nvar; ++i)  { yEnd[i] = y[i]; }     367   for (i=0; i<nvar; ++i)  { yEnd[i] = y[i]; }
354                                                   368 
355   // Put back the values.                         369   // Put back the values.
356   y_current.LoadFromArray( yEnd, fNoIntegratio    370   y_current.LoadFromArray( yEnd, fNoIntegrationVariables );
357   y_current.SetCurveLength( x );                  371   y_current.SetCurveLength( x );
358                                                   372 
359   if(nstp > fMaxNoSteps)                          373   if(nstp > fMaxNoSteps)
360   {                                               374   {
                                                   >> 375     ++no_warnings;
361     succeeded = false;                            376     succeeded = false;
362 #ifdef G4DEBUG_FIELD                              377 #ifdef G4DEBUG_FIELD
363     ++no_warnings;                             << 
364     if (dbg)                                      378     if (dbg)
365     {                                             379     {
366       WarnTooManyStep( x1, x2, x );  //  Issue    380       WarnTooManyStep( x1, x2, x );  //  Issue WARNING
367       PrintStatus( yEnd, x1, y, x, hstep, -nst    381       PrintStatus( yEnd, x1, y, x, hstep, -nstp);
368     }                                             382     }
369 #endif                                            383 #endif
370   }                                               384   }
371                                                   385 
372 #ifdef G4DEBUG_FIELD                              386 #ifdef G4DEBUG_FIELD
373   if( dbg && no_warnings )                        387   if( dbg && no_warnings )
374   {                                               388   {
375     G4cerr << "G4MagIntegratorDriver exit stat    389     G4cerr << "G4MagIntegratorDriver exit status: no-steps " << nstp << G4endl;
376     PrintStatus( yEnd, x1, y, x, hstep, nstp);    390     PrintStatus( yEnd, x1, y, x, hstep, nstp);
377   }                                               391   }
378 #endif                                            392 #endif
379                                                   393 
380   return succeeded;                               394   return succeeded;
381 }  // end of AccurateAdvance .................    395 }  // end of AccurateAdvance ...........................
382                                                   396 
383 // -------------------------------------------    397 // ---------------------------------------------------------
384                                                   398 
385 void                                              399 void
386 G4MagInt_Driver::WarnSmallStepSize( G4double h    400 G4MagInt_Driver::WarnSmallStepSize( G4double hnext, G4double hstep, 
387                                     G4double h    401                                     G4double h, G4double xDone,
388                                     G4int nstp    402                                     G4int nstp)
389 {                                                 403 {
390   static G4ThreadLocal G4int noWarningsIssued     404   static G4ThreadLocal G4int noWarningsIssued = 0;
391   const  G4int maxNoWarnings = 10;   // Number    405   const  G4int maxNoWarnings = 10;   // Number of verbose warnings
392   std::ostringstream message;                     406   std::ostringstream message;
393   if( (noWarningsIssued < maxNoWarnings) || fV    407   if( (noWarningsIssued < maxNoWarnings) || fVerboseLevel > 10 )
394   {                                               408   {
395     message << "The stepsize for the next iter    409     message << "The stepsize for the next iteration, " << hnext
396             << ", is too small - in Step numbe    410             << ", is too small - in Step number " << nstp << "." << G4endl
397             << "The minimum for the driver is     411             << "The minimum for the driver is " << Hmin()  << G4endl
398             << "Requested integr. length was "    412             << "Requested integr. length was " << hstep << " ." << G4endl
399             << "The size of this sub-step was     413             << "The size of this sub-step was " << h     << " ." << G4endl
400             << "The integrations has already g    414             << "The integrations has already gone " << xDone;
401   }                                               415   }
402   else                                            416   else
403   {                                               417   {
404     message << "Too small 'next' step " << hne    418     message << "Too small 'next' step " << hnext
405             << ", step-no: " << nstp << G4endl    419             << ", step-no: " << nstp << G4endl
406             << ", this sub-step: " << h           420             << ", this sub-step: " << h     
407             << ",  req_tot_len: " << hstep        421             << ",  req_tot_len: " << hstep 
408             << ", done: " << xDone << ", min:     422             << ", done: " << xDone << ", min: " << Hmin();
409   }                                               423   }
410   G4Exception("G4MagInt_Driver::WarnSmallStepS    424   G4Exception("G4MagInt_Driver::WarnSmallStepSize()", "GeomField1001",
411               JustWarning, message);              425               JustWarning, message);
412   ++noWarningsIssued;                             426   ++noWarningsIssued;
413 }                                                 427 }
414                                                   428 
415 // -------------------------------------------    429 // ---------------------------------------------------------
416                                                   430 
417 void                                              431 void
418 G4MagInt_Driver::WarnTooManyStep( G4double x1s    432 G4MagInt_Driver::WarnTooManyStep( G4double x1start, 
419                                   G4double x2e    433                                   G4double x2end, 
420                                   G4double xCu    434                                   G4double xCurrent )
421 {                                                 435 {
422    std::ostringstream message;                    436    std::ostringstream message;
423    message << "The number of steps used in the    437    message << "The number of steps used in the Integration driver"
424            << " (Runge-Kutta) is too many." <<    438            << " (Runge-Kutta) is too many." << G4endl
425            << "Integration of the interval was    439            << "Integration of the interval was not completed !" << G4endl
426            << "Only a " << (xCurrent-x1start)*    440            << "Only a " << (xCurrent-x1start)*100/(x2end-x1start)
427            << " % fraction of it was done.";      441            << " % fraction of it was done.";
428    G4Exception("G4MagInt_Driver::WarnTooManySt    442    G4Exception("G4MagInt_Driver::WarnTooManyStep()", "GeomField1001",
429                JustWarning, message);             443                JustWarning, message);
430 }                                                 444 }
431                                                   445 
432 // -------------------------------------------    446 // ---------------------------------------------------------
433                                                   447 
434 void                                              448 void
435 G4MagInt_Driver::WarnEndPointTooFar (G4double     449 G4MagInt_Driver::WarnEndPointTooFar (G4double endPointDist, 
436                                      G4double     450                                      G4double h , 
437                                      G4double     451                                      G4double eps,
438                                      G4int        452                                      G4int    dbg)
439 {                                                 453 {
440   static G4ThreadLocal G4double maxRelError =     454   static G4ThreadLocal G4double maxRelError = 0.0;
441   G4bool isNewMax, prNewMax;                      455   G4bool isNewMax, prNewMax;
442                                                   456 
443   isNewMax = endPointDist > (1.0 + maxRelError    457   isNewMax = endPointDist > (1.0 + maxRelError) * h;
444   prNewMax = endPointDist > (1.0 + 1.05 * maxR    458   prNewMax = endPointDist > (1.0 + 1.05 * maxRelError) * h;
445   if( isNewMax ) { maxRelError= endPointDist /    459   if( isNewMax ) { maxRelError= endPointDist / h - 1.0; }
446                                                   460 
447   if( (dbg != 0) && (h > G4GeometryTolerance:: << 461   if( dbg && (h > G4GeometryTolerance::GetInstance()->GetSurfaceTolerance()) 
448           && ( (dbg>1) || prNewMax || (endPoin    462           && ( (dbg>1) || prNewMax || (endPointDist >= h*(1.+eps) ) ) )
449   {                                               463   { 
450     static G4ThreadLocal G4int noWarnings = 0;    464     static G4ThreadLocal G4int noWarnings = 0;
451     std::ostringstream message;                   465     std::ostringstream message;
452     if( (noWarnings++ < 10) || (dbg>2) )          466     if( (noWarnings++ < 10) || (dbg>2) )
453     {                                             467     {
454       message << "The integration produced an     468       message << "The integration produced an end-point which " << G4endl
455               << "is further from the start-po    469               << "is further from the start-point than the curve length."
456               << G4endl;                          470               << G4endl;
457     }                                             471     }
458     message << "  Distance of endpoints = " <<    472     message << "  Distance of endpoints = " << endPointDist
459             << ", curve length = " << h << G4e    473             << ", curve length = " << h << G4endl
460             << "  Difference (curveLen-endpDis    474             << "  Difference (curveLen-endpDist)= " << (h - endPointDist)
461             << ", relative = " << (h-endPointD    475             << ", relative = " << (h-endPointDist) / h 
462             << ", epsilon =  " << eps;            476             << ", epsilon =  " << eps;
463     G4Exception("G4MagInt_Driver::WarnEndPoint    477     G4Exception("G4MagInt_Driver::WarnEndPointTooFar()", "GeomField1001",
464                 JustWarning, message);            478                 JustWarning, message);
465   }                                               479   }
466 }                                                 480 }
467                                                   481 
468 // -------------------------------------------    482 // ---------------------------------------------------------
469                                                   483 
470 void                                              484 void
471 G4MagInt_Driver::OneGoodStep(      G4double y[    485 G4MagInt_Driver::OneGoodStep(      G4double y[],        // InOut
472                              const G4double dy    486                              const G4double dydx[],
473                                    G4double& x    487                                    G4double& x,         // InOut
474                                    G4double ht    488                                    G4double htry,
475                                    G4double ep    489                                    G4double eps_rel_max,
476                                    G4double& h    490                                    G4double& hdid,      // Out
477                                    G4double& h    491                                    G4double& hnext )    // Out
478                                                   492 
479 // Driver for one Runge-Kutta Step with monito    493 // Driver for one Runge-Kutta Step with monitoring of local truncation error
480 // to ensure accuracy and adjust stepsize. Inp    494 // to ensure accuracy and adjust stepsize. Input are dependent variable
481 // array y[0,...,5] and its derivative dydx[0,    495 // array y[0,...,5] and its derivative dydx[0,...,5] at the
482 // starting value of the independent variable     496 // starting value of the independent variable x . Also input are stepsize
483 // to be attempted htry, and the required accu    497 // to be attempted htry, and the required accuracy eps. On output y and x
484 // are replaced by their new values, hdid is t    498 // are replaced by their new values, hdid is the stepsize that was actually
485 // accomplished, and hnext is the estimated ne    499 // accomplished, and hnext is the estimated next stepsize. 
486 // This is similar to the function rkqs from t    500 // This is similar to the function rkqs from the book:
487 // Numerical Recipes in C: The Art of Scientif    501 // Numerical Recipes in C: The Art of Scientific Computing (NRC), Second
488 // Edition, by William H. Press, Saul A. Teuko    502 // Edition, by William H. Press, Saul A. Teukolsky, William T.
489 // Vetterling, and Brian P. Flannery (Cambridg    503 // Vetterling, and Brian P. Flannery (Cambridge University Press 1992),
490 // 16.2 Adaptive StepSize Control for Runge-Ku    504 // 16.2 Adaptive StepSize Control for Runge-Kutta, p. 719
491                                                   505 
492 {                                                 506 {
493   G4double errmax_sq;                             507   G4double errmax_sq;
494   G4double h, htemp, xnew ;                       508   G4double h, htemp, xnew ;
495                                                   509 
496   G4double yerr[G4FieldTrack::ncompSVEC], ytem    510   G4double yerr[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC];
497                                                   511 
498   h = htry ; // Set stepsize to the initial tr    512   h = htry ; // Set stepsize to the initial trial value
499                                                   513 
500   G4double inv_eps_vel_sq = 1.0 / (eps_rel_max    514   G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max);
501                                                   515 
502   G4double errpos_sq = 0.0;    // square of di    516   G4double errpos_sq = 0.0;    // square of displacement error
503   G4double errvel_sq = 0.0;    // square of mo    517   G4double errvel_sq = 0.0;    // square of momentum vector difference
504   G4double errspin_sq = 0.0;   // square of sp    518   G4double errspin_sq = 0.0;   // square of spin vector difference
505                                                   519 
                                                   >> 520   static G4ThreadLocal G4int tot_no_trials=0; 
506   const G4int max_trials=100;                     521   const G4int max_trials=100; 
507                                                   522 
508   G4ThreeVector Spin(y[9],y[10],y[11]);           523   G4ThreeVector Spin(y[9],y[10],y[11]);
509   G4double spin_mag2 = Spin.mag2();               524   G4double spin_mag2 = Spin.mag2();
510   G4bool hasSpin = (spin_mag2 > 0.0);             525   G4bool hasSpin = (spin_mag2 > 0.0); 
511                                                   526 
512   for (G4int iter=0; iter<max_trials; ++iter)     527   for (G4int iter=0; iter<max_trials; ++iter)
513   {                                               528   {
                                                   >> 529     ++tot_no_trials;
514     pIntStepper-> Stepper(y,dydx,h,ytemp,yerr)    530     pIntStepper-> Stepper(y,dydx,h,ytemp,yerr); 
515     //            *******                         531     //            *******
516     G4double eps_pos = eps_rel_max * std::max(    532     G4double eps_pos = eps_rel_max * std::max(h, fMinimumStep); 
517     G4double inv_eps_pos_sq = 1.0 / (eps_pos*e    533     G4double inv_eps_pos_sq = 1.0 / (eps_pos*eps_pos); 
518                                                   534 
519     // Evaluate accuracy                          535     // Evaluate accuracy
520     //                                            536     //
521     errpos_sq =  sqr(yerr[0]) + sqr(yerr[1]) +    537     errpos_sq =  sqr(yerr[0]) + sqr(yerr[1]) + sqr(yerr[2]) ;
522     errpos_sq *= inv_eps_pos_sq; // Scale rela    538     errpos_sq *= inv_eps_pos_sq; // Scale relative to required tolerance
523                                                   539 
524     // Accuracy for momentum                      540     // Accuracy for momentum
525     G4double magvel_sq=  sqr(y[3]) + sqr(y[4])    541     G4double magvel_sq=  sqr(y[3]) + sqr(y[4]) + sqr(y[5]) ;
526     G4double sumerr_sq =  sqr(yerr[3]) + sqr(y    542     G4double sumerr_sq =  sqr(yerr[3]) + sqr(yerr[4]) + sqr(yerr[5]) ; 
527     if( magvel_sq > 0.0 )                         543     if( magvel_sq > 0.0 )
528     {                                             544     { 
529        errvel_sq = sumerr_sq / magvel_sq;         545        errvel_sq = sumerr_sq / magvel_sq; 
530     }                                             546     }
531     else                                          547     else
532     {                                             548     {
533        std::ostringstream message;                549        std::ostringstream message;
534        message << "Found case of zero momentum    550        message << "Found case of zero momentum." << G4endl
535                << "- iteration= " << iter << "    551                << "- iteration= " << iter << "; h= " << h;
536        G4Exception("G4MagInt_Driver::OneGoodSt    552        G4Exception("G4MagInt_Driver::OneGoodStep()",
537                    "GeomField1001", JustWarnin    553                    "GeomField1001", JustWarning, message);
538        errvel_sq = sumerr_sq;                     554        errvel_sq = sumerr_sq; 
539     }                                             555     }
540     errvel_sq *= inv_eps_vel_sq;                  556     errvel_sq *= inv_eps_vel_sq;
541     errmax_sq = std::max( errpos_sq, errvel_sq    557     errmax_sq = std::max( errpos_sq, errvel_sq ); // Square of maximum error
542                                                   558 
543     if( hasSpin )                                 559     if( hasSpin )
544     {                                             560     { 
545       // Accuracy for spin                        561       // Accuracy for spin
546       errspin_sq =  ( sqr(yerr[9]) + sqr(yerr[    562       errspin_sq =  ( sqr(yerr[9]) + sqr(yerr[10]) + sqr(yerr[11]) )
547                     /  spin_mag2; // ( sqr(y[9    563                     /  spin_mag2; // ( sqr(y[9]) + sqr(y[10]) + sqr(y[11]) );
548       errspin_sq *= inv_eps_vel_sq;               564       errspin_sq *= inv_eps_vel_sq;
549       errmax_sq = std::max( errmax_sq, errspin    565       errmax_sq = std::max( errmax_sq, errspin_sq ); 
550     }                                             566     }
551                                                   567 
552     if ( errmax_sq <= 1.0 )  { break; } // Ste    568     if ( errmax_sq <= 1.0 )  { break; } // Step succeeded. 
553                                                   569 
554     // Step failed; compute the size of retria    570     // Step failed; compute the size of retrial Step.
555     htemp = GetSafety() * h * std::pow( errmax    571     htemp = GetSafety() * h * std::pow( errmax_sq, 0.5*GetPshrnk() );
556                                                   572 
557     if (htemp >= 0.1*h)  { h = htemp; }  // Tr    573     if (htemp >= 0.1*h)  { h = htemp; }  // Truncation error too large,
558     else  { h = 0.1*h; }                 // re    574     else  { h = 0.1*h; }                 // reduce stepsize, but no more
559                                          // th    575                                          // than a factor of 10
560     xnew = x + h;                                 576     xnew = x + h;
561     if(xnew == x)                                 577     if(xnew == x)
562     {                                             578     {
563       std::ostringstream message;                 579       std::ostringstream message;
564       message << "Stepsize underflow in Steppe    580       message << "Stepsize underflow in Stepper !" << G4endl
565               << "- Step's start x=" << x << "    581               << "- Step's start x=" << x << " and end x= " << xnew 
566               << " are equal !! " << G4endl       582               << " are equal !! " << G4endl
567               << "  Due to step-size= " << h      583               << "  Due to step-size= " << h 
568               << ". Note that input step was "    584               << ". Note that input step was " << htry;
569       G4Exception("G4MagInt_Driver::OneGoodSte    585       G4Exception("G4MagInt_Driver::OneGoodStep()",
570                   "GeomField1001", JustWarning    586                   "GeomField1001", JustWarning, message);
571       break;                                      587       break;
572     }                                             588     }
573   }                                               589   }
574                                                   590 
575   // Compute size of next Step                    591   // Compute size of next Step
576   if (errmax_sq > errcon*errcon)                  592   if (errmax_sq > errcon*errcon)
577   {                                               593   { 
578     hnext = GetSafety()*h*std::pow(errmax_sq,     594     hnext = GetSafety()*h*std::pow(errmax_sq, 0.5*GetPgrow());
579   }                                               595   }
580   else                                            596   else
581   {                                               597   {
582     hnext = max_stepping_increase*h ; // No mo    598     hnext = max_stepping_increase*h ; // No more than a factor of 5 increase
583   }                                               599   }
584   x += (hdid = h);                                600   x += (hdid = h);
585                                                   601 
586   for(G4int k=0; k<fNoIntegrationVariables; ++    602   for(G4int k=0; k<fNoIntegrationVariables; ++k) { y[k] = ytemp[k]; }
587                                                   603 
588   return;                                         604   return;
589 }                                                 605 }
590                                                   606 
591 //--------------------------------------------    607 //----------------------------------------------------------------------
592                                                   608 
593 // QuickAdvance just tries one Step - it does     609 // QuickAdvance just tries one Step - it does not ensure accuracy
594 //                                                610 //
595 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTr    611 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTrack& y_posvel,    // INOUT
596                                const G4double     612                                const G4double      dydx[],  
597                                      G4double     613                                      G4double      hstep,       // In
598                                      G4double&    614                                      G4double&     dchord_step,
599                                      G4double&    615                                      G4double&     dyerr_pos_sq,
600                                      G4double&    616                                      G4double&     dyerr_mom_rel_sq )  
601 {                                                 617 {
602   G4Exception("G4MagInt_Driver::QuickAdvance()    618   G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001",
603               FatalException, "Not yet impleme    619               FatalException, "Not yet implemented."); 
604                                                   620 
605   // Use the parameters of this method, to ple    621   // Use the parameters of this method, to please compiler
606   //                                              622   //
607   dchord_step = dyerr_pos_sq = hstep * hstep *    623   dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0]; 
608   dyerr_mom_rel_sq = y_posvel.GetPosition().ma    624   dyerr_mom_rel_sq = y_posvel.GetPosition().mag2();
609   return true;                                    625   return true;
610 }                                                 626 }
611                                                   627 
612 //--------------------------------------------    628 //----------------------------------------------------------------------
613                                                   629 
614 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTr    630 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTrack& y_posvel,    // INOUT
615                                const G4double     631                                const G4double      dydx[],  
616                                      G4double     632                                      G4double      hstep,       // In
617                                      G4double&    633                                      G4double&     dchord_step,
618                                      G4double&    634                                      G4double&     dyerr )
619 {                                                 635 {
620   G4double dyerr_pos_sq, dyerr_mom_rel_sq;        636   G4double dyerr_pos_sq, dyerr_mom_rel_sq;  
621   G4double yerr_vec[G4FieldTrack::ncompSVEC],     637   G4double yerr_vec[G4FieldTrack::ncompSVEC],
622            yarrin[G4FieldTrack::ncompSVEC], ya    638            yarrin[G4FieldTrack::ncompSVEC], yarrout[G4FieldTrack::ncompSVEC]; 
623   G4double s_start;                               639   G4double s_start;
624   G4double dyerr_mom_sq, vel_mag_sq, inv_vel_m    640   G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq;
625                                                   641 
                                                   >> 642   static G4ThreadLocal G4int no_call = 0; 
                                                   >> 643   ++no_call; 
                                                   >> 644 
626   // Move data into array                         645   // Move data into array
627   y_posvel.DumpToArray( yarrin );      //  yar    646   y_posvel.DumpToArray( yarrin );      //  yarrin  <== y_posvel 
628   s_start = y_posvel.GetCurveLength();            647   s_start = y_posvel.GetCurveLength();
629                                                   648 
630   // Do an Integration Step                       649   // Do an Integration Step
631   pIntStepper-> Stepper(yarrin, dydx, hstep, y    650   pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ; 
632                                                   651 
633   // Estimate curve-chord distance                652   // Estimate curve-chord distance
634   dchord_step= pIntStepper-> DistChord();         653   dchord_step= pIntStepper-> DistChord();
635                                                   654 
636   // Put back the values.  yarrout ==> y_posve    655   // Put back the values.  yarrout ==> y_posvel
637   y_posvel.LoadFromArray( yarrout, fNoIntegrat    656   y_posvel.LoadFromArray( yarrout, fNoIntegrationVariables );
638   y_posvel.SetCurveLength( s_start + hstep );     657   y_posvel.SetCurveLength( s_start + hstep );
639                                                   658 
640 #ifdef  G4DEBUG_FIELD                             659 #ifdef  G4DEBUG_FIELD
641   if(fVerboseLevel>2)                             660   if(fVerboseLevel>2)
642   {                                               661   {
643     G4cout << "G4MagIntDrv: Quick Advance" <<     662     G4cout << "G4MagIntDrv: Quick Advance" << G4endl;
644     PrintStatus( yarrin, s_start, yarrout, s_s    663     PrintStatus( yarrin, s_start, yarrout, s_start+hstep, hstep,  1); 
645   }                                               664   }
646 #endif                                            665 #endif
647                                                   666 
648   // A single measure of the error                667   // A single measure of the error   
649   //      TO-DO :  account for  energy,  spin,    668   //      TO-DO :  account for  energy,  spin, ... ? 
650   vel_mag_sq   = ( sqr(yarrout[3])+sqr(yarrout    669   vel_mag_sq   = ( sqr(yarrout[3])+sqr(yarrout[4])+sqr(yarrout[5]) );
651   inv_vel_mag_sq = 1.0 / vel_mag_sq;              670   inv_vel_mag_sq = 1.0 / vel_mag_sq; 
652   dyerr_pos_sq = ( sqr(yerr_vec[0])+sqr(yerr_v    671   dyerr_pos_sq = ( sqr(yerr_vec[0])+sqr(yerr_vec[1])+sqr(yerr_vec[2]));
653   dyerr_mom_sq = ( sqr(yerr_vec[3])+sqr(yerr_v    672   dyerr_mom_sq = ( sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(yerr_vec[5]));
654   dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_ma    673   dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_mag_sq;
655                                                   674 
656   // Calculate also the change in the momentum    675   // Calculate also the change in the momentum squared also ???
657   // G4double veloc_square = y_posvel.GetVeloc    676   // G4double veloc_square = y_posvel.GetVelocity().mag2();
658   // ...                                          677   // ...
659                                                   678 
660 #ifdef RETURN_A_NEW_STEP_LENGTH                   679 #ifdef RETURN_A_NEW_STEP_LENGTH
661   // The following step cannot be done here be    680   // The following step cannot be done here because "eps" is not known.
662   dyerr_len = std::sqrt( dyerr_len_sq );          681   dyerr_len = std::sqrt( dyerr_len_sq ); 
663   dyerr_len_sq /= eps ;                           682   dyerr_len_sq /= eps ;
664                                                   683 
665   // Look at the velocity deviation ?             684   // Look at the velocity deviation ?
666   //  sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(ye    685   //  sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(yerr_vec[5]));
667                                                   686 
668   // Set suggested new step                       687   // Set suggested new step
669   hstep = ComputeNewStepSize( dyerr_len, hstep    688   hstep = ComputeNewStepSize( dyerr_len, hstep);
670 #endif                                            689 #endif
671                                                   690 
672   if( dyerr_pos_sq > ( dyerr_mom_rel_sq * sqr(    691   if( dyerr_pos_sq > ( dyerr_mom_rel_sq * sqr(hstep) ) )
673   {                                               692   {
674     dyerr = std::sqrt(dyerr_pos_sq);              693     dyerr = std::sqrt(dyerr_pos_sq);
675   }                                               694   }
676   else                                            695   else
677   {                                               696   {
678     // Scale it to the current step size - for    697     // Scale it to the current step size - for now
679     dyerr = std::sqrt(dyerr_mom_rel_sq) * hste    698     dyerr = std::sqrt(dyerr_mom_rel_sq) * hstep;
680   }                                               699   }
681                                                   700 
682   return true;                                    701   return true;
683 }                                                 702 }
684                                                   703 
685 // -------------------------------------------    704 // --------------------------------------------------------------------------
686                                                   705 
687 #ifdef QUICK_ADV_ARRAY_IN_AND_OUT                 706 #ifdef QUICK_ADV_ARRAY_IN_AND_OUT
688 G4bool  G4MagInt_Driver::QuickAdvance(G4double    707 G4bool  G4MagInt_Driver::QuickAdvance(G4double  yarrin[],    // In
689                                 const G4double    708                                 const G4double  dydx[],  
690                                       G4double    709                                       G4double  hstep,       // In
691                                       G4double    710                                       G4double  yarrout[],
692                                       G4double    711                                       G4double& dchord_step,
693                                       G4double    712                                       G4double& dyerr )      // In length
694 {                                                 713 {
695   G4Exception("G4MagInt_Driver::QuickAdvance()    714   G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001",
696               FatalException, "Not yet impleme    715               FatalException, "Not yet implemented.");
697   dyerr = dchord_step = hstep * yarrin[0] * dy    716   dyerr = dchord_step = hstep * yarrin[0] * dydx[0];
698   yarrout[0]= yarrin[0];                          717   yarrout[0]= yarrin[0];
699 }                                                 718 }
700 #endif                                            719 #endif 
701                                                   720 
702 // -------------------------------------------    721 // --------------------------------------------------------------------------
703                                                   722 
704 // This method computes new step sizes - but d    723 // This method computes new step sizes - but does not limit changes to
705 // within  certain factors                        724 // within  certain factors
706 //                                                725 // 
707 G4double G4MagInt_Driver::                        726 G4double G4MagInt_Driver::
708 ComputeNewStepSize_WithoutReductionLimit(G4dou    727 ComputeNewStepSize_WithoutReductionLimit(G4double  errMaxNorm,    // max error  (normalised)
709                    G4double  hstepCurrent)  //    728                    G4double  hstepCurrent)  // current step size
710 {                                                 729 {
711   G4double hnew;                                  730   G4double hnew;
712                                                   731 
713   // Compute size of next Step for a failed st    732   // Compute size of next Step for a failed step
714   if(errMaxNorm > 1.0 )                           733   if(errMaxNorm > 1.0 )
715   {                                               734   {
716     // Step failed; compute the size of retria    735     // Step failed; compute the size of retrial Step.
717     hnew = GetSafety()*hstepCurrent*std::pow(e    736     hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPshrnk()) ;
718   }                                               737   }
719   else if(errMaxNorm > 0.0 )                      738   else if(errMaxNorm > 0.0 )
720   {                                               739   {
721     // Compute size of next Step for a success    740     // Compute size of next Step for a successful step
722     hnew = GetSafety()*hstepCurrent*std::pow(e    741     hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPgrow()) ;
723   }                                               742   }
724   else                                            743   else
725   {                                               744   {
726     // if error estimate is zero (possible) or    745     // if error estimate is zero (possible) or negative (dubious)
727     hnew = max_stepping_increase * hstepCurren    746     hnew = max_stepping_increase * hstepCurrent; 
728   }                                               747   }
729                                                   748 
730   return hnew;                                    749   return hnew;
731 }                                                 750 }
732                                                   751 
733 // -------------------------------------------    752 // ---------------------------------------------------------------------------
734                                                   753 
735 G4double                                          754 G4double 
736 G4MagInt_Driver::ComputeNewStepSize(              755 G4MagInt_Driver::ComputeNewStepSize(
737                           G4double  errMaxNorm    756                           G4double  errMaxNorm,    // max error  (normalised)
738                           G4double  hstepCurre    757                           G4double  hstepCurrent)  // current step size
739 {                                                 758 {
740    // Legacy behaviour:                           759    // Legacy behaviour:
741    return ComputeNewStepSize_WithoutReductionL    760    return ComputeNewStepSize_WithoutReductionLimit( errMaxNorm, hstepCurrent );
742    // 'Improved' behaviour - at least more con    761    // 'Improved' behaviour - at least more consistent with other step estimates:
743    // return ComputeNewStepSize_WithinLimits(     762    // return ComputeNewStepSize_WithinLimits( errMaxNorm, hstepCurrent );
744 }                                                 763 }
745                                                   764 
746 // This method computes new step sizes limitin    765 // This method computes new step sizes limiting changes within certain factors
747 //                                                766 // 
748 // It shares its logic with AccurateAdvance.      767 // It shares its logic with AccurateAdvance.
749 // They are kept separate currently for optimi    768 // They are kept separate currently for optimisation.
750 //                                                769 //
751 G4double                                          770 G4double 
752 G4MagInt_Driver::ComputeNewStepSize_WithinLimi    771 G4MagInt_Driver::ComputeNewStepSize_WithinLimits( 
753                           G4double  errMaxNorm    772                           G4double  errMaxNorm,    // max error  (normalised)
754                           G4double  hstepCurre    773                           G4double  hstepCurrent)  // current step size
755 {                                                 774 {
756   G4double hnew;                                  775   G4double hnew;
757                                                   776 
758   // Compute size of next Step for a failed st    777   // Compute size of next Step for a failed step
759   if (errMaxNorm > 1.0 )                          778   if (errMaxNorm > 1.0 )
760   {                                               779   {
761     // Step failed; compute the size of retria    780     // Step failed; compute the size of retrial Step.
762     hnew = GetSafety()*hstepCurrent*std::pow(e    781     hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPshrnk()) ;
763                                                   782   
764     if (hnew < max_stepping_decrease*hstepCurr    783     if (hnew < max_stepping_decrease*hstepCurrent)
765     {                                             784     {
766       hnew = max_stepping_decrease*hstepCurren    785       hnew = max_stepping_decrease*hstepCurrent ;
767                          // reduce stepsize, b    786                          // reduce stepsize, but no more
768                          // than this factor (    787                          // than this factor (value= 1/10)
769     }                                             788     }
770   }                                               789   }
771   else                                            790   else
772   {                                               791   {
773     // Compute size of next Step for a success    792     // Compute size of next Step for a successful step
774     if (errMaxNorm > errcon)                      793     if (errMaxNorm > errcon)
775      { hnew = GetSafety()*hstepCurrent*std::po    794      { hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPgrow()); }
776     else  // No more than a factor of 5 increa    795     else  // No more than a factor of 5 increase
777      { hnew = max_stepping_increase * hstepCur    796      { hnew = max_stepping_increase * hstepCurrent; }
778   }                                               797   }
779   return hnew;                                    798   return hnew;
780 }                                                 799 }
781                                                   800 
782 // -------------------------------------------    801 // ---------------------------------------------------------------------------
783                                                   802 
784 void G4MagInt_Driver::PrintStatus( const G4dou    803 void G4MagInt_Driver::PrintStatus( const G4double* StartArr,  
785                                          G4dou    804                                          G4double  xstart,
786                                    const G4dou    805                                    const G4double* CurrentArr, 
787                                          G4dou    806                                          G4double  xcurrent,
788                                          G4dou    807                                          G4double  requestStep, 
789                                          G4int    808                                          G4int     subStepNo )
790   // Potentially add as arguments:                809   // Potentially add as arguments:  
791   //                                 <dydx>       810   //                                 <dydx>           - as Initial Force
792   //                                 stepTaken    811   //                                 stepTaken(hdid)  - last step taken
793   //                                 nextStep     812   //                                 nextStep (hnext) - proposal for size
794 {                                                 813 {
795    G4FieldTrack  StartFT(G4ThreeVector(0,0,0),    814    G4FieldTrack  StartFT(G4ThreeVector(0,0,0),
796                  G4ThreeVector(0,0,0), 0., 0.,    815                  G4ThreeVector(0,0,0), 0., 0., 0., 0. );
797    G4FieldTrack  CurrentFT (StartFT);             816    G4FieldTrack  CurrentFT (StartFT);
798                                                   817 
799    StartFT.LoadFromArray( StartArr, fNoIntegra    818    StartFT.LoadFromArray( StartArr, fNoIntegrationVariables); 
800    StartFT.SetCurveLength( xstart);               819    StartFT.SetCurveLength( xstart);
801    CurrentFT.LoadFromArray( CurrentArr, fNoInt    820    CurrentFT.LoadFromArray( CurrentArr, fNoIntegrationVariables); 
802    CurrentFT.SetCurveLength( xcurrent );          821    CurrentFT.SetCurveLength( xcurrent );
803                                                   822 
804    PrintStatus(StartFT, CurrentFT, requestStep    823    PrintStatus(StartFT, CurrentFT, requestStep, subStepNo ); 
805 }                                                 824 }
806                                                   825 
807 // -------------------------------------------    826 // ---------------------------------------------------------------------------
808                                                   827 
809 void G4MagInt_Driver::PrintStatus(const G4Fiel    828 void G4MagInt_Driver::PrintStatus(const G4FieldTrack& StartFT,
810                                   const G4Fiel    829                                   const G4FieldTrack& CurrentFT, 
811                                         G4doub    830                                         G4double      requestStep, 
812                                         G4int     831                                         G4int         subStepNo)
813 {                                                 832 {
814     G4int verboseLevel= fVerboseLevel;            833     G4int verboseLevel= fVerboseLevel;
815     const G4int noPrecision = 5;                  834     const G4int noPrecision = 5;
816     G4long oldPrec= G4cout.precision(noPrecisi << 835     G4int oldPrec= G4cout.precision(noPrecision);
817     // G4cout.setf(ios_base::fixed,ios_base::f    836     // G4cout.setf(ios_base::fixed,ios_base::floatfield);
818                                                   837 
819     const G4ThreeVector StartPosition=       S    838     const G4ThreeVector StartPosition=       StartFT.GetPosition();
820     const G4ThreeVector StartUnitVelocity=   S    839     const G4ThreeVector StartUnitVelocity=   StartFT.GetMomentumDir();
821     const G4ThreeVector CurrentPosition=     C    840     const G4ThreeVector CurrentPosition=     CurrentFT.GetPosition();
822     const G4ThreeVector CurrentUnitVelocity= C    841     const G4ThreeVector CurrentUnitVelocity= CurrentFT.GetMomentumDir();
823                                                   842 
824     G4double  DotStartCurrentVeloc= StartUnitV    843     G4double  DotStartCurrentVeloc= StartUnitVelocity.dot(CurrentUnitVelocity);
825                                                   844 
826     G4double step_len= CurrentFT.GetCurveLengt    845     G4double step_len= CurrentFT.GetCurveLength() - StartFT.GetCurveLength();
827     G4double subStepSize = step_len;              846     G4double subStepSize = step_len;
828                                                   847      
829     if( (subStepNo <= 1) || (verboseLevel > 3)    848     if( (subStepNo <= 1) || (verboseLevel > 3) )
830     {                                             849     {
831        subStepNo = - subStepNo;        // To a    850        subStepNo = - subStepNo;        // To allow printing banner
832                                                   851 
833        G4cout << std::setw( 6)  << " " << std:    852        G4cout << std::setw( 6)  << " " << std::setw( 25)
834               << " G4MagInt_Driver: Current Po    853               << " G4MagInt_Driver: Current Position  and  Direction" << " "
835               << G4endl;                          854               << G4endl; 
836        G4cout << std::setw( 5) << "Step#" << "    855        G4cout << std::setw( 5) << "Step#" << " "
837               << std::setw( 7) << "s-curve" <<    856               << std::setw( 7) << "s-curve" << " "
838               << std::setw( 9) << "X(mm)" << "    857               << std::setw( 9) << "X(mm)" << " "
839               << std::setw( 9) << "Y(mm)" << "    858               << std::setw( 9) << "Y(mm)" << " "  
840               << std::setw( 9) << "Z(mm)" << "    859               << std::setw( 9) << "Z(mm)" << " "
841               << std::setw( 8) << " N_x " << "    860               << std::setw( 8) << " N_x " << " "
842               << std::setw( 8) << " N_y " << "    861               << std::setw( 8) << " N_y " << " "
843               << std::setw( 8) << " N_z " << "    862               << std::setw( 8) << " N_z " << " "
844               << std::setw( 8) << " N^2-1 " <<    863               << std::setw( 8) << " N^2-1 " << " "
845               << std::setw(10) << " N(0).N " <    864               << std::setw(10) << " N(0).N " << " "
846               << std::setw( 7) << "KinEner " <    865               << std::setw( 7) << "KinEner " << " "
847               << std::setw(12) << "Track-l" <<    866               << std::setw(12) << "Track-l" << " "   // Add the Sub-step ??
848               << std::setw(12) << "Step-len" <    867               << std::setw(12) << "Step-len" << " " 
849               << std::setw(12) << "Step-len" <    868               << std::setw(12) << "Step-len" << " " 
850               << std::setw( 9) << "ReqStep" <<    869               << std::setw( 9) << "ReqStep" << " "  
851               << G4endl;                          870               << G4endl;
852     }                                             871     }
853                                                   872 
854     if( (subStepNo <= 0) )                        873     if( (subStepNo <= 0) )
855     {                                             874     {
856       PrintStat_Aux( StartFT,  requestStep, 0.    875       PrintStat_Aux( StartFT,  requestStep, 0., 
857                        0,        0.0,             876                        0,        0.0,         1.0);
858     }                                             877     }
859                                                   878 
860     if( verboseLevel <= 3 )                       879     if( verboseLevel <= 3 )
861     {                                             880     {
862       G4cout.precision(noPrecision);              881       G4cout.precision(noPrecision);
863       PrintStat_Aux( CurrentFT, requestStep, s    882       PrintStat_Aux( CurrentFT, requestStep, step_len, 
864                      subStepNo, subStepSize, D    883                      subStepNo, subStepSize, DotStartCurrentVeloc );
865     }                                             884     }
866                                                   885 
867     G4cout.precision(oldPrec);                    886     G4cout.precision(oldPrec);
868 }                                                 887 }
869                                                   888 
870 // -------------------------------------------    889 // ---------------------------------------------------------------------------
871                                                   890 
872 void G4MagInt_Driver::PrintStat_Aux(const G4Fi    891 void G4MagInt_Driver::PrintStat_Aux(const G4FieldTrack& aFieldTrack,
873                                           G4do    892                                           G4double      requestStep, 
874                                           G4do    893                                           G4double      step_len,
875                                           G4in    894                                           G4int         subStepNo,
876                                           G4do    895                                           G4double      subStepSize,
877                                           G4do    896                                           G4double      dotVeloc_StartCurr)
878 {                                                 897 {
879     const G4ThreeVector Position = aFieldTrack    898     const G4ThreeVector Position = aFieldTrack.GetPosition();
880     const G4ThreeVector UnitVelocity = aFieldT    899     const G4ThreeVector UnitVelocity = aFieldTrack.GetMomentumDir();
881                                                   900  
882     if( subStepNo >= 0)                           901     if( subStepNo >= 0)
883     {                                             902     {
884        G4cout << std::setw( 5) << subStepNo <<    903        G4cout << std::setw( 5) << subStepNo << " ";
885     }                                             904     }
886     else                                          905     else
887     {                                             906     {
888        G4cout << std::setw( 5) << "Start" << "    907        G4cout << std::setw( 5) << "Start" << " ";
889     }                                             908     }
890     G4double curveLen= aFieldTrack.GetCurveLen    909     G4double curveLen= aFieldTrack.GetCurveLength();
891     G4cout << std::setw( 7) << curveLen;          910     G4cout << std::setw( 7) << curveLen;
892     G4cout << std::setw( 9) << Position.x() <<    911     G4cout << std::setw( 9) << Position.x() << " "
893            << std::setw( 9) << Position.y() <<    912            << std::setw( 9) << Position.y() << " "
894            << std::setw( 9) << Position.z() <<    913            << std::setw( 9) << Position.z() << " "
895            << std::setw( 8) << UnitVelocity.x(    914            << std::setw( 8) << UnitVelocity.x() << " "
896            << std::setw( 8) << UnitVelocity.y(    915            << std::setw( 8) << UnitVelocity.y() << " "
897            << std::setw( 8) << UnitVelocity.z(    916            << std::setw( 8) << UnitVelocity.z() << " ";
898     G4long oldprec= G4cout.precision(3);       << 917     G4int oldprec= G4cout.precision(3);
899     G4cout << std::setw( 8) << UnitVelocity.ma    918     G4cout << std::setw( 8) << UnitVelocity.mag2()-1.0 << " ";
900     G4cout.precision(6);                          919     G4cout.precision(6);
901     G4cout << std::setw(10) << dotVeloc_StartC    920     G4cout << std::setw(10) << dotVeloc_StartCurr << " ";
902     G4cout.precision(oldprec);                    921     G4cout.precision(oldprec);
903     G4cout << std::setw( 7) << aFieldTrack.Get    922     G4cout << std::setw( 7) << aFieldTrack.GetKineticEnergy();
904     G4cout << std::setw(12) << step_len << " "    923     G4cout << std::setw(12) << step_len << " ";
905                                                   924 
906     static G4ThreadLocal G4double oldCurveLeng    925     static G4ThreadLocal G4double oldCurveLength = 0.0;
907     static G4ThreadLocal G4double oldSubStepLe    926     static G4ThreadLocal G4double oldSubStepLength = 0.0;
908     static G4ThreadLocal G4int oldSubStepNo =     927     static G4ThreadLocal G4int oldSubStepNo = -1;
909                                                   928 
910     G4double subStep_len = 0.0;                   929     G4double subStep_len = 0.0;
911     if( curveLen > oldCurveLength )               930     if( curveLen > oldCurveLength )
912     {                                             931     {
913       subStep_len= curveLen - oldCurveLength;     932       subStep_len= curveLen - oldCurveLength;
914     }                                             933     }
915     else if (subStepNo == oldSubStepNo)           934     else if (subStepNo == oldSubStepNo)
916     {                                             935     {
917       subStep_len= oldSubStepLength;              936       subStep_len= oldSubStepLength;
918     }                                             937     }
919     oldCurveLength= curveLen;                     938     oldCurveLength= curveLen;
920     oldSubStepLength= subStep_len;                939     oldSubStepLength= subStep_len;
921                                                   940 
922     G4cout << std::setw(12) << subStep_len <<     941     G4cout << std::setw(12) << subStep_len << " "; 
923     G4cout << std::setw(12) << subStepSize <<     942     G4cout << std::setw(12) << subStepSize << " "; 
924     if( requestStep != -1.0 )                     943     if( requestStep != -1.0 )
925     {                                             944     {
926       G4cout << std::setw( 9) << requestStep <    945       G4cout << std::setw( 9) << requestStep << " ";
927     }                                             946     }
928     else                                          947     else
929     {                                             948     {
930        G4cout << std::setw( 9) << " InitialSte    949        G4cout << std::setw( 9) << " InitialStep " << " ";
931     }                                             950     }
932     G4cout << G4endl;                             951     G4cout << G4endl;
933 }                                                 952 }
934                                                   953 
935 // -------------------------------------------    954 // ---------------------------------------------------------------------------
936                                                   955 
937 void G4MagInt_Driver::PrintStatisticsReport()     956 void G4MagInt_Driver::PrintStatisticsReport()
938 {                                                 957 {
939   G4int noPrecBig = 6;                            958   G4int noPrecBig = 6;
940   G4long oldPrec = G4cout.precision(noPrecBig) << 959   G4int oldPrec = G4cout.precision(noPrecBig);
941                                                   960 
942   G4cout << "G4MagInt_Driver Statistics of ste    961   G4cout << "G4MagInt_Driver Statistics of steps undertaken. " << G4endl;
943   G4cout << "G4MagInt_Driver: Number of Steps:    962   G4cout << "G4MagInt_Driver: Number of Steps: "
944          << " Total= " <<  fNoTotalSteps          963          << " Total= " <<  fNoTotalSteps
945          << " Bad= "   <<  fNoBadSteps            964          << " Bad= "   <<  fNoBadSteps 
946          << " Small= " <<  fNoSmallSteps          965          << " Small= " <<  fNoSmallSteps 
947          << " Non-initial small= " << (fNoSmal    966          << " Non-initial small= " << (fNoSmallSteps-fNoInitialSmallSteps)
948          << G4endl;                               967          << G4endl;
949  G4cout.precision(oldPrec);                       968  G4cout.precision(oldPrec);
950 }                                                 969 }
951                                                   970  
952 // -------------------------------------------    971 // ---------------------------------------------------------------------------
953                                                   972 
954 void G4MagInt_Driver::SetSmallestFraction(G4do    973 void G4MagInt_Driver::SetSmallestFraction(G4double newFraction)
955 {                                                 974 {
956   if( (newFraction > 1.e-16) && (newFraction <    975   if( (newFraction > 1.e-16) && (newFraction < 1e-8) )
957   {                                               976   {
958     fSmallestFraction= newFraction;               977     fSmallestFraction= newFraction;
959   }                                               978   }
960   else                                            979   else
961   {                                               980   { 
962     std::ostringstream message;                   981     std::ostringstream message;
963     message << "Smallest Fraction not changed.    982     message << "Smallest Fraction not changed. " << G4endl
964             << "  Proposed value was " << newF    983             << "  Proposed value was " << newFraction << G4endl
965             << "  Value must be between 1.e-8     984             << "  Value must be between 1.e-8 and 1.e-16";
966     G4Exception("G4MagInt_Driver::SetSmallestF    985     G4Exception("G4MagInt_Driver::SetSmallestFraction()",
967                 "GeomField1001", JustWarning,     986                 "GeomField1001", JustWarning, message);
968   }                                               987   }
969 }                                                 988 }
970                                                   989 
971 void G4MagInt_Driver::                            990 void G4MagInt_Driver::
972 GetDerivatives(const G4FieldTrack& y_curr, G4d    991 GetDerivatives(const G4FieldTrack& y_curr, G4double* dydx) const
973 {                                                 992 {
974     G4double ytemp[G4FieldTrack::ncompSVEC];      993     G4double ytemp[G4FieldTrack::ncompSVEC];
975     y_curr.DumpToArray(ytemp);                    994     y_curr.DumpToArray(ytemp);
976     pIntStepper->RightHandSide(ytemp, dydx);      995     pIntStepper->RightHandSide(ytemp, dydx);
977       // Avoid virtual call for GetStepper        996       // Avoid virtual call for GetStepper
978       // Was: GetStepper()->ComputeRightHandSi    997       // Was: GetStepper()->ComputeRightHandSide(ytemp, dydx);
979 }                                                 998 }
980                                                   999 
981 void G4MagInt_Driver::GetDerivatives(const G4F    1000 void G4MagInt_Driver::GetDerivatives(const G4FieldTrack& track,
982                                      G4double     1001                                      G4double dydx[],
983                                      G4double     1002                                      G4double field[]) const
984 {                                                 1003 {
985     G4double ytemp[G4FieldTrack::ncompSVEC];      1004     G4double ytemp[G4FieldTrack::ncompSVEC];
986     track.DumpToArray(ytemp);                     1005     track.DumpToArray(ytemp);
987     pIntStepper->RightHandSide(ytemp, dydx, fi    1006     pIntStepper->RightHandSide(ytemp, dydx, field);
988 }                                                 1007 }
989                                                   1008 
990 G4EquationOfMotion* G4MagInt_Driver::GetEquati    1009 G4EquationOfMotion* G4MagInt_Driver::GetEquationOfMotion()
991 {                                                 1010 {
992     return pIntStepper->GetEquationOfMotion();    1011     return pIntStepper->GetEquationOfMotion();
993 }                                                 1012 }
994                                                   1013 
995 void G4MagInt_Driver::SetEquationOfMotion(G4Eq    1014 void G4MagInt_Driver::SetEquationOfMotion(G4EquationOfMotion *equation)
996 {                                                 1015 {
997     pIntStepper->SetEquationOfMotion(equation)    1016     pIntStepper->SetEquationOfMotion(equation);
998 }                                                 1017 }
999                                                   1018 
1000 const G4MagIntegratorStepper* G4MagInt_Driver    1019 const G4MagIntegratorStepper* G4MagInt_Driver::GetStepper() const
1001 {                                                1020 {
1002     return pIntStepper;                          1021     return pIntStepper;
1003 }                                                1022 }
1004                                                  1023 
1005 G4MagIntegratorStepper* G4MagInt_Driver::GetS    1024 G4MagIntegratorStepper* G4MagInt_Driver::GetStepper()
1006 {                                                1025 {
1007     return pIntStepper;                          1026     return pIntStepper;
1008 }                                                1027 }
1009                                                  1028 
1010 void G4MagInt_Driver::                           1029 void G4MagInt_Driver::
1011 RenewStepperAndAdjust(G4MagIntegratorStepper*    1030 RenewStepperAndAdjust(G4MagIntegratorStepper* pItsStepper)
1012 {                                                1031 {  
1013     pIntStepper = pItsStepper;                   1032     pIntStepper = pItsStepper;
1014     ReSetParameters();                           1033     ReSetParameters();
1015 }                                                1034 }
1016                                                  1035 
1017 void G4MagInt_Driver::StreamInfo( std::ostrea    1036 void G4MagInt_Driver::StreamInfo( std::ostream& os ) const
1018 {                                                1037 {
1019     os << "State of G4MagInt_Driver: " << std    1038     os << "State of G4MagInt_Driver: " << std::endl;
1020     os << "  Max number of Steps = " << fMaxN    1039     os << "  Max number of Steps = " << fMaxNoSteps
1021        << "    (base # = " << fMaxStepBase <<    1040        << "    (base # = " << fMaxStepBase << " )" << std::endl;
1022     os << "  Safety factor       = " << safet    1041     os << "  Safety factor       = " << safety  << std::endl;
1023     os << "  Power - shrink      = " << pshrn    1042     os << "  Power - shrink      = " << pshrnk << std::endl;
1024     os << "  Power - grow        = " << pgrow    1043     os << "  Power - grow        = " << pgrow << std::endl;
1025     os << "  threshold (errcon)  = " << errco    1044     os << "  threshold (errcon)  = " << errcon << std::endl;
1026                                                  1045 
1027     os << "    fMinimumStep =      " << fMini    1046     os << "    fMinimumStep =      " << fMinimumStep  << std::endl;
1028     os << "    Smallest Fraction = " << fSmal    1047     os << "    Smallest Fraction = " << fSmallestFraction << std::endl;
1029                                                  1048 
1030     os << "    No Integrat Vars  = " << fNoIn    1049     os << "    No Integrat Vars  = " << fNoIntegrationVariables << std::endl;
1031     os << "    Min No Vars       = " << fMinN    1050     os << "    Min No Vars       = " << fMinNoVars << std::endl;
1032     os << "    Num-Vars          = " << fNoVa    1051     os << "    Num-Vars          = " << fNoVars << std::endl;
1033                                                  1052     
1034     os << "    verbose level     = " << fVerb    1053     os << "    verbose level     = " << fVerboseLevel << std::endl;
1035     os << "    Reintegrates      = " << DoesR    1054     os << "    Reintegrates      = " << DoesReIntegrate() << std::endl;
1036 }                                                1055 }
1037                                                  1056 
1038 void PrintInfo( const G4MagInt_Driver & magDr    1057 void PrintInfo( const G4MagInt_Driver & magDrv, std::ostream& os )
1039 {                                                1058 {
1040     os << "State of G4MagInt_Driver: " << std    1059     os << "State of G4MagInt_Driver: " << std::endl;
1041     os << "  Max number of Steps = " << magDr    1060     os << "  Max number of Steps = " << magDrv.GetMaxNoSteps();
1042     //   << "    (base # = " << magDrv.fMaxSt    1061     //   << "    (base # = " << magDrv.fMaxStepBase << " )" << std::endl;
1043     os << "  Safety factor       = " << magDr    1062     os << "  Safety factor       = " << magDrv.GetSafety()  << std::endl;
1044     os << "  Power - shrink      = " << magDr    1063     os << "  Power - shrink      = " << magDrv.GetPshrnk() << std::endl;
1045     os << "  Power - grow        = " << magDr    1064     os << "  Power - grow        = " << magDrv.GetPgrow() << std::endl;
1046     os << "  threshold (errcon)  = " << magDr    1065     os << "  threshold (errcon)  = " << magDrv.GetErrcon() << std::endl;
1047                                                  1066 
1048     os << "    fMinimumStep =      " << magDr    1067     os << "    fMinimumStep =      " << magDrv.GetHmin()  << std::endl;
1049     os << "    Smallest Fraction = " << magDr    1068     os << "    Smallest Fraction = " << magDrv.GetSmallestFraction() << std::endl;
1050                                                  1069 
1051     /*****                                       1070     /*****
1052     os << "    No Integrat Vars  = " << magDr    1071     os << "    No Integrat Vars  = " << magDrv.GetNoIntegrationVariables << std::endl;
1053     os << "    Min No Vars       = " << magDr    1072     os << "    Min No Vars       = " << magDrv.GetMinNoVars << std::endl;
1054     os << "    Num-Vars          = " << magDr    1073     os << "    Num-Vars          = " << magDrv.GetNoVars << std::endl;
1055     *****/                                       1074     *****/
1056     os << "    verbose level     = " << magDr    1075     os << "    verbose level     = " << magDrv.GetVerboseLevel() << std::endl;
1057     os << "    Reintegrates      = " << magDr    1076     os << "    Reintegrates      = " << magDrv.DoesReIntegrate() << std::endl;
1058 }                                                1077 }
1059                                                  1078