52 G4int statisticsVerbose)
53 : fNoIntegrationVariables(numComponents),
54 fNoVars(
std::max( fNoIntegrationVariables, fMinNoVars )),
55 fStatisticsVerboseLevel(statisticsVerbose)
61 fMinimumStep = hminimum;
68 if( (fVerboseLevel > 0) || (fStatisticsVerboseLevel > 1) )
70 G4cout <<
"MagIntDriver version: Accur-Adv: "
71 <<
"invE_nS, QuickAdv-2sqrt with Statistics "
87 if( fStatisticsVerboseLevel > 1 )
111 G4int no_warnings = 0;
112 static G4int dbg = 1;
113 static G4int nStpPr = 50;
125 const G4int nvar = fNoVars;
135 std::ostringstream message;
136 message <<
"Proposed step is zero; hstep = " << hstep <<
" !";
143 std::ostringstream message;
144 message <<
"Invalid run condition." <<
G4endl
145 <<
"Proposed step is negative; hstep = " << hstep <<
"." <<
G4endl
146 <<
"Requested step cannot be negative! Aborting event.";
156 x1= startCurveLength;
159 if ( (hinitial > 0.0) && (hinitial < hstep)
160 && (hinitial > perMillion * hstep) )
171 for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; }
182 for (i=0; i<nvar; ++i) { ySubStepStart[i] = y[i]; }
192 if( h > fMinimumStep )
208 G4double dchord_step, dyerr, dyerr_len;
212 QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
219 if ( dyerr_len > fDyerr_max ) { fDyerr_max = dyerr_len; }
220 fDyerrPos_smTot += dyerr_len;
222 if (nstp==1) { ++fNoInitialSmallSteps; }
227 if(fNoSmallSteps<2) {
PrintStatus(ySubStepStart, x1, y, x, h, -nstp); }
228 G4cout <<
"Another sub-min step, no " << fNoSmallSteps
229 <<
" of " << fNoTotalSteps <<
" this time " << nstp <<
G4endl;
231 G4cout <<
" dyerr= " << dyerr_len <<
" relative = " << dyerr_len / h
232 <<
" epsilon= " << eps <<
" hstep= " << hstep
233 <<
" h= " << h <<
" hmin= " << fMinimumStep <<
G4endl;
240 "Integration Step became Zero!");
242 dyerr = dyerr_len / h;
253 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
255 if( nstp==nStpPr ) {
G4cout <<
"***** Many steps ****" <<
G4endl; }
257 G4cout <<
"hdid=" << std::setw(12) << hdid <<
" "
258 <<
"hnext=" << std::setw(12) << hnext <<
" "
259 <<
"hstep=" << std::setw(12) << hstep <<
" (requested) "
261 PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp);
266 G4double endPointDist= (EndPos-StartPos).mag();
267 if ( endPointDist >= hdid*(1.+perMillion) )
273 if ( endPointDist >= hdid*(1.+perThousand) )
279 G4cerr <<
" Total steps: bad " << fNoBadSteps
280 <<
" current h= " << hdid <<
G4endl;
281 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
289 if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) )
297 if(std::fabs(hnext) <=
Hmin())
301 if( (x < x2 * (1-eps) ) &&
302 (std::fabs(hstep) >
Hmin()) )
307 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
333 int prec=
G4cout.precision(12);
334 G4cout <<
"Warning: G4MagIntegratorDriver::AccurateAdvance"
336 <<
" Integration step 'h' became "
337 << h <<
" due to roundoff. " <<
G4endl
338 <<
" Calculated as difference of x2= "<< x2 <<
" and x=" << x
339 <<
" Forcing termination of advance." <<
G4endl;
345 }
while ( ((++nstp)<=fMaxNoSteps) && (x < x2) && (!lastStep) );
353 for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; }
359 if(nstp > fMaxNoSteps)
373 if( dbg && no_warnings )
375 G4cerr <<
"G4MagIntegratorDriver exit status: no-steps " << nstp <<
G4endl;
391 const G4int maxNoWarnings = 10;
392 std::ostringstream message;
393 if( (noWarningsIssued < maxNoWarnings) || fVerboseLevel > 10 )
395 message <<
"The stepsize for the next iteration, " << hnext
396 <<
", is too small - in Step number " << nstp <<
"." <<
G4endl
397 <<
"The minimum for the driver is " <<
Hmin() <<
G4endl
398 <<
"Requested integr. length was " << hstep <<
" ." <<
G4endl
399 <<
"The size of this sub-step was " << h <<
" ." <<
G4endl
400 <<
"The integrations has already gone " << xDone;
404 message <<
"Too small 'next' step " << hnext
405 <<
", step-no: " << nstp <<
G4endl
406 <<
", this sub-step: " << h
407 <<
", req_tot_len: " << hstep
408 <<
", done: " << xDone <<
", min: " <<
Hmin();
410 G4Exception(
"G4MagInt_Driver::WarnSmallStepSize()",
"GeomField1001",
422 std::ostringstream message;
423 message <<
"The number of steps used in the Integration driver"
424 <<
" (Runge-Kutta) is too many." <<
G4endl
425 <<
"Integration of the interval was not completed !" <<
G4endl
426 <<
"Only a " << (xCurrent-x1start)*100/(x2end-x1start)
427 <<
" % fraction of it was done.";
428 G4Exception(
"G4MagInt_Driver::WarnTooManyStep()",
"GeomField1001",
441 G4bool isNewMax, prNewMax;
443 isNewMax = endPointDist > (1.0 + maxRelError) * h;
444 prNewMax = endPointDist > (1.0 + 1.05 * maxRelError) * h;
445 if( isNewMax ) { maxRelError= endPointDist / h - 1.0; }
448 && ( (dbg>1) || prNewMax || (endPointDist >= h*(1.+eps) ) ) )
451 std::ostringstream message;
452 if( (noWarnings++ < 10) || (dbg>2) )
454 message <<
"The integration produced an end-point which " <<
G4endl
455 <<
"is further from the start-point than the curve length."
458 message <<
" Distance of endpoints = " << endPointDist
459 <<
", curve length = " << h <<
G4endl
460 <<
" Difference (curveLen-endpDist)= " << (h - endPointDist)
461 <<
", relative = " << (h-endPointDist) / h
462 <<
", epsilon = " << eps;
463 G4Exception(
"G4MagInt_Driver::WarnEndPointTooFar()",
"GeomField1001",
500 G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max);
506 const G4int max_trials=100;
510 G4bool hasSpin = (spin_mag2 > 0.0);
512 for (
G4int iter=0; iter<max_trials; ++iter)
514 pIntStepper-> Stepper(y,dydx,h,ytemp,yerr);
516 G4double eps_pos = eps_rel_max * std::max(h, fMinimumStep);
517 G4double inv_eps_pos_sq = 1.0 / (eps_pos*eps_pos);
521 errpos_sq =
sqr(yerr[0]) +
sqr(yerr[1]) +
sqr(yerr[2]) ;
522 errpos_sq *= inv_eps_pos_sq;
527 if( magvel_sq > 0.0 )
529 errvel_sq = sumerr_sq / magvel_sq;
533 std::ostringstream message;
534 message <<
"Found case of zero momentum." <<
G4endl
535 <<
"- iteration= " << iter <<
"; h= " << h;
538 errvel_sq = sumerr_sq;
540 errvel_sq *= inv_eps_vel_sq;
541 errmax_sq = std::max( errpos_sq, errvel_sq );
546 errspin_sq = (
sqr(yerr[9]) +
sqr(yerr[10]) +
sqr(yerr[11]) )
548 errspin_sq *= inv_eps_vel_sq;
549 errmax_sq = std::max( errmax_sq, errspin_sq );
552 if ( errmax_sq <= 1.0 ) {
break; }
557 if (htemp >= 0.1*h) { h = htemp; }
563 std::ostringstream message;
564 message <<
"Stepsize underflow in Stepper !" <<
G4endl
565 <<
"- Step's start x=" << x <<
" and end x= " << xnew
566 <<
" are equal !! " <<
G4endl
567 <<
" Due to step-size= " << h
568 <<
". Note that input step was " << htry;
576 if (errmax_sq > errcon*errcon)
586 for(
G4int k=0; k<fNoIntegrationVariables; ++k) { y[k] = ytemp[k]; }
602 G4Exception(
"G4MagInt_Driver::QuickAdvance()",
"GeomField0001",
607 dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0];
620 G4double dyerr_pos_sq, dyerr_mom_rel_sq;
624 G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq;
631 pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ;
634 dchord_step= pIntStepper-> DistChord();
644 PrintStatus( yarrin, s_start, yarrout, s_start+hstep, hstep, 1);
650 vel_mag_sq = (
sqr(yarrout[3])+
sqr(yarrout[4])+
sqr(yarrout[5]) );
651 inv_vel_mag_sq = 1.0 / vel_mag_sq;
652 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_vec[4])+
sqr(yerr_vec[5]));
654 dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_mag_sq;
660#ifdef RETURN_A_NEW_STEP_LENGTH
662 dyerr_len = std::sqrt( dyerr_len_sq );
663 dyerr_len_sq /= eps ;
672 if( dyerr_pos_sq > ( dyerr_mom_rel_sq *
sqr(hstep) ) )
674 dyerr = std::sqrt(dyerr_pos_sq);
679 dyerr = std::sqrt(dyerr_mom_rel_sq) * hstep;
687#ifdef QUICK_ADV_ARRAY_IN_AND_OUT
695 G4Exception(
"G4MagInt_Driver::QuickAdvance()",
"GeomField0001",
697 dyerr = dchord_step = hstep * yarrin[0] * dydx[0];
698 yarrout[0]= yarrin[0];
714 if(errMaxNorm > 1.0 )
719 else if(errMaxNorm > 0.0 )
759 if (errMaxNorm > 1.0 )
774 if (errMaxNorm > errcon)
801 CurrentFT.
LoadFromArray( CurrentArr, fNoIntegrationVariables);
804 PrintStatus(StartFT, CurrentFT, requestStep, subStepNo );
814 G4int verboseLevel= fVerboseLevel;
824 G4double DotStartCurrentVeloc= StartUnitVelocity.
dot(CurrentUnitVelocity);
829 if( (subStepNo <= 1) || (verboseLevel > 3) )
831 subStepNo = - subStepNo;
833 G4cout << std::setw( 6) <<
" " << std::setw( 25)
834 <<
" G4MagInt_Driver: Current Position and Direction" <<
" "
836 G4cout << std::setw( 5) <<
"Step#" <<
" "
837 << std::setw( 7) <<
"s-curve" <<
" "
838 << std::setw( 9) <<
"X(mm)" <<
" "
839 << std::setw( 9) <<
"Y(mm)" <<
" "
840 << std::setw( 9) <<
"Z(mm)" <<
" "
841 << std::setw( 8) <<
" N_x " <<
" "
842 << std::setw( 8) <<
" N_y " <<
" "
843 << std::setw( 8) <<
" N_z " <<
" "
844 << std::setw( 8) <<
" N^2-1 " <<
" "
845 << std::setw(10) <<
" N(0).N " <<
" "
846 << std::setw( 7) <<
"KinEner " <<
" "
847 << std::setw(12) <<
"Track-l" <<
" "
848 << std::setw(12) <<
"Step-len" <<
" "
849 << std::setw(12) <<
"Step-len" <<
" "
850 << std::setw( 9) <<
"ReqStep" <<
" "
854 if( (subStepNo <= 0) )
860 if( verboseLevel <= 3 )
864 subStepNo, subStepSize, DotStartCurrentVeloc );
867 G4cout.precision(oldPrec);
884 G4cout << std::setw( 5) << subStepNo <<
" ";
888 G4cout << std::setw( 5) <<
"Start" <<
" ";
891 G4cout << std::setw( 7) << curveLen;
892 G4cout << std::setw( 9) << Position.x() <<
" "
893 << std::setw( 9) << Position.y() <<
" "
894 << std::setw( 9) << Position.z() <<
" "
895 << std::setw( 8) << UnitVelocity.
x() <<
" "
896 << std::setw( 8) << UnitVelocity.
y() <<
" "
897 << std::setw( 8) << UnitVelocity.
z() <<
" ";
899 G4cout << std::setw( 8) << UnitVelocity.
mag2()-1.0 <<
" ";
901 G4cout << std::setw(10) << dotVeloc_StartCurr <<
" ";
902 G4cout.precision(oldprec);
904 G4cout << std::setw(12) << step_len <<
" ";
911 if( curveLen > oldCurveLength )
913 subStep_len= curveLen - oldCurveLength;
915 else if (subStepNo == oldSubStepNo)
917 subStep_len= oldSubStepLength;
919 oldCurveLength= curveLen;
920 oldSubStepLength= subStep_len;
922 G4cout << std::setw(12) << subStep_len <<
" ";
923 G4cout << std::setw(12) << subStepSize <<
" ";
924 if( requestStep != -1.0 )
926 G4cout << std::setw( 9) << requestStep <<
" ";
930 G4cout << std::setw( 9) <<
" InitialStep " <<
" ";
942 G4cout <<
"G4MagInt_Driver Statistics of steps undertaken. " <<
G4endl;
943 G4cout <<
"G4MagInt_Driver: Number of Steps: "
944 <<
" Total= " << fNoTotalSteps
945 <<
" Bad= " << fNoBadSteps
946 <<
" Small= " << fNoSmallSteps
947 <<
" Non-initial small= " << (fNoSmallSteps-fNoInitialSmallSteps)
949 G4cout.precision(oldPrec);
956 if( (newFraction > 1.e-16) && (newFraction < 1e-8) )
958 fSmallestFraction= newFraction;
962 std::ostringstream message;
963 message <<
"Smallest Fraction not changed. " <<
G4endl
964 <<
" Proposed value was " << newFraction <<
G4endl
965 <<
" Value must be between 1.e-8 and 1.e-16";
966 G4Exception(
"G4MagInt_Driver::SetSmallestFraction()",
1013 pIntStepper = pItsStepper;
1019 os <<
"State of G4MagInt_Driver: " << std::endl;
1020 os <<
" Max number of Steps = " << fMaxNoSteps
1021 <<
" (base # = " << fMaxStepBase <<
" )" << std::endl;
1022 os <<
" Safety factor = " << safety << std::endl;
1023 os <<
" Power - shrink = " << pshrnk << std::endl;
1024 os <<
" Power - grow = " << pgrow << std::endl;
1025 os <<
" threshold (errcon) = " << errcon << std::endl;
1027 os <<
" fMinimumStep = " << fMinimumStep << std::endl;
1028 os <<
" Smallest Fraction = " << fSmallestFraction << std::endl;
1030 os <<
" No Integrat Vars = " << fNoIntegrationVariables << std::endl;
1031 os <<
" Min No Vars = " << fMinNoVars << std::endl;
1032 os <<
" Num-Vars = " << fNoVars << std::endl;
1034 os <<
" verbose level = " << fVerboseLevel << std::endl;
1040 os <<
"State of G4MagInt_Driver: " << std::endl;
1043 os <<
" Safety factor = " << magDrv.
GetSafety() << std::endl;
1044 os <<
" Power - shrink = " << magDrv.
GetPshrnk() << std::endl;
1045 os <<
" Power - grow = " << magDrv.
GetPgrow() << std::endl;
1046 os <<
" threshold (errcon) = " << magDrv.
GetErrcon() << std::endl;
1048 os <<
" fMinimumStep = " << magDrv.
GetHmin() << std::endl;
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
void PrintInfo(const G4MagInt_Driver &magDrv, std::ostream &os)
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cerr
G4GLOB_DLL std::ostream G4cout
double dot(const Hep3Vector &) const
static void PrintStatus(const G4double *StartArr, G4double xstart, const G4double *CurrentArr, G4double xcurrent, G4double requestStep, unsigned int subStepNo, unsigned int noIntegrationVariables)
const G4ThreeVector & GetMomentumDir() const
G4double GetCurveLength() const
void SetCurveLength(G4double nCurve_s)
G4double GetKineticEnergy() const
G4ThreeVector GetPosition() const
void DumpToArray(G4double valArr[ncompSVEC]) const
void LoadFromArray(const G4double valArr[ncompSVEC], G4int noVarsIntegrated)
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetPshrnk() const
G4double ComputeNewStepSize_WithinLimits(G4double errMaxNorm, G4double hstepCurrent)
virtual void GetDerivatives(const G4FieldTrack &y_curr, G4double dydx[]) const override
G4MagInt_Driver(G4double hminimum, G4MagIntegratorStepper *pItsStepper, G4int numberOfComponents=6, G4int statisticsVerbosity=0)
void PrintStatus(const G4double *StartArr, G4double xstart, const G4double *CurrentArr, G4double xcurrent, G4double requestStep, G4int subStepNo)
virtual ~G4MagInt_Driver() override
void PrintStatisticsReport()
virtual void SetEquationOfMotion(G4EquationOfMotion *equation) override
virtual void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper) override
G4double GetErrcon() const
void SetSmallestFraction(G4double val)
virtual const G4MagIntegratorStepper * GetStepper() const override
virtual G4bool QuickAdvance(G4FieldTrack &y_val, const G4double dydx[], G4double hstep, G4double &dchord_step, G4double &dyerr) override
G4double GetSafety() const
virtual G4bool AccurateAdvance(G4FieldTrack &y_current, G4double hstep, G4double eps, G4double hinitial=0.0) override
void WarnSmallStepSize(G4double hnext, G4double hstep, G4double h, G4double xDone, G4int noSteps)
virtual G4int GetVerboseLevel() const override
void WarnEndPointTooFar(G4double endPointDist, G4double hStepSize, G4double epsilonRelative, G4int debugFlag)
G4int GetMaxNoSteps() const
void OneGoodStep(G4double ystart[], const G4double dydx[], G4double &x, G4double htry, G4double eps, G4double &hdid, G4double &hnext)
G4double ComputeNewStepSize_WithoutReductionLimit(G4double errMaxNorm, G4double hstepCurrent)
virtual G4EquationOfMotion * GetEquationOfMotion() override
void PrintStat_Aux(const G4FieldTrack &aFieldTrack, G4double requestStep, G4double actualStep, G4int subStepNo, G4double subStepSize, G4double dotVelocities)
G4double GetSmallestFraction() const
G4double GetPgrow() const
virtual G4bool DoesReIntegrate() const override
virtual G4double ComputeNewStepSize(G4double errMaxNorm, G4double hstepCurrent) override
void WarnTooManyStep(G4double x1start, G4double x2end, G4double xCurrent)
void StreamInfo(std::ostream &os) const override
void ReSetParameters(G4double new_safety=0.9)
G4EquationOfMotion * GetEquationOfMotion()
void RightHandSide(const G4double y[], G4double dydx[]) const
void SetEquationOfMotion(G4EquationOfMotion *newEquation)
virtual G4int IntegratorOrder() const =0
static constexpr G4double max_stepping_decrease
static constexpr G4double max_stepping_increase