RungeKuttaFehlbergIntegrator.cpp

Go to the documentation of this file.
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; // state + time
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./*0.275*/* K5; 
00066             K6 = h * _odeFunctorPtr(tTemp, temp, _pOrbit, _pAttitude, _constants, _functorPtr);
00067 
00068             // Check that all the variables are within tolerance
00069             for (int jj = MatrixIndexBase; jj < MatrixIndexBase + numEqs; ++jj)
00070             {
00071                 //  If error <= tolerance, calculate integral & output
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 //      Could be used for testing
00075 //                wTilda = 16/135*K1(jj) + 6656/12825 * K3(jj) + 28561/56430 * K4(jj) - 9/50 * K5(jj) + 2/55*K6(jj);
00076 //                w = 25/216 * K1(jj) + 1408/2565 * K3(jj) + 2197/4104 * K4(jj) - 0.2* K5(jj);
00077 //                Error(jj) = abs(wTilda - w);
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                 {// if error > tolerance, calc new step size, and re-integrate this step
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             // if all variables are within tolerance, then save output and step forward
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         // Because we used a dynamic vector<Vector>, we need to move this a Matrix    
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 } // close namespace O_SESSAME
00124 
00125 // Do not change the comments below - they will be added automatically by CVS
00126 /*****************************************************************************
00127 *       $Log: RungeKuttaFehlbergIntegrator.cpp,v $
00128 *       Revision 1.5  2003/06/05 20:30:52  nilspace
00129 *       Removed testing cout commands.
00130 *       
00131 *       Revision 1.4  2003/06/05 20:09:14  nilspace
00132 *       Finished implementation and verified against a short 2 second integration.
00133 *       
00134 *       Revision 1.3  2003/05/22 02:59:15  nilspace
00135 *       Updated comments. Changed to pass in pointers to Orbit & Attitude objects.
00136 *       
00137 *       Revision 1.2  2003/04/25 13:45:55  nilspace
00138 *       const'd Get() functions.
00139 *       
00140 *       Revision 1.1  2003/04/23 15:08:28  nilspace
00141 *       Initial submission of RKF integrator.
00142 *       
00143 *       
00144 ******************************************************************************/
00145 
00146 

Generated on Wed Aug 6 12:58:52 2003 for Open-Sessame Framework by doxygen1.3