File indexing completed on 2025-01-18 09:42:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_NUMERIC_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED
0019 #define BOOST_NUMERIC_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED
0020
0021 #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp>
0022 #include <boost/numeric/odeint/stepper/stepper_categories.hpp>
0023
0024 #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
0025 #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
0026 #include <boost/numeric/odeint/util/resizer.hpp>
0027 #include <boost/numeric/odeint/util/state_wrapper.hpp>
0028 #include <boost/numeric/odeint/util/unwrap_reference.hpp>
0029
0030 #include <boost/numeric/odeint/util/bind.hpp>
0031 #include <boost/numeric/odeint/util/copy.hpp>
0032 #include <boost/numeric/odeint/util/resizer.hpp>
0033
0034
0035
0036
0037
0038 namespace boost {
0039 namespace numeric {
0040 namespace odeint {
0041
0042
0043
0044 template <
0045 class Coor ,
0046 class Velocity = Coor ,
0047 class Value = double ,
0048 class Acceleration = Coor ,
0049 class Time = Value ,
0050 class TimeSq = Time ,
0051 class Algebra = typename algebra_dispatcher< Coor >::algebra_type ,
0052 class Operations = typename operations_dispatcher< Coor >::operations_type ,
0053 class Resizer = initially_resizer
0054 >
0055 class velocity_verlet : public algebra_stepper_base< Algebra , Operations >
0056 {
0057 public:
0058
0059 typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type;
0060 typedef typename algebra_stepper_base_type::algebra_type algebra_type;
0061 typedef typename algebra_stepper_base_type::operations_type operations_type;
0062
0063 typedef Coor coor_type;
0064 typedef Velocity velocity_type;
0065 typedef Acceleration acceleration_type;
0066 typedef std::pair< coor_type , velocity_type > state_type;
0067 typedef std::pair< velocity_type , acceleration_type > deriv_type;
0068 typedef state_wrapper< acceleration_type > wrapped_acceleration_type;
0069 typedef Value value_type;
0070 typedef Time time_type;
0071 typedef TimeSq time_square_type;
0072 typedef Resizer resizer_type;
0073 typedef stepper_tag stepper_category;
0074
0075 typedef unsigned short order_type;
0076
0077 static const order_type order_value = 1;
0078
0079
0080
0081
0082 order_type order( void ) const
0083 {
0084 return order_value;
0085 }
0086
0087
0088 velocity_verlet( const algebra_type & algebra = algebra_type() )
0089 : algebra_stepper_base_type( algebra ) , m_first_call( true )
0090 , m_a1() , m_a2() , m_current_a1( true ) { }
0091
0092
0093 template< class System , class StateInOut >
0094 void do_step( System system , StateInOut & x , time_type t , time_type dt )
0095 {
0096 do_step_v1( system , x , t , dt );
0097 }
0098
0099
0100 template< class System , class StateInOut >
0101 void do_step( System system , const StateInOut & x , time_type t , time_type dt )
0102 {
0103 do_step_v1( system , x , t , dt );
0104 }
0105
0106
0107 template< class System , class CoorIn , class VelocityIn , class AccelerationIn ,
0108 class CoorOut , class VelocityOut , class AccelerationOut >
0109 void do_step( System system , CoorIn const & qin , VelocityIn const & pin , AccelerationIn const & ain ,
0110 CoorOut & qout , VelocityOut & pout , AccelerationOut & aout , time_type t , time_type dt )
0111 {
0112 const value_type one = static_cast< value_type >( 1.0 );
0113 const value_type one_half = static_cast< value_type >( 0.5 );
0114
0115 algebra_stepper_base_type::m_algebra.for_each4(
0116 qout , qin , pin , ain ,
0117 typename operations_type::template scale_sum3< value_type , time_type , time_square_type >( one , one * dt , one_half * dt * dt ) );
0118
0119 typename odeint::unwrap_reference< System >::type & sys = system;
0120
0121 sys( qout , pin , aout , t + dt );
0122
0123 algebra_stepper_base_type::m_algebra.for_each4(
0124 pout , pin , ain , aout ,
0125 typename operations_type::template scale_sum3< value_type , time_type , time_type >( one , one_half * dt , one_half * dt ) );
0126 }
0127
0128
0129 template< class StateIn >
0130 void adjust_size( const StateIn & x )
0131 {
0132 if( resize_impl( x ) )
0133 m_first_call = true;
0134 }
0135
0136 void reset( void )
0137 {
0138 m_first_call = true;
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148 template< class AccelerationIn >
0149 void initialize( const AccelerationIn & ain )
0150 {
0151
0152 m_resizer.adjust_size( ain ,
0153 detail::bind( &velocity_verlet::template resize_impl< AccelerationIn > ,
0154 detail::ref( *this ) , detail::_1 ) );
0155 boost::numeric::odeint::copy( ain , get_current_acc() );
0156 m_first_call = false;
0157 }
0158
0159
0160 template< class System , class CoorIn , class VelocityIn >
0161 void initialize( System system , const CoorIn & qin , const VelocityIn & pin , time_type t )
0162 {
0163 m_resizer.adjust_size( qin ,
0164 detail::bind( &velocity_verlet::template resize_impl< CoorIn > ,
0165 detail::ref( *this ) , detail::_1 ) );
0166 initialize_acc( system , qin , pin , t );
0167 }
0168
0169 bool is_initialized( void ) const
0170 {
0171 return ! m_first_call;
0172 }
0173
0174
0175 private:
0176
0177 template< class System , class CoorIn , class VelocityIn >
0178 void initialize_acc( System system , const CoorIn & qin , const VelocityIn & pin , time_type t )
0179 {
0180 typename odeint::unwrap_reference< System >::type & sys = system;
0181 sys( qin , pin , get_current_acc() , t );
0182 m_first_call = false;
0183 }
0184
0185 template< class System , class StateInOut >
0186 void do_step_v1( System system , StateInOut & x , time_type t , time_type dt )
0187 {
0188 typedef typename odeint::unwrap_reference< StateInOut >::type state_in_type;
0189 typedef typename odeint::unwrap_reference< typename state_in_type::first_type >::type coor_in_type;
0190 typedef typename odeint::unwrap_reference< typename state_in_type::second_type >::type momentum_in_type;
0191
0192 typedef typename boost::remove_reference< coor_in_type >::type xyz_type;
0193 state_in_type & statein = x;
0194 coor_in_type & qinout = statein.first;
0195 momentum_in_type & pinout = statein.second;
0196
0197
0198 if( m_resizer.adjust_size( qinout ,
0199 detail::bind( &velocity_verlet::template resize_impl< xyz_type > ,
0200 detail::ref( *this ) , detail::_1 ) )
0201 || m_first_call )
0202 {
0203 initialize_acc( system , qinout , pinout , t );
0204 }
0205
0206
0207 do_step( system , qinout , pinout , get_current_acc() , qinout , pinout , get_old_acc() , t , dt );
0208 toggle_current_acc();
0209 }
0210
0211 template< class StateIn >
0212 bool resize_impl( const StateIn & x )
0213 {
0214 bool resized = false;
0215 resized |= adjust_size_by_resizeability( m_a1 , x , typename is_resizeable< acceleration_type >::type() );
0216 resized |= adjust_size_by_resizeability( m_a2 , x , typename is_resizeable< acceleration_type >::type() );
0217 return resized;
0218 }
0219
0220 acceleration_type & get_current_acc( void )
0221 {
0222 return m_current_a1 ? m_a1.m_v : m_a2.m_v ;
0223 }
0224
0225 const acceleration_type & get_current_acc( void ) const
0226 {
0227 return m_current_a1 ? m_a1.m_v : m_a2.m_v ;
0228 }
0229
0230 acceleration_type & get_old_acc( void )
0231 {
0232 return m_current_a1 ? m_a2.m_v : m_a1.m_v ;
0233 }
0234
0235 const acceleration_type & get_old_acc( void ) const
0236 {
0237 return m_current_a1 ? m_a2.m_v : m_a1.m_v ;
0238 }
0239
0240 void toggle_current_acc( void )
0241 {
0242 m_current_a1 = ! m_current_a1;
0243 }
0244
0245 resizer_type m_resizer;
0246 bool m_first_call;
0247 wrapped_acceleration_type m_a1 , m_a2;
0248 bool m_current_a1;
0249 };
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
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 #endif