1 /*
2   [auto_generated]
3   boost/numeric/odeint/stepper/velocity_verlet.hpp
4 
5   [begin_description]
6   tba.
7   [end_description]
8 
9   Copyright 2009-2012 Karsten Ahnert
10   Copyright 2009-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 #ifndef BOOST_NUMERIC_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED
19 #define BOOST_NUMERIC_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED
20 
21 #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp>
22 #include <boost/numeric/odeint/stepper/stepper_categories.hpp>
23 
24 #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
25 #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
26 #include <boost/numeric/odeint/util/resizer.hpp>
27 #include <boost/numeric/odeint/util/state_wrapper.hpp>
28 #include <boost/numeric/odeint/util/unwrap_reference.hpp>
29 
30 #include <boost/numeric/odeint/util/bind.hpp>
31 #include <boost/numeric/odeint/util/copy.hpp>
32 #include <boost/numeric/odeint/util/resizer.hpp>
33 // #include <boost/numeric/odeint/util/is_pair.hpp>
34 // #include <boost/array.hpp>
35 
36 
37 
38 namespace boost {
39 namespace numeric {
40 namespace odeint {
41 
42 
43 
44 template <
45     class Coor ,
46     class Velocity = Coor ,
47     class Value = double ,
48     class Acceleration = Coor ,
49     class Time = Value ,
50     class TimeSq = Time ,
51     class Algebra = typename algebra_dispatcher< Coor >::algebra_type ,
52     class Operations = typename operations_dispatcher< Coor >::operations_type ,
53     class Resizer = initially_resizer
54       >
55 class velocity_verlet : public algebra_stepper_base< Algebra , Operations >
56 {
57 public:
58 
59     typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type;
60     typedef typename algebra_stepper_base_type::algebra_type algebra_type;
61     typedef typename algebra_stepper_base_type::operations_type operations_type;
62 
63     typedef Coor coor_type;
64     typedef Velocity velocity_type;
65     typedef Acceleration acceleration_type;
66     typedef std::pair< coor_type , velocity_type > state_type;
67     typedef std::pair< velocity_type , acceleration_type > deriv_type;
68     typedef state_wrapper< acceleration_type > wrapped_acceleration_type;
69     typedef Value value_type;
70     typedef Time time_type;
71     typedef TimeSq time_square_type;
72     typedef Resizer resizer_type;
73     typedef stepper_tag stepper_category;
74 
75     typedef unsigned short order_type;
76 
77     static const order_type order_value = 1;
78 
79     /**
80      * \return Returns the order of the stepper.
81      */
order(void) const82     order_type order( void ) const
83     {
84         return order_value;
85     }
86 
87 
velocity_verlet(const algebra_type & algebra=algebra_type ())88     velocity_verlet( const algebra_type & algebra = algebra_type() )
89         : algebra_stepper_base_type( algebra ) , m_first_call( true )
90         , m_a1() , m_a2() , m_current_a1( true ) { }
91 
92 
93     template< class System , class StateInOut >
do_step(System system,StateInOut & x,time_type t,time_type dt)94     void do_step( System system , StateInOut & x , time_type t , time_type dt )
95     {
96         do_step_v1( system , x , t , dt );
97     }
98 
99 
100     template< class System , class StateInOut >
do_step(System system,const StateInOut & x,time_type t,time_type dt)101     void do_step( System system , const StateInOut & x , time_type t , time_type dt )
102     {
103         do_step_v1( system , x , t , dt );
104     }
105 
106 
107     template< class System , class CoorIn , class VelocityIn , class AccelerationIn ,
108                              class CoorOut , class VelocityOut , class AccelerationOut >
do_step(System system,CoorIn const & qin,VelocityIn const & pin,AccelerationIn const & ain,CoorOut & qout,VelocityOut & pout,AccelerationOut & aout,time_type t,time_type dt)109     void do_step( System system , CoorIn const & qin , VelocityIn const & pin , AccelerationIn const & ain ,
110                   CoorOut & qout , VelocityOut & pout , AccelerationOut & aout , time_type t , time_type dt )
111     {
112         const value_type one = static_cast< value_type >( 1.0 );
113         const value_type one_half = static_cast< value_type >( 0.5 );
114 
115         algebra_stepper_base_type::m_algebra.for_each4(
116             qout , qin , pin , ain ,
117             typename operations_type::template scale_sum3< value_type , time_type , time_square_type >( one , one * dt , one_half * dt * dt ) );
118 
119         typename odeint::unwrap_reference< System >::type & sys = system;
120 
121         sys( qout , pin , aout , t + dt );
122 
123         algebra_stepper_base_type::m_algebra.for_each4(
124             pout , pin , ain , aout ,
125             typename operations_type::template scale_sum3< value_type , time_type , time_type >( one , one_half * dt , one_half * dt ) );
126     }
127 
128 
129     template< class StateIn >
adjust_size(const StateIn & x)130     void adjust_size( const StateIn & x )
131     {
132         if( resize_impl( x ) )
133             m_first_call = true;
134     }
135 
reset(void)136     void reset( void )
137     {
138         m_first_call = true;
139     }
140 
141 
142     /**
143      * \fn velocity_verlet::initialize( const AccelerationIn &qin )
144      * \brief Initializes the internal state of the stepper.
145      * \param deriv The acceleration of x. The next call of `do_step` expects that the acceleration of `x` passed to `do_step`
146      *              has the value of `qin`.
147      */
148     template< class AccelerationIn >
initialize(const AccelerationIn & ain)149     void initialize( const AccelerationIn & ain )
150     {
151         // alloc a
152         m_resizer.adjust_size( ain ,
153                                detail::bind( &velocity_verlet::template resize_impl< AccelerationIn > ,
154                                              detail::ref( *this ) , detail::_1 ) );
155         boost::numeric::odeint::copy( ain , get_current_acc() );
156         m_first_call = false;
157     }
158 
159 
160     template< class System , class CoorIn , class VelocityIn >
initialize(System system,const CoorIn & qin,const VelocityIn & pin,time_type t)161     void initialize( System system , const CoorIn & qin , const VelocityIn & pin , time_type t )
162     {
163         m_resizer.adjust_size( qin ,
164                                detail::bind( &velocity_verlet::template resize_impl< CoorIn > ,
165                                              detail::ref( *this ) , detail::_1 ) );
166         initialize_acc( system , qin , pin , t );
167     }
168 
is_initialized(void) const169     bool is_initialized( void ) const
170     {
171         return ! m_first_call;
172     }
173 
174 
175 private:
176 
177     template< class System , class CoorIn , class VelocityIn >
initialize_acc(System system,const CoorIn & qin,const VelocityIn & pin,time_type t)178     void initialize_acc( System system , const CoorIn & qin , const VelocityIn & pin , time_type t )
179     {
180         typename odeint::unwrap_reference< System >::type & sys = system;
181         sys( qin , pin , get_current_acc() , t );
182         m_first_call = false;
183     }
184 
185     template< class System , class StateInOut >
do_step_v1(System system,StateInOut & x,time_type t,time_type dt)186     void do_step_v1( System system , StateInOut & x , time_type t , time_type dt )
187     {
188         typedef typename odeint::unwrap_reference< StateInOut >::type state_in_type;
189         typedef typename odeint::unwrap_reference< typename state_in_type::first_type >::type coor_in_type;
190         typedef typename odeint::unwrap_reference< typename state_in_type::second_type >::type momentum_in_type;
191 
192         typedef typename boost::remove_reference< coor_in_type >::type xyz_type;
193         state_in_type & statein = x;
194         coor_in_type & qinout = statein.first;
195         momentum_in_type & pinout = statein.second;
196 
197         // alloc a
198         if( m_resizer.adjust_size( qinout ,
199                                    detail::bind( &velocity_verlet::template resize_impl< xyz_type > ,
200                                                  detail::ref( *this ) , detail::_1 ) )
201          || m_first_call )
202         {
203             initialize_acc( system , qinout , pinout , t );
204         }
205 
206         // check first
207         do_step( system , qinout , pinout , get_current_acc() , qinout , pinout , get_old_acc() , t , dt );
208         toggle_current_acc();
209     }
210 
211     template< class StateIn >
resize_impl(const StateIn & x)212     bool resize_impl( const StateIn & x )
213     {
214         bool resized = false;
215         resized |= adjust_size_by_resizeability( m_a1 , x , typename is_resizeable< acceleration_type >::type() );
216         resized |= adjust_size_by_resizeability( m_a2 , x , typename is_resizeable< acceleration_type >::type() );
217         return resized;
218     }
219 
get_current_acc(void)220     acceleration_type & get_current_acc( void )
221     {
222         return m_current_a1 ? m_a1.m_v : m_a2.m_v ;
223     }
224 
get_current_acc(void) const225     const acceleration_type & get_current_acc( void ) const
226     {
227         return m_current_a1 ? m_a1.m_v : m_a2.m_v ;
228     }
229 
get_old_acc(void)230     acceleration_type & get_old_acc( void )
231     {
232         return m_current_a1 ? m_a2.m_v : m_a1.m_v ;
233     }
234 
get_old_acc(void) const235     const acceleration_type & get_old_acc( void ) const
236     {
237         return m_current_a1 ? m_a2.m_v : m_a1.m_v ;
238     }
239 
toggle_current_acc(void)240     void toggle_current_acc( void )
241     {
242         m_current_a1 = ! m_current_a1;
243     }
244 
245     resizer_type m_resizer;
246     bool m_first_call;
247     wrapped_acceleration_type m_a1 , m_a2;
248     bool m_current_a1;
249 };
250 
251 /**
252  * \class velocity_verlet
253  * \brief The Velocity-Verlet algorithm.
254  *
255  * <a href="http://en.wikipedia.org/wiki/Verlet_integration" >The Velocity-Verlet algorithm</a> is a method for simulation of molecular dynamics systems. It solves the ODE
256  * a=f(r,v',t)  where r are the coordinates, v are the velocities and a are the accelerations, hence v = dr/dt, a=dv/dt.
257  *
258  * \tparam Coor The type representing the coordinates.
259  * \tparam Velocity The type representing the velocities.
260  * \tparam Value The type value type.
261  * \tparam Acceleration The type representing the acceleration.
262  * \tparam Time The time representing the independent variable - the time.
263  * \tparam TimeSq The time representing the square of the time.
264  * \tparam Algebra The algebra.
265  * \tparam Operations The operations type.
266  * \tparam Resizer The resizer policy type.
267  */
268 
269 
270     /**
271      * \fn velocity_verlet::velocity_verlet( const algebra_type &algebra )
272      * \brief Constructs the velocity_verlet class. This constructor can be used as a default
273      * constructor if the algebra has a default constructor.
274      * \param algebra A copy of algebra is made and stored.
275      */
276 
277 
278     /**
279      * \fn velocity_verlet::do_step( System system , StateInOut &x , time_type t , time_type dt )
280      * \brief This method performs one step. It transforms the result in-place.
281      *
282      * It can be used like
283      * \code
284      * pair< coordinates , velocities > state;
285      * stepper.do_step( sys , x , t , dt );
286      * \endcode
287      *
288      * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the
289      *               Second Order System concept.
290      * \param x The state of the ODE which should be solved. The state is pair of Coor and Velocity.
291      * \param t The value of the time, at which the step should be performed.
292      * \param dt The step size.
293      */
294 
295     /**
296      * \fn velocity_verlet::do_step( System system , const StateInOut &x , time_type t , time_type dt )
297      * \brief This method performs one step. It transforms the result in-place.
298      *
299      * It can be used like
300      * \code
301      * pair< coordinates , velocities > state;
302      * stepper.do_step( sys , x , t , dt );
303      * \endcode
304      *
305      * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the
306      *               Second Order System concept.
307      * \param x The state of the ODE which should be solved. The state is pair of Coor and Velocity.
308      * \param t The value of the time, at which the step should be performed.
309      * \param dt The step size.
310      */
311 
312 
313 
314     /**
315      * \fn velocity_verlet::do_step( System system , CoorIn const & qin , VelocityIn const & pin , AccelerationIn const & ain , CoorOut & qout , VelocityOut & pout , AccelerationOut & aout , time_type t , time_type dt )
316      * \brief This method performs one step. It transforms the result in-place. Additionally to the other methods
317      * the coordinates, velocities and accelerations are passed directly to do_step and they are transformed out-of-place.
318      *
319      * It can be used like
320      * \code
321      * coordinates qin , qout;
322      * velocities pin , pout;
323      * accelerations ain, aout;
324      * stepper.do_step( sys , qin , pin , ain , qout , pout , aout , t , dt );
325      * \endcode
326      *
327      * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the
328      *               Second Order System concept.
329      * \param x The state of the ODE which should be solved. The state is pair of Coor and Velocity.
330      * \param t The value of the time, at which the step should be performed.
331      * \param dt The step size.
332      */
333 
334 
335     /**
336      * \fn void velocity_verlet::adjust_size( const StateIn &x )
337      * \brief Adjust the size of all temporaries in the stepper manually.
338      * \param x A state from which the size of the temporaries to be resized is deduced.
339      */
340 
341 
342     /**
343      * \fn velocity_verlet::reset( void )
344      * \brief Resets the internal state of this stepper. After calling this method it is safe to use all
345      * `do_step` method without explicitly initializing the stepper.
346      */
347 
348 
349 
350     /**
351      * \fn velocity_verlet::initialize( System system , const CoorIn &qin , const VelocityIn &pin , time_type t )
352      * \brief Initializes the internal state of the stepper.
353      *
354      * This method is equivalent to
355      * \code
356      * Acceleration a;
357      * system( qin , pin , a , t );
358      * stepper.initialize( a );
359      * \endcode
360      *
361      * \param system The system function for the next calls of `do_step`.
362      * \param qin The current coordinates of the ODE.
363      * \param pin The current velocities of the ODE.
364      * \param t The current time of the ODE.
365      */
366 
367 
368     /**
369      * \fn velocity_verlet::is_initialized()
370      * \returns Returns if the stepper is initialized.
371     */
372 
373 
374 
375 
376 } // namespace odeint
377 } // namespace numeric
378 } // namespace boost
379 
380 
381 #endif // BOOST_NUMERIC_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED
382