Go to the documentation of this file.00001 #include "RK4PreciseStep.h"
00002 #include "RK4OneStep.h"
00003
00004 #include <iostream>
00005
00006 CartesianState
00007 RK4PreciseStep::operator()( const CartesianState& start, const RKCartesianDerivative& deriv,
00008 double step, double eps) const
00009 {
00010 const double Safety = 0.9;
00011 double remainigStep = step;
00012 double stepSize = step;
00013 CartesianState currentStart = start;
00014 int nsteps = 0;
00015 std::pair<CartesianState, double> tryStep;
00016
00017 do {
00018 tryStep = stepWithAccuracy( currentStart, deriv, stepSize);
00019 nsteps++;
00020 if (tryStep.second <eps) {
00021 if (remainigStep - stepSize < eps/2) {
00022 if (verbose()) std::cout << "Accuracy reached, and full step taken in "
00023 << nsteps << " steps" << std::endl;
00024 return tryStep.first;
00025 }
00026 else {
00027 remainigStep -= stepSize;
00028
00029 double factor = std::min( Safety * pow( fabs(eps/tryStep.second),0.2), 4.);
00030 stepSize = std::min( stepSize*factor, remainigStep);
00031 currentStart = tryStep.first;
00032 if (verbose()) std::cout << "Accuracy reached, but " << remainigStep
00033 << " remain after " << nsteps << " steps. Step size increased by "
00034 << factor << " to " << stepSize << std::endl;
00035 }
00036 }
00037 else {
00038
00039 double factor = std::max( Safety * pow( fabs(eps/tryStep.second),0.25), 0.1);
00040 stepSize *= factor;
00041 if (verbose()) std::cout << "Accuracy not yet reached: delta = " << tryStep.second
00042 << ", step reduced by " << factor << " to " << stepSize
00043 << ", (R,z)= " << currentStart.position().perp()
00044 << ", " << currentStart.position().z() << std::endl;
00045 }
00046 } while (remainigStep > eps/2);
00047
00048 return tryStep.first;
00049 }
00050
00051 std::pair<CartesianState, double>
00052 RK4PreciseStep::stepWithAccuracy( const CartesianState& start, const RKCartesianDerivative& deriv,
00053 double step) const
00054 {
00055 RK4OneStep solver;
00056 CartesianState one(solver(start, deriv, step));
00057 CartesianState firstHalf(solver(start, deriv, step/2));
00058 CartesianState secondHalf(solver(firstHalf, deriv, step/2));
00059 double diff = distance(one, secondHalf);
00060 return std::pair<CartesianState, double>(secondHalf,diff);
00061 }
00062
00063 double RK4PreciseStep::distance( const CartesianState& a, const CartesianState& b) const
00064 {
00065 return (a.position() - b.position()).mag() + (a.momentum() - b.momentum()).mag() / b.momentum().mag();
00066 }
00067
00068 bool RK4PreciseStep::verbose() const
00069 {
00070
00071
00072 static bool verb = true;
00073 return verb;
00074 }