/* Boost numeric test of the runge kutta steppers test file Copyright 2012 Mario Mulansky Copyright 2012 Karsten Ahnert Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ // disable checked iterator warning for msvc #include #ifdef BOOST_MSVC #pragma warning(disable:4996) #endif #define BOOST_TEST_MODULE numeric_runge_kutta #include #include #include #include #include #include using namespace boost::unit_test; using namespace boost::numeric::odeint; namespace mpl = boost::mpl; typedef double value_type; typedef std::array< double , 1 > state_type; // harmonic oscillator, analytic solution x[0] = sin( t ) struct osc { void operator()( const state_type &x, const state_type &v, state_type &a, const double t ) const { a[0] = -x[0]; } }; BOOST_AUTO_TEST_SUITE( velocity_verlet_test ) BOOST_AUTO_TEST_CASE( numeric_velocity_verlet_test ) { velocity_verlet stepper; const int steps = 10; // order of the error is order of approximation + 1 const int o = stepper.order() + 1; const state_type x0 = {{ 0.0 }}; const state_type v0 = {{ 1.0 }}; state_type x = x0; state_type v = v0; const double t = 0.0; /* do a first step with dt=0.1 to get an estimate on the prefactor of the error dx = f * dt^(order+1) */ double dt = 0.5; for ( int step = 0; step < steps; ++step ) { stepper.do_step( osc(), std::make_pair( boost::ref( x ), boost::ref( v ) ), t, dt ); } const double f = steps * std::abs( sin( steps * dt ) - x[0] ) / std::pow( dt, o ); // upper bound std::cout << o << " , " << f << std::endl; /* as long as we have errors above machine precision */ while( f*std::pow( dt , o ) > 1E-16 ) { x = x0; v = v0; stepper.reset(); for ( int step = 0; step < steps; ++step ) { stepper.do_step( osc() , std::make_pair(boost::ref(x), boost::ref(v)) , t , dt ); } std::cout << "Testing dt=" << dt << std::endl; BOOST_CHECK_LT( std::abs( sin( steps * dt ) - x[0] ), f * std::pow( dt, o ) ); dt *= 0.5; } }; BOOST_AUTO_TEST_SUITE_END()