Skip to content

Commit

Permalink
Merge pull request #22 from Reneh107/Runge_Kutta_56
Browse files Browse the repository at this point in the history
Add Runge Kutta 56 integrator to coefficient list + Unit test
  • Loading branch information
magnific0 committed May 13, 2016
2 parents da0b495 + aac9b70 commit efd07f2
Show file tree
Hide file tree
Showing 6 changed files with 393 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Tudat/Mathematics/NumericalIntegrators/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ add_executable(test_RungeKuttaFehlberg45Integrator "${SRCROOT}${MATHEMATICSDIR}/
setup_custom_test_program(test_RungeKuttaFehlberg45Integrator "${SRCROOT}${MATHEMATICSDIR}/NumericalIntegrators")
target_link_libraries(test_RungeKuttaFehlberg45Integrator tudat_numerical_integrators tudat_input_output ${Boost_LIBRARIES})

add_executable(test_RungeKuttaFehlberg56Integrator "${SRCROOT}${MATHEMATICSDIR}/NumericalIntegrators/UnitTests/unitTestRungeKuttaFehlberg56Integrator.cpp")
setup_custom_test_program(test_RungeKuttaFehlberg56Integrator "${SRCROOT}${MATHEMATICSDIR}/NumericalIntegrators")
target_link_libraries(test_RungeKuttaFehlberg56Integrator tudat_numerical_integrators tudat_input_output ${Boost_LIBRARIES})

add_executable(test_RungeKuttaFehlberg78Integrator "${SRCROOT}${MATHEMATICSDIR}/NumericalIntegrators/UnitTests/unitTestRungeKuttaFehlberg78Integrator.cpp")
setup_custom_test_program(test_RungeKuttaFehlberg78Integrator "${SRCROOT}${MATHEMATICSDIR}/NumericalIntegrators")
target_link_libraries(test_RungeKuttaFehlberg78Integrator tudat_numerical_integrators tudat_input_output ${Boost_LIBRARIES})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,72 @@ static inline Eigen::VectorXd computeVanDerPolStateDerivative( const double time
return vanDerPolStateDerivative;
}

//! Computes state derivative of a Logarithmic 2-dimensional ODE
/*!
* Computes the state derivative of a 2-dimensional ODE that is autonomous and includes log functions.
* This function is used by Fehlberg for testing the RK5(6) integrator and has an analytical solution.
*
* \f{eqnarray*}{
* \frac{ dx }{ dt }( 0 ) &=& -2 * t * x( 0 ) * log( x(1) ) \\
* \frac{ dx }{ dt }( 0 ) &=& 2 * t * x( 1 ) * log( x(0) ) \\
* \f}
*
* Reference: Fehlberg, E. (1968). Classical Fifth-, Sixth-, Seventh- and Eigth-Order Runge-Kutta
* Formulas with Stepsize Control (page 30)
*
* \param time Time at which the state derivative needs to be evaluated.
* \param state State at which the state derivative needs to be evaluated.
* \return Computed state derivative.
*/
static inline Eigen::VectorXd
computeFehlbergLogirithmicTestODEStateDerivative( const double time,
const Eigen::VectorXd& state){
// Declare state derivative vector
Eigen::VectorXd stateDerivative( state.rows() );

// Compute state derivative
stateDerivative( 0 ) = -2.0 * time * state(0) * std::log( state(1) );
stateDerivative( 1 ) = 2.0 * time * state(1) * std::log( state(0) );

// Return computed state derivative.
return stateDerivative;
}

//! Computes the analytical solution of the state for the Logarithmic test ODE of Fehlberg
/*!
* Analytical solution:
* \f{eqnarray*}{
* x(0) = exp( cos( t^{2} ) ) \\
* x(1) = exp( sin( t^{2} ) ) \\
* \f}
*
* with initial conditions:
* \f{eqnarray*}{
* x_{0}(0) = exp(1) \\
* x_{0}(1) = 1
* \f}
*
* Reference: Fehlberg, E. (1968). Classical Fifth-, Sixth-, Seventh- and Eigth-Order Runge-Kutta
* Formulas with Stepsize Control (page 30)
*
* \param time Time at which the state derivative needs to be evaluated.
* \param initialState State at which the state derivative needs to be evaluated.
* \return Computed state.
*/

static inline Eigen::VectorXd computeAnalyticalStateFehlbergODE( const double time,
const Eigen::VectorXd& initialState){
// Declare state derivative vector
Eigen::VectorXd state( initialState.rows() );

// Compute state derivative
state(0) = exp( cos( pow(time,2.0) ) ) ; // x(0) = exp( cos( t^{2} ) )
state(1) = exp( sin( pow(time,2.0) ) ) ; // x(1) = exp( sin( t^{2} ) )

// Return computed state derivative.
return state;
}

//! Compute non-autonomous model state derivative.
/*!
* Computes the state derivative for a non-autonomous ordinary differential equation. The state
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
/* Copyright (c) 2010-2016, Delft University of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* - Neither the name of the Delft University of Technology nor the names of its contributors
* may be used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Changelog
* YYMMDD Author Comment
* 120203 B. Tong Minh Copied RungeKutta4Stepsize unit test.
* 120207 K. Kumar Adapted to use modified benchmark functions in Tudat Core.
* 120213 K. Kumar Modified getCurrentInterval( ) to getIndependentVariable( );
* transferred to Boost unit test framework.
* 120321 K. Kumar Updated (Burden and Faires, 2011) benchmark function call.
* 120323 K. Kumar Rewrote unit tests to use benchmark data from
* (Burden and Faires, 2011); removed test against benchmark
* functions; renamed file to RFK45 unit test. Other unit tests
* for other Runge-Kutta methods will appear in other dedicated
* unit test files.
* 120327 K. Kumar Added missing comments; added unit test based on output data
* generated by (The Mathworks, 2012).
* 120328 K. Kumar Moved (Burden and Faires, 2011) test class to its own file;
* modified MATLAB unit tests to test forward and backwards in
* time and "forced" and "free" adaptive step size adjustment and
* moved to separate file (added call to function to run Matlab
* tests); added rollback tests for all cases.
* 120404 K. Kumar Updated Matlab unit test by adding discrete-event data file.
* 130118 K. Kumar Rewrote unit test to make use of testing code for numerical
* integrators migrated to Tudat Core.
* 130906 K. Kumar Updated error tolerances for MuPAD-based tests.
*
* 160321 R. Hoogendoorn Created Runge Kutta 56 test
*
* References
* Burden, R.L., Faires, J.D. Numerical Analysis, 7th Edition, Books/Cole, 2001.
* Montenbruck, O., Gill, E. Satellite Orbits: Models, Methods, Applications, Springer, 2005.
* The MathWorks, Inc. RKF54b, Symbolic Math Toolbox, 2012.
*
* Notes
* For the tests using data from the Symbolic Math Toolbox (MathWorks, 2012), the single step
* and full integration error tolerances were picked to be as small as possible, without
* causing the tests to fail. These values are not deemed to indicate any bugs in the code;
* however, it is important to take these discrepancies into account when using this numerical
* integrator.
*
*/

#define BOOST_TEST_MAIN

#include <limits>
#include <string>

#include <cmath>

#include <Eigen/Core>

#include <boost/test/unit_test.hpp>

#include "Tudat/Mathematics/NumericalIntegrators/rungeKuttaVariableStepSizeIntegrator.h"
#include "Tudat/Mathematics/NumericalIntegrators/rungeKuttaCoefficients.h"
#include "Tudat/Mathematics/NumericalIntegrators/UnitTests/numericalIntegratorTestFunctions.h"

namespace tudat
{
namespace unit_tests
{

BOOST_AUTO_TEST_SUITE( test_runge_kutta_fehlberg_56_integrator )

using numerical_integrator_test_functions::computeNonAutonomousModelStateDerivative;
using numerical_integrator_test_functions::computeVanDerPolStateDerivative;
using numerical_integrator_test_functions::computeFehlbergLogirithmicTestODEStateDerivative;
using numerical_integrator_test_functions::computeAnalyticalStateFehlbergODE;

using namespace numerical_integrators;

//! Compare with analytical solution of Fehlberg
BOOST_AUTO_TEST_CASE( test_RungeKuttaFehlberg56_Integrator_Fehlberg_Benchmark )
{
RungeKuttaCoefficients coeff56 =
RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg56);

// Integrator settings
double minimumStepSize = std::numeric_limits< double >::epsilon( );
double maximumStepSize = std::numeric_limits< double >::infinity( );
double initialStepSize = 1E-6; // Don't make this too small
double relativeTolerance = 1E-16;
double absoluteTolerance = 1E-16;

// Initial conditions
double initialTime = 0.0;
double finalTime = 5.0;
Eigen::Vector2d initialState( exp( 1.0 ), 1.0);

// Setup integrator
RungeKuttaVariableStepSizeIntegratorXd integrator56(
coeff56, computeFehlbergLogirithmicTestODEStateDerivative,
initialTime, initialState, minimumStepSize,
maximumStepSize, relativeTolerance, absoluteTolerance );


// Obtain numerical solution
Eigen::Vector2d numericalSolution = integrator56.integrateTo( finalTime, initialStepSize );

// Analytical solution
// (page 30, Fehlberg, E. (1968). Classical Fifth-, Sixth-, Seventh- and Eigth-Order Runge-Kutta
// Formulas with Stepsize Control)
Eigen::Vector2d analyticalSolution =
computeAnalyticalStateFehlbergODE( finalTime, initialState );

Eigen::Vector2d computedError = numericalSolution - analyticalSolution;
BOOST_CHECK_SMALL( std::fabs( computedError( 0 ) ), 1E-12 );
BOOST_CHECK_SMALL( std::fabs( computedError( 1 ) ), 1E-12 );

// Error calculated by -> Fehlberg, E. (1968) page 30
// Initial stepsize unknown..
Eigen::VectorXd fehlbergError( 2 );
fehlbergError << 0.1072E-12, -0.2190E-12;

// Sign check
// Not always same sign -> initial step size = 1 or 1E-2, failure: computedError( 1 ),
// fehlbergError( 1 ) not same sign
BOOST_CHECK_GE( computedError( 0 ) / fehlbergError( 0 ), 0.0 );
BOOST_CHECK_GE( computedError( 1 ) / fehlbergError( 1 ), 0.0 );

// Check error is similar in magnitude
BOOST_CHECK_SMALL( std::fabs( computedError( 0 ) / fehlbergError( 0 ) ), 3.0);
BOOST_CHECK_SMALL( std::fabs( computedError( 1 ) / fehlbergError( 1 ) ), 1.0);
}


//! Test Compare with Runge Kutta 78
BOOST_AUTO_TEST_CASE( test_RungeKuttaFehlberg56_Integrator_Compare78 )
{
// Setup integrator
RungeKuttaCoefficients coeff56 =
RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg56);

RungeKuttaCoefficients coeff78 =
RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg78);

// Integrator settings
double minimumStepSize = std::numeric_limits< double >::epsilon( );
double maximumStepSize = std::numeric_limits< double >::infinity( );
double initialStepSize = 1E-4; // Don't make this too small
double relativeTolerance = 1E-15;
double absoluteTolerance = 1E-15;

// Initial conditions
double initialTime = 0.5;
Eigen::VectorXd InitialState( 1 );
InitialState << 0.5; // 1 large error

// Setup integrator
RungeKuttaVariableStepSizeIntegratorXd integrator56(
coeff56, computeNonAutonomousModelStateDerivative, initialTime, InitialState,
minimumStepSize, maximumStepSize, relativeTolerance, absoluteTolerance );

RungeKuttaVariableStepSizeIntegratorXd integrator78(
coeff78, computeNonAutonomousModelStateDerivative, initialTime, InitialState,
minimumStepSize, maximumStepSize, relativeTolerance, absoluteTolerance );

double endTime = 1.5;
Eigen::VectorXd solution56 = integrator56.integrateTo( endTime, initialStepSize );
Eigen::VectorXd solution78 = integrator78.integrateTo( endTime, initialStepSize );

Eigen::VectorXd difference = solution78 - solution56;

BOOST_CHECK_SMALL( std::fabs( difference( 0 ) ), 1E-13 );
}

