00001
00002
00008
00011
00012
00013
00014 #include "RungeKuttaFehlbergIntegrator.h"
00015 namespace O_SESSAME {
00016
00017 RungeKuttaFehlbergIntegrator::RungeKuttaFehlbergIntegrator() : m_Tolerance(0.00001), m_minStepSize(0.01), m_maxStepSize(0.25)
00018 {
00019 }
00020
00021 Matrix RungeKuttaFehlbergIntegrator::Integrate(const vector<ssfTime>& _propTime, odeFunctor _odeFunctorPtr, const Vector& _initialConditions, Orbit* _pOrbit, Attitude* _pAttitude, const Matrix& _constants, const Functor& _functorPtr)
00022 {
00023 vector<ssfTime>::const_iterator timeIterator = _propTime.begin();
00024
00025 ssfTime timeInitial = (*timeIterator);
00026 timeIterator = _propTime.end() - 1;
00027 ssfTime timeFinal = (*timeIterator);
00028 ssfTime t = timeInitial;
00029 double h = m_maxStepSize;
00030 double delta;
00031 bool hAccepted = false;
00032
00033 int numEqs = _initialConditions.getIndexCount();
00034 Vector inputs = _initialConditions;
00035 Vector tempVector = inputs;
00036 Vector Error(numEqs);
00037 Vector K1(numEqs);
00038 Vector K2(numEqs);
00039 Vector K3(numEqs);
00040 Vector K4(numEqs);
00041 Vector K5(numEqs);
00042 Vector K6(numEqs);
00043 vector<Vector> output;
00044 output.reserve(floor((timeFinal-timeInitial) / m_maxStepSize));
00045
00046 output.push_back(Vector(numEqs+1));
00047 output[0](MatrixIndexBase) = timeInitial.GetSeconds();
00048 output[0](_(MatrixIndexBase+1,MatrixIndexBase+numEqs)) = _initialConditions;
00049
00050 ssfTime tTemp;
00051 Vector temp(numEqs);
00052 int ii = 1;
00053 while (t.GetSeconds() < timeFinal.GetSeconds())
00054 {
00055 hAccepted = true;
00056 K1 = h * _odeFunctorPtr(t, inputs, _pOrbit, _pAttitude, _constants, _functorPtr);
00057 tTemp = t + h / 4.; temp = inputs + K1 / 4.0;
00058 K2 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr);
00059 tTemp = t + 3/8. * h; temp = inputs + (3/32. * K1 + 9/32. * K2);
00060 K3 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr);
00061 tTemp = t + 12/13. * h; temp = inputs + (1932. * K1 - 7200. * K2 + 7296. * K3) / 2197.;
00062 K4 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr);
00063 tTemp = t + h; temp = inputs + (439/216. * K1 - 8. * K2 +3680/513. * K3 - 845/4104. * K4);
00064 K5 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr);
00065 tTemp = t + h / 2; temp = inputs - 8/27. * K1 +2. * K2 - 3544/2565. * K3 + 1859/4104. * K4 - 11/40.* K5;
00066 K6 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr);
00067
00068
00069 for (int jj = MatrixIndexBase; jj < MatrixIndexBase + numEqs; ++jj)
00070 {
00071
00072 Error(jj) = 1/h * abs(K1(jj)/360. - 128/4275. * K3(jj) - 2197/75240. * K4(jj) + K5(jj)/50. + K6(jj)/27.5);
00073
00074
00075
00076
00077
00078
00079 if((Error(jj) <= m_Tolerance) || (h < m_minStepSize))
00080 {
00081 tempVector(jj) = inputs(jj) + 25/216. * K1(jj) + 1408/2565. * K3(jj) + 2197/4104. * K4(jj) - 0.2* K5(jj);
00082 }
00083 else
00084 {
00085 hAccepted = false;
00086 delta = 0.84 * pow((m_Tolerance / Error(jj)), 0.25);
00087 if(delta <= 0.1)
00088 h = 0.1*h;
00089 else if(delta > 4)
00090 h = 4*h;
00091 else
00092 h = delta * h;
00093 if (h > m_maxStepSize)
00094 h = m_maxStepSize;
00095 break;
00096 }
00097 }
00098
00099 if(hAccepted)
00100 {
00101 t = t + h;
00102 inputs = tempVector;
00103 output.push_back(Vector(numEqs+1));
00104 output[ii](MatrixIndexBase) = t.GetSeconds();
00105 output[ii](_(MatrixIndexBase+1,MatrixIndexBase+numEqs)) = inputs;
00106 ++ii;
00107
00108 if(t.GetSeconds() + h > timeFinal.GetSeconds())
00109 h = timeFinal - t;
00110 }
00111
00112 }
00113
00114
00115 Matrix outputMatrix(output.size(), numEqs + 1);
00116
00117 for(ii = 0; ii < output.size(); ++ii)
00118 {
00119 outputMatrix(MatrixIndexBase + ii,_) = ~output[ii](_);
00120 }
00121 return outputMatrix;
00122 }
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146