48 G4int statisticsVerbose)
49 : fNoIntegrationVariables(numComponents),
50 fNoVars( std::
max( fNoIntegrationVariables, fMinNoVars )),
51 fStatisticsVerboseLevel(statisticsVerbose)
66 G4cout <<
"MagIntDriver version: Accur-Adv: "
67 <<
"invE_nS, QuickAdv-2sqrt with Statistics "
103 G4int nstp, i, no_warnings = 0;
107 static G4int dbg = 1;
108 static G4int nStpPr = 50;
116 G4bool succeeded =
true, lastStepSucceeded;
120 G4int noFullIntegr = 0, noSmallIntegr = 0;
133 message <<
"Proposed step is zero; hstep = " << hstep <<
" !";
141 message <<
"Invalid run condition." <<
G4endl
142 <<
"Proposed step is negative; hstep = " << hstep <<
"." <<
G4endl
143 <<
"Requested step cannot be negative! Aborting event.";
153 x1= startCurveLength;
156 if ( (hinitial > 0.0) && (hinitial < hstep)
168 for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; }
179 for (i=0; i<nvar; ++i) { ySubStepStart[i] = y[i]; }
193 lastStepSucceeded = (hdid ==
h);
197 PrintStatus( ySubStepStart, xSubStepStart, y, x, h, nstp);
205 G4double dchord_step, dyerr, dyerr_len;
209 QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
228 G4cout <<
" dyerr= " << dyerr_len <<
" relative = " << dyerr_len / h
229 <<
" epsilon= " << eps <<
" hstep= " << hstep
237 "Integration Step became Zero!");
239 dyerr = dyerr_len /
h;
247 lastStepSucceeded = (dyerr<=
eps);
250 if (lastStepSucceeded) { ++noFullIntegr; }
251 else { ++noSmallIntegr; }
256 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
258 if( nstp==nStpPr ) {
G4cout <<
"***** Many steps ****" <<
G4endl; }
260 G4cout <<
"hdid=" << std::setw(12) << hdid <<
" "
261 <<
"hnext=" << std::setw(12) << hnext <<
" "
262 <<
"hstep=" << std::setw(12) << hstep <<
" (requested) "
264 PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp);
269 G4double endPointDist= (EndPos-StartPos).mag();
283 <<
" good " << noGoodSteps <<
" current h= " << hdid
285 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
306 if(std::fabs(hnext) <=
Hmin())
310 if( (x < x2 * (1-eps) ) &&
311 (std::fabs(hstep) >
Hmin()) )
316 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
343 G4cout <<
"Warning: G4MagIntegratorDriver::AccurateAdvance"
345 <<
" Integration step 'h' became "
346 << h <<
" due to roundoff. " <<
G4endl
347 <<
" Calculated as difference of x2= "<< x2 <<
" and x=" << x
348 <<
" Forcing termination of advance." <<
G4endl;
354 }
while ( ((nstp++)<=
fMaxNoSteps) && (x < x2) && (!lastStep) );
362 for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; }
382 if( dbg && no_warnings )
384 G4cerr <<
"G4MagIntegratorDriver exit status: no-steps " << nstp <<
G4endl;
400 const G4int maxNoWarnings = 10;
402 if( (noWarningsIssued < maxNoWarnings) ||
fVerboseLevel > 10 )
404 message <<
"The stepsize for the next iteration, " << hnext
405 <<
", is too small - in Step number " << nstp <<
"." <<
G4endl
406 <<
"The minimum for the driver is " <<
Hmin() <<
G4endl
407 <<
"Requested integr. length was " << hstep <<
" ." <<
G4endl
408 <<
"The size of this sub-step was " << h <<
" ." <<
G4endl
409 <<
"The integrations has already gone " << xDone;
413 message <<
"Too small 'next' step " << hnext
414 <<
", step-no: " << nstp <<
G4endl
415 <<
", this sub-step: " << h
416 <<
", req_tot_len: " << hstep
417 <<
", done: " << xDone <<
", min: " <<
Hmin();
419 G4Exception(
"G4MagInt_Driver::WarnSmallStepSize()",
"GeomField1001",
432 message <<
"The number of steps used in the Integration driver"
433 <<
" (Runge-Kutta) is too many." <<
G4endl
434 <<
"Integration of the interval was not completed !" <<
G4endl
435 <<
"Only a " << (xCurrent-x1start)*100/(x2end-x1start)
436 <<
" % fraction of it was done.";
437 G4Exception(
"G4MagInt_Driver::WarnTooManyStep()",
"GeomField1001",
450 G4bool isNewMax, prNewMax;
452 isNewMax = endPointDist > (1.0 + maxRelError) * h;
453 prNewMax = endPointDist > (1.0 + 1.05 * maxRelError) * h;
454 if( isNewMax ) { maxRelError= endPointDist / h - 1.0; }
457 && ( (dbg>1) || prNewMax || (endPointDist >= h*(1.+
eps) ) ) )
461 if( (noWarnings++ < 10) || (dbg>2) )
463 message <<
"The integration produced an end-point which " <<
G4endl
464 <<
"is further from the start-point than the curve length."
467 message <<
" Distance of endpoints = " << endPointDist
468 <<
", curve length = " << h <<
G4endl
469 <<
" Difference (curveLen-endpDist)= " << (h - endPointDist)
470 <<
", relative = " << (h-endPointDist) / h
471 <<
", epsilon = " <<
eps;
472 G4Exception(
"G4MagInt_Driver::WarnEndPointTooFar()",
"GeomField1001",
509 G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max);
516 const G4int max_trials=100;
520 G4bool hasSpin = (spin_mag2 > 0.0);
522 for (
G4int iter=0; iter<max_trials; ++iter)
528 G4double inv_eps_pos_sq = 1.0 / (eps_pos*eps_pos);
532 errpos_sq =
sqr(yerr[0]) +
sqr(yerr[1]) +
sqr(yerr[2]) ;
533 errpos_sq *= inv_eps_pos_sq;
538 if( magvel_sq > 0.0 )
540 errvel_sq = sumerr_sq / magvel_sq;
545 message <<
"Found case of zero momentum." <<
G4endl
546 <<
"- iteration= " << iter <<
"; h= " <<
h;
549 errvel_sq = sumerr_sq;
551 errvel_sq *= inv_eps_vel_sq;
552 errmax_sq =
std::max( errpos_sq, errvel_sq );
557 errspin_sq = (
sqr(yerr[9]) +
sqr(yerr[10]) +
sqr(yerr[11]) )
559 errspin_sq *= inv_eps_vel_sq;
560 errmax_sq =
std::max( errmax_sq, errspin_sq );
563 if ( errmax_sq <= 1.0 ) {
break; }
568 if (htemp >= 0.1*h) { h = htemp; }
575 message <<
"Stepsize underflow in Stepper !" <<
G4endl
576 <<
"- Step's start x=" << x <<
" and end x= " << xnew
577 <<
" are equal !! " <<
G4endl
578 <<
" Due to step-size= " << h
579 <<
". Note that input step was " << htry;
613 G4Exception(
"G4MagInt_Driver::QuickAdvance()",
"GeomField0001",
618 dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0];
631 G4double dyerr_pos_sq, dyerr_mom_rel_sq;
635 G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq;
658 PrintStatus( yarrin, s_start, yarrout, s_start+hstep, hstep, 1);
664 vel_mag_sq = (
sqr(yarrout[3])+
sqr(yarrout[4])+
sqr(yarrout[5]) );
665 inv_vel_mag_sq = 1.0 / vel_mag_sq;
666 dyerr_pos_sq = (
sqr(yerr_vec[0])+
sqr(yerr_vec[1])+
sqr(yerr_vec[2]));
667 dyerr_mom_sq = (
sqr(yerr_vec[3])+
sqr(yerr_vec[4])+
sqr(yerr_vec[5]));
668 dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_mag_sq;
674 #ifdef RETURN_A_NEW_STEP_LENGTH
676 dyerr_len = std::sqrt( dyerr_len_sq );
677 dyerr_len_sq /=
eps ;
686 if( dyerr_pos_sq > ( dyerr_mom_rel_sq *
sqr(hstep) ) )
688 dyerr = std::sqrt(dyerr_pos_sq);
693 dyerr = std::sqrt(dyerr_mom_rel_sq) * hstep;
701 #ifdef QUICK_ADV_ARRAY_IN_AND_OUT
709 G4Exception(
"G4MagInt_Driver::QuickAdvance()",
"GeomField0001",
711 dyerr = dchord_step = hstep * yarrin[0] * dydx[0];
712 yarrout[0]= yarrin[0];
728 if(errMaxNorm > 1.0 )
733 else if(errMaxNorm > 0.0 )
762 if (errMaxNorm > 1.0 )
807 PrintStatus(StartFT, CurrentFT, requestStep, subStepNo );
818 const G4int noPrecision = 5;
827 G4double DotStartCurrentVeloc= StartUnitVelocity.
dot(CurrentUnitVelocity);
832 if( (subStepNo <= 1) || (verboseLevel > 3) )
834 subStepNo = - subStepNo;
836 G4cout << std::setw( 6) <<
" " << std::setw( 25)
837 <<
" G4MagInt_Driver: Current Position and Direction" <<
" "
839 G4cout << std::setw( 5) <<
"Step#" <<
" "
840 << std::setw( 7) <<
"s-curve" <<
" "
841 << std::setw( 9) <<
"X(mm)" <<
" "
842 << std::setw( 9) <<
"Y(mm)" <<
" "
843 << std::setw( 9) <<
"Z(mm)" <<
" "
844 << std::setw( 8) <<
" N_x " <<
" "
845 << std::setw( 8) <<
" N_y " <<
" "
846 << std::setw( 8) <<
" N_z " <<
" "
847 << std::setw( 8) <<
" N^2-1 " <<
" "
848 << std::setw(10) <<
" N(0).N " <<
" "
849 << std::setw( 7) <<
"KinEner " <<
" "
850 << std::setw(12) <<
"Track-l" <<
" "
851 << std::setw(12) <<
"Step-len" <<
" "
852 << std::setw(12) <<
"Step-len" <<
" "
853 << std::setw( 9) <<
"ReqStep" <<
" "
857 if( (subStepNo <= 0) )
863 if( verboseLevel <= 3 )
865 G4cout.precision(noPrecision);
867 subStepNo, subStepSize, DotStartCurrentVeloc );
870 G4cout.precision(oldPrec);
887 G4cout << std::setw( 5) << subStepNo <<
" ";
891 G4cout << std::setw( 5) <<
"Start" <<
" ";
894 G4cout << std::setw( 7) << curveLen;
895 G4cout << std::setw( 9) << Position.
x() <<
" "
896 << std::setw( 9) << Position.
y() <<
" "
897 << std::setw( 9) << Position.
z() <<
" "
898 << std::setw( 8) << UnitVelocity.
x() <<
" "
899 << std::setw( 8) << UnitVelocity.
y() <<
" "
900 << std::setw( 8) << UnitVelocity.
z() <<
" ";
902 G4cout << std::setw( 8) << UnitVelocity.
mag2()-1.0 <<
" ";
904 G4cout << std::setw(10) << dotVeloc_StartCurr <<
" ";
905 G4cout.precision(oldprec);
907 G4cout << std::setw(12) << step_len <<
" ";
914 if( curveLen > oldCurveLength )
916 subStep_len= curveLen - oldCurveLength;
918 else if (subStepNo == oldSubStepNo)
920 subStep_len= oldSubStepLength;
922 oldCurveLength= curveLen;
923 oldSubStepLength= subStep_len;
925 G4cout << std::setw(12) << subStep_len <<
" ";
926 G4cout << std::setw(12) << subStepSize <<
" ";
927 if( requestStep != -1.0 )
929 G4cout << std::setw( 9) << requestStep <<
" ";
933 G4cout << std::setw( 9) <<
" InitialStep " <<
" ";
945 G4cout <<
"G4MagInt_Driver Statistics of steps undertaken. " <<
G4endl;
946 G4cout <<
"G4MagInt_Driver: Number of Steps: "
952 G4cout.precision(oldPrec);
959 if( (newFraction > 1.
e-16) && (newFraction < 1
e-8) )
966 message <<
"Smallest Fraction not changed. " <<
G4endl
967 <<
" Proposed value was " << newFraction <<
G4endl
968 <<
" Value must be between 1.e-8 and 1.e-16";
969 G4Exception(
"G4MagInt_Driver::SetSmallestFraction()",