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