File indexing completed on 2025-07-15 08:40:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef BOOST_NUMERIC_ODEINT_STEPPER_BASE_SYMPLECTIC_RKN_STEPPER_BASE_HPP_INCLUDED
0020 #define BOOST_NUMERIC_ODEINT_STEPPER_BASE_SYMPLECTIC_RKN_STEPPER_BASE_HPP_INCLUDED
0021
0022 #include <array>
0023 #include <type_traits>
0024
0025 #include <boost/numeric/odeint/util/bind.hpp>
0026 #include <boost/numeric/odeint/util/unwrap_reference.hpp>
0027
0028 #include <boost/numeric/odeint/util/copy.hpp>
0029 #include <boost/numeric/odeint/util/is_pair.hpp>
0030
0031 #include <boost/numeric/odeint/util/state_wrapper.hpp>
0032 #include <boost/numeric/odeint/util/resizer.hpp>
0033
0034 #include <boost/numeric/odeint/stepper/stepper_categories.hpp>
0035
0036 #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp>
0037
0038
0039
0040
0041 namespace boost {
0042 namespace numeric {
0043 namespace odeint {
0044
0045
0046 template<
0047 size_t NumOfStages ,
0048 unsigned short Order ,
0049 class Coor ,
0050 class Momentum ,
0051 class Value ,
0052 class CoorDeriv ,
0053 class MomentumDeriv ,
0054 class Time ,
0055 class Algebra ,
0056 class Operations ,
0057 class Resizer
0058 >
0059 class symplectic_nystroem_stepper_base : public algebra_stepper_base< Algebra , Operations >
0060 {
0061
0062 public:
0063
0064 typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type;
0065 typedef typename algebra_stepper_base_type::algebra_type algebra_type;
0066 typedef typename algebra_stepper_base_type::operations_type operations_type;
0067
0068 const static size_t num_of_stages = NumOfStages;
0069 typedef Coor coor_type;
0070 typedef Momentum momentum_type;
0071 typedef std::pair< coor_type , momentum_type > state_type;
0072 typedef CoorDeriv coor_deriv_type;
0073 typedef state_wrapper< coor_deriv_type> wrapped_coor_deriv_type;
0074 typedef MomentumDeriv momentum_deriv_type;
0075 typedef state_wrapper< momentum_deriv_type > wrapped_momentum_deriv_type;
0076 typedef std::pair< coor_deriv_type , momentum_deriv_type > deriv_type;
0077 typedef Value value_type;
0078 typedef Time time_type;
0079 typedef Resizer resizer_type;
0080 typedef stepper_tag stepper_category;
0081
0082 #ifndef DOXYGEN_SKIP
0083 typedef symplectic_nystroem_stepper_base< NumOfStages , Order , Coor , Momentum , Value ,
0084 CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > internal_stepper_base_type;
0085 #endif
0086 typedef unsigned short order_type;
0087
0088 static const order_type order_value = Order;
0089
0090 typedef std::array< value_type , num_of_stages > coef_type;
0091
0092 symplectic_nystroem_stepper_base( const coef_type &coef_a , const coef_type &coef_b , const algebra_type &algebra = algebra_type() )
0093 : algebra_stepper_base_type( algebra ) , m_coef_a( coef_a ) , m_coef_b( coef_b ) ,
0094 m_dqdt_resizer() , m_dpdt_resizer() , m_dqdt() , m_dpdt()
0095 { }
0096
0097
0098 order_type order( void ) const
0099 {
0100 return order_value;
0101 }
0102
0103
0104
0105
0106
0107
0108 template< class System , class StateInOut >
0109 void do_step( System system , const StateInOut &state , time_type t , time_type dt )
0110 {
0111 typedef typename odeint::unwrap_reference< System >::type system_type;
0112 do_step_impl( system , state , t , state , dt , typename is_pair< system_type >::type() );
0113 }
0114
0115
0116
0117
0118
0119 template< class System , class StateInOut >
0120 void do_step( System system , StateInOut &state , time_type t , time_type dt )
0121 {
0122 typedef typename odeint::unwrap_reference< System >::type system_type;
0123 do_step_impl( system , state , t , state , dt , typename is_pair< system_type >::type() );
0124 }
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 template< class System , class CoorInOut , class MomentumInOut >
0137 void do_step( System system , CoorInOut &q , MomentumInOut &p , time_type t , time_type dt )
0138 {
0139 do_step( system , std::make_pair( std::ref( q ) , std::ref( p ) ) , t , dt );
0140 }
0141
0142
0143
0144
0145
0146 template< class System , class CoorInOut , class MomentumInOut >
0147 void do_step( System system , const CoorInOut &q , const MomentumInOut &p , time_type t , time_type dt )
0148 {
0149 do_step( system , std::make_pair( std::ref( q ) , std::ref( p ) ) , t , dt );
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 template< class System , class StateIn , class StateOut >
0162 void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt )
0163 {
0164 typedef typename odeint::unwrap_reference< System >::type system_type;
0165 do_step_impl( system , in , t , out , dt , typename is_pair< system_type >::type() );
0166 }
0167
0168
0169 template< class StateType >
0170 void adjust_size( const StateType &x )
0171 {
0172 resize_dqdt( x );
0173 resize_dpdt( x );
0174 }
0175
0176
0177 const coef_type& coef_a( void ) const { return m_coef_a; }
0178
0179
0180 const coef_type& coef_b( void ) const { return m_coef_b; }
0181
0182 private:
0183
0184
0185 template< class System , class StateIn , class StateOut >
0186 void do_step_impl( System system , const StateIn &in , time_type , StateOut &out , time_type dt , std::integral_constant<bool, true> )
0187 {
0188 typedef typename odeint::unwrap_reference< System >::type system_type;
0189 typedef typename odeint::unwrap_reference< typename system_type::first_type >::type coor_deriv_func_type;
0190 typedef typename odeint::unwrap_reference< typename system_type::second_type >::type momentum_deriv_func_type;
0191 system_type &sys = system;
0192 coor_deriv_func_type &coor_func = sys.first;
0193 momentum_deriv_func_type &momentum_func = sys.second;
0194
0195 typedef typename odeint::unwrap_reference< StateIn >::type state_in_type;
0196 typedef typename odeint::unwrap_reference< typename state_in_type::first_type >::type coor_in_type;
0197 typedef typename odeint::unwrap_reference< typename state_in_type::second_type >::type momentum_in_type;
0198 const state_in_type &state_in = in;
0199 const coor_in_type &coor_in = state_in.first;
0200 const momentum_in_type &momentum_in = state_in.second;
0201
0202 typedef typename odeint::unwrap_reference< StateOut >::type state_out_type;
0203 typedef typename odeint::unwrap_reference< typename state_out_type::first_type >::type coor_out_type;
0204 typedef typename odeint::unwrap_reference< typename state_out_type::second_type >::type momentum_out_type;
0205 state_out_type &state_out = out;
0206 coor_out_type &coor_out = state_out.first;
0207 momentum_out_type &momentum_out = state_out.second;
0208
0209 m_dqdt_resizer.adjust_size(coor_in, [this](auto&& arg) { return this->resize_dqdt<coor_in_type>(std::forward<decltype(arg)>(arg)); });
0210 m_dpdt_resizer.adjust_size(momentum_in, [this](auto&& arg) { return this->resize_dpdt<momentum_in_type>(std::forward<decltype(arg)>(arg)); });
0211
0212
0213
0214 for( size_t l=0 ; l<num_of_stages ; ++l )
0215 {
0216 if( l == 0 )
0217 {
0218 coor_func( momentum_in , m_dqdt.m_v );
0219 this->m_algebra.for_each3( coor_out , coor_in , m_dqdt.m_v ,
0220 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[l] * dt ) );
0221 momentum_func( coor_out , m_dpdt.m_v );
0222 this->m_algebra.for_each3( momentum_out , momentum_in , m_dpdt.m_v ,
0223 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[l] * dt ) );
0224 }
0225 else
0226 {
0227 coor_func( momentum_out , m_dqdt.m_v );
0228 this->m_algebra.for_each3( coor_out , coor_out , m_dqdt.m_v ,
0229 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[l] * dt ) );
0230 momentum_func( coor_out , m_dpdt.m_v );
0231 this->m_algebra.for_each3( momentum_out , momentum_out , m_dpdt.m_v ,
0232 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[l] * dt ) );
0233 }
0234 }
0235 }
0236
0237
0238
0239 template< class System , class StateIn , class StateOut >
0240 void do_step_impl( System system , const StateIn &in , time_type , StateOut &out , time_type dt , std::integral_constant<bool, false> )
0241 {
0242 typedef typename odeint::unwrap_reference< System >::type momentum_deriv_func_type;
0243 momentum_deriv_func_type &momentum_func = system;
0244
0245 typedef typename odeint::unwrap_reference< StateIn >::type state_in_type;
0246 typedef typename odeint::unwrap_reference< typename state_in_type::first_type >::type coor_in_type;
0247 typedef typename odeint::unwrap_reference< typename state_in_type::second_type >::type momentum_in_type;
0248 const state_in_type &state_in = in;
0249 const coor_in_type &coor_in = state_in.first;
0250 const momentum_in_type &momentum_in = state_in.second;
0251
0252 typedef typename odeint::unwrap_reference< StateOut >::type state_out_type;
0253 typedef typename odeint::unwrap_reference< typename state_out_type::first_type >::type coor_out_type;
0254 typedef typename odeint::unwrap_reference< typename state_out_type::second_type >::type momentum_out_type;
0255 state_out_type &state_out = out;
0256 coor_out_type &coor_out = state_out.first;
0257 momentum_out_type &momentum_out = state_out.second;
0258
0259
0260
0261 m_dpdt_resizer.adjust_size(momentum_in, [this](auto&& arg) { return this->resize_dpdt<momentum_in_type>(std::forward<decltype(arg)>(arg)); });
0262
0263
0264
0265
0266
0267 this->m_algebra.for_each3( coor_out , coor_in , momentum_in ,
0268 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[0] * dt ) );
0269 momentum_func( coor_out , m_dpdt.m_v );
0270 this->m_algebra.for_each3( momentum_out , momentum_in , m_dpdt.m_v ,
0271 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[0] * dt ) );
0272
0273 for( size_t l=1 ; l<num_of_stages ; ++l )
0274 {
0275 this->m_algebra.for_each3( coor_out , coor_out , momentum_out ,
0276 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[l] * dt ) );
0277 momentum_func( coor_out , m_dpdt.m_v );
0278 this->m_algebra.for_each3( momentum_out , momentum_out , m_dpdt.m_v ,
0279 typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[l] * dt ) );
0280 }
0281 }
0282
0283 template< class StateIn >
0284 bool resize_dqdt( const StateIn &x )
0285 {
0286 return adjust_size_by_resizeability( m_dqdt , x , typename is_resizeable<coor_deriv_type>::type() );
0287 }
0288
0289 template< class StateIn >
0290 bool resize_dpdt( const StateIn &x )
0291 {
0292 return adjust_size_by_resizeability( m_dpdt , x , typename is_resizeable<momentum_deriv_type>::type() );
0293 }
0294
0295
0296 const coef_type m_coef_a;
0297 const coef_type m_coef_b;
0298
0299 resizer_type m_dqdt_resizer;
0300 resizer_type m_dpdt_resizer;
0301 wrapped_coor_deriv_type m_dqdt;
0302 wrapped_momentum_deriv_type m_dpdt;
0303
0304 };
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426 }
0427 }
0428 }
0429
0430
0431 #endif