51 G4int statisticsVerbose)
52 : fNoIntegrationVariables(numComponents),
53 fNoVars( std::max( fNoIntegrationVariables, fMinNoVars )),
54 fStatisticsVerboseLevel(statisticsVerbose)
60 fMinimumStep = hminimum;
67 if( (fVerboseLevel > 0) || (fStatisticsVerboseLevel > 1) )
69 G4cout <<
"MagIntDriver version: Accur-Adv: "
70 <<
"invE_nS, QuickAdv-2sqrt with Statistics "
86 if( fStatisticsVerboseLevel > 1 )
106 G4int nstp, i, no_warnings = 0;
110 static G4int dbg = 1;
118 G4bool succeeded =
true, lastStepSucceeded;
122 G4int noFullIntegr = 0, noSmallIntegr = 0;
124 const G4int nvar = fNoVars;
134 std::ostringstream message;
135 message <<
"Proposed step is zero; hstep = " << hstep <<
" !";
136 G4Exception(
"G4OldMagIntDriver::AccurateAdvance()",
142 std::ostringstream message;
143 message <<
"Invalid run condition." <<
G4endl
144 <<
"Proposed step is negative; hstep = " << hstep <<
"." <<
G4endl
145 <<
"Requested step cannot be negative! Aborting event.";
146 G4Exception(
"G4OldMagIntDriver::AccurateAdvance()",
155 x1= startCurveLength;
158 if ( (hinitial > 0.0) && (hinitial < hstep)
159 && (hinitial > perMillion * hstep) )
170 for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; }
174 G4cout <<
"IDriver::AccurAdv called. "
175 <<
" Input: hstep = " << hstep <<
" hinitial= " << hinitial <<
" , current: h = " << h <<
G4endl;
187 for (i=0; i<nvar; ++i) { ySubStepStart[i] = y[i]; }
199 if( h > fMinimumStep )
203 lastStepSucceeded = (hdid == h);
207 G4cout <<
"IntegrationDriver -- after OneGoodStep / requesting step = " << h <<
G4endl;
217 G4double dchord_step, dyerr, dyerr_len;
221 QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
228 if ( dyerr_len > fDyerr_max ) { fDyerr_max = dyerr_len; }
229 fDyerrPos_smTot += dyerr_len;
231 if (nstp<=1) { ++fNoInitialSmallSteps; }
236 if(fNoSmallSteps<2) {
PrintStatus(ySubStepStart, x1, y, x, h, -nstp); }
237 G4cout <<
"Another sub-min step, no " << fNoSmallSteps
238 <<
" of " << fNoTotalSteps <<
" this time " << nstp <<
G4endl;
240 G4cout <<
" dyerr= " << dyerr_len <<
" relative = " << dyerr_len / h
241 <<
" epsilon= " << eps <<
" hstep= " << hstep
242 <<
" h= " << h <<
" hmin= " << fMinimumStep <<
G4endl;
247 G4Exception(
"G4OldMagIntDriver::AccurateAdvance()",
249 "Integration Step became Zero!");
251 dyerr = dyerr_len / h;
259 lastStepSucceeded = (dyerr<= eps);
262 if (lastStepSucceeded) { ++noFullIntegr; }
263 else { ++noSmallIntegr; }
268 static G4int nStpPr = 50;
269 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
271 if( nstp==nStpPr ) {
G4cout <<
"***** Many steps ****" <<
G4endl; }
273 G4cout <<
"hdid=" << std::setw(12) << hdid <<
" "
274 <<
"hnext=" << std::setw(12) << hnext <<
" "
275 <<
"hstep=" << std::setw(12) << hstep <<
" (requested) "
277 PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp);
282 G4double endPointDist= (EndPos-StartPos).mag();
283 if ( endPointDist >= hdid*(1.+perMillion) )
289 if ( endPointDist >= hdid*(1.+perThousand) )
295 G4cerr <<
" Total steps: bad " << fNoBadSteps
296 <<
" good " << noGoodSteps <<
" current h= " << hdid
298 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
311 if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) )
319 if(std::fabs(hnext) <=
Hmin())
323 if( (x < x2 * (1-eps) ) &&
324 (std::fabs(hstep) >
Hmin()) )
329 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
355 int prec=
G4cout.precision(12);
356 G4cout <<
"Warning: G4MagIntegratorDriver::AccurateAdvance"
358 <<
" Integration step 'h' became "
359 << h <<
" due to roundoff. " <<
G4endl
360 <<
" Calculated as difference of x2= "<< x2 <<
" and x=" << x
361 <<
" Forcing termination of advance." <<
G4endl;
367 }
while ( ((nstp++)<=fMaxNoSteps) && (x < x2) && (!lastStep) );
375 for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; }
381 if(nstp > fMaxNoSteps)
395 if( dbg && no_warnings )
397 G4cerr <<
"G4MagIntegratorDriver exit status: no-steps " << nstp <<
G4endl;
413 const G4int maxNoWarnings = 10;
414 std::ostringstream message;
415 if( (noWarningsIssued < maxNoWarnings) || fVerboseLevel > 10 )
417 message <<
"The stepsize for the next iteration, " << hnext
418 <<
", is too small - in Step number " << nstp <<
"." <<
G4endl
419 <<
"The minimum for the driver is " <<
Hmin() <<
G4endl
420 <<
"Requested integr. length was " << hstep <<
" ." <<
G4endl
421 <<
"The size of this sub-step was " << h <<
" ." <<
G4endl
422 <<
"The integrations has already gone " << xDone;
426 message <<
"Too small 'next' step " << hnext
427 <<
", step-no: " << nstp <<
G4endl
428 <<
", this sub-step: " << h
429 <<
", req_tot_len: " << hstep
430 <<
", done: " << xDone <<
", min: " <<
Hmin();
432 G4Exception(
"G4OldMagIntDriver::WarnSmallStepSize()",
"GeomField1001",
444 std::ostringstream message;
445 message <<
"The number of steps used in the Integration driver"
446 <<
" (Runge-Kutta) is too many." <<
G4endl
447 <<
"Integration of the interval was not completed !" <<
G4endl
448 <<
"Only a " << (xCurrent-x1start)*100/(x2end-x1start)
449 <<
" % fraction of it was done.";
450 G4Exception(
"G4OldMagIntDriver::WarnTooManyStep()",
"GeomField1001",
463 G4bool isNewMax, prNewMax;
465 isNewMax = endPointDist > (1.0 + maxRelError) * h;
466 prNewMax = endPointDist > (1.0 + 1.05 * maxRelError) * h;
467 if( isNewMax ) { maxRelError= endPointDist / h - 1.0; }
470 && ( (dbg>1) || prNewMax || (endPointDist >= h*(1.+eps) ) ) )
473 std::ostringstream message;
474 if( (noWarnings++ < 10) || (dbg>2) )
476 message <<
"The integration produced an end-point which " <<
G4endl
477 <<
"is further from the start-point than the curve length."
480 message <<
" Distance of endpoints = " << endPointDist
481 <<
", curve length = " << h <<
G4endl
482 <<
" Difference (curveLen-endpDist)= " << (h - endPointDist)
483 <<
", relative = " << (h-endPointDist) / h
484 <<
", epsilon = " << eps;
485 G4Exception(
"G4OldMagIntDriver::WarnEndPointTooFar()",
"GeomField1001",
522 G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max);
529 const G4int max_trials=100;
533 G4bool hasSpin = (spin_mag2 > 0.0);
535 for (
G4int iter=0; iter<max_trials; ++iter)
538 pIntStepper-> Stepper(y,dydx,h,ytemp,yerr);
540 G4double eps_pos = eps_rel_max * std::max(h, fMinimumStep);
541 G4double inv_eps_pos_sq = 1.0 / (eps_pos*eps_pos);
545 errpos_sq =
sqr(yerr[0]) +
sqr(yerr[1]) +
sqr(yerr[2]) ;
546 errpos_sq *= inv_eps_pos_sq;
551 if( magvel_sq > 0.0 )
553 errvel_sq = sumerr_sq / magvel_sq;
557 std::ostringstream message;
558 message <<
"Found case of zero momentum." <<
G4endl
559 <<
"- iteration= " << iter <<
"; h= " << h;
562 errvel_sq = sumerr_sq;
564 errvel_sq *= inv_eps_vel_sq;
565 errmax_sq = std::max( errpos_sq, errvel_sq );
570 errspin_sq = (
sqr(yerr[9]) +
sqr(yerr[10]) +
sqr(yerr[11]) )
572 errspin_sq *= inv_eps_vel_sq;
573 errmax_sq = std::max( errmax_sq, errspin_sq );
576 if ( errmax_sq <= 1.0 ) {
break; }
581 if (htemp >= 0.1*h) { h = htemp; }
587 std::ostringstream message;
588 message <<
"Stepsize underflow in Stepper !" <<
G4endl
589 <<
"- Step's start x=" << x <<
" and end x= " << xnew
590 <<
" are equal !! " <<
G4endl
591 <<
" Due to step-size= " << h
592 <<
". Note that input step was " << htry;
600 if (errmax_sq > errcon*errcon)
610 for(
G4int k=0; k<fNoIntegrationVariables; ++k) { y[k] = ytemp[k]; }
626 G4Exception(
"G4OldMagIntDriver::QuickAdvance()",
"GeomField0001",
631 dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0];
644 G4double dyerr_pos_sq, dyerr_mom_rel_sq;
648 G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq;
662 pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ;
665 dchord_step= pIntStepper-> DistChord();
675 PrintStatus( yarrin, s_start, yarrout, s_start+hstep, hstep, 1);
681 vel_mag_sq = (
sqr(yarrout[3])+
sqr(yarrout[4])+
sqr(yarrout[5]) );
682 inv_vel_mag_sq = 1.0 / vel_mag_sq;
683 dyerr_pos_sq = (
sqr(yerr_vec[0])+
sqr(yerr_vec[1])+
sqr(yerr_vec[2]));
684 dyerr_mom_sq = (
sqr(yerr_vec[3])+
sqr(yerr_vec[4])+
sqr(yerr_vec[5]));
685 dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_mag_sq;
691#ifdef RETURN_A_NEW_STEP_LENGTH
693 dyerr_len = std::sqrt( dyerr_len_sq );
694 dyerr_len_sq /= eps ;
703 if( dyerr_pos_sq > ( dyerr_mom_rel_sq *
sqr(hstep) ) )
705 dyerr = std::sqrt(dyerr_pos_sq);
710 dyerr = std::sqrt(dyerr_mom_rel_sq) * hstep;
716 <<
"QuickAdvance call # " << no_call <<
G4endl
717 <<
" Input: hstep= " << hstep <<
G4endl
718 <<
" track= " << startTrack <<
G4endl
719 <<
" Output: track= " << y_posvel <<
G4endl
720 <<
" d_chord = " << dchord_step
721 <<
" dyerr = " << dyerr <<
G4endl;
729#ifdef QUICK_ADV_ARRAY_IN_AND_OUT
737 G4Exception(
"G4OldMagIntDriver::QuickAdvance()",
"GeomField0001",
739 dyerr = dchord_step = hstep * yarrin[0] * dydx[0];
740 yarrout[0]= yarrin[0];
756 if(errMaxNorm > 1.0 )
761 else if(errMaxNorm > 0.0 )
790 if (errMaxNorm > 1.0 )
805 if (errMaxNorm > errcon)
832 CurrentFT.
LoadFromArray( CurrentArr, fNoIntegrationVariables);
835 PrintStatus(StartFT, CurrentFT, requestStep, subStepNo );
845 G4int verboseLevel= fVerboseLevel;
855 G4double DotStartCurrentVeloc= StartUnitVelocity.
dot(CurrentUnitVelocity);
860 if( (subStepNo <= 1) || (verboseLevel > 3) )
862 subStepNo = - subStepNo;
864 G4cout << std::setw( 6) <<
" " << std::setw( 25)
865 <<
" G4OldMagIntDriver: Current Position and Direction" <<
" "
867 G4cout << std::setw( 5) <<
"Step#" <<
" "
868 << std::setw( 7) <<
"s-curve" <<
" "
869 << std::setw( 9) <<
"X(mm)" <<
" "
870 << std::setw( 9) <<
"Y(mm)" <<
" "
871 << std::setw( 9) <<
"Z(mm)" <<
" "
872 << std::setw( 8) <<
" N_x " <<
" "
873 << std::setw( 8) <<
" N_y " <<
" "
874 << std::setw( 8) <<
" N_z " <<
" "
875 << std::setw( 8) <<
" N^2-1 " <<
" "
876 << std::setw(10) <<
" N(0).N " <<
" "
877 << std::setw( 7) <<
"KinEner " <<
" "
878 << std::setw(12) <<
"Track-l" <<
" "
879 << std::setw(12) <<
"Step-len" <<
" "
880 << std::setw(12) <<
"Step-len" <<
" "
881 << std::setw( 9) <<
"ReqStep" <<
" "
885 if( (subStepNo <= 0) )
891 if( verboseLevel <= 3 )
895 subStepNo, subStepSize, DotStartCurrentVeloc );
898 G4cout.precision(oldPrec);
915 G4cout << std::setw( 5) << subStepNo <<
" ";
919 G4cout << std::setw( 5) <<
"Start" <<
" ";
922 G4cout << std::setw( 7) << curveLen;
923 G4cout << std::setw( 9) << Position.x() <<
" "
924 << std::setw( 9) << Position.y() <<
" "
925 << std::setw( 9) << Position.z() <<
" "
926 << std::setw( 8) << UnitVelocity.
x() <<
" "
927 << std::setw( 8) << UnitVelocity.
y() <<
" "
928 << std::setw( 8) << UnitVelocity.
z() <<
" ";
930 G4cout << std::setw( 8) << UnitVelocity.
mag2()-1.0 <<
" ";
932 G4cout << std::setw(10) << dotVeloc_StartCurr <<
" ";
933 G4cout.precision(oldprec);
935 G4cout << std::setw(12) << step_len <<
" ";
942 if( curveLen > oldCurveLength )
944 subStep_len= curveLen - oldCurveLength;
946 else if (subStepNo == oldSubStepNo)
948 subStep_len= oldSubStepLength;
950 oldCurveLength= curveLen;
951 oldSubStepLength= subStep_len;
953 G4cout << std::setw(12) << subStep_len <<
" ";
954 G4cout << std::setw(12) << subStepSize <<
" ";
955 if( requestStep != -1.0 )
957 G4cout << std::setw( 9) << requestStep <<
" ";
961 G4cout << std::setw( 9) <<
" InitialStep " <<
" ";
973 G4cout <<
"G4OldMagIntDriver Statistics of steps undertaken. " <<
G4endl;
974 G4cout <<
"G4OldMagIntDriver: Number of Steps: "
975 <<
" Total= " << fNoTotalSteps
976 <<
" Bad= " << fNoBadSteps
977 <<
" Small= " << fNoSmallSteps
978 <<
" Non-initial small= " << (fNoSmallSteps-fNoInitialSmallSteps)
980 G4cout.precision(oldPrec);
987 if( (newFraction > 1.e-16) && (newFraction < 1e-8) )
989 fSmallestFraction= newFraction;
993 std::ostringstream message;
994 message <<
"Smallest Fraction not changed. " <<
G4endl
995 <<
" Proposed value was " << newFraction <<
G4endl
996 <<
" Value must be between 1.e-8 and 1.e-16";
997 G4Exception(
"G4OldMagIntDriver::SetSmallestFraction()",
1044 pIntStepper = pItsStepper;
1050 os <<
"State of G4OldMagIntDriver: " << std::endl;
1051 os <<
" Max number of Steps = " << fMaxNoSteps
1052 <<
" (base # = " << fMaxStepBase <<
" )" << std::endl;
1053 os <<
" Safety factor = " << safety << std::endl;
1054 os <<
" Power - shrink = " << pshrnk << std::endl;
1055 os <<
" Power - grow = " << pgrow << std::endl;
1056 os <<
" threshold (errcon) = " << errcon << std::endl;
1058 os <<
" fMinimumStep = " << fMinimumStep << std::endl;
1059 os <<
" Smallest Fraction = " << fSmallestFraction << std::endl;
1061 os <<
" No Integrat Vars = " << fNoIntegrationVariables << std::endl;
1062 os <<
" Min No Vars = " << fMinNoVars << std::endl;
1063 os <<
" Num-Vars = " << fNoVars << std::endl;
1065 os <<
" verbose level = " << fVerboseLevel << std::endl;
1070 os <<
" Reintegrates = " << does << std::endl;
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
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()
G4EquationOfMotion * GetEquationOfMotion()
void RightHandSide(const G4double y[], G4double dydx[]) const
void SetEquationOfMotion(G4EquationOfMotion *newEquation)
virtual G4int IntegratorOrder() const =0
void PrintStat_Aux(const G4FieldTrack &aFieldTrack, G4double requestStep, G4double actualStep, G4int subStepNo, G4double subStepSize, G4double dotVelocities)
virtual G4bool QuickAdvance(G4FieldTrack &y_val, const G4double dydx[], G4double hstep, G4double &dchord_step, G4double &dyerr) override
virtual G4bool DoesReIntegrate() const override
void PrintStatisticsReport()
G4double ComputeNewStepSize_WithinLimits(G4double errMaxNorm, G4double hstepCurrent)
void PrintStatus(const G4double *StartArr, G4double xstart, const G4double *CurrentArr, G4double xcurrent, G4double requestStep, G4int subStepNo)
G4double GetPgrow() const
virtual G4bool AccurateAdvance(G4FieldTrack &y_current, G4double hstep, G4double eps, G4double hinitial=0.0) override
void OneGoodStep(G4double ystart[], const G4double dydx[], G4double &x, G4double htry, G4double eps, G4double &hdid, G4double &hnext)
void WarnSmallStepSize(G4double hnext, G4double hstep, G4double h, G4double xDone, G4int noSteps)
void ReSetParameters(G4double new_safety=0.9)
virtual ~G4OldMagIntDriver() override
virtual void SetEquationOfMotion(G4EquationOfMotion *equation) override
G4double GetSafety() const
void SetSmallestFraction(G4double val)
void StreamInfo(std::ostream &os) const override
virtual G4double ComputeNewStepSize(G4double errMaxNorm, G4double hstepCurrent) override
virtual void GetDerivatives(const G4FieldTrack &y_curr, G4double dydx[]) const override
virtual G4EquationOfMotion * GetEquationOfMotion() override
virtual void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper) override
G4double GetPshrnk() const
virtual const G4MagIntegratorStepper * GetStepper() const override
G4OldMagIntDriver(G4double hminimum, G4MagIntegratorStepper *pItsStepper, G4int numberOfComponents=6, G4int statisticsVerbosity=0)
void WarnEndPointTooFar(G4double endPointDist, G4double hStepSize, G4double epsilonRelative, G4int debugFlag)
void WarnTooManyStep(G4double x1start, G4double x2end, G4double xCurrent)
static constexpr G4double max_stepping_decrease
static constexpr G4double max_stepping_increase