//! Test Compare with Runge Kutta 78
BOOST_AUTO_TEST_CASE( test_RungeKuttaFehlberg56_Integrator_Compare78_v2 )
{
// Setup integrator
RungeKuttaCoefficients coeff56 =
RungeKuttaCoefficients::get(
RungeKuttaCoefficients::rungeKuttaFehlberg56 );

RungeKuttaCoefficients coeff78 =
RungeKuttaCoefficients::get(
RungeKuttaCoefficients::rungeKuttaFehlberg78 );

// Integrator settings
double minimumStepSize = std::numeric_limits< double >::epsilon( );
double maximumStepSize = std::numeric_limits< double >::infinity( );
double initialStepSize = 1.0; // Don't make this too small
double relativeTolerance = 1E-10;
double absoluteTolerance = 1E-10;

// Initial conditions
double initialTime = 0.2;
Eigen::VectorXd InitialState( 1 );
InitialState << -1.0;

// Setup integrator
RungeKuttaVariableStepSizeIntegratorXd integrator56(
coeff56, computeNonAutonomousModelStateDerivative, initialTime, InitialState,
minimumStepSize, maximumStepSize, relativeTolerance, absoluteTolerance );

RungeKuttaVariableStepSizeIntegratorXd integrator78(
coeff78, computeNonAutonomousModelStateDerivative, initialTime, InitialState,
minimumStepSize, maximumStepSize, relativeTolerance, absoluteTolerance );

double endTime = 2.0;
Eigen::VectorXd solution56 = integrator56.integrateTo( endTime, initialStepSize );
Eigen::VectorXd solution78 = integrator78.integrateTo( endTime, initialStepSize );

Eigen::VectorXd difference = solution78 - solution56;

BOOST_CHECK_SMALL( std::fabs( difference( 0 ) ), 1E-8 );
}

