CLHEP VERSION Reference Documentation
   
CLHEP Home Page     CLHEP Documentation     CLHEP Bug Reports

AdaptiveRKStepper.cc

Go to the documentation of this file.
00001 #include "CLHEP/GenericFunctions/AdaptiveRKStepper.hh"
00002 #include "CLHEP/GenericFunctions/EmbeddedRKStepper.hh"
00003 #include <cmath>
00004 #include <stdexcept>
00005 namespace Genfun {
00006 
00007   AdaptiveRKStepper::AdaptiveRKStepper(const EEStepper *stepper):
00008     eeStepper(stepper ? stepper->clone():new EmbeddedRKStepper()),
00009     T(1.0E-6),
00010     sStepsize(0.01),
00011     S(0.9),
00012     Rmin(0.0),
00013     Rmax(5.0),
00014     stepsize(sStepsize)
00015   {
00016   }
00017 
00018   AdaptiveRKStepper::AdaptiveRKStepper(const AdaptiveRKStepper & right):
00019     RKStepper(right),
00020     eeStepper(right.eeStepper->clone()),
00021     T(right.T),
00022     sStepsize(right.sStepsize),
00023     S(right.S),
00024     Rmin(right.Rmin),
00025     Rmax(right.Rmax),
00026     stepsize(right.sStepsize)
00027   {
00028   }
00029 
00030 
00031   void AdaptiveRKStepper::step(const RKIntegrator::RKData       * data, 
00032                               const RKIntegrator::RKData::Data & s, 
00033                               RKIntegrator::RKData::Data       & d,
00034                               double                             timeLimit) const {
00035     //
00036     // Adaptive stepsize control
00037     //
00038     if (s.time==0.0) {
00039       stepsize=sStepsize;
00040     }
00041     const unsigned int p = eeStepper->order();  // Order of the stepper
00042     const double deltaMax = T*std::pow(S/Rmax, (int)(p+1)); // Maximum error 4 adjustment.
00043     const double TINY   = 1.0E-30;              // Denominator regularization
00044     double hnext;
00045     //
00046     // Time limited step ? 
00047     // 
00048     d.time= timeLimit==0? s.time+stepsize : timeLimit;
00049 
00050     //--------------------------------------//
00051     // Take one step, from s to d:    //
00052     //--------------------------------------//
00053     double h = d.time-s.time;
00054     while (1) {
00055       std::vector<double> errors;
00056       eeStepper->step(data, s, d, errors);
00057       if (timeLimit!=0.0) return;
00058       
00059       // Take absolute value:
00060       for (size_t e=0;e<errors.size();e++) errors[e] = fabs(errors[e]);
00061     
00062       // Select the largest:
00063       double delta = (*std::max_element(errors.begin(),errors.end()));
00064       if (delta > T) {
00065         //
00066         // Bail out and try a smaller step.
00067         //
00068         h = std::max(S*h*std::pow(T/(delta + TINY), 1.0/(p+1)),Rmin*h);
00069         if  (!(((float) s.time+h - (float) s.time) > 0) ) {
00070           std::cerr << "Warning, RK Integrator step underflow" << std::endl;
00071         }
00072         d.time = s.time+h;
00073         hnext=h;
00074         continue;
00075       }
00076       else {
00077         if (delta > deltaMax) {
00078           hnext = S*h*std::pow(T/(delta + TINY),1.0/(p+1));
00079         }
00080         else {
00081           hnext = Rmax*h;
00082         }
00083       }
00084       break;
00085     }
00086     stepsize=hnext;
00087     return;
00088   }
00089   
00090 
00091 
00092   AdaptiveRKStepper::~AdaptiveRKStepper(){
00093     delete eeStepper;
00094   }
00095   
00096   AdaptiveRKStepper *AdaptiveRKStepper::clone() const {
00097     return new AdaptiveRKStepper(*this);
00098   }
00099 
00100   AdaptiveRKStepper::EEStepper::~EEStepper() {
00101   }
00102  
00103   double & AdaptiveRKStepper::tolerance(){
00104     return T;
00105   }
00106 
00107   const double & AdaptiveRKStepper::tolerance() const{
00108     return T;
00109   }
00110   
00111   double & AdaptiveRKStepper::startingStepsize(){
00112     return sStepsize;
00113   }
00114   const double & AdaptiveRKStepper::startingStepsize() const{
00115     return sStepsize;
00116   }
00117   
00118   double & AdaptiveRKStepper::safetyFactor(){
00119     return S;
00120   }
00121 
00122   const double & AdaptiveRKStepper::safetyFactor() const{
00123     return S;
00124   }
00125   
00126   double & AdaptiveRKStepper::rmin(){
00127     return Rmin;
00128   }
00129   const double & AdaptiveRKStepper::rmin() const{
00130     return Rmin;
00131   }
00132   
00133   double & AdaptiveRKStepper::rmax(){
00134     return Rmax;
00135   }
00136   const double & AdaptiveRKStepper::rmax() const{
00137     return Rmax;
00138   }
00139 
00140 }

Generated on 15 Nov 2012 for CLHEP by  doxygen 1.4.7