symplectic_steppers.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. [auto_generated]
  3. libs/numeric/odeint/test/symplectic_steppers.cpp
  4. [begin_description]
  5. tba.
  6. [end_description]
  7. Copyright 2012 Karsten Ahnert
  8. Copyright 2013 Mario Mulansky
  9. Distributed under the Boost Software License, Version 1.0.
  10. (See accompanying file LICENSE_1_0.txt or
  11. copy at http://www.boost.org/LICENSE_1_0.txt)
  12. */
  13. #include <boost/config.hpp>
  14. #ifdef BOOST_MSVC
  15. #pragma warning(disable:4996)
  16. #endif
  17. #define BOOST_TEST_MODULE odeint_symplectic_steppers
  18. #define BOOST_FUSION_INVOKE_MAX_ARITY 15
  19. #define BOOST_RESULT_OF_NUM_ARGS 15
  20. #define FUSION_MAX_VECTOR_SIZE 15
  21. #include <boost/test/unit_test.hpp>
  22. #include <boost/array.hpp>
  23. #include <boost/static_assert.hpp>
  24. #include <boost/type_traits/is_same.hpp>
  25. #include <boost/mpl/vector.hpp>
  26. #include <boost/mpl/zip_view.hpp>
  27. #include <boost/mpl/vector_c.hpp>
  28. #include <boost/mpl/insert_range.hpp>
  29. #include <boost/mpl/end.hpp>
  30. #include <boost/mpl/size.hpp>
  31. #include <boost/mpl/copy.hpp>
  32. #include <boost/mpl/placeholders.hpp>
  33. #include <boost/mpl/inserter.hpp>
  34. #include <boost/mpl/at.hpp>
  35. #include <boost/fusion/container/vector.hpp>
  36. #include <boost/fusion/include/make_vector.hpp>
  37. #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp>
  38. #include <boost/numeric/odeint/algebra/fusion_algebra.hpp>
  39. #include <boost/numeric/odeint/stepper/symplectic_euler.hpp>
  40. #include <boost/numeric/odeint/stepper/symplectic_rkn_sb3a_mclachlan.hpp>
  41. #include <boost/numeric/odeint/stepper/symplectic_rkn_sb3a_m4_mclachlan.hpp>
  42. #include <boost/numeric/odeint/integrate/integrate_const.hpp>
  43. #include "diagnostic_state_type.hpp"
  44. #include "const_range.hpp"
  45. #include "dummy_odes.hpp"
  46. #include "boost_units_helpers.hpp"
  47. using namespace boost::unit_test;
  48. using namespace boost::numeric::odeint;
  49. namespace mpl = boost::mpl;
  50. namespace fusion = boost::fusion;
  51. class custom_range_algebra : public range_algebra { };
  52. class custom_default_operations : public default_operations { };
  53. template< class Coor , class Mom , class Value , class CoorDeriv , class MomDeriv , class Time ,
  54. class Algebra , class Operations , class Resizer >
  55. class complete_steppers : public mpl::vector<
  56. symplectic_euler< Coor , Mom , Value , CoorDeriv , MomDeriv , Time ,
  57. Algebra , Operations , Resizer >
  58. , symplectic_rkn_sb3a_mclachlan< Coor , Mom , Value , CoorDeriv , MomDeriv , Time ,
  59. Algebra , Operations , Resizer >
  60. , symplectic_rkn_sb3a_m4_mclachlan< Coor , Mom , Value , CoorDeriv , MomDeriv , Time ,
  61. Algebra , Operations , Resizer >
  62. > {};
  63. template< class Resizer >
  64. class vector_steppers : public complete_steppers<
  65. diagnostic_state_type , diagnostic_state_type2 , double ,
  66. diagnostic_deriv_type , diagnostic_deriv_type2 , double ,
  67. custom_range_algebra , custom_default_operations , Resizer
  68. > { };
  69. typedef mpl::vector< initially_resizer , always_resizer , never_resizer > resizers;
  70. typedef mpl::vector_c< int , 1 , 3 , 0 > resizer_multiplicities ;
  71. typedef mpl::copy<
  72. resizers ,
  73. mpl::inserter<
  74. mpl::vector0<> ,
  75. mpl::insert_range<
  76. mpl::_1 ,
  77. mpl::end< mpl::_1 > ,
  78. vector_steppers< mpl::_2 >
  79. >
  80. >
  81. >::type all_stepper_methods;
  82. typedef mpl::size< vector_steppers< initially_resizer > >::type num_steppers;
  83. typedef mpl::copy<
  84. resizer_multiplicities ,
  85. mpl::inserter<
  86. mpl::vector0<> ,
  87. mpl::insert_range<
  88. mpl::_1 ,
  89. mpl::end< mpl::_1 > ,
  90. const_range< num_steppers , mpl::_2 >
  91. >
  92. >
  93. >::type all_multiplicities;
  94. BOOST_AUTO_TEST_SUITE( symplectic_steppers_test )
  95. BOOST_AUTO_TEST_CASE_TEMPLATE( test_assoc_types , Stepper , vector_steppers< initially_resizer > )
  96. {
  97. BOOST_STATIC_ASSERT_MSG(
  98. ( boost::is_same< typename Stepper::coor_type , diagnostic_state_type >::value ) ,
  99. "Coordinate type" );
  100. BOOST_STATIC_ASSERT_MSG(
  101. ( boost::is_same< typename Stepper::momentum_type , diagnostic_state_type2 >::value ) ,
  102. "Momentum type" );
  103. BOOST_STATIC_ASSERT_MSG(
  104. ( boost::is_same< typename Stepper::coor_deriv_type , diagnostic_deriv_type >::value ) ,
  105. "Coordinate deriv type" );
  106. BOOST_STATIC_ASSERT_MSG(
  107. ( boost::is_same< typename Stepper::momentum_deriv_type , diagnostic_deriv_type2 >::value ) ,
  108. "Momentum deriv type" );
  109. BOOST_STATIC_ASSERT_MSG(
  110. ( boost::is_same< typename Stepper::state_type , std::pair< diagnostic_state_type , diagnostic_state_type2 > >::value ) ,
  111. "State type" );
  112. BOOST_STATIC_ASSERT_MSG(
  113. ( boost::is_same< typename Stepper::deriv_type , std::pair< diagnostic_deriv_type , diagnostic_deriv_type2 > >::value ) ,
  114. "Deriv type" );
  115. BOOST_STATIC_ASSERT_MSG( ( boost::is_same< typename Stepper::value_type , double >::value ) , "Value type" );
  116. BOOST_STATIC_ASSERT_MSG( ( boost::is_same< typename Stepper::time_type , double >::value ) , "Time type" );
  117. BOOST_STATIC_ASSERT_MSG( ( boost::is_same< typename Stepper::algebra_type , custom_range_algebra >::value ) , "Algebra type" );
  118. BOOST_STATIC_ASSERT_MSG( ( boost::is_same< typename Stepper::operations_type , custom_default_operations >::value ) , "Operations type" );
  119. BOOST_STATIC_ASSERT_MSG( ( boost::is_same< typename Stepper::resizer_type , initially_resizer >::value ) , "Resizer type" );
  120. BOOST_STATIC_ASSERT_MSG( ( boost::is_same< typename Stepper::stepper_category , stepper_tag >::value ) , "Stepper category" );
  121. }
  122. BOOST_AUTO_TEST_CASE_TEMPLATE( test_adjust_size , Stepper , vector_steppers< initially_resizer > )
  123. {
  124. counter_state::init_counter();
  125. counter_deriv::init_counter();
  126. counter_state2::init_counter();
  127. counter_deriv2::init_counter();
  128. {
  129. Stepper stepper;
  130. diagnostic_state_type x;
  131. stepper.adjust_size( x );
  132. }
  133. TEST_COUNTERS( counter_state , 0 , 0 , 0 , 0 );
  134. TEST_COUNTERS( counter_state2 , 0 , 0 , 0 , 0 );
  135. TEST_COUNTERS( counter_deriv , 1 , 1 , 0 , 1 );
  136. TEST_COUNTERS( counter_deriv2 , 1 , 1 , 0 , 1 );
  137. }
  138. typedef mpl::zip_view< mpl::vector< all_stepper_methods , all_multiplicities > >::type zipped_steppers;
  139. BOOST_AUTO_TEST_CASE_TEMPLATE( test_resizing , Stepper , zipped_steppers )
  140. {
  141. typedef typename mpl::at_c< Stepper , 0 >::type stepper_type;
  142. const size_t multiplicity = mpl::at_c< Stepper , 1 >::type::value;
  143. counter_state::init_counter();
  144. counter_deriv::init_counter();
  145. counter_state2::init_counter();
  146. counter_deriv2::init_counter();
  147. {
  148. stepper_type stepper;
  149. std::pair< diagnostic_state_type , diagnostic_state_type2 > x;
  150. stepper.do_step( constant_mom_func() , x , 0.0 , 0.1 );
  151. stepper.do_step( constant_mom_func() , x , 0.0 , 0.1 );
  152. stepper.do_step( constant_mom_func() , x , 0.0 , 0.1 );
  153. }
  154. TEST_COUNTERS( counter_state , 0 , 0 , 0 , 0 );
  155. TEST_COUNTERS( counter_state2 , 0 , 0 , 0 , 0 );
  156. // dqdt is not needed when called with mom func only, so no resizing
  157. // TEST_COUNTERS( counter_deriv , multiplicity , 1 , 0 , 1 );
  158. TEST_COUNTERS( counter_deriv2 , multiplicity , 1 , 0 , 1 );
  159. }
  160. BOOST_AUTO_TEST_CASE_TEMPLATE( test_copying1 , Stepper , vector_steppers< initially_resizer > )
  161. {
  162. counter_state::init_counter();
  163. counter_deriv::init_counter();
  164. counter_state2::init_counter();
  165. counter_deriv2::init_counter();
  166. {
  167. Stepper stepper;
  168. Stepper stepper2( stepper );
  169. }
  170. TEST_COUNTERS( counter_state , 0 , 0 , 0 , 0 );
  171. TEST_COUNTERS( counter_state2 , 0 , 0 , 0 , 0 );
  172. TEST_COUNTERS( counter_deriv , 0 , 2 , 1 , 2 );
  173. TEST_COUNTERS( counter_deriv2 , 0 , 2 , 1 , 2 );
  174. }
  175. BOOST_AUTO_TEST_CASE_TEMPLATE( test_copying2 , Stepper , vector_steppers< initially_resizer > )
  176. {
  177. counter_state::init_counter();
  178. counter_deriv::init_counter();
  179. counter_state2::init_counter();
  180. counter_deriv2::init_counter();
  181. {
  182. Stepper stepper;
  183. std::pair< diagnostic_state_type , diagnostic_state_type2 > x;
  184. stepper.do_step( constant_mom_func() , x , 0.0 , 0.1 );
  185. Stepper stepper2( stepper );
  186. }
  187. TEST_COUNTERS( counter_state , 0 , 0 , 0 , 0 );
  188. TEST_COUNTERS( counter_state2 , 0 , 0 , 0 , 0 );
  189. // dqdt is not needed when called with mom func only, so no resizing
  190. //TEST_COUNTERS( counter_deriv , 1 , 2 , 1 , 2 );
  191. TEST_COUNTERS( counter_deriv2 , 1 , 2 , 1 , 2 );
  192. }
  193. BOOST_AUTO_TEST_CASE_TEMPLATE( test_do_step_v1 , Stepper , vector_steppers< initially_resizer > )
  194. {
  195. Stepper s;
  196. std::pair< diagnostic_state_type , diagnostic_state_type2 > x1 , x2 , x3 , x4;
  197. x1.first[0] = 1.0;
  198. x1.second[0] = 2.0;
  199. x2 = x3 = x4 = x1;
  200. diagnostic_state_type x5_coor , x5_mom;
  201. x5_coor[0] = x1.first[0];
  202. x5_mom[0] = x1.second[0];
  203. s.do_step( constant_mom_func() , x1 , 0.0 , 0.1 );
  204. s.do_step( std::make_pair( default_coor_func() , constant_mom_func() ) , x2 , 0.0 , 0.1 );
  205. default_coor_func cf;
  206. constant_mom_func mf;
  207. s.do_step( std::make_pair( boost::ref( cf ) , boost::ref( mf ) ) , x3 , 0.0 , 0.1 );
  208. std::pair< default_coor_func , constant_mom_func > pf;
  209. s.do_step( boost::ref( pf ) , x4 , 0.0 , 0.1 );
  210. s.do_step( constant_mom_func() , std::make_pair( boost::ref( x5_coor ) , boost::ref( x5_mom ) ) , 0.0 , 0.1 );
  211. // checking for absolute values is not possible here, since the steppers are to different
  212. BOOST_CHECK_CLOSE( x1.first[0] , x2.first[0] , 1.0e-14 );
  213. BOOST_CHECK_CLOSE( x2.first[0] , x3.first[0] , 1.0e-14 );
  214. BOOST_CHECK_CLOSE( x3.first[0] , x4.first[0] , 1.0e-14 );
  215. BOOST_CHECK_CLOSE( x4.first[0] , x5_coor[0] , 1.0e-14 );
  216. BOOST_CHECK_CLOSE( x1.second[0] , x2.second[0] , 1.0e-14 );
  217. BOOST_CHECK_CLOSE( x2.second[0] , x3.second[0] , 1.0e-14 );
  218. BOOST_CHECK_CLOSE( x3.second[0] , x4.second[0] , 1.0e-14 );
  219. BOOST_CHECK_CLOSE( x4.second[0] , x5_mom[0] , 1.0e-14 );
  220. }
  221. BOOST_AUTO_TEST_CASE_TEMPLATE( test_do_step_range , Stepper , vector_steppers< initially_resizer > )
  222. {
  223. Stepper s;
  224. diagnostic_state_type q , p ;
  225. q[0] = 1.0;
  226. p[0] = 2.0;
  227. std::vector< double > x;
  228. x.push_back( 1.0 );
  229. x.push_back( 2.0 );
  230. s.do_step( constant_mom_func() ,
  231. std::make_pair( x.begin() , x.begin() + 1 ) ,
  232. std::make_pair( x.begin() + 1 , x.begin() + 2 ) ,
  233. 0.0 , 0.1 );
  234. s.do_step( constant_mom_func() , q , p , 0.0 , 0.1 );
  235. BOOST_CHECK_CLOSE( q[0] , x[0] , 1.0e-14 );
  236. BOOST_CHECK_CLOSE( p[0] , x[1] , 1.0e-14 );
  237. }
  238. BOOST_AUTO_TEST_CASE_TEMPLATE( test_do_step_v2 , Stepper , vector_steppers< initially_resizer > )
  239. {
  240. Stepper s;
  241. diagnostic_state_type q , p ;
  242. q[0] = 1.0;
  243. p[0] = 2.0;
  244. diagnostic_state_type q2 = q , p2 = p;
  245. s.do_step( constant_mom_func() , q , p , 0.0 , 0.1 );
  246. s.do_step( constant_mom_func() , std::make_pair( boost::ref( q2 ) , boost::ref( p2 ) ) , 0.0 , 0.1 );
  247. BOOST_CHECK_CLOSE( q[0] , q2[0] , 1.0e-14 );
  248. BOOST_CHECK_CLOSE( p[0] , p2[0] , 1.0e-14 );
  249. }
  250. BOOST_AUTO_TEST_CASE_TEMPLATE( test_do_step_v3 , Stepper , vector_steppers< initially_resizer > )
  251. {
  252. Stepper s;
  253. std::pair< diagnostic_state_type , diagnostic_state_type2 > x_in , x_out;
  254. x_in.first[0] = 1.0;
  255. x_in.second[0] = 2.0;
  256. diagnostic_state_type q2 , p2;
  257. q2[0] = x_in.first[0];
  258. p2[0] = x_in.second[0];
  259. s.do_step( constant_mom_func() , x_in , 0.0 , x_out , 0.1 );
  260. s.do_step( constant_mom_func() , std::make_pair( boost::ref( q2 ) , boost::ref( p2 ) ) , 0.0 , 0.1 );
  261. BOOST_CHECK_CLOSE( x_in.first[0] , 1.0 , 1.0e-14 );
  262. BOOST_CHECK_CLOSE( x_in.second[0] , 2.0 , 1.0e-14 );
  263. BOOST_CHECK_CLOSE( x_out.first[0] , q2[0] , 1.0e-14 );
  264. BOOST_CHECK_CLOSE( x_out.second[0] , p2[0] , 1.0e-14 );
  265. }
  266. typedef double vector_space;
  267. typedef complete_steppers< vector_space , vector_space , double ,
  268. vector_space , vector_space , double ,
  269. vector_space_algebra , default_operations , initially_resizer > vector_space_steppers;
  270. BOOST_AUTO_TEST_CASE_TEMPLATE( test_with_vector_space_algebra , Stepper , vector_space_steppers )
  271. {
  272. Stepper s;
  273. std::pair< vector_space , vector_space > x;
  274. s.do_step( constant_mom_func_vector_space_1d() , x , 0.0 , 0.1 );
  275. s.do_step( std::make_pair( default_coor_func_vector_space_1d() , constant_mom_func_vector_space_1d() ) , x , 0.0 , 0.1 );
  276. }
  277. typedef boost::fusion::vector< length_type > coor_type;
  278. typedef boost::fusion::vector< velocity_type > mom_type;
  279. typedef boost::fusion::vector< acceleration_type > acc_type;
  280. typedef complete_steppers< coor_type , mom_type , double ,
  281. mom_type , acc_type , time_type,
  282. fusion_algebra , default_operations , initially_resizer > boost_unit_steppers;
  283. BOOST_AUTO_TEST_CASE_TEMPLATE( test_with_boost_units , Stepper , boost_unit_steppers )
  284. {
  285. namespace fusion = boost::fusion;
  286. namespace si = boost::units::si;
  287. Stepper s;
  288. coor_type q = fusion::make_vector( 1.0 * si::meter );
  289. mom_type p = fusion::make_vector( 2.0 * si::meter_per_second );
  290. time_type t = 0.0 * si::second;
  291. time_type dt = 0.1 * si::second;
  292. coor_type q1 = q , q2 = q;
  293. mom_type p1 = p , p2 = p;
  294. s.do_step( oscillator_mom_func_units() , std::make_pair( boost::ref( q ) , boost::ref( p ) ) , t , dt );
  295. s.do_step( std::make_pair( oscillator_coor_func_units() , oscillator_mom_func_units() ) ,
  296. std::make_pair( boost::ref( q1 ) , boost::ref( p1 ) ) , t , dt );
  297. s.do_step( oscillator_mom_func_units() , q2 , p2 , t , dt );
  298. BOOST_CHECK_CLOSE( ( fusion::at_c< 0 >( q ).value() ) , ( fusion::at_c< 0 >( q1 ).value() ) , 1.0e-14 );
  299. BOOST_CHECK_CLOSE( ( fusion::at_c< 0 >( q1 ).value() ) , ( fusion::at_c< 0 >( q2 ).value() ) , 1.0e-14 );
  300. BOOST_CHECK_CLOSE( ( fusion::at_c< 0 >( p ).value() ) , ( fusion::at_c< 0 >( p1 ).value() ) , 1.0e-14 );
  301. BOOST_CHECK_CLOSE( ( fusion::at_c< 0 >( p1 ).value() ) , ( fusion::at_c< 0 >( p2 ).value() ) , 1.0e-14 );
  302. }
  303. BOOST_AUTO_TEST_SUITE_END()