3 boost/numeric/odeint/stepper/modified_midpoint.hpp
6 Modified midpoint method for the use in Burlish-Stoer stepper.
9 Copyright 2011-2013 Mario Mulansky
10 Copyright 2011-2013 Karsten Ahnert
11 Copyright 2012 Christoph Koke
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)
19 #ifndef BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED
20 #define BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED
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>
39 class Value = double ,
42 class Algebra = typename algebra_dispatcher< State >::algebra_type ,
43 class Operations = typename operations_dispatcher< State >::operations_type ,
44 class Resizer = initially_resizer
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 >
52 class modified_midpoint : public explicit_stepper_base
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;
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;
74 modified_midpoint( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() )
75 : stepper_base_type( algebra ) , m_steps( steps )
78 template< class System , class StateIn , class DerivIn , class StateOut >
79 void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt )
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 );
84 m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) );
86 const time_type h = dt / static_cast<value_type>( m_steps );
87 const time_type h2 = static_cast<value_type>(2) * h;
89 typename odeint::unwrap_reference< System >::type &sys = system;
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 ) );
97 sys( m_x1.m_v , m_dxdt.m_v , th );
99 boost::numeric::odeint::copy( in , m_x0.m_v );
101 unsigned short i = 1;
102 while( i != m_steps )
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 ) );
109 sys( m_x1.m_v , m_dxdt.m_v , th);
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 ) );
120 void set_steps( unsigned short steps )
124 unsigned short steps( void ) const
128 template< class StateIn >
129 void adjust_size( const StateIn &x )
132 stepper_base_type::adjust_size( x );
137 template< class StateIn >
138 bool resize_impl( const StateIn &x )
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() );
148 unsigned short m_steps;
150 resizer_type m_resizer;
152 wrapped_state_type m_x0;
153 wrapped_state_type m_x1;
154 wrapped_deriv_type m_dxdt;
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.
164 class Value = double ,
165 class Deriv = State ,
167 class Algebra = typename algebra_dispatcher< State >::algebra_type ,
168 class Operations = typename operations_dispatcher< State >::operations_type ,
169 class Resizer = initially_resizer
171 class modified_midpoint_dense_out
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;
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;
189 modified_midpoint_dense_out( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() )
190 : m_algebra( algebra ) , m_steps( steps )
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
199 template< class System , class StateIn , class DerivIn , class StateOut >
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 )
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 );
207 m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize< StateIn > , detail::ref( *this ) , detail::_1 ) );
209 const time_type h = dt / static_cast<value_type>( m_steps );
210 const time_type h2 = static_cast<value_type>( 2 ) * h;
212 typename odeint::unwrap_reference< System >::type &sys = system;
214 time_type th = t + h;
217 m_algebra.for_each3( m_x1.m_v , in , dxdt ,
218 typename operations_type::template scale_sum2< value_type , time_type >( val1 , h ) );
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 );
224 sys( m_x1.m_v , derivs[0].m_v , th );
226 boost::numeric::odeint::copy( in , m_x0.m_v );
228 unsigned short i = 1;
229 while( i != m_steps )
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 );
240 sys( m_x1.m_v , derivs[i].m_v , th);
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 ) );
251 void set_steps( unsigned short steps )
255 unsigned short steps( void ) const
259 template< class StateIn >
260 bool resize( const StateIn &x )
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() );
268 template< class StateIn >
269 void adjust_size( const StateIn &x )
276 algebra_type m_algebra;
278 unsigned short m_steps;
280 resizer_type m_resizer;
282 wrapped_state_type m_x0;
283 wrapped_state_type m_x1;
289 /********** DOXYGEN ***********/
292 * \class modified_midpoint
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.
301 * \class modified_midpoint_dense_out
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.
315 #endif // BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED