1 /*
2  [auto_generated]
3  boost/numeric/odeint/stepper/modified_midpoint.hpp
4 
5  [begin_description]
6  Modified midpoint method for the use in Burlish-Stoer stepper.
7  [end_description]
8 
9  Copyright 2011-2013 Mario Mulansky
10  Copyright 2011-2013 Karsten Ahnert
11  Copyright 2012 Christoph Koke
12 
13  Distributed under the Boost Software License, Version 1.0.
14  (See accompanying file LICENSE_1_0.txt or
15  copy at http://www.boost.org/LICENSE_1_0.txt)
16  */
17 
18 
19 #ifndef BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED
20 #define BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED
21 
22 #include <vector>
23 
24 #include <boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp>
25 #include <boost/numeric/odeint/util/resizer.hpp>
26 #include <boost/numeric/odeint/util/is_resizeable.hpp>
27 #include <boost/numeric/odeint/algebra/range_algebra.hpp>
28 #include <boost/numeric/odeint/algebra/default_operations.hpp>
29 #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
30 #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
31 #include <boost/numeric/odeint/util/copy.hpp>
32 
33 namespace boost {
34 namespace numeric {
35 namespace odeint {
36 
37 template<
38 class State ,
39 class Value = double ,
40 class Deriv = State ,
41 class Time = Value ,
42 class Algebra = typename algebra_dispatcher< State >::algebra_type ,
43 class Operations = typename operations_dispatcher< State >::operations_type ,
44 class Resizer = initially_resizer
45 >
46 #ifndef DOXYGEN_SKIP
47 class modified_midpoint
48 : public explicit_stepper_base<
49   modified_midpoint< State , Value , Deriv , Time , Algebra , Operations , Resizer > ,
50   2 , State , Value , Deriv , Time , Algebra , Operations , Resizer >
51 #else
52 class modified_midpoint : public explicit_stepper_base
53 #endif
54 {
55 
56 public :
57 
58     typedef explicit_stepper_base<
59     modified_midpoint< State , Value , Deriv , Time , Algebra , Operations , Resizer > ,
60     2 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type;
61 
62     typedef typename stepper_base_type::state_type state_type;
63     typedef typename stepper_base_type::wrapped_state_type wrapped_state_type;
64     typedef typename stepper_base_type::value_type value_type;
65     typedef typename stepper_base_type::deriv_type deriv_type;
66     typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type;
67     typedef typename stepper_base_type::time_type time_type;
68     typedef typename stepper_base_type::algebra_type algebra_type;
69     typedef typename stepper_base_type::operations_type operations_type;
70     typedef typename stepper_base_type::resizer_type resizer_type;
71     typedef typename stepper_base_type::stepper_type stepper_type;
72 
73 
modified_midpoint(unsigned short steps=2,const algebra_type & algebra=algebra_type ())74     modified_midpoint( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() )
75     : stepper_base_type( algebra ) , m_steps( steps )
76     { }
77 
78     template< class System , class StateIn , class DerivIn , class StateOut >
do_step_impl(System system,const StateIn & in,const DerivIn & dxdt,time_type t,StateOut & out,time_type dt)79     void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt )
80     {
81         static const value_type val1 = static_cast< value_type >( 1 );
82         static const value_type val05 = static_cast< value_type >( 1 ) / static_cast< value_type >( 2 );
83 
84         m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) );
85 
86         const time_type h = dt /  static_cast<value_type>( m_steps );
87         const time_type h2 = static_cast<value_type>(2) * h;
88 
89         typename odeint::unwrap_reference< System >::type &sys = system;
90 
91         time_type th = t + h;
92 
93         // m_x1 = x + h*dxdt
94         stepper_base_type::m_algebra.for_each3( m_x1.m_v , in , dxdt ,
95                 typename operations_type::template scale_sum2< value_type , time_type >( val1 , h ) );
96 
97         sys( m_x1.m_v , m_dxdt.m_v , th );
98 
99         boost::numeric::odeint::copy( in , m_x0.m_v );
100 
101         unsigned short i = 1;
102         while( i != m_steps )
103         {
104             // general step
105             //tmp = m_x1; m_x1 = m_x0 + h2*m_dxdt; m_x0 = tmp
106             stepper_base_type::m_algebra.for_each3( m_x1.m_v , m_x0.m_v , m_dxdt.m_v ,
107                     typename operations_type::template scale_sum_swap2< value_type , time_type >( val1 , h2 ) );
108             th += h;
109             sys( m_x1.m_v , m_dxdt.m_v , th);
110             i++;
111         }
112 
113         // last step
114         // x = 0.5*( m_x0 + m_x1 + h*m_dxdt )
115         stepper_base_type::m_algebra.for_each4( out , m_x0.m_v , m_x1.m_v , m_dxdt.m_v ,
116                 typename operations_type::template scale_sum3< value_type , value_type , time_type >( val05 , val05 , val05*h ) );
117     }
118 
119 
set_steps(unsigned short steps)120     void set_steps( unsigned short steps )
121     {   m_steps = steps; }
122 
123 
steps(void) const124     unsigned short steps( void ) const
125     {   return m_steps; }
126 
127 
128     template< class StateIn >
adjust_size(const StateIn & x)129     void adjust_size( const StateIn &x )
130     {
131         resize_impl( x );
132         stepper_base_type::adjust_size( x );
133     }
134 
135 private:
136 
137     template< class StateIn >
resize_impl(const StateIn & x)138     bool resize_impl( const StateIn &x )
139     {
140         bool resized( false );
141         resized |= adjust_size_by_resizeability( m_x0 , x , typename is_resizeable<state_type>::type() );
142         resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() );
143         resized |= adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() );
144         return resized;
145     }
146 
147 
148     unsigned short m_steps;
149 
150     resizer_type m_resizer;
151 
152     wrapped_state_type m_x0;
153     wrapped_state_type m_x1;
154     wrapped_deriv_type m_dxdt;
155 
156 };
157 
158 
159 /* Modified midpoint which stores derivatives and state at dt/2 in some external storage for later usage in dense output calculation
160  * This Stepper is for use in Bulirsch Stoer only. It DOES NOT meet any stepper concept.
161  */
162 template<
163 class State ,
164 class Value = double ,
165 class Deriv = State ,
166 class Time = Value ,
167 class Algebra = typename algebra_dispatcher< State >::algebra_type ,
168 class Operations = typename operations_dispatcher< State >::operations_type ,
169 class Resizer = initially_resizer
170 >
171 class modified_midpoint_dense_out
172 {
173 
174 public :
175 
176     typedef State state_type;
177     typedef Value value_type;
178     typedef Deriv deriv_type;
179     typedef Time time_type;
180     typedef Algebra algebra_type;
181     typedef Operations operations_type;
182     typedef Resizer resizer_type;
183     typedef state_wrapper< state_type > wrapped_state_type;
184     typedef state_wrapper< deriv_type > wrapped_deriv_type;
185 
186     typedef modified_midpoint_dense_out< State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_type;
187     typedef std::vector< wrapped_deriv_type > deriv_table_type;
188 
modified_midpoint_dense_out(unsigned short steps=2,const algebra_type & algebra=algebra_type ())189     modified_midpoint_dense_out( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() )
190     : m_algebra( algebra ) , m_steps( steps )
191     { }
192 
193     /*
194      * performs a modified midpoint step with m_steps intermediate points
195      * stores approximation for x(t+dt/2) in x_mp and all evaluated function results in derivs
196      *
197      */
198 
199     template< class System , class StateIn , class DerivIn , class StateOut >
do_step(System system,const StateIn & in,const DerivIn & dxdt,time_type t,StateOut & out,time_type dt,state_type & x_mp,deriv_table_type & derivs)200     void do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ,
201             state_type &x_mp , deriv_table_type &derivs )
202     {
203 
204         static const value_type val1 = static_cast< value_type >( 1 );
205         static const value_type val05 = static_cast< value_type >( 1 ) / static_cast< value_type >( 2 );
206 
207         m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize< StateIn > , detail::ref( *this ) , detail::_1 ) );
208 
209         const time_type h = dt / static_cast<value_type>( m_steps );
210         const time_type h2 = static_cast<value_type>( 2 ) * h;
211 
212         typename odeint::unwrap_reference< System >::type &sys = system;
213 
214         time_type th = t + h;
215 
216         // m_x1 = x + h*dxdt
217         m_algebra.for_each3( m_x1.m_v , in , dxdt ,
218                 typename operations_type::template scale_sum2< value_type , time_type >( val1 , h ) );
219 
220         if( m_steps == 2 )
221             // result of first step already gives approximation at the center of the interval
222             boost::numeric::odeint::copy( m_x1.m_v , x_mp );
223 
224         sys( m_x1.m_v , derivs[0].m_v , th );
225 
226         boost::numeric::odeint::copy( in , m_x0.m_v );
227 
228         unsigned short i = 1;
229         while( i != m_steps )
230         {
231             // general step
232             //tmp = m_x1; m_x1 = m_x0 + h2*m_dxdt; m_x0 = tmp
233             m_algebra.for_each3( m_x1.m_v , m_x0.m_v , derivs[i-1].m_v ,
234                     typename operations_type::template scale_sum_swap2< value_type , time_type >( val1 , h2 ) );
235             if( i == m_steps/2-1 )
236                 // save approximation at the center of the interval
237                 boost::numeric::odeint::copy( m_x1.m_v , x_mp );
238 
239             th += h;
240             sys( m_x1.m_v , derivs[i].m_v , th);
241             i++;
242         }
243 
244         // last step
245         // x = 0.5*( m_x0 + m_x1 + h*m_dxdt )
246         m_algebra.for_each4( out , m_x0.m_v , m_x1.m_v , derivs[m_steps-1].m_v ,
247                 typename operations_type::template scale_sum3< value_type , value_type , time_type >( val05 , val05 , val05*h ) );
248     }
249 
250 
set_steps(unsigned short steps)251     void set_steps( unsigned short steps )
252     {   m_steps = steps; }
253 
254 
steps(void) const255     unsigned short steps( void ) const
256     {   return m_steps; }
257 
258 
259     template< class StateIn >
resize(const StateIn & x)260     bool resize( const StateIn &x )
261     {
262         bool resized( false );
263         resized |= adjust_size_by_resizeability( m_x0 , x , typename is_resizeable<state_type>::type() );
264         resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() );
265         return resized;
266     }
267 
268     template< class StateIn >
adjust_size(const StateIn & x)269     void adjust_size( const StateIn &x )
270     {
271         resize( x );
272     }
273 
274 private:
275 
276     algebra_type m_algebra;
277 
278     unsigned short m_steps;
279 
280     resizer_type m_resizer;
281 
282     wrapped_state_type m_x0;
283     wrapped_state_type m_x1;
284 
285 };
286 
287 
288 
289 /********** DOXYGEN ***********/
290 
291 /**
292  * \class modified_midpoint
293  *
294  * Implementation of the modified midpoint method with a configurable
295  * number of intermediate steps. This class is used by the Bulirsch-Stoer
296  * algorithm and is not meant for direct usage.
297  */
298 
299 
300 /**
301  * \class modified_midpoint_dense_out
302  *
303  * Implementation of the modified midpoint method with a configurable
304  * number of intermediate steps. This class is used by the dense output
305  * Bulirsch-Stoer algorithm and is not meant for direct usage.
306  * \note This stepper is for internal use only and does not meet
307  * any stepper concept.
308  */
309 
310 
311 }
312 }
313 }
314 
315 #endif // BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED
316