99{
100
101
102
103
104
105
108
109#ifdef G4DEBUG_FIELD
110 G4int no_warnings = 0;
111 static G4int dbg = 1;
114#endif
115
120
122
123 const G4int nvar = fNoVars;
124
126
127
128
129 if( hstep <= 0.0 )
130 {
131 if( hstep == 0.0 )
132 {
133 std::ostringstream message;
134 message << "Proposed step is zero; hstep = " << hstep << " !";
135 G4Exception(
"G4OldMagIntDriver::AccurateAdvance()",
137 return succeeded;
138 }
139
140 std::ostringstream message;
141 message <<
"Invalid run condition." <<
G4endl
142 <<
"Proposed step is negative; hstep = " << hstep <<
"." <<
G4endl
143 << "Requested step cannot be negative! Aborting event.";
144 G4Exception(
"G4OldMagIntDriver::AccurateAdvance()",
146 return false;
147 }
148
150
152 x1= startCurveLength;
153 x2= x1 + hstep;
154
155 if ( (hinitial > 0.0) && (hinitial < hstep)
156 && (hinitial > perMillion * hstep) )
157 {
158 h = hinitial;
159 }
160 else
161 {
162 h = hstep;
163 }
164
165 x = x1;
166
167 for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; }
168
169#ifdef G4DEBUG_FIELD
170
171 G4cout <<
"IDriver::AccurAdv called. "
172 <<
" Input: hstep = " << hstep <<
" hinitial= " << hinitial <<
" , current: h = " << h <<
G4endl;
173#endif
174
176 nstp = 1;
177
178 do
179 {
181
182#ifdef G4DEBUG_FIELD
184 for (i=0; i<nvar; ++i) { ySubStepStart[i] = y[i]; }
185 yFldTrkStart.LoadFromArray(y, fNoIntegrationVariables);
186 yFldTrkStart.SetCurveLength(x);
187 if(dbg)
189#endif
190
192 ++fNoTotalSteps;
193
194
195
196 if( h > fMinimumStep )
197 {
199
200
201#ifdef G4DEBUG_FIELD
202 if (dbg)
203 {
204 G4cout <<
"IntegrationDriver -- after OneGoodStep / requesting step = " << h <<
G4endl;
205
207 }
208#endif
209 }
210 else
211 {
214 G4double dchord_step, dyerr, dyerr_len;
215 yFldTrk.LoadFromArray(y, fNoIntegrationVariables);
216 yFldTrk.SetCurveLength( x );
217
218 QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
219
220
221 yFldTrk.DumpToArray(y);
222
223#ifdef G4FLD_STATS
224 ++fNoSmallSteps;
225 if ( dyerr_len > fDyerr_max ) { fDyerr_max = dyerr_len; }
226 fDyerrPos_smTot += dyerr_len;
227 fSumH_sm += h;
228 if (nstp<=1) { ++fNoInitialSmallSteps; }
229#endif
230#ifdef G4DEBUG_FIELD
231 if (dbg>1)
232 {
233 if(fNoSmallSteps<2) {
PrintStatus(ySubStepStart, x1, y, x, h, -nstp); }
234 G4cout <<
"Another sub-min step, no " << fNoSmallSteps
235 <<
" of " << fNoTotalSteps <<
" this time " << nstp <<
G4endl;
237 G4cout <<
" dyerr= " << dyerr_len <<
" relative = " << dyerr_len / h
238 << " epsilon= " << eps << " hstep= " << hstep
239 <<
" h= " << h <<
" hmin= " << fMinimumStep <<
G4endl;
240 }
241#endif
242 if( h == 0.0 )
243 {
244 G4Exception(
"G4OldMagIntDriver::AccurateAdvance()",
246 "Integration Step became Zero!");
247 }
248 dyerr = dyerr_len / h;
249 hdid = h;
250 x += hdid;
251
252
254
255
256 }
257
259
260#if (G4DEBUG_FIELD>1)
261 static G4int nStpPr = 50;
262 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
263 {
264 if( nstp==nStpPr ) {
G4cout <<
"***** Many steps ****" <<
G4endl; }
266 G4cout <<
"hdid=" << std::setw(12) << hdid <<
" "
267 << "hnext=" << std::setw(12) << hnext << " "
268 << "hstep=" << std::setw(12) << hstep << " (requested) "
270 PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp);
271 }
272#endif
273
274
275 G4double endPointDist= (EndPos-StartPos).mag();
276 if ( endPointDist >= hdid*(1.+perMillion) )
277 {
278 ++fNoBadSteps;
279
280
281
282 if ( endPointDist >= hdid*(1.+perThousand) )
283 {
284#ifdef G4DEBUG_FIELD
285 if (dbg)
286 {
288 G4cerr <<
" Total steps: bad " << fNoBadSteps
289 <<
" current h= " << hdid <<
G4endl;
290 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
291 }
292 ++no_warnings;
293#endif
294 }
295 }
296
297
298 if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) )
299 {
300
301 lastStep = true;
302 }
303 else
304 {
305
306 if(std::fabs(hnext) <=
Hmin())
307 {
308#ifdef G4DEBUG_FIELD
309
310 if( (x < x2 * (1-eps) ) &&
311 (std::fabs(hstep) >
Hmin()) )
312 {
313 if(dbg>0)
314 {
316 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
317 }
318 ++no_warnings;
319 }
320#endif
321
323 }
324 else
325 {
326 h = hnext;
327 }
328
329
330 if ( x+h > x2 )
331 {
332 h = x2 - x ;
333 }
334
335 if ( h == 0.0 )
336 {
337
338 lastStep = true;
339#ifdef G4DEBUG_FIELD
340 if (dbg>2)
341 {
342 int prec=
G4cout.precision(12);
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;
350 }
351#endif
352 }
353 }
354 } while ( ((nstp++)<=fMaxNoSteps) && (x < x2) && (!lastStep) );
355
356
357
358
359
360 succeeded = (x>=x2);
361
362 for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; }
363
364
367
368 if(nstp > fMaxNoSteps)
369 {
370 succeeded = false;
371#ifdef G4DEBUG_FIELD
372 ++no_warnings;
373 if (dbg)
374 {
377 }
378#endif
379 }
380
381#ifdef G4DEBUG_FIELD
382 if( dbg && no_warnings )
383 {
384 G4cerr <<
"G4MagIntegratorDriver exit status: no-steps " << nstp <<
G4endl;
386 }
387#endif
388
389 return succeeded;
390}
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 RightHandSide(const G4double y[], G4double dydx[]) const
G4bool QuickAdvance(G4FieldTrack &y_val, const G4double dydx[], G4double hstep, G4double &dchord_step, G4double &dyerr) override
void PrintStatus(const G4double *StartArr, G4double xstart, const G4double *CurrentArr, G4double xcurrent, G4double requestStep, G4int subStepNo)
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)
G4double ComputeNewStepSize(G4double errMaxNorm, G4double hstepCurrent) override
void WarnEndPointTooFar(G4double endPointDist, G4double hStepSize, G4double epsilonRelative, G4int debugFlag)
void WarnTooManyStep(G4double x1start, G4double x2end, G4double xCurrent)