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