CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
00001 #include "CLHEP/GenericFunctions/StepDoublingRKStepper.hh" 00002 #include <stdexcept> 00003 #include <cmath> 00004 namespace Genfun { 00005 00006 00007 StepDoublingRKStepper::StepDoublingRKStepper(const ButcherTableau & xtableau):tableau(xtableau) { 00008 } 00009 00010 StepDoublingRKStepper::~StepDoublingRKStepper() { 00011 } 00012 00013 void StepDoublingRKStepper::step (const RKIntegrator::RKData * data, 00014 const RKIntegrator::RKData::Data & s, 00015 RKIntegrator::RKData::Data & d, 00016 std::vector<double> & errors) const { 00017 const unsigned int nvar = s.variable.size(); 00018 RKIntegrator::RKData::Data d1(nvar),d2(nvar); 00019 00020 doStep(data,s,d); 00021 double dt = (d.time - s.time); 00022 d1.time = s.time + dt/2.0; 00023 d2.time = d.time; 00024 00025 doStep(data, s,d1); 00026 doStep(data,d1,d2); 00027 00028 // Error estimate: 00029 errors.resize(nvar); 00030 for (size_t v=0;v<nvar;v++) errors[v]=fabs(d2.variable[v]-d.variable[v]); 00031 00032 // Final correction: 00033 for (size_t v=0;v<nvar;v++) d.variable[v] = d2.variable[v] + ((d2.variable[v]-d.variable[v])/double(std::pow(2.,(int)(tableau.order())-1))); 00034 00035 } 00036 00037 void StepDoublingRKStepper::doStep(const RKIntegrator::RKData * data, 00038 const RKIntegrator::RKData::Data & s, 00039 RKIntegrator::RKData::Data & d) const { 00040 // First step: 00041 double h = (d.time - s.time); 00042 00043 00044 if (h<=0) throw std::runtime_error ("SimpleRKStepper: negative stepsize"); 00045 const unsigned int nvar = s.variable.size(); 00046 // Compute all of the k's..: 00047 // 00048 std::vector<std::vector<double> >k(tableau.nSteps()); 00049 for (unsigned int i=0;i<tableau.nSteps();i++) { 00050 k[i].resize(nvar,0); 00051 Argument arg(nvar); 00052 for (unsigned int v=0;v<nvar;v++) arg[v]=s.variable[v]; 00053 for (unsigned int j=0;j<i;j++) { 00054 for (unsigned int v=0;v<nvar;v++) arg[v] += h*tableau.A(i,j)*k[j][v]; 00055 } 00056 for (unsigned int v=0;v<nvar;v++) k[i][v]=(*data->_diffEqn[v])(arg); 00057 } 00058 // 00059 // Final result. 00060 // 00061 for (unsigned int v=0;v<nvar;v++) d.firstDerivative[v] = 0; 00062 for (unsigned int i=0;i<tableau.nSteps();i++) { 00063 for (unsigned int v=0;v<nvar;v++) d.firstDerivative[v] += tableau.b(i)*k[i][v]; 00064 } 00065 for (unsigned int v=0;v<nvar;v++) d.variable[v] =s.variable[v]+h*d.firstDerivative[v]; 00066 00067 } 00068 00069 00070 00071 00072 StepDoublingRKStepper *StepDoublingRKStepper::clone() const { 00073 return new StepDoublingRKStepper(*this); 00074 } 00075 00076 unsigned int StepDoublingRKStepper::order() const { 00077 return tableau.order(); 00078 } 00079 00080 00081 }