00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <iomanip>
00043
00044 #include "globals.hh"
00045 #include "G4SystemOfUnits.hh"
00046 #include "G4GeometryTolerance.hh"
00047 #include "G4MagIntegratorDriver.hh"
00048 #include "G4FieldTrack.hh"
00049
00050
00051
00052
00053 const G4double G4MagInt_Driver::max_stepping_increase = 5.0;
00054 const G4double G4MagInt_Driver::max_stepping_decrease = 0.1;
00055
00056
00057
00058
00059 const G4int G4MagInt_Driver::fMaxStepBase = 250;
00060
00061 #ifndef G4NO_FIELD_STATISTICS
00062 #define G4FLD_STATS 1
00063 #endif
00064
00065
00066
00067
00068
00069 G4MagInt_Driver::G4MagInt_Driver( G4double hminimum,
00070 G4MagIntegratorStepper *pStepper,
00071 G4int numComponents,
00072 G4int statisticsVerbose)
00073 : fSmallestFraction( 1.0e-12 ),
00074 fNoIntegrationVariables(numComponents),
00075 fMinNoVars(12),
00076 fNoVars( std::max( fNoIntegrationVariables, fMinNoVars )),
00077 fStatisticsVerboseLevel(statisticsVerbose),
00078 fNoTotalSteps(0), fNoBadSteps(0), fNoSmallSteps(0),
00079 fNoInitialSmallSteps(0),
00080 fDyerr_max(0.0), fDyerr_mx2(0.0),
00081 fDyerrPos_smTot(0.0), fDyerrPos_lgTot(0.0), fDyerrVel_lgTot(0.0),
00082 fSumH_sm(0.0), fSumH_lg(0.0),
00083 fVerboseLevel(0)
00084 {
00085
00086
00087
00088 RenewStepperAndAdjust( pStepper );
00089 fMinimumStep= hminimum;
00090 fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
00091 #ifdef G4DEBUG_FIELD
00092 fVerboseLevel=2;
00093 #endif
00094
00095 if( (fVerboseLevel > 0) || (fStatisticsVerboseLevel > 1) )
00096 {
00097 G4cout << "MagIntDriver version: Accur-Adv: "
00098 << "invE_nS, QuickAdv-2sqrt with Statistics "
00099 #ifdef G4FLD_STATS
00100 << " enabled "
00101 #else
00102 << " disabled "
00103 #endif
00104 << G4endl;
00105 }
00106 }
00107
00108
00109
00110
00111
00112 G4MagInt_Driver::~G4MagInt_Driver()
00113 {
00114 if( fStatisticsVerboseLevel > 1 )
00115 {
00116 PrintStatisticsReport();
00117 }
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 G4bool
00127 G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
00128 G4double hstep,
00129 G4double eps,
00130 G4double hinitial )
00131 {
00132
00133
00134
00135
00136
00137
00138 G4int nstp, i, no_warnings=0;
00139 G4double x, hnext, hdid, h;
00140
00141 #ifdef G4DEBUG_FIELD
00142 static G4int dbg=1;
00143 static G4int nStpPr=50;
00144 G4double ySubStepStart[G4FieldTrack::ncompSVEC];
00145 G4FieldTrack yFldTrkStart(y_current);
00146 #endif
00147
00148 G4double y[G4FieldTrack::ncompSVEC], dydx[G4FieldTrack::ncompSVEC];
00149 G4double ystart[G4FieldTrack::ncompSVEC], yEnd[G4FieldTrack::ncompSVEC];
00150 G4double x1, x2;
00151 G4bool succeeded = true, lastStepSucceeded;
00152
00153 G4double startCurveLength;
00154
00155 G4int noFullIntegr=0, noSmallIntegr = 0 ;
00156 static G4int noGoodSteps =0 ;
00157 const G4int nvar= fNoVars;
00158
00159 G4FieldTrack yStartFT(y_current);
00160
00161
00162
00163 if( hstep <= 0.0 )
00164 {
00165 if(hstep==0.0)
00166 {
00167 std::ostringstream message;
00168 message << "Proposed step is zero; hstep = " << hstep << " !";
00169 G4Exception("G4MagInt_Driver::AccurateAdvance()",
00170 "GeomField1001", JustWarning, message);
00171 return succeeded;
00172 }
00173 else
00174 {
00175 std::ostringstream message;
00176 message << "Invalid run condition." << G4endl
00177 << "Proposed step is negative; hstep = " << hstep << "." << G4endl
00178 << "Requested step cannot be negative! Aborting event.";
00179 G4Exception("G4MagInt_Driver::AccurateAdvance()",
00180 "GeomField0003", EventMustBeAborted, message);
00181 return false;
00182 }
00183 }
00184
00185 y_current.DumpToArray( ystart );
00186
00187 startCurveLength= y_current.GetCurveLength();
00188 x1= startCurveLength;
00189 x2= x1 + hstep;
00190
00191 if ( (hinitial > 0.0) && (hinitial < hstep)
00192 && (hinitial > perMillion * hstep) )
00193 {
00194 h = hinitial;
00195 }
00196 else
00197 {
00198 h = hstep;
00199 }
00200
00201 x = x1;
00202
00203 for (i=0;i<nvar;i++) { y[i] = ystart[i]; }
00204
00205 G4bool lastStep= false;
00206 nstp=1;
00207
00208 do
00209 {
00210 G4ThreeVector StartPos( y[0], y[1], y[2] );
00211
00212 #ifdef G4DEBUG_FIELD
00213 G4double xSubStepStart= x;
00214 for (i=0;i<nvar;i++) { ySubStepStart[i] = y[i]; }
00215 yFldTrkStart.LoadFromArray(y, fNoIntegrationVariables);
00216 yFldTrkStart.SetCurveLength(x);
00217 #endif
00218
00219
00220
00221
00222 pIntStepper->ComputeRightHandSide( y, dydx );
00223 fNoTotalSteps++;
00224
00225
00226
00227 if( h > fMinimumStep )
00228 {
00229 OneGoodStep(y,dydx,x,h,eps,hdid,hnext) ;
00230
00231 lastStepSucceeded= (hdid == h);
00232 #ifdef G4DEBUG_FIELD
00233 if (dbg>2) {
00234 PrintStatus( ySubStepStart, xSubStepStart, y, x, h, nstp);
00235 }
00236 #endif
00237 }
00238 else
00239 {
00240 G4FieldTrack yFldTrk( G4ThreeVector(0,0,0),
00241 G4ThreeVector(0,0,0), 0., 0., 0., 0. );
00242 G4double dchord_step, dyerr, dyerr_len;
00243 yFldTrk.LoadFromArray(y, fNoIntegrationVariables);
00244 yFldTrk.SetCurveLength( x );
00245
00246 QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
00247
00248
00249 yFldTrk.DumpToArray(y);
00250
00251 #ifdef G4FLD_STATS
00252 fNoSmallSteps++;
00253 if ( dyerr_len > fDyerr_max) { fDyerr_max= dyerr_len; }
00254 fDyerrPos_smTot += dyerr_len;
00255 fSumH_sm += h;
00256 if (nstp<=1) { fNoInitialSmallSteps++; }
00257 #endif
00258 #ifdef G4DEBUG_FIELD
00259 if (dbg>1)
00260 {
00261 if(fNoSmallSteps<2) { PrintStatus(ySubStepStart, x1, y, x, h, -nstp); }
00262 G4cout << "Another sub-min step, no " << fNoSmallSteps
00263 << " of " << fNoTotalSteps << " this time " << nstp << G4endl;
00264 PrintStatus( ySubStepStart, x1, y, x, h, nstp);
00265 G4cout << " dyerr= " << dyerr_len << " relative = " << dyerr_len / h
00266 << " epsilon= " << eps << " hstep= " << hstep
00267 << " h= " << h << " hmin= " << fMinimumStep << G4endl;
00268 }
00269 #endif
00270 if( h == 0.0 )
00271 {
00272 G4Exception("G4MagInt_Driver::AccurateAdvance()",
00273 "GeomField0003", FatalException,
00274 "Integration Step became Zero!");
00275 }
00276 dyerr = dyerr_len / h;
00277 hdid= h;
00278 x += hdid;
00279
00280
00281 hnext= ComputeNewStepSize( dyerr/eps, h);
00282
00283
00284 lastStepSucceeded= (dyerr<= eps);
00285 }
00286
00287 if (lastStepSucceeded) { noFullIntegr++; }
00288 else { noSmallIntegr++; }
00289
00290 G4ThreeVector EndPos( y[0], y[1], y[2] );
00291
00292 #ifdef G4DEBUG_FIELD
00293 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr))
00294 {
00295 if( nstp==nStpPr ) { G4cout << "***** Many steps ****" << G4endl; }
00296 G4cout << "MagIntDrv: " ;
00297 G4cout << "hdid=" << std::setw(12) << hdid << " "
00298 << "hnext=" << std::setw(12) << hnext << " "
00299 << "hstep=" << std::setw(12) << hstep << " (requested) "
00300 << G4endl;
00301 PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp);
00302 }
00303 #endif
00304
00305
00306 G4double endPointDist= (EndPos-StartPos).mag();
00307 if ( endPointDist >= hdid*(1.+perMillion) )
00308 {
00309 fNoBadSteps++;
00310
00311
00312
00313 if ( endPointDist >= hdid*(1.+perThousand) )
00314 {
00315 #ifdef G4DEBUG_FIELD
00316 if (dbg)
00317 {
00318 WarnEndPointTooFar ( endPointDist, hdid, eps, dbg );
00319 G4cerr << " Total steps: bad " << fNoBadSteps
00320 << " good " << noGoodSteps << " current h= " << hdid
00321 << G4endl;
00322 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
00323 }
00324 #endif
00325 no_warnings++;
00326 }
00327 }
00328 else
00329 {
00330 noGoodSteps ++;
00331 }
00332
00333
00334
00335 if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) )
00336 {
00337
00338 lastStep = true;
00339 }
00340 else
00341 {
00342
00343 if(std::fabs(hnext) <= Hmin())
00344 {
00345 #ifdef G4DEBUG_FIELD
00346
00347 if( (x < x2 * (1-eps) ) &&
00348 (std::fabs(hstep) > Hmin()) )
00349 {
00350 if(dbg>0)
00351 {
00352 WarnSmallStepSize( hnext, hstep, h, x-x1, nstp );
00353 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
00354 }
00355 no_warnings++;
00356 }
00357 #endif
00358
00359 h = Hmin();
00360 }
00361 else
00362 {
00363 h = hnext;
00364 }
00365
00366
00367 if ( x+h > x2 )
00368 {
00369 h = x2 - x ;
00370 }
00371
00372 if ( h == 0.0 )
00373 {
00374
00375 lastStep = true;
00376 #ifdef G4DEBUG_FIELD
00377 if (dbg>2)
00378 {
00379 int prec= G4cout.precision(12);
00380 G4cout << "Warning: G4MagIntegratorDriver::AccurateAdvance"
00381 << G4endl
00382 << " Integration step 'h' became "
00383 << h << " due to roundoff. " << G4endl
00384 << " Calculated as difference of x2= "<< x2 << " and x=" << x
00385 << " Forcing termination of advance." << G4endl;
00386 G4cout.precision(prec);
00387 }
00388 #endif
00389 }
00390 }
00391 } while ( ((nstp++)<=fMaxNoSteps) && (x < x2) && (!lastStep) );
00392
00393
00394
00395 succeeded= (x>=x2);
00396
00397 for (i=0;i<nvar;i++) { yEnd[i] = y[i]; }
00398
00399
00400 y_current.LoadFromArray( yEnd, fNoIntegrationVariables );
00401 y_current.SetCurveLength( x );
00402
00403 if(nstp > fMaxNoSteps)
00404 {
00405 no_warnings++;
00406 succeeded = false;
00407 #ifdef G4DEBUG_FIELD
00408 if (dbg)
00409 {
00410 WarnTooManyStep( x1, x2, x );
00411 PrintStatus( yEnd, x1, y, x, hstep, -nstp);
00412 }
00413 #endif
00414 }
00415
00416 #ifdef G4DEBUG_FIELD
00417 if( dbg && no_warnings )
00418 {
00419 G4cerr << "G4MagIntegratorDriver exit status: no-steps " << nstp <<G4endl;
00420 PrintStatus( yEnd, x1, y, x, hstep, nstp);
00421 }
00422 #endif
00423
00424 return succeeded;
00425 }
00426
00427
00428
00429 void
00430 G4MagInt_Driver::WarnSmallStepSize( G4double hnext, G4double hstep,
00431 G4double h, G4double xDone,
00432 G4int nstp)
00433 {
00434 static G4int noWarningsIssued =0;
00435 const G4int maxNoWarnings = 10;
00436 std::ostringstream message;
00437 if( (noWarningsIssued < maxNoWarnings) || fVerboseLevel > 10 )
00438 {
00439 message << "The stepsize for the next iteration, " << hnext
00440 << ", is too small - in Step number " << nstp << "." << G4endl
00441 << "The minimum for the driver is " << Hmin() << G4endl
00442 << "Requested integr. length was " << hstep << " ." << G4endl
00443 << "The size of this sub-step was " << h << " ." << G4endl
00444 << "The integrations has already gone " << xDone;
00445 }
00446 else
00447 {
00448 message << "Too small 'next' step " << hnext
00449 << ", step-no: " << nstp << G4endl
00450 << ", this sub-step: " << h
00451 << ", req_tot_len: " << hstep
00452 << ", done: " << xDone << ", min: " << Hmin();
00453 }
00454 G4Exception("G4MagInt_Driver::WarnSmallStepSize()", "GeomField1001",
00455 JustWarning, message);
00456 noWarningsIssued++;
00457 }
00458
00459
00460
00461 void
00462 G4MagInt_Driver::WarnTooManyStep( G4double x1start,
00463 G4double x2end,
00464 G4double xCurrent)
00465 {
00466 std::ostringstream message;
00467 message << "The number of steps used in the Integration driver"
00468 << " (Runge-Kutta) is too many." << G4endl
00469 << "Integration of the interval was not completed !" << G4endl
00470 << "Only a " << (xCurrent-x1start)*100/(x2end-x1start)
00471 << " % fraction of it was done.";
00472 G4Exception("G4MagInt_Driver::WarnTooManyStep()", "GeomField1001",
00473 JustWarning, message);
00474 }
00475
00476
00477
00478 void
00479 G4MagInt_Driver::WarnEndPointTooFar (G4double endPointDist,
00480 G4double h ,
00481 G4double eps,
00482 G4int dbg)
00483 {
00484 static G4double maxRelError=0.0;
00485 G4bool isNewMax, prNewMax;
00486
00487 isNewMax = endPointDist > (1.0 + maxRelError) * h;
00488 prNewMax = endPointDist > (1.0 + 1.05 * maxRelError) * h;
00489 if( isNewMax ) { maxRelError= endPointDist / h - 1.0; }
00490
00491 if( dbg && (h > G4GeometryTolerance::GetInstance()->GetSurfaceTolerance())
00492 && ( (dbg>1) || prNewMax || (endPointDist >= h*(1.+eps) ) ) )
00493 {
00494 static G4int noWarnings = 0;
00495 std::ostringstream message;
00496 if( (noWarnings ++ < 10) || (dbg>2) )
00497 {
00498 message << "The integration produced an end-point which " << G4endl
00499 << "is further from the start-point than the curve length."
00500 << G4endl;
00501 }
00502 message << " Distance of endpoints = " << endPointDist
00503 << ", curve length = " << h << G4endl
00504 << " Difference (curveLen-endpDist)= " << (h - endPointDist)
00505 << ", relative = " << (h-endPointDist) / h
00506 << ", epsilon = " << eps;
00507 G4Exception("G4MagInt_Driver::WarnEndPointTooFar()", "GeomField1001",
00508 JustWarning, message);
00509 }
00510 }
00511
00512
00513
00514 void
00515 G4MagInt_Driver::OneGoodStep( G4double y[],
00516 const G4double dydx[],
00517 G4double& x,
00518 G4double htry,
00519 G4double eps_rel_max,
00520 G4double& hdid,
00521 G4double& hnext )
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 {
00537 G4double errmax_sq;
00538 G4double h, htemp, xnew ;
00539
00540 G4double yerr[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC];
00541
00542 h = htry ;
00543
00544 G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max);
00545
00546 G4double errpos_sq=0.0;
00547 G4double errvel_sq=0.0;
00548 G4double errspin_sq=0.0;
00549
00550 G4int iter;
00551
00552 static G4int tot_no_trials=0;
00553 const G4int max_trials=100;
00554
00555 G4ThreeVector Spin(y[9],y[10],y[11]);
00556 G4bool hasSpin= (Spin.mag2() > 0.0);
00557
00558 for (iter=0; iter<max_trials ;iter++)
00559 {
00560 tot_no_trials++;
00561 pIntStepper-> Stepper(y,dydx,h,ytemp,yerr);
00562
00563 G4double eps_pos = eps_rel_max * std::max(h, fMinimumStep);
00564 G4double inv_eps_pos_sq = 1.0 / (eps_pos*eps_pos);
00565
00566
00567
00568 errpos_sq = sqr(yerr[0]) + sqr(yerr[1]) + sqr(yerr[2]) ;
00569 errpos_sq *= inv_eps_pos_sq;
00570
00571
00572 errvel_sq = (sqr(yerr[3]) + sqr(yerr[4]) + sqr(yerr[5]) )
00573 / (sqr(y[3]) + sqr(y[4]) + sqr(y[5]) );
00574 errvel_sq *= inv_eps_vel_sq;
00575 errmax_sq = std::max( errpos_sq, errvel_sq );
00576
00577 if( hasSpin )
00578 {
00579
00580 errspin_sq = ( sqr(yerr[9]) + sqr(yerr[10]) + sqr(yerr[11]) )
00581 / ( sqr(y[9]) + sqr(y[10]) + sqr(y[11]) );
00582 errspin_sq *= inv_eps_vel_sq;
00583 errmax_sq = std::max( errmax_sq, errspin_sq );
00584 }
00585
00586 if ( errmax_sq <= 1.0 ) { break; }
00587
00588
00589 htemp = GetSafety()*h* std::pow( errmax_sq, 0.5*GetPshrnk() );
00590
00591 if (htemp >= 0.1*h) { h = htemp; }
00592 else { h = 0.1*h; }
00593
00594 xnew = x + h;
00595 if(xnew == x)
00596 {
00597 G4cerr << "G4MagIntegratorDriver::OneGoodStep:" << G4endl
00598 << " Stepsize underflow in Stepper " << G4endl ;
00599 G4cerr << " Step's start x=" << x << " and end x= " << xnew
00600 << " are equal !! " << G4endl
00601 <<" Due to step-size= " << h
00602 << " . Note that input step was " << htry << G4endl;
00603 break;
00604 }
00605 }
00606
00607 #ifdef G4FLD_STATS
00608
00609 fSumH_lg += h;
00610 fDyerrPos_lgTot += errpos_sq;
00611 fDyerrVel_lgTot += errvel_sq * h * h;
00612 #endif
00613
00614
00615 if (errmax_sq > errcon*errcon)
00616 {
00617 hnext = GetSafety()*h*std::pow(errmax_sq, 0.5*GetPgrow());
00618 }
00619 else
00620 {
00621 hnext = max_stepping_increase*h ;
00622 }
00623 x += (hdid = h);
00624
00625 for(G4int k=0;k<fNoIntegrationVariables;k++) { y[k] = ytemp[k]; }
00626
00627 return;
00628 }
00629
00630
00631
00632
00633
00634 G4bool G4MagInt_Driver::QuickAdvance(
00635 G4FieldTrack& y_posvel,
00636 const G4double dydx[],
00637 G4double hstep,
00638 G4double& dchord_step,
00639 G4double& dyerr_pos_sq,
00640 G4double& dyerr_mom_rel_sq )
00641 {
00642 G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001",
00643 FatalException, "Not yet implemented.");
00644
00645
00646 dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0];
00647 dyerr_mom_rel_sq = y_posvel.GetPosition().mag2();
00648 return true;
00649 }
00650
00651
00652
00653 G4bool G4MagInt_Driver::QuickAdvance(
00654 G4FieldTrack& y_posvel,
00655 const G4double dydx[],
00656 G4double hstep,
00657 G4double& dchord_step,
00658 G4double& dyerr )
00659 {
00660 G4double dyerr_pos_sq, dyerr_mom_rel_sq;
00661 G4double yerr_vec[G4FieldTrack::ncompSVEC],
00662 yarrin[G4FieldTrack::ncompSVEC], yarrout[G4FieldTrack::ncompSVEC];
00663 G4double s_start;
00664 G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq;
00665
00666 static G4int no_call=0;
00667 no_call ++;
00668
00669
00670 y_posvel.DumpToArray( yarrin );
00671 s_start = y_posvel.GetCurveLength();
00672
00673
00674 pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ;
00675
00676
00677
00678 dchord_step= pIntStepper-> DistChord();
00679
00680
00681
00682 y_posvel.LoadFromArray( yarrout, fNoIntegrationVariables );
00683 y_posvel.SetCurveLength( s_start + hstep );
00684
00685 #ifdef G4DEBUG_FIELD
00686 if(fVerboseLevel>2)
00687 {
00688 G4cout << "G4MagIntDrv: Quick Advance" << G4endl;
00689 PrintStatus( yarrin, s_start, yarrout, s_start+hstep, hstep, 1);
00690 }
00691 #endif
00692
00693
00694
00695 vel_mag_sq = ( sqr(yarrout[3])+sqr(yarrout[4])+sqr(yarrout[5]) );
00696 inv_vel_mag_sq = 1.0 / vel_mag_sq;
00697 dyerr_pos_sq = ( sqr(yerr_vec[0])+sqr(yerr_vec[1])+sqr(yerr_vec[2]));
00698 dyerr_mom_sq = ( sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(yerr_vec[5]));
00699 dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_mag_sq;
00700
00701
00702
00703
00704
00705 #ifdef RETURN_A_NEW_STEP_LENGTH
00706
00707 dyerr_len = std::sqrt( dyerr_len_sq );
00708 dyerr_len_sq /= eps ;
00709
00710
00711
00712
00713
00714 hstep= ComputeNewStepSize( dyerr_len, hstep);
00715 #endif
00716
00717 if( dyerr_pos_sq > ( dyerr_mom_rel_sq * sqr(hstep) ) )
00718 {
00719 dyerr = std::sqrt(dyerr_pos_sq);
00720 }
00721 else
00722 {
00723
00724 dyerr = std::sqrt(dyerr_mom_rel_sq) * hstep;
00725 }
00726
00727 return true;
00728 }
00729
00730
00731
00732 #ifdef QUICK_ADV_ARRAY_IN_AND_OUT
00733 G4bool G4MagInt_Driver::QuickAdvance(
00734 G4double yarrin[],
00735 const G4double dydx[],
00736 G4double hstep,
00737 G4double yarrout[],
00738 G4double& dchord_step,
00739 G4double& dyerr )
00740 {
00741 G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001",
00742 FatalException, "Not yet implemented.");
00743 dyerr = dchord_step = hstep * yarrin[0] * dydx[0];
00744 yarrout[0]= yarrin[0];
00745 }
00746 #endif
00747
00748
00749
00750
00751
00752
00753 G4double
00754 G4MagInt_Driver::ComputeNewStepSize(
00755 G4double errMaxNorm,
00756 G4double hstepCurrent)
00757 {
00758 G4double hnew;
00759
00760
00761 if(errMaxNorm > 1.0 )
00762 {
00763
00764 hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPshrnk()) ;
00765 } else if(errMaxNorm > 0.0 ) {
00766
00767 hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPgrow()) ;
00768 } else {
00769
00770 hnew = max_stepping_increase * hstepCurrent;
00771 }
00772
00773 return hnew;
00774 }
00775
00776
00777
00778
00779
00780
00781
00782
00783 G4double
00784 G4MagInt_Driver::ComputeNewStepSize_WithinLimits(
00785 G4double errMaxNorm,
00786 G4double hstepCurrent)
00787 {
00788 G4double hnew;
00789
00790
00791 if (errMaxNorm > 1.0 )
00792 {
00793
00794 hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPshrnk()) ;
00795
00796 if (hnew < max_stepping_decrease*hstepCurrent)
00797 {
00798 hnew = max_stepping_decrease*hstepCurrent ;
00799
00800
00801 }
00802 }
00803 else
00804 {
00805
00806 if (errMaxNorm > errcon)
00807 { hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPgrow()); }
00808 else
00809 { hnew = max_stepping_increase * hstepCurrent; }
00810 }
00811 return hnew;
00812 }
00813
00814
00815
00816 void G4MagInt_Driver::PrintStatus( const G4double* StartArr,
00817 G4double xstart,
00818 const G4double* CurrentArr,
00819 G4double xcurrent,
00820 G4double requestStep,
00821 G4int subStepNo)
00822
00823
00824
00825
00826 {
00827 G4FieldTrack StartFT(G4ThreeVector(0,0,0),
00828 G4ThreeVector(0,0,0), 0., 0., 0., 0. );
00829 G4FieldTrack CurrentFT (StartFT);
00830
00831 StartFT.LoadFromArray( StartArr, fNoIntegrationVariables);
00832 StartFT.SetCurveLength( xstart);
00833 CurrentFT.LoadFromArray( CurrentArr, fNoIntegrationVariables);
00834 CurrentFT.SetCurveLength( xcurrent );
00835
00836 PrintStatus(StartFT, CurrentFT, requestStep, subStepNo );
00837 }
00838
00839
00840
00841 void G4MagInt_Driver::PrintStatus(
00842 const G4FieldTrack& StartFT,
00843 const G4FieldTrack& CurrentFT,
00844 G4double requestStep,
00845 G4int subStepNo)
00846 {
00847 G4int verboseLevel= fVerboseLevel;
00848 static G4int noPrecision= 5;
00849 G4int oldPrec= G4cout.precision(noPrecision);
00850
00851
00852 const G4ThreeVector StartPosition= StartFT.GetPosition();
00853 const G4ThreeVector StartUnitVelocity= StartFT.GetMomentumDir();
00854 const G4ThreeVector CurrentPosition= CurrentFT.GetPosition();
00855 const G4ThreeVector CurrentUnitVelocity= CurrentFT.GetMomentumDir();
00856
00857 G4double DotStartCurrentVeloc= StartUnitVelocity.dot(CurrentUnitVelocity);
00858
00859 G4double step_len= CurrentFT.GetCurveLength() - StartFT.GetCurveLength();
00860 G4double subStepSize = step_len;
00861
00862 if( (subStepNo <= 1) || (verboseLevel > 3) )
00863 {
00864 subStepNo = - subStepNo;
00865
00866 G4cout << std::setw( 6) << " " << std::setw( 25)
00867 << " G4MagInt_Driver: Current Position and Direction" << " "
00868 << G4endl;
00869 G4cout << std::setw( 5) << "Step#" << " "
00870 << std::setw( 7) << "s-curve" << " "
00871 << std::setw( 9) << "X(mm)" << " "
00872 << std::setw( 9) << "Y(mm)" << " "
00873 << std::setw( 9) << "Z(mm)" << " "
00874 << std::setw( 8) << " N_x " << " "
00875 << std::setw( 8) << " N_y " << " "
00876 << std::setw( 8) << " N_z " << " "
00877 << std::setw( 8) << " N^2-1 " << " "
00878 << std::setw(10) << " N(0).N " << " "
00879 << std::setw( 7) << "KinEner " << " "
00880 << std::setw(12) << "Track-l" << " "
00881 << std::setw(12) << "Step-len" << " "
00882 << std::setw(12) << "Step-len" << " "
00883 << std::setw( 9) << "ReqStep" << " "
00884 << G4endl;
00885 }
00886
00887 if( (subStepNo <= 0) )
00888 {
00889 PrintStat_Aux( StartFT, requestStep, 0.,
00890 0, 0.0, 1.0);
00891
00892 }
00893
00894 if( verboseLevel <= 3 )
00895 {
00896 G4cout.precision(noPrecision);
00897 PrintStat_Aux( CurrentFT, requestStep, step_len,
00898 subStepNo, subStepSize, DotStartCurrentVeloc );
00899
00900 }
00901
00902 else
00903 {
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 }
00914 G4cout.precision(oldPrec);
00915 }
00916
00917
00918
00919 void G4MagInt_Driver::PrintStat_Aux(
00920 const G4FieldTrack& aFieldTrack,
00921 G4double requestStep,
00922 G4double step_len,
00923 G4int subStepNo,
00924 G4double subStepSize,
00925 G4double dotVeloc_StartCurr)
00926 {
00927 const G4ThreeVector Position= aFieldTrack.GetPosition();
00928 const G4ThreeVector UnitVelocity= aFieldTrack.GetMomentumDir();
00929
00930 if( subStepNo >= 0)
00931 {
00932 G4cout << std::setw( 5) << subStepNo << " ";
00933 }
00934 else
00935 {
00936 G4cout << std::setw( 5) << "Start" << " ";
00937 }
00938 G4double curveLen= aFieldTrack.GetCurveLength();
00939 G4cout << std::setw( 7) << curveLen;
00940 G4cout << std::setw( 9) << Position.x() << " "
00941 << std::setw( 9) << Position.y() << " "
00942 << std::setw( 9) << Position.z() << " "
00943 << std::setw( 8) << UnitVelocity.x() << " "
00944 << std::setw( 8) << UnitVelocity.y() << " "
00945 << std::setw( 8) << UnitVelocity.z() << " ";
00946 G4int oldprec= G4cout.precision(3);
00947 G4cout << std::setw( 8) << UnitVelocity.mag2()-1.0 << " ";
00948 G4cout.precision(6);
00949 G4cout << std::setw(10) << dotVeloc_StartCurr << " ";
00950 G4cout.precision(oldprec);
00951 G4cout << std::setw( 7) << aFieldTrack.GetKineticEnergy();
00952 G4cout << std::setw(12) << step_len << " ";
00953
00954 static G4double oldCurveLength= 0.0;
00955 static G4double oldSubStepLength= 0.0;
00956 static G4int oldSubStepNo= -1;
00957
00958 G4double subStep_len=0.0;
00959 if( curveLen > oldCurveLength )
00960 {
00961 subStep_len= curveLen - oldCurveLength;
00962 }
00963 else if (subStepNo == oldSubStepNo)
00964 {
00965 subStep_len= oldSubStepLength;
00966 }
00967 oldCurveLength= curveLen;
00968 oldSubStepLength= subStep_len;
00969
00970 G4cout << std::setw(12) << subStep_len << " ";
00971 G4cout << std::setw(12) << subStepSize << " ";
00972 if( requestStep != -1.0 )
00973 {
00974 G4cout << std::setw( 9) << requestStep << " ";
00975 }
00976 else
00977 {
00978 G4cout << std::setw( 9) << " InitialStep " << " ";
00979 }
00980 G4cout << G4endl;
00981 }
00982
00983
00984
00985 void G4MagInt_Driver::PrintStatisticsReport()
00986 {
00987 G4int noPrecBig= 6;
00988 G4int oldPrec= G4cout.precision(noPrecBig);
00989
00990 G4cout << "G4MagInt_Driver Statistics of steps undertaken. " << G4endl;
00991 G4cout << "G4MagInt_Driver: Number of Steps: "
00992 << " Total= " << fNoTotalSteps
00993 << " Bad= " << fNoBadSteps
00994 << " Small= " << fNoSmallSteps
00995 << " Non-initial small= " << (fNoSmallSteps-fNoInitialSmallSteps)
00996 << G4endl;
00997
00998 #ifdef G4FLD_STATS
00999 G4cout << "MID dyerr: "
01000 << " maximum= " << fDyerr_max
01001 << " Sum small= " << fDyerrPos_smTot
01002 << " std::sqrt(Sum large^2): pos= " << std::sqrt(fDyerrPos_lgTot)
01003 << " vel= " << std::sqrt( fDyerrVel_lgTot )
01004 << " Total h-distance: small= " << fSumH_sm
01005 << " large= " << fSumH_lg
01006 << G4endl;
01007
01008 #if 0
01009 G4int noPrecSmall=4;
01010
01011 G4cout.precision(noPrecSmall);
01012 G4cout << "MIDnums: " << fMinimumStep
01013 << " " << fNoTotalSteps
01014 << " " << fNoSmallSteps
01015 << " " << fNoSmallSteps-fNoInitialSmallSteps
01016 << " " << fNoBadSteps
01017 << " " << fDyerr_max
01018 << " " << fDyerr_mx2
01019 << " " << fDyerrPos_smTot
01020 << " " << fSumH_sm
01021 << " " << fDyerrPos_lgTot
01022 << " " << fDyerrVel_lgTot
01023 << " " << fSumH_lg
01024 << G4endl;
01025 #endif
01026 #endif
01027
01028 G4cout.precision(oldPrec);
01029 }
01030
01031
01032
01033 void G4MagInt_Driver::SetSmallestFraction(G4double newFraction)
01034 {
01035 if( (newFraction > 1.e-16) && (newFraction < 1e-8) )
01036 {
01037 fSmallestFraction= newFraction;
01038 }
01039 else
01040 {
01041 G4cerr << "Warning: SmallestFraction not changed. " << G4endl
01042 << " Proposed value was " << newFraction << G4endl
01043 << " Value must be between 1.e-8 and 1.e-16" << G4endl;
01044 }
01045 }