00001 ////////////////////////////////////////////////////////////////////////////////////////////////// 00002 /*! \file RungeKuttaFehlbergIntegrator.cpp 00003 * \brief Implementation of the Runge-Kutta-Fehlberg Fourth Order integrator. 00004 * \author $Author: jayhawk_hokie $ 00005 * \version $Revision: 1.2 $ 00006 * \date $Date: 2007/08/02 22:06:34 $ 00007 *////////////////////////////////////////////////////////////////////////////////////////////////// 00008 /*! \warning NOT VERIFIED 00009 * \todo Add test cases 00010 */ 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 /* 00022 Matrix RungeKuttaFehlbergIntegrator::Integrate(const vector<ssfTime>& _propTime, odeFunctor _odeFunctorPtr, const Vector& _initialConditions, Orbit* _pOrbit, Attitude* _pAttitude, const Matrix& _constants, const Functor& _functorPtr) 00023 { 00024 vector<ssfTime>::const_iterator timeIterator = _propTime.begin(); 00025 00026 ssfTime timeInitial = (*timeIterator); 00027 timeIterator = _propTime.end() - 1; 00028 ssfTime timeFinal = (*timeIterator); 00029 ssfTime t = timeInitial; 00030 double h = m_maxStepSize; 00031 double delta; 00032 bool hAccepted = false; 00033 00034 int numEqs = _initialConditions.getIndexCount(); 00035 Vector inputs = _initialConditions; 00036 Vector tempVector = inputs; 00037 Vector Error(numEqs); 00038 Vector K1(numEqs); 00039 Vector K2(numEqs); 00040 Vector K3(numEqs); 00041 Vector K4(numEqs); 00042 Vector K5(numEqs); 00043 Vector K6(numEqs); 00044 vector<Vector> output; // state + time 00045 output.reserve( floor((timeFinal-timeInitial) / m_maxStepSize) ); 00046 00047 output.push_back(Vector(numEqs+1)); 00048 output[0](MatrixIndexBase) = timeInitial.GetSeconds(); 00049 output[0](_(MatrixIndexBase+1,MatrixIndexBase+numEqs)) = _initialConditions; 00050 00051 ssfTime tTemp; 00052 Vector temp(numEqs); 00053 int ii = 1; 00054 while (t.GetSeconds() < timeFinal.GetSeconds()) 00055 { 00056 hAccepted = true; 00057 K1 = h * _odeFunctorPtr(t, inputs, _pOrbit, _pAttitude, _constants, _functorPtr); 00058 tTemp = t + h / 4.; temp = inputs + K1 / 4.0; 00059 K2 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr); 00060 tTemp = t + 3/8. * h; temp = inputs + (3/32. * K1 + 9/32. * K2); 00061 K3 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr); 00062 tTemp = t + 12/13. * h; temp = inputs + (1932. * K1 - 7200. * K2 + 7296. * K3) / 2197.; 00063 K4 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr); 00064 tTemp = t + h; temp = inputs + (439/216. * K1 - 8. * K2 +3680/513. * K3 - 845/4104. * K4); 00065 K5 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr); 00066 tTemp = t + h / 2; temp = inputs - 8/27. * K1 +2. * K2 - 3544/2565. * K3 + 1859/4104. * K4 - 11/40.* K5; 00067 K6 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr); 00068 00069 // Check that all the variables are within tolerance 00070 for (int jj = MatrixIndexBase; jj < MatrixIndexBase + numEqs; ++jj) 00071 { 00072 // If error <= tolerance, calculate integral & output 00073 Error(jj) = 1/h * abs(K1(jj)/360. - 128/4275. * K3(jj) - 2197/75240. * K4(jj) + K5(jj)/50. + K6(jj)/27.5); 00074 00075 // Could be used for testing 00076 // wTilda = 16/135*K1(jj) + 6656/12825 * K3(jj) + 28561/56430 * K4(jj) - 9/50 * K5(jj) + 2/55*K6(jj); 00077 // w = 25/216 * K1(jj) + 1408/2565 * K3(jj) + 2197/4104 * K4(jj) - 0.2* K5(jj); 00078 // Error(jj) = abs(wTilda - w); 00079 00080 if((Error(jj) <= m_Tolerance) || (h < m_minStepSize)) 00081 { 00082 tempVector(jj) = inputs(jj) + 25/216. * K1(jj) + 1408/2565. * K3(jj) + 2197/4104. * K4(jj) - 0.2* K5(jj); 00083 } 00084 else 00085 {// if error > tolerance, calc new step size, and re-integrate this step 00086 hAccepted = false; 00087 delta = 0.84 * pow((m_Tolerance / Error(jj)), 0.25); 00088 if(delta <= 0.1) 00089 h = 0.1*h; 00090 else if(delta > 4) 00091 h = 4*h; 00092 else 00093 h = delta * h; 00094 if (h > m_maxStepSize) 00095 h = m_maxStepSize; 00096 break; 00097 } 00098 } 00099 // if all variables are within tolerance, then save output and step forward 00100 if(hAccepted) 00101 { 00102 t = t + h; 00103 inputs = tempVector; 00104 output.push_back(Vector(numEqs+1)); 00105 output[ii](MatrixIndexBase) = t.GetSeconds(); 00106 output[ii](_(MatrixIndexBase+1,MatrixIndexBase+numEqs)) = inputs; 00107 ++ii; 00108 00109 if(t.GetSeconds() + h > timeFinal.GetSeconds()) 00110 h = timeFinal - t; 00111 } 00112 00113 } 00114 00115 // Because we used a dynamic vector<Vector>, we need to move this a Matrix 00116 Matrix outputMatrix(output.size(), numEqs + 1); 00117 00118 for(ii = 0; ii < output.size(); ++ii) 00119 { 00120 outputMatrix(MatrixIndexBase + ii,_) = ~output[ii](_); 00121 } 00122 return outputMatrix; 00123 } 00124 */ 00125 00126 } // close namespace O_SESSAME 00127 00128 // Do not change the comments below - they will be added automatically by CVS 00129 /***************************************************************************** 00130 * $Log: RungeKuttaFehlbergIntegrator.cpp,v $ 00131 * Revision 1.2 2007/08/02 22:06:34 jayhawk_hokie 00132 * Commented function. 00133 * 00134 * Revision 1.1.1.1 2005/04/26 17:41:00 cakinli 00135 * Adding OpenSESSAME to DSACSS distrib to capture fixed version. 00136 * 00137 * Revision 1.5 2003/06/05 20:30:52 nilspace 00138 * Removed testing cout commands. 00139 * 00140 * Revision 1.4 2003/06/05 20:09:14 nilspace 00141 * Finished implementation and verified against a short 2 second integration. 00142 * 00143 * Revision 1.3 2003/05/22 02:59:15 nilspace 00144 * Updated comments. Changed to pass in pointers to Orbit & Attitude objects. 00145 * 00146 * Revision 1.2 2003/04/25 13:45:55 nilspace 00147 * const'd Get() functions. 00148 * 00149 * Revision 1.1 2003/04/23 15:08:28 nilspace 00150 * Initial submission of RKF integrator. 00151 * 00152 * 00153 ******************************************************************************/ 00154 00155