//! Test Compare with Runge Kutta 78
BOOST_AUTO_TEST_CASE( test_RungeKuttaFehlberg56_Integrator_Compare78_VanDerPol )
{
// Setup integrator
RungeKuttaCoefficients coeff56 =
RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg56 );

RungeKuttaCoefficients coeff78 =
RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg78 );

// Integrator settings
double minimumStepSize = std::numeric_limits< double >::epsilon( );
double maximumStepSize = std::numeric_limits< double >::infinity( );
double initialStepSize = 1; // Don't make this too small
double relativeTolerance = 1E-15;
double absoluteTolerance = 1E-15;

// Initial conditions
double initialTime = 0.2;
Eigen::VectorXd InitialState( 2 );
InitialState << -1.0, 1.0;

// Setup integrator
RungeKuttaVariableStepSizeIntegratorXd integrator56(
coeff56, computeVanDerPolStateDerivative, initialTime, InitialState, minimumStepSize,
maximumStepSize, relativeTolerance, absoluteTolerance );

RungeKuttaVariableStepSizeIntegratorXd integrator78(
coeff78, computeVanDerPolStateDerivative, initialTime, InitialState, minimumStepSize,
maximumStepSize, relativeTolerance, absoluteTolerance );

double endTime = 1.4;
Eigen::VectorXd solution56 = integrator56.integrateTo(endTime,initialStepSize);
Eigen::VectorXd solution78 = integrator78.integrateTo(endTime,initialStepSize);

Eigen::VectorXd difference = solution78 - solution56;

BOOST_CHECK_SMALL( std::fabs( difference( 0 ) ), 1E-13 );
BOOST_CHECK_SMALL( std::fabs( difference( 1 ) ), 1E-13 );
}

BOOST_AUTO_TEST_SUITE_END( )

} // namespace unit_tests
} // namespace tudat
Loading

0 comments on commit efd07f2

Please sign in to comment.