Brian Silverman | 7c33ab2 | 2018-08-04 17:14:51 -0700 | [diff] [blame^] | 1 | /* |
| 2 | [auto_generated] |
| 3 | libs/numeric/odeint/test/adams_bashforth.cpp |
| 4 | |
| 5 | [begin_description] |
| 6 | This file tests the use of the adams bashforth stepper. |
| 7 | [end_description] |
| 8 | |
| 9 | Copyright 2011-2012 Karsten Ahnert |
| 10 | Copyright 2011-2012 Mario Mulansky |
| 11 | |
| 12 | Distributed under the Boost Software License, Version 1.0. |
| 13 | (See accompanying file LICENSE_1_0.txt or |
| 14 | copy at http://www.boost.org/LICENSE_1_0.txt) |
| 15 | */ |
| 16 | |
| 17 | |
| 18 | // disable checked iterator warning for msvc |
| 19 | |
| 20 | #include <boost/config.hpp> |
| 21 | #ifdef BOOST_MSVC |
| 22 | #pragma warning(disable:4996) |
| 23 | #endif |
| 24 | |
| 25 | #define BOOST_TEST_MODULE odeint_adams_bashforth |
| 26 | |
| 27 | #include <utility> |
| 28 | |
| 29 | #include <boost/array.hpp> |
| 30 | |
| 31 | #include <boost/test/unit_test.hpp> |
| 32 | |
| 33 | #include <boost/mpl/list.hpp> |
| 34 | #include <boost/mpl/size_t.hpp> |
| 35 | #include <boost/mpl/range_c.hpp> |
| 36 | |
| 37 | |
| 38 | #include <boost/numeric/odeint/stepper/adams_bashforth.hpp> |
| 39 | #include <boost/numeric/odeint/stepper/runge_kutta4.hpp> |
| 40 | |
| 41 | using namespace boost::unit_test; |
| 42 | using namespace boost::numeric::odeint; |
| 43 | |
| 44 | typedef double value_type; |
| 45 | |
| 46 | struct lorenz |
| 47 | { |
| 48 | template< class State , class Deriv , class Value > |
| 49 | void operator()( const State &_x , Deriv &_dxdt , const Value &dt ) const |
| 50 | { |
| 51 | const value_type sigma = 10.0; |
| 52 | const value_type R = 28.0; |
| 53 | const value_type b = 8.0 / 3.0; |
| 54 | |
| 55 | typename boost::range_iterator< const State >::type x = boost::begin( _x ); |
| 56 | typename boost::range_iterator< Deriv >::type dxdt = boost::begin( _dxdt ); |
| 57 | |
| 58 | dxdt[0] = sigma * ( x[1] - x[0] ); |
| 59 | dxdt[1] = R * x[0] - x[1] - x[0] * x[2]; |
| 60 | dxdt[2] = x[0]*x[1] - b * x[2]; |
| 61 | } |
| 62 | }; |
| 63 | |
| 64 | template< class State > |
| 65 | class rk4_decorator |
| 66 | { |
| 67 | public: |
| 68 | |
| 69 | size_t do_count; |
| 70 | |
| 71 | template< class System , class StateIn , class DerivIn , class StateOut > |
| 72 | void do_step_dxdt_impl( System system , const StateIn &in , const DerivIn &dxdt , value_type t , StateOut &out , value_type dt ) |
| 73 | { |
| 74 | m_stepper.do_step( system , in , dxdt , t , out , dt ); |
| 75 | ++do_count; |
| 76 | } |
| 77 | |
| 78 | template< class System , class StateInOut , class DerivIn > |
| 79 | void do_step_dxdt_impl( System system , StateInOut &x , const DerivIn &dxdt , value_type t , value_type dt ) |
| 80 | { |
| 81 | m_stepper.do_step( system , x , dxdt , t , dt ); |
| 82 | ++do_count; |
| 83 | } |
| 84 | |
| 85 | |
| 86 | runge_kutta4< State > m_stepper; |
| 87 | |
| 88 | private: |
| 89 | |
| 90 | |
| 91 | }; |
| 92 | |
| 93 | |
| 94 | BOOST_AUTO_TEST_SUITE( adams_bashforth_test ) |
| 95 | |
| 96 | BOOST_AUTO_TEST_CASE( test_adams_bashforth_coefficients ) |
| 97 | { |
| 98 | detail::adams_bashforth_coefficients< value_type , 1 > c1; |
| 99 | detail::adams_bashforth_coefficients< value_type , 2 > c2; |
| 100 | detail::adams_bashforth_coefficients< value_type , 3 > c3; |
| 101 | detail::adams_bashforth_coefficients< value_type , 4 > c4; |
| 102 | detail::adams_bashforth_coefficients< value_type , 5 > c5; |
| 103 | detail::adams_bashforth_coefficients< value_type , 6 > c6; |
| 104 | detail::adams_bashforth_coefficients< value_type , 7 > c7; |
| 105 | detail::adams_bashforth_coefficients< value_type , 8 > c8; |
| 106 | } |
| 107 | |
| 108 | BOOST_AUTO_TEST_CASE( test_rotating_buffer ) |
| 109 | { |
| 110 | const size_t N = 5; |
| 111 | detail::rotating_buffer< size_t , N > buffer; |
| 112 | for( size_t i=0 ; i<N ; ++i ) buffer[i] = i; |
| 113 | |
| 114 | for( size_t i=0 ; i<N ; ++i ) |
| 115 | BOOST_CHECK_EQUAL( buffer[i] , i ); |
| 116 | |
| 117 | buffer.rotate(); |
| 118 | |
| 119 | for( size_t i=1 ; i<N ; ++i ) |
| 120 | BOOST_CHECK_EQUAL( buffer[i] , i - 1 ); |
| 121 | BOOST_CHECK_EQUAL( buffer[0] , size_t( N-1 ) ); |
| 122 | } |
| 123 | |
| 124 | BOOST_AUTO_TEST_CASE( test_copying ) |
| 125 | { |
| 126 | typedef boost::array< double , 1 > state_type; |
| 127 | typedef adams_bashforth< 2 , state_type > stepper_type; |
| 128 | |
| 129 | stepper_type s1; |
| 130 | s1.step_storage()[0].m_v[0] = 1.5; |
| 131 | s1.step_storage()[1].m_v[0] = 2.25; |
| 132 | |
| 133 | stepper_type s2( s1 ); |
| 134 | BOOST_CHECK_CLOSE( s1.step_storage()[0].m_v[0] , s2.step_storage()[0].m_v[0] , 1.0e-14 ); |
| 135 | BOOST_CHECK_CLOSE( s1.step_storage()[1].m_v[0] , s2.step_storage()[1].m_v[0] , 1.0e-14 ); |
| 136 | BOOST_CHECK( ( &(s1.step_storage()[0]) ) != ( &(s2.step_storage()[0]) ) ); |
| 137 | |
| 138 | stepper_type s3; |
| 139 | state_type *p1 = &( s3.step_storage()[0].m_v ) , *p2 = &( s3.step_storage()[1].m_v ); |
| 140 | s3 = s1; |
| 141 | BOOST_CHECK( p1 == ( &( s3.step_storage()[0].m_v ) ) ); |
| 142 | BOOST_CHECK( p2 == ( &( s3.step_storage()[1].m_v ) ) ); |
| 143 | |
| 144 | BOOST_CHECK_CLOSE( s1.step_storage()[0].m_v[0] , s3.step_storage()[0].m_v[0] , 1.0e-14 ); |
| 145 | BOOST_CHECK_CLOSE( s1.step_storage()[1].m_v[0] , s3.step_storage()[1].m_v[0] , 1.0e-14 ); |
| 146 | } |
| 147 | |
| 148 | typedef boost::mpl::range_c< size_t , 1 , 6 > vector_of_steps; |
| 149 | |
| 150 | BOOST_AUTO_TEST_CASE_TEMPLATE( test_init_and_steps , step_type , vector_of_steps ) |
| 151 | { |
| 152 | const static size_t steps = step_type::value; |
| 153 | typedef boost::array< value_type , 3 > state_type; |
| 154 | |
| 155 | adams_bashforth< steps , state_type > stepper; |
| 156 | state_type x = {{ 10.0 , 10.0 , 10.0 }}; |
| 157 | const value_type dt = 0.01; |
| 158 | value_type t = 0.0; |
| 159 | |
| 160 | stepper.initialize( lorenz() , x , t , dt ); |
| 161 | BOOST_CHECK_CLOSE( t , value_type( steps - 1 ) * dt , 1.0e-14 ); |
| 162 | |
| 163 | stepper.do_step( lorenz() , x , t , dt ); |
| 164 | } |
| 165 | |
| 166 | BOOST_AUTO_TEST_CASE( test_instantiation ) |
| 167 | { |
| 168 | typedef boost::array< double , 3 > state_type; |
| 169 | adams_bashforth< 1 , state_type > s1; |
| 170 | adams_bashforth< 2 , state_type > s2; |
| 171 | adams_bashforth< 3 , state_type > s3; |
| 172 | adams_bashforth< 4 , state_type > s4; |
| 173 | adams_bashforth< 5 , state_type > s5; |
| 174 | adams_bashforth< 6 , state_type > s6; |
| 175 | adams_bashforth< 7 , state_type > s7; |
| 176 | adams_bashforth< 8 , state_type > s8; |
| 177 | |
| 178 | state_type x = {{ 10.0 , 10.0 , 10.0 }}; |
| 179 | value_type t = 0.0 , dt = 0.01; |
| 180 | s1.do_step( lorenz() , x , t , dt ); |
| 181 | s2.do_step( lorenz() , x , t , dt ); |
| 182 | s3.do_step( lorenz() , x , t , dt ); |
| 183 | s4.do_step( lorenz() , x , t , dt ); |
| 184 | s5.do_step( lorenz() , x , t , dt ); |
| 185 | s6.do_step( lorenz() , x , t , dt ); |
| 186 | // s7.do_step( lorenz() , x , t , dt ); |
| 187 | // s8.do_step( lorenz() , x , t , dt ); |
| 188 | } |
| 189 | |
| 190 | BOOST_AUTO_TEST_CASE( test_auto_initialization ) |
| 191 | { |
| 192 | typedef boost::array< double , 3 > state_type; |
| 193 | state_type x = {{ 10.0 , 10.0 , 10.0 }}; |
| 194 | |
| 195 | adams_bashforth< 3 , state_type , value_type , state_type , value_type , range_algebra , default_operations , |
| 196 | initially_resizer , rk4_decorator< state_type > > adams; |
| 197 | |
| 198 | adams.initializing_stepper().do_count = 0; |
| 199 | adams.do_step( lorenz() , x , 0.0 , x , 0.1 ); |
| 200 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 1 ) ); |
| 201 | |
| 202 | adams.do_step( lorenz() , x , 0.0 , x , 0.1 ); |
| 203 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 2 ) ); |
| 204 | |
| 205 | adams.do_step( lorenz() , x , 0.0 , x , 0.1 ); |
| 206 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 2 ) ); |
| 207 | |
| 208 | adams.do_step( lorenz() , x , 0.0 , x , 0.1 ); |
| 209 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 2 ) ); |
| 210 | |
| 211 | adams.reset(); |
| 212 | |
| 213 | adams.do_step( lorenz() , x , 0.0 , x , 0.1 ); |
| 214 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 3 ) ); |
| 215 | |
| 216 | adams.do_step( lorenz() , x , 0.0 , x , 0.1 ); |
| 217 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 4 ) ); |
| 218 | } |
| 219 | |
| 220 | BOOST_AUTO_TEST_CASE( test_manual_initialization ) |
| 221 | { |
| 222 | typedef boost::array< double , 3 > state_type; |
| 223 | state_type x = {{ 10.0 , 10.0 , 10.0 }}; |
| 224 | |
| 225 | adams_bashforth< 3 , state_type , value_type , state_type , value_type , range_algebra , default_operations , |
| 226 | initially_resizer , rk4_decorator< state_type > > adams; |
| 227 | |
| 228 | adams.initializing_stepper().do_count = 0; |
| 229 | double t = 0.0 , dt = 0.1; |
| 230 | adams.initialize( lorenz() , x , t , dt ); |
| 231 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 2 ) ); |
| 232 | |
| 233 | adams.do_step( lorenz() , x , 0.0 , x , 0.1 ); |
| 234 | BOOST_CHECK_EQUAL( adams.initializing_stepper().do_count , size_t( 2 ) ); |
| 235 | } |
| 236 | |
| 237 | BOOST_AUTO_TEST_SUITE_END() |