Advances integration accurately by relative accuracy better than 'eps'.
99{
100
101
102
103
104
105
108
109#ifdef G4DEBUG_FIELD
110 G4int no_warnings = 0;
111 static G4int dbg = 1;
112 static G4int nStpPr = 50;
114 G4FieldTrack yFldTrkStart(y_current);
115#endif
116
117 G4double y[
G4FieldTrack::ncompSVEC] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
118 G4double dydx[
G4FieldTrack::ncompSVEC] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
119 G4double ystart[
G4FieldTrack::ncompSVEC] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
120 G4double yEnd[
G4FieldTrack::ncompSVEC] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
123
125
126 const G4int nvar = fNoVars;
127
128 G4FieldTrack yStartFT(y_current);
129
130
131
132 if( hstep <= 0.0 )
133 {
134 if( hstep == 0.0 )
135 {
136 std::ostringstream message;
137 message << "Proposed step is zero; hstep = " << hstep << " !";
140 return succeeded;
141 }
142
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.";
149 return false;
150 }
151
153
155 x1= startCurveLength;
156 x2= x1 + hstep;
157
158 if ( (hinitial > 0.0) && (hinitial < hstep)
159 && (hinitial > perMillion * hstep) )
160 {
161 h = hinitial;
162 }
163 else
164 {
165 h = hstep;
166 }
167
168 x = x1;
169
170 for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; }
171
173 nstp = 1;
174
175 do
176 {
178
179#ifdef G4DEBUG_FIELD
181 for (i=0; i<nvar; ++i) { ySubStepStart[i] = y[i]; }
182 yFldTrkStart.LoadFromArray(y, fNoIntegrationVariables);
183 yFldTrkStart.SetCurveLength(x);
184#endif
185
186 pIntStepper->RightHandSide( y, dydx );
187 ++fNoTotalSteps;
188
189
190
191 if( h > fMinimumStep )
192 {
194
195#ifdef G4DEBUG_FIELD
196 if (dbg>2)
197 {
198
200 }
201#endif
202 }
203 else
204 {
207 G4double dchord_step, dyerr, dyerr_len;
208 yFldTrk.LoadFromArray(y, fNoIntegrationVariables);
209 yFldTrk.SetCurveLength( x );
210
211 QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
212
213
214 yFldTrk.DumpToArray(y);
215
216#ifdef G4FLD_STATS
217 ++fNoSmallSteps;
218 if ( dyerr_len > fDyerr_max ) { fDyerr_max = dyerr_len; }
219 fDyerrPos_smTot += dyerr_len;
220 fSumH_sm += h;
221 if (nstp==1) { ++fNoInitialSmallSteps; }
222#endif
223#ifdef G4DEBUG_FIELD
224 if (dbg>1)
225 {
226 if(fNoSmallSteps<2) {
PrintStatus(ySubStepStart, x1, y, x, h, -nstp); }
227 G4cout <<
"Another sub-min step, no " << fNoSmallSteps
228 <<
" of " << fNoTotalSteps <<
" this time " << nstp <<
G4endl;
230 G4cout <<
" dyerr= " << dyerr_len <<
" relative = " << dyerr_len / h
231 << " epsilon= " << eps << " hstep= " << hstep
232 <<
" h= " << h <<
" hmin= " << fMinimumStep <<
G4endl;
233 }
234#endif
235 if( h == 0.0 )
236 {
239 "Integration Step became Zero!");
240 }
241 dyerr = dyerr_len / h;
242 hdid = h;
243 x += hdid;
244
245
247 }
248
250
251#ifdef G4DEBUG_FIELD
252 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
253 {
254 if( nstp==nStpPr ) {
G4cout <<
"***** Many steps ****" <<
G4endl; }
256 G4cout <<
"hdid=" << std::setw(12) << hdid <<
" "
257 << "hnext=" << std::setw(12) << hnext << " "
258 << "hstep=" << std::setw(12) << hstep << " (requested) "
260 PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp);
261 }
262#endif
263
264
265 G4double endPointDist= (EndPos-StartPos).mag();
266 if ( endPointDist >= hdid*(1.+perMillion) )
267 {
268 ++fNoBadSteps;
269
270
271
272 if ( endPointDist >= hdid*(1.+perThousand) )
273 {
274#ifdef G4DEBUG_FIELD
275 if (dbg)
276 {
278 G4cerr <<
" Total steps: bad " << fNoBadSteps
279 <<
" current h= " << hdid <<
G4endl;
280 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
281 }
282 ++no_warnings;
283#endif
284 }
285 }
286
287
288 if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) )
289 {
290
291 lastStep = true;
292 }
293 else
294 {
295
296 if(std::fabs(hnext) <=
Hmin())
297 {
298#ifdef G4DEBUG_FIELD
299
300 if( (x < x2 * (1-eps) ) &&
301 (std::fabs(hstep) >
Hmin()) )
302 {
303 if(dbg>0)
304 {
306 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
307 }
308 ++no_warnings;
309 }
310#endif
311
313 }
314 else
315 {
316 h = hnext;
317 }
318
319
320 if ( x+h > x2 )
321 {
322 h = x2 - x ;
323 }
324
325 if ( h == 0.0 )
326 {
327
328 lastStep = true;
329#ifdef G4DEBUG_FIELD
330 if (dbg>2)
331 {
332 int prec=
G4cout.precision(12);
333 G4cout <<
"Warning: G4MagIntegratorDriver::AccurateAdvance"
335 << " Integration step 'h' became "
336 << h <<
" due to roundoff. " <<
G4endl
337 << " Calculated as difference of x2= "<< x2 << " and x=" << x
338 <<
" Forcing termination of advance." <<
G4endl;
340 }
341#endif
342 }
343 }
344 } while ( ((++nstp)<=fMaxNoSteps) && (x < x2) && (!lastStep) );
345
346
347
348
349
350 succeeded = (x>=x2);
351
352 for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; }
353
354
357
358 if(nstp > fMaxNoSteps)
359 {
360 succeeded = false;
361#ifdef G4DEBUG_FIELD
362 ++no_warnings;
363 if (dbg)
364 {
367 }
368#endif
369 }
370
371#ifdef G4DEBUG_FIELD
372 if( dbg && no_warnings )
373 {
374 G4cerr <<
"G4MagIntegratorDriver exit status: no-steps " << nstp <<
G4endl;
376 }
377#endif
378
379 return succeeded;
380}
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cerr
static void PrintStatus(const G4double *StartArr, G4double xstart, const G4double *CurrentArr, G4double xcurrent, G4double requestStep, unsigned int subStepNo, unsigned int noIntegrationVariables)
G4double GetCurveLength() const
void SetCurveLength(G4double nCurve_s)
void DumpToArray(G4double valArr[ncompSVEC]) const
void LoadFromArray(const G4double valArr[ncompSVEC], G4int noVarsIntegrated)
void PrintStatus(const G4double *StartArr, G4double xstart, const G4double *CurrentArr, G4double xcurrent, G4double requestStep, G4int subStepNo)
G4bool QuickAdvance(G4FieldTrack &y_val, const G4double dydx[], G4double hstep, G4double &dchord_step, G4double &dyerr) override
void WarnSmallStepSize(G4double hnext, G4double hstep, G4double h, G4double xDone, G4int noSteps)
void WarnEndPointTooFar(G4double endPointDist, G4double hStepSize, G4double epsilonRelative, G4int debugFlag)
void OneGoodStep(G4double ystart[], const G4double dydx[], G4double &x, G4double htry, G4double eps, G4double &hdid, G4double &hnext)
G4double ComputeNewStepSize(G4double errMaxNorm, G4double hstepCurrent) override
void WarnTooManyStep(G4double x1start, G4double x2end, G4double xCurrent)