53 const G4double G4MagInt_Driver::max_stepping_increase = 5.0;
 
   54 const G4double G4MagInt_Driver::max_stepping_decrease = 0.1;
 
   59 const G4int  G4MagInt_Driver::fMaxStepBase = 250;  
 
   61 #ifndef G4NO_FIELD_STATISTICS 
   72                                   G4int                   statisticsVerbose)
 
   73   : fSmallestFraction( 1.0
e-12 ), 
 
   74     fNoIntegrationVariables(numComponents), 
 
   76     fNoVars( std::max( fNoIntegrationVariables, fMinNoVars )),
 
   77     fStatisticsVerboseLevel(statisticsVerbose),
 
   78     fNoTotalSteps(0),  fNoBadSteps(0), fNoSmallSteps(0),
 
   79     fNoInitialSmallSteps(0), 
 
   80     fDyerr_max(0.0), fDyerr_mx2(0.0), 
 
   81     fDyerrPos_smTot(0.0), fDyerrPos_lgTot(0.0), fDyerrVel_lgTot(0.0), 
 
   82     fSumH_sm(0.0), fSumH_lg(0.0),
 
   89   fMinimumStep= hminimum;
 
   95   if( (fVerboseLevel > 0) || (fStatisticsVerboseLevel > 1) )
 
   97     G4cout << 
"MagIntDriver version: Accur-Adv: " 
   98            << 
"invE_nS, QuickAdv-2sqrt with Statistics " 
  114   if( fStatisticsVerboseLevel > 1 )
 
  138   G4int nstp, i, no_warnings=0;
 
  143   static G4int nStpPr=50;   
 
  151   G4bool succeeded = 
true, lastStepSucceeded;
 
  155   G4int  noFullIntegr=0, noSmallIntegr = 0 ;
 
  156   static G4int  noGoodSteps =0 ;  
 
  157   const  G4int  nvar= fNoVars;
 
  167       std::ostringstream message;
 
  168       message << 
"Proposed step is zero; hstep = " << hstep << 
" !";
 
  175       std::ostringstream message;
 
  176       message << 
"Invalid run condition." << 
G4endl 
  177               << 
"Proposed step is negative; hstep = " << hstep << 
"." << 
G4endl 
  178               << 
"Requested step cannot be negative! Aborting event.";
 
  188   x1= startCurveLength; 
 
  191   if ( (hinitial > 0.0) && (hinitial < hstep)
 
  203   for (i=0;i<nvar;i++)  { y[i] = ystart[i]; }
 
  214     for (i=0;i<nvar;i++)  { ySubStepStart[i] = y[i]; }
 
  227     if( h > fMinimumStep )
 
  231       lastStepSucceeded= (hdid == h);   
 
  234         PrintStatus( ySubStepStart, xSubStepStart, y, x, h,  nstp); 
 
  242       G4double dchord_step, dyerr, dyerr_len;   
 
  246       QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len ); 
 
  253       if ( dyerr_len > fDyerr_max)  { fDyerr_max= dyerr_len; }
 
  254       fDyerrPos_smTot += dyerr_len;
 
  256       if (nstp<=1)  { fNoInitialSmallSteps++; }
 
  261         if(fNoSmallSteps<2) { 
PrintStatus(ySubStepStart, x1, y, x, h, -nstp); }
 
  262         G4cout << 
"Another sub-min step, no " << fNoSmallSteps 
 
  263                << 
" of " << fNoTotalSteps << 
" this time " << nstp << 
G4endl; 
 
  265         G4cout << 
" dyerr= " << dyerr_len << 
" relative = " << dyerr_len / h 
 
  266                << 
" epsilon= " << eps << 
" hstep= " << hstep 
 
  267                << 
" h= " << h << 
" hmin= " << fMinimumStep << 
G4endl;
 
  274                     "Integration Step became Zero!"); 
 
  276       dyerr = dyerr_len / h;
 
  284       lastStepSucceeded= (dyerr<= eps);
 
  287     if (lastStepSucceeded)  { noFullIntegr++; }
 
  288     else                    { noSmallIntegr++; }
 
  293     if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
 
  295       if( nstp==nStpPr )  { 
G4cout << 
"***** Many steps ****" << 
G4endl; }
 
  297       G4cout << 
"hdid="  << std::setw(12) << hdid  << 
" " 
  298              << 
"hnext=" << std::setw(12) << hnext << 
" "  
  299          << 
"hstep=" << std::setw(12) << hstep << 
" (requested) "  
  301       PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp); 
 
  306     G4double endPointDist= (EndPos-StartPos).mag(); 
 
  319           G4cerr << 
"  Total steps:  bad " << fNoBadSteps
 
  320                  << 
" good " << noGoodSteps << 
" current h= " << hdid
 
  322           PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);  
 
  335     if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) )
 
  343       if(std::fabs(hnext) <= 
Hmin())
 
  347         if( (x < x2 * (1-eps) ) &&        
 
  348             (std::fabs(hstep) > 
Hmin()) ) 
 
  353             PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
 
  379           int prec= 
G4cout.precision(12); 
 
  380           G4cout << 
"Warning: G4MagIntegratorDriver::AccurateAdvance" 
  382                  << 
"  Integration step 'h' became " 
  383                  << h << 
" due to roundoff. " << 
G4endl 
  384          << 
" Calculated as difference of x2= "<< x2 << 
" and x=" << x
 
  385                  << 
"  Forcing termination of advance." << 
G4endl;
 
  391   } 
while ( ((nstp++)<=fMaxNoSteps) && (x < x2) && (!lastStep) );
 
  397   for (i=0;i<nvar;i++)  { yEnd[i] = y[i]; }
 
  403   if(nstp > fMaxNoSteps)
 
  417   if( dbg && no_warnings )
 
  419     G4cerr << 
"G4MagIntegratorDriver exit status: no-steps " << nstp <<
G4endl;
 
  434   static G4int noWarningsIssued =0;
 
  435   const  G4int maxNoWarnings =  10;   
 
  436   std::ostringstream message;
 
  437   if( (noWarningsIssued < maxNoWarnings) || fVerboseLevel > 10 )
 
  439     message << 
"The stepsize for the next iteration, " << hnext
 
  440             << 
", is too small - in Step number " << nstp << 
"." << 
G4endl 
  441             << 
"The minimum for the driver is " << 
Hmin()  << 
G4endl 
  442             << 
"Requested integr. length was " << hstep << 
" ." << 
G4endl 
  443             << 
"The size of this sub-step was " << h     << 
" ." << 
G4endl 
  444             << 
"The integrations has already gone " << xDone;
 
  448     message << 
"Too small 'next' step " << hnext
 
  449             << 
", step-no: " << nstp << 
G4endl 
  450             << 
", this sub-step: " << h     
 
  451             << 
",  req_tot_len: " << hstep 
 
  452             << 
", done: " << xDone << 
", min: " << 
Hmin();
 
  454   G4Exception(
"G4MagInt_Driver::WarnSmallStepSize()", 
"GeomField1001",
 
  466     std::ostringstream message;
 
  467     message << 
"The number of steps used in the Integration driver" 
  468             << 
" (Runge-Kutta) is too many." << 
G4endl 
  469             << 
"Integration of the interval was not completed !" << 
G4endl 
  470             << 
"Only a " << (xCurrent-x1start)*100/(x2end-x1start)
 
  471             << 
" % fraction of it was done.";
 
  472     G4Exception(
"G4MagInt_Driver::WarnTooManyStep()", 
"GeomField1001",
 
  485   G4bool isNewMax, prNewMax;
 
  487   isNewMax = endPointDist > (1.0 + maxRelError) * h;
 
  488   prNewMax = endPointDist > (1.0 + 1.05 * maxRelError) * h;
 
  489   if( isNewMax ) { maxRelError= endPointDist / h - 1.0; }
 
  492           && ( (dbg>1) || prNewMax || (endPointDist >= h*(1.+eps) ) ) )
 
  494     static G4int noWarnings = 0;
 
  495     std::ostringstream message;
 
  496     if( (noWarnings ++ < 10) || (dbg>2) )
 
  498       message << 
"The integration produced an end-point which " << 
G4endl 
  499               << 
"is further from the start-point than the curve length." 
  502     message << 
"  Distance of endpoints = " << endPointDist
 
  503             << 
", curve length = " << h << 
G4endl 
  504             << 
"  Difference (curveLen-endpDist)= " << (h - endPointDist)
 
  505             << 
", relative = " << (h-endPointDist) / h 
 
  506             << 
", epsilon =  " << eps;
 
  507     G4Exception(
"G4MagInt_Driver::WarnEndPointTooFar()", 
"GeomField1001",
 
  544   G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max);
 
  552   static G4int tot_no_trials=0; 
 
  553   const G4int max_trials=100; 
 
  558   for (iter=0; iter<max_trials ;iter++)
 
  561     pIntStepper-> Stepper(y,dydx,h,ytemp,yerr); 
 
  563     G4double eps_pos = eps_rel_max * std::max(h, fMinimumStep); 
 
  564     G4double inv_eps_pos_sq = 1.0 / (eps_pos*eps_pos); 
 
  568     errpos_sq =  
sqr(yerr[0]) + 
sqr(yerr[1]) + 
sqr(yerr[2]) ;
 
  569     errpos_sq *= inv_eps_pos_sq; 
 
  572     errvel_sq =  (
sqr(yerr[3]) + 
sqr(yerr[4]) + 
sqr(yerr[5]) )
 
  574     errvel_sq *= inv_eps_vel_sq;
 
  575     errmax_sq = std::max( errpos_sq, errvel_sq ); 
 
  580       errspin_sq =  ( 
sqr(yerr[9]) + 
sqr(yerr[10]) + 
sqr(yerr[11]) )
 
  581                  /  ( 
sqr(y[9]) + 
sqr(y[10]) + 
sqr(y[11]) );
 
  582       errspin_sq *= inv_eps_vel_sq;
 
  583       errmax_sq = std::max( errmax_sq, errspin_sq ); 
 
  586     if ( errmax_sq <= 1.0 )  { 
break; } 
 
  591     if (htemp >= 0.1*h)  { h = htemp; }  
 
  597       G4cerr << 
"G4MagIntegratorDriver::OneGoodStep:" << 
G4endl 
  598              << 
"  Stepsize underflow in Stepper " << 
G4endl ;
 
  599       G4cerr << 
"  Step's start x=" << x << 
" and end x= " << xnew 
 
  600              << 
" are equal !! " << G4endl
 
  601              <<
"  Due to step-size= " << h 
 
  602              << 
" . Note that input step was " << htry << 
G4endl;
 
  610   fDyerrPos_lgTot += errpos_sq;
 
  611   fDyerrVel_lgTot += errvel_sq * h * h; 
 
  615   if (errmax_sq > errcon*errcon)
 
  621     hnext = max_stepping_increase*h ; 
 
  625   for(
G4int k=0;k<fNoIntegrationVariables;k++) { y[k] = ytemp[k]; }
 
  642   G4Exception(
"G4MagInt_Driver::QuickAdvance()", 
"GeomField0001",
 
  646   dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0]; 
 
  660   G4double dyerr_pos_sq, dyerr_mom_rel_sq;  
 
  664   G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq;
 
  666   static G4int no_call=0; 
 
  674   pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ; 
 
  678   dchord_step= pIntStepper-> DistChord();
 
  689     PrintStatus( yarrin, s_start, yarrout, s_start+hstep, hstep,  1); 
 
  695   vel_mag_sq   = ( 
sqr(yarrout[3])+
sqr(yarrout[4])+
sqr(yarrout[5]) );
 
  696   inv_vel_mag_sq = 1.0 / vel_mag_sq; 
 
  697   dyerr_pos_sq = ( 
sqr(yerr_vec[0])+
sqr(yerr_vec[1])+
sqr(yerr_vec[2]));
 
  698   dyerr_mom_sq = ( 
sqr(yerr_vec[3])+
sqr(yerr_vec[4])+
sqr(yerr_vec[5]));
 
  699   dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_mag_sq;
 
  705 #ifdef RETURN_A_NEW_STEP_LENGTH 
  707   dyerr_len = std::sqrt( dyerr_len_sq ); 
 
  708   dyerr_len_sq /= eps ;
 
  717   if( dyerr_pos_sq > ( dyerr_mom_rel_sq * 
sqr(hstep) ) )
 
  719     dyerr = std::sqrt(dyerr_pos_sq);
 
  724     dyerr = std::sqrt(dyerr_mom_rel_sq) * hstep;
 
  732 #ifdef QUICK_ADV_ARRAY_IN_AND_OUT 
  741   G4Exception(
"G4MagInt_Driver::QuickAdvance()", 
"GeomField0001",
 
  743   dyerr = dchord_step = hstep * yarrin[0] * dydx[0];
 
  744   yarrout[0]= yarrin[0];
 
  761   if(errMaxNorm > 1.0 )
 
  765   } 
else if(errMaxNorm > 0.0 ) {
 
  770     hnew = max_stepping_increase * hstepCurrent; 
 
  791   if (errMaxNorm > 1.0 )
 
  796     if (hnew < max_stepping_decrease*hstepCurrent)
 
  798       hnew = max_stepping_decrease*hstepCurrent ;
 
  806     if (errMaxNorm > errcon)
 
  809      { hnew = max_stepping_increase * hstepCurrent; }
 
  833    CurrentFT.
LoadFromArray( CurrentArr, fNoIntegrationVariables); 
 
  836    PrintStatus(StartFT, CurrentFT, requestStep, subStepNo ); 
 
  847     G4int verboseLevel= fVerboseLevel;
 
  848     static G4int noPrecision= 5;
 
  857     G4double  DotStartCurrentVeloc= StartUnitVelocity.
dot(CurrentUnitVelocity);
 
  862     if( (subStepNo <= 1) || (verboseLevel > 3) )
 
  864        subStepNo = - subStepNo;        
 
  866        G4cout << std::setw( 6)  << 
" " << std::setw( 25)
 
  867               << 
" G4MagInt_Driver: Current Position  and  Direction" << 
" " 
  869        G4cout << std::setw( 5) << 
"Step#" << 
" " 
  870               << std::setw( 7) << 
"s-curve" << 
" " 
  871               << std::setw( 9) << 
"X(mm)" << 
" " 
  872               << std::setw( 9) << 
"Y(mm)" << 
" "   
  873               << std::setw( 9) << 
"Z(mm)" << 
" " 
  874               << std::setw( 8) << 
" N_x " << 
" " 
  875               << std::setw( 8) << 
" N_y " << 
" " 
  876               << std::setw( 8) << 
" N_z " << 
" " 
  877               << std::setw( 8) << 
" N^2-1 " << 
" " 
  878               << std::setw(10) << 
" N(0).N " << 
" " 
  879               << std::setw( 7) << 
"KinEner " << 
" " 
  880               << std::setw(12) << 
"Track-l" << 
" "    
  881               << std::setw(12) << 
"Step-len" << 
" "  
  882               << std::setw(12) << 
"Step-len" << 
" "  
  883               << std::setw( 9) << 
"ReqStep" << 
" "   
  887     if( (subStepNo <= 0) )
 
  894     if( verboseLevel <= 3 )
 
  896       G4cout.precision(noPrecision);
 
  898                      subStepNo, subStepSize, DotStartCurrentVeloc );
 
  914     G4cout.precision(oldPrec);
 
  932        G4cout << std::setw( 5) << subStepNo << 
" ";
 
  936        G4cout << std::setw( 5) << 
"Start" << 
" ";
 
  939     G4cout << std::setw( 7) << curveLen;
 
  940     G4cout << std::setw( 9) << Position.
x() << 
" " 
  941            << std::setw( 9) << Position.
y() << 
" " 
  942            << std::setw( 9) << Position.
z() << 
" " 
  943            << std::setw( 8) << UnitVelocity.
x() << 
" " 
  944            << std::setw( 8) << UnitVelocity.
y() << 
" " 
  945            << std::setw( 8) << UnitVelocity.
z() << 
" ";
 
  947     G4cout << std::setw( 8) << UnitVelocity.
mag2()-1.0 << 
" ";
 
  949     G4cout << std::setw(10) << dotVeloc_StartCurr << 
" ";
 
  950     G4cout.precision(oldprec);
 
  952     G4cout << std::setw(12) << step_len << 
" ";
 
  954     static G4double oldCurveLength= 0.0;
 
  955     static G4double oldSubStepLength= 0.0;
 
  956     static G4int oldSubStepNo= -1;
 
  959     if( curveLen > oldCurveLength )
 
  961       subStep_len= curveLen - oldCurveLength;
 
  963     else if (subStepNo == oldSubStepNo)
 
  965       subStep_len= oldSubStepLength;
 
  967     oldCurveLength= curveLen;
 
  968     oldSubStepLength= subStep_len;
 
  970     G4cout << std::setw(12) << subStep_len << 
" "; 
 
  971     G4cout << std::setw(12) << subStepSize << 
" "; 
 
  972     if( requestStep != -1.0 )
 
  974       G4cout << std::setw( 9) << requestStep << 
" ";
 
  978        G4cout << std::setw( 9) << 
" InitialStep " << 
" ";
 
  990   G4cout << 
"G4MagInt_Driver Statistics of steps undertaken. " << 
G4endl;
 
  991   G4cout << 
"G4MagInt_Driver: Number of Steps: " 
  992          << 
" Total= " <<  fNoTotalSteps
 
  993          << 
" Bad= "   <<  fNoBadSteps 
 
  994          << 
" Small= " <<  fNoSmallSteps 
 
  995          << 
" Non-initial small= " << (fNoSmallSteps-fNoInitialSmallSteps)
 
 1000          << 
" maximum= " << fDyerr_max 
 
 1001          << 
" Sum small= " << fDyerrPos_smTot 
 
 1002          << 
" std::sqrt(Sum large^2): pos= " << std::sqrt(fDyerrPos_lgTot)
 
 1003          << 
" vel= " << std::sqrt( fDyerrVel_lgTot )
 
 1004          << 
" Total h-distance: small= " << fSumH_sm 
 
 1005          << 
" large= " << fSumH_lg
 
 1009   G4int noPrecSmall=4; 
 
 1011   G4cout.precision(noPrecSmall);
 
 1012   G4cout << 
"MIDnums: " << fMinimumStep
 
 1013          << 
"   " << fNoTotalSteps 
 
 1014          << 
"  "  <<  fNoSmallSteps
 
 1015          << 
"  "  << fNoSmallSteps-fNoInitialSmallSteps
 
 1016          << 
"  "  << fNoBadSteps         
 
 1017          << 
"   " << fDyerr_max
 
 1018          << 
"   " << fDyerr_mx2 
 
 1019          << 
"   " << fDyerrPos_smTot 
 
 1021          << 
"   " << fDyerrPos_lgTot
 
 1022          << 
"   " << fDyerrVel_lgTot
 
 1028  G4cout.precision(oldPrec);
 
 1035   if( (newFraction > 1.
e-16) && (newFraction < 1
e-8) )
 
 1037     fSmallestFraction= newFraction;
 
 1041     G4cerr << 
"Warning: SmallestFraction not changed. " << 
G4endl 
 1042            << 
"  Proposed value was " << newFraction << 
G4endl 
 1043            << 
"  Value must be between 1.e-8 and 1.e-16" << 
G4endl;