48 : fDefaultDeltaChord( 0.25 *
mm ),
49 fDeltaChord( fDefaultDeltaChord ),
50 fFirstFraction(0.999), fFractionLast(1.00), fFractionNextEstimate(0.98),
51 fMultipleRadius(15.0),
54 fAllocatedStepper(false),
56 fTotalNoTrials_FNC(0), fNoCalls_FNC(0), fmaxTrials_FNC(0)
59 fIntgrDriver= pIntegrationDriver;
60 fAllocatedStepper=
false;
62 fLastStepEstimate_Unconstrained =
DBL_MAX;
74 : fDefaultDeltaChord( 0.25 *
mm ),
75 fDeltaChord( fDefaultDeltaChord ),
76 fFirstFraction(0.999), fFractionLast(1.00), fFractionNextEstimate(0.98),
77 fMultipleRadius(15.0),
80 fAllocatedStepper(false),
82 fTotalNoTrials_FNC(0), fNoCalls_FNC(0), fmaxTrials_FNC(0)
88 fEquation = pEquation;
89 fLastStepEstimate_Unconstrained =
DBL_MAX;
98 if( pItsStepper == 0 )
100 pItsStepper = fDriversStepper =
106 fAllocatedStepper=
true;
110 fAllocatedStepper=
false;
122 if( fAllocatedStepper)
124 delete fDriversStepper;
138 if( fractLast == -1.0 ) fractLast = 1.0;
139 if( fractNext == -1.0 ) fractNext = 0.98;
146 G4cout <<
" ChordFnd> Trying to set fractions: "
147 <<
" first " << fFirstFraction
148 <<
" last " << fractLast
149 <<
" next " << fractNext
150 <<
" and multiple " << fMultipleRadius
154 if( (fractLast > 0.0) && (fractLast <=1.0) )
156 fFractionLast= fractLast;
160 G4cerr <<
"G4ChordFinder::SetFractions_Last_Next: Invalid "
161 <<
" fraction Last = " << fractLast
162 <<
" must be 0 < fractionLast <= 1 " <<
G4endl;
164 if( (fractNext > 0.0) && (fractNext <1.0) )
166 fFractionNextEstimate = fractNext;
170 G4cerr <<
"G4ChordFinder:: SetFractions_Last_Next: Invalid "
171 <<
" fraction Next = " << fractNext
172 <<
" must be 0 < fractionNext < 1 " <<
G4endl;
192 stepPossible=
FindNextChord(yCurrent, stepMax, yEnd, dyErr, epsStep,
193 &nextStep, latestSafetyOrigin, latestSafetyRadius
199 if ( dyErr < epsStep * stepPossible )
212 if ( ! good_advance )
238 G4double stepTrial, stepForAccuracy;
245 G4bool validEndPoint=
false;
246 G4double dChordStep, lastStepLength;
248 fIntgrDriver-> GetDerivatives( yCurrent, dydx );
250 unsigned int noTrials=0;
251 const unsigned int maxTrials= 75;
253 const G4double safetyFactor= fFirstFraction;
255 stepTrial =
std::min( stepMax, safetyFactor*fLastStepEstimate_Unconstrained );
264 dChordStep, dyErrPos);
270 lastStepLength = stepTrial;
273 stepForChord =
NewStep(stepTrial, dChordStep, newStepEst_Uncons );
275 if( ! validEndPoint )
279 stepTrial = stepForChord;
281 else if (stepForChord <= stepTrial)
284 stepTrial =
std::min( stepForChord, fFractionLast * stepTrial);
293 while( (! validEndPoint) && (noTrials < maxTrials) );
296 if( noTrials >= maxTrials )
298 std::ostringstream message;
299 message <<
"Exceeded maximum number of trials= " << maxTrials <<
G4endl
300 <<
"Current sagita dist= " << dChordStep <<
G4endl
301 <<
"Step sizes (actual and proposed): " <<
G4endl
302 <<
"Last trial = " << lastStepLength <<
G4endl
303 <<
"Next trial = " << stepTrial <<
G4endl
304 <<
"Proposed for chord = " << stepForChord <<
G4endl
306 G4Exception(
"G4ChordFinder::FindNextChord()",
"GeomField0003",
310 if( newStepEst_Uncons > 0.0 )
312 fLastStepEstimate_Unconstrained= newStepEst_Uncons;
317 if( pStepForAccuracy )
321 G4double dyErr_relative = dyErrPos/(epsStep*lastStepLength);
322 if( dyErr_relative > 1.0 )
329 stepForAccuracy = 0.0;
331 *pStepForAccuracy = stepForAccuracy;
334 #ifdef TEST_CHORD_PRINT
338 G4cout <<
"ChordF/FindNextChord: NoTrials= " << noTrials
339 <<
" StepForGoodChord=" << std::setw(10) << stepTrial <<
G4endl;
351 G4double& stepEstimate_Unconstrained )
361 if (dChordStep > 0.0)
363 stepEstimate_Unconstrained =
364 stepTrialOld*std::sqrt( fDeltaChord / dChordStep );
365 stepTrial = fFractionNextEstimate * stepEstimate_Unconstrained;
370 stepTrial = stepTrialOld * 2.;
373 if( stepTrial <= 0.001 * stepTrialOld)
375 if ( dChordStep > 1000.0 * fDeltaChord )
377 stepTrial= stepTrialOld * 0.03;
381 if ( dChordStep > 100. * fDeltaChord )
383 stepTrial= stepTrialOld * 0.1;
387 stepTrial= stepTrialOld * 0.5;
391 else if (stepTrial > 1000.0 * stepTrialOld)
393 stepTrial= 1000.0 * stepTrialOld;
396 if( stepTrial == 0.0 )
403 if ( dChordStep > 1000. * fDeltaChord )
405 stepTrial= stepTrialOld * 0.03;
409 if ( dChordStep > 100. * fDeltaChord )
411 stepTrial= stepTrialOld * 0.1;
415 stepTrial= stepTrialOld * 0.5;
455 if(!first){EndPoint= ApproxCurveV;}
468 ya=(PointG-Point_A).mag();
469 xb=(Point_A-CurrentF_Point).mag();
470 yb=-(PointG-CurrentF_Point).mag();
471 xc=(Point_A-Point_B).mag();
472 yc=-(CurrentE_Point-Point_B).mag();
477 ya=(Point_A-CurrentE_Point).mag();
478 xb=(Point_A-CurrentF_Point).mag();
479 yb=(PointG-CurrentF_Point).mag();
480 xc=(Point_A-Point_B).mag();
481 yc=-(Point_B-PointG).mag();
486 CurrentE_Point, eps_step);
492 if(std::abs(ya)<=tolerance||std::abs(yc)<=tolerance)
508 test_step=(test_step-xb);
511 xb=(CurrentF_Point-Point_B).mag();
514 if(test_step<=0) { test_step=0.1*xb; }
515 if(test_step>=xb) { test_step=0.5*xb; }
516 if(test_step>=curve){ test_step=0.5*curve; }
518 if(curve*(1.+eps_step)<xb)
528 G4cout <<
"G4ChordFinder::ApproxCurvePointS() - test-step ShF = "
529 << test_step <<
" EndPoint = " << EndPoint <<
G4endl;
535 CurveB_PointVelocity,
536 CurrentE_Point, eps_step );
538 G4cout <<
"G4ChordFinder::BrentApprox = " << EndPoint <<
G4endl;
539 G4cout <<
"G4ChordFinder::LinearApprox= " << TestTrack <<
G4endl;
557 G4FieldTrack Current_PointVelocity = CurveA_PointVelocity;
573 if( curve_length < ABdist * (1. - integrationInaccuracyLimit) )
576 G4cerr <<
" Warning in G4ChordFinder::ApproxCurvePoint: "
578 <<
" The two points are further apart than the curve length "
580 <<
" Dist = " << ABdist
581 <<
" curve length = " << curve_length
582 <<
" relativeDiff = " << (curve_length-ABdist)/ABdist
584 if( curve_length < ABdist * (1. - 10*eps_step) )
586 std::ostringstream message;
587 message <<
"Unphysical curve length." <<
G4endl
588 <<
"The size of the above difference exceeds allowed limits."
591 G4Exception(
"G4ChordFinder::ApproxCurvePointV()",
"GeomField0003",
604 AE_fraction = ChordAE_Vector.
mag() / ABdist;
610 G4cout <<
"Warning in G4ChordFinder::ApproxCurvePointV():"
611 <<
" A and B are the same point!" <<
G4endl
612 <<
" Chord AB length = " << ChordAE_Vector.
mag() <<
G4endl
617 if( (AE_fraction> 1.0 +
perMillion) || (AE_fraction< 0.) )
620 G4cerr <<
" G4ChordFinder::ApproxCurvePointV() - Warning:"
621 <<
" Anomalous condition:AE > AB or AE/AB <= 0 " <<
G4endl
622 <<
" AE_fraction = " << AE_fraction <<
G4endl
623 <<
" Chord AE length = " << ChordAE_Vector.
mag() <<
G4endl
625 G4cerr <<
" OK if this condition occurs after a recalculation of 'B'"
626 << G4endl <<
" Otherwise it is an error. " <<
G4endl ;
636 new_st_length= AE_fraction * curve_length;
638 if ( AE_fraction > 0.0 )
641 new_st_length, eps_step );
651 return Current_PointVelocity;
662 G4cout <<
"G4ChordFinder statistics report: " <<
G4endl;
664 <<
" No trials: " << fTotalNoTrials_FNC
665 <<
" No Calls: " << fNoCalls_FNC
666 <<
" Max-trial: " << fmaxTrials_FNC
670 <<
" fFirstFraction " << fFirstFraction
671 <<
" fFractionLast " << fFractionLast
672 <<
" fFractionNextEstimate " << fFractionNextEstimate
685 G4cout <<
" ChF/fnc: notrial " << std::setw( 3) << noTrials
686 <<
" this_step= " << std::setw(10) << lastStepTrial;
687 if( std::fabs( (dChordStep / fDeltaChord) - 1.0 ) < 0.001 )
695 G4cout <<
" dChordStep= " << std::setw(12) << dChordStep;
696 if( dChordStep > fDeltaChord ) {
G4cout <<
" d+"; }
699 G4cout <<
" new_step= " << std::setw(10)
700 << fLastStepEstimate_Unconstrained
701 <<
" new_step_constr= " << std::setw(10)
702 << lastStepTrial <<
G4endl;
703 G4cout <<
" nextStepTrial = " << std::setw(10) << nextStepTrial <<
G4endl;
704 G4cout.precision(oldprec);
static constexpr double perMillion
G4double InvParabolic(const G4double xa, const G4double ya, const G4double xb, const G4double yb, const G4double xc, const G4double yc)
static constexpr double mm
G4double GetCurveLength() const
G4ChordFinder(G4MagInt_Driver *pIntegrationDriver)
G4FieldTrack ApproxCurvePointV(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4ThreeVector ¤tEPoint, G4double epsStep)
virtual void PrintStatistics()
G4int GetNumberOfVariables() const
virtual G4double FindNextChord(const G4FieldTrack &yStart, G4double stepMax, G4FieldTrack &yEnd, G4double &dyErr, G4double epsStep, G4double *pNextStepForAccuracy, const G4ThreeVector latestSafetyOrigin, G4double latestSafetyRadius)
G4ThreeVector GetPosition() const
G4GLOB_DLL std::ostream G4cout
void TestChordPrint(G4int noTrials, G4int lastStepTrial, G4double dChordStep, G4double nextStepTrial)
G4bool AcceptableMissDist(G4double dChordStep) const
void AccumulateStatistics(G4int noTrials)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4double AdvanceChordLimited(G4FieldTrack &yCurrent, G4double stepInitial, G4double epsStep_Relative, const G4ThreeVector latestSafetyOrigin, G4double lasestSafetyRadius)
G4bool QuickAdvance(G4FieldTrack &y_val, const G4double dydx[], G4double hstep, G4double &dchord_step, G4double &dyerr)
T max(const T t1, const T t2)
brief Return the largest of the two arguments
void SetFractions_Last_Next(G4double fractLast=0.90, G4double fractNext=0.95)
G4double NewStep(G4double stepTrialOld, G4double dChordStep, G4double &stepEstimate_Unconstrained)
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4double ComputeNewStepSize(G4double errMaxNorm, G4double hstepCurrent)
G4FieldTrack ApproxCurvePointS(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4FieldTrack &ApproxCurveV, const G4ThreeVector ¤tEPoint, const G4ThreeVector ¤tFPoint, const G4ThreeVector &PointG, G4bool first, G4double epsStep)
G4bool AccurateAdvance(G4FieldTrack &y_current, G4double hstep, G4double eps, G4double hinitial=0.0)
G4GLOB_DLL std::ostream G4cerr