CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
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 }