Chris@16: /* Chris@16: [auto_generated] Chris@16: boost/numeric/odeint/stepper/adams_bashforth.hpp Chris@16: Chris@16: [begin_description] Chris@16: Implementaton of the Adam-Bashforth method a multistep method used for the predictor step in the Chris@16: Adams-Bashforth-Moulton method. Chris@16: [end_description] Chris@16: Chris@101: Copyright 2011-2013 Karsten Ahnert Chris@101: Copyright 2011-2013 Mario Mulansky Chris@101: Copyright 2012 Christoph Koke Chris@101: Copyright 2013 Pascal Germroth Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. Chris@16: (See accompanying file LICENSE_1_0.txt or Chris@16: copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: */ Chris@16: Chris@16: Chris@16: #ifndef BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_BASHFORTH_HPP_INCLUDED Chris@16: #define BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_BASHFORTH_HPP_INCLUDED Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@101: #include Chris@101: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: Chris@101: namespace mpl = boost::mpl; Chris@16: Chris@16: Chris@16: namespace boost { Chris@16: namespace numeric { Chris@16: namespace odeint { Chris@16: Chris@101: using mpl::int_; Chris@101: Chris@101: /* if N >= 4, returns the smallest even number > N, otherwise returns 4 */ Chris@101: template < int N > Chris@101: struct order_helper Chris@101: : mpl::max< typename mpl::eval_if< Chris@101: mpl::equal_to< mpl::modulus< int_< N >, int_< 2 > >, Chris@101: int_< 0 > >, Chris@101: int_< N >, int_< N + 1 > >::type, Chris@101: int_< 4 > >::type Chris@101: { }; Chris@16: Chris@16: template< Chris@16: size_t Steps , Chris@16: class State , Chris@16: class Value = double , Chris@16: class Deriv = State , Chris@16: class Time = Value , Chris@101: class Algebra = typename algebra_dispatcher< State >::algebra_type , Chris@101: class Operations = typename operations_dispatcher< State >::operations_type , Chris@16: class Resizer = initially_resizer , Chris@101: class InitializingStepper = extrapolation_stepper< order_helper::value, Chris@101: State, Value, Deriv, Time, Chris@101: Algebra, Operations, Resizer > Chris@16: > Chris@16: class adams_bashforth : public algebra_stepper_base< Algebra , Operations > Chris@16: { Chris@16: Chris@16: #ifndef DOXYGEN_SKIP Chris@16: BOOST_STATIC_ASSERT(( Steps > 0 )); Chris@16: BOOST_STATIC_ASSERT(( Steps < 9 )); Chris@16: #endif Chris@16: Chris@16: public : Chris@16: Chris@16: typedef State state_type; Chris@16: typedef state_wrapper< state_type > wrapped_state_type; Chris@16: typedef Value value_type; Chris@16: typedef Deriv deriv_type; Chris@16: typedef state_wrapper< deriv_type > wrapped_deriv_type; Chris@16: typedef Time time_type; Chris@16: typedef Resizer resizer_type; Chris@16: typedef stepper_tag stepper_category; Chris@16: Chris@16: typedef InitializingStepper initializing_stepper_type; Chris@16: Chris@101: typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; Chris@101: typedef typename algebra_stepper_base_type::algebra_type algebra_type; Chris@101: typedef typename algebra_stepper_base_type::operations_type operations_type; Chris@16: #ifndef DOXYGEN_SKIP Chris@16: typedef adams_bashforth< Steps , State , Value , Deriv , Time , Algebra , Operations , Resizer , InitializingStepper > stepper_type; Chris@16: #endif Chris@16: static const size_t steps = Steps; Chris@16: Chris@16: Chris@16: Chris@16: typedef unsigned short order_type; Chris@16: static const order_type order_value = steps; Chris@16: Chris@16: typedef detail::rotating_buffer< wrapped_deriv_type , steps > step_storage_type; Chris@16: Chris@16: Chris@16: Chris@16: order_type order( void ) const { return order_value; } Chris@16: Chris@16: adams_bashforth( const algebra_type &algebra = algebra_type() ) Chris@101: : algebra_stepper_base_type( algebra ) , Chris@101: m_step_storage() , m_resizer() , m_coefficients() , Chris@101: m_steps_initialized( 0 ) , m_initializing_stepper() Chris@16: { } Chris@16: Chris@16: Chris@16: Chris@16: /* Chris@16: * Version 1 : do_step( system , x , t , dt ); Chris@16: * Chris@16: * solves the forwarding problem Chris@16: */ Chris@16: template< class System , class StateInOut > Chris@16: void do_step( System system , StateInOut &x , time_type t , time_type dt ) Chris@16: { Chris@16: do_step( system , x , t , x , dt ); Chris@16: } Chris@16: Chris@16: /** Chris@16: * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. Chris@16: */ Chris@16: template< class System , class StateInOut > Chris@16: void do_step( System system , const StateInOut &x , time_type t , time_type dt ) Chris@16: { Chris@16: do_step( system , x , t , x , dt ); Chris@16: } Chris@16: Chris@16: Chris@16: Chris@16: /* Chris@16: * Version 2 : do_step( system , in , t , out , dt ); Chris@16: * Chris@16: * solves the forwarding problem Chris@16: */ Chris@16: Chris@16: template< class System , class StateIn , class StateOut > Chris@16: void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) Chris@16: { Chris@16: do_step_impl( system , in , t , out , dt ); Chris@16: } Chris@16: Chris@16: /** Chris@16: * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateOut. Chris@16: */ Chris@16: template< class System , class StateIn , class StateOut > Chris@16: void do_step( System system , const StateIn &in , time_type t , const StateOut &out , time_type dt ) Chris@16: { Chris@16: do_step_impl( system , in , t , out , dt ); Chris@16: } Chris@16: Chris@16: Chris@16: template< class StateType > Chris@16: void adjust_size( const StateType &x ) Chris@16: { Chris@16: resize_impl( x ); Chris@16: } Chris@16: Chris@16: const step_storage_type& step_storage( void ) const Chris@16: { Chris@16: return m_step_storage; Chris@16: } Chris@16: Chris@16: step_storage_type& step_storage( void ) Chris@16: { Chris@16: return m_step_storage; Chris@16: } Chris@16: Chris@16: template< class ExplicitStepper , class System , class StateIn > Chris@16: void initialize( ExplicitStepper explicit_stepper , System system , StateIn &x , time_type &t , time_type dt ) Chris@16: { Chris@16: typename odeint::unwrap_reference< ExplicitStepper >::type &stepper = explicit_stepper; Chris@16: typename odeint::unwrap_reference< System >::type &sys = system; Chris@16: Chris@16: m_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_impl , detail::ref( *this ) , detail::_1 ) ); Chris@16: Chris@101: for( size_t i=0 ; i+1 Chris@16: void initialize( System system , StateIn &x , time_type &t , time_type dt ) Chris@16: { Chris@16: initialize( detail::ref( m_initializing_stepper ) , system , x , t , dt ); Chris@16: } Chris@16: Chris@16: void reset( void ) Chris@16: { Chris@16: m_steps_initialized = 0; Chris@16: } Chris@16: Chris@16: bool is_initialized( void ) const Chris@16: { Chris@101: return m_steps_initialized >= ( steps - 1 ); Chris@16: } Chris@16: Chris@16: const initializing_stepper_type& initializing_stepper( void ) const { return m_initializing_stepper; } Chris@16: Chris@16: initializing_stepper_type& initializing_stepper( void ) { return m_initializing_stepper; } Chris@16: Chris@16: private: Chris@16: Chris@16: template< class System , class StateIn , class StateOut > Chris@16: void do_step_impl( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) Chris@16: { Chris@16: typename odeint::unwrap_reference< System >::type &sys = system; Chris@16: if( m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl , detail::ref( *this ) , detail::_1 ) ) ) Chris@16: { Chris@16: m_steps_initialized = 0; Chris@16: } Chris@16: Chris@101: if( m_steps_initialized + 1 < steps ) Chris@16: { Chris@16: if( m_steps_initialized != 0 ) m_step_storage.rotate(); Chris@16: sys( in , m_step_storage[0].m_v , t ); Chris@101: m_initializing_stepper.do_step_dxdt_impl( Chris@101: system, in, m_step_storage[0].m_v, t, out, dt ); Chris@101: ++m_steps_initialized; Chris@16: } Chris@16: else Chris@16: { Chris@16: m_step_storage.rotate(); Chris@16: sys( in , m_step_storage[0].m_v , t ); Chris@101: detail::adams_bashforth_call_algebra< steps , algebra_type , operations_type >()( this->m_algebra , in , out , m_step_storage , m_coefficients , dt ); Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: template< class StateIn > Chris@16: bool resize_impl( const StateIn &x ) Chris@16: { Chris@16: bool resized( false ); Chris@16: for( size_t i=0 ; i::type() ); Chris@16: } Chris@16: return resized; Chris@16: } Chris@16: Chris@16: step_storage_type m_step_storage; Chris@16: resizer_type m_resizer; Chris@101: detail::adams_bashforth_coefficients< value_type , steps > m_coefficients; Chris@16: size_t m_steps_initialized; Chris@16: initializing_stepper_type m_initializing_stepper; Chris@16: Chris@16: }; Chris@16: Chris@16: Chris@16: /***** DOXYGEN *****/ Chris@16: Chris@16: /** Chris@16: * \class adams_bashforth Chris@16: * \brief The Adams-Bashforth multistep algorithm. Chris@16: * Chris@16: * The Adams-Bashforth method is a multi-step algorithm with configurable step Chris@16: * number. The step number is specified as template parameter Steps and it Chris@16: * then uses the result from the previous Steps steps. See also Chris@16: * en.wikipedia.org/wiki/Linear_multistep_method. Chris@16: * Currently, a maximum of Steps=8 is supported. Chris@16: * The method is explicit and fulfills the Stepper concept. Step size control Chris@16: * or continuous output are not provided. Chris@16: * Chris@16: * This class derives from algebra_base and inherits its interface via Chris@16: * CRTP (current recurring template pattern). For more details see Chris@16: * algebra_stepper_base. Chris@16: * Chris@16: * \tparam Steps The number of steps (maximal 8). Chris@16: * \tparam State The state type. Chris@16: * \tparam Value The value type. Chris@16: * \tparam Deriv The type representing the time derivative of the state. Chris@16: * \tparam Time The time representing the independent variable - the time. Chris@16: * \tparam Algebra The algebra type. Chris@16: * \tparam Operations The operations type. Chris@16: * \tparam Resizer The resizer policy type. Chris@16: * \tparam InitializingStepper The stepper for the first two steps. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn adams_bashforth::adams_bashforth( const algebra_type &algebra ) Chris@16: * \brief Constructs the adams_bashforth class. This constructor can be used as a default Chris@16: * constructor if the algebra has a default constructor. Chris@16: * \param algebra A copy of algebra is made and stored. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn order_type adams_bashforth::order( void ) const Chris@16: * \brief Returns the order of the algorithm, which is equal to the number of steps. Chris@16: * \return order of the method. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn void adams_bashforth::do_step( System system , StateInOut &x , time_type t , time_type dt ) Chris@16: * \brief This method performs one step. It transforms the result in-place. Chris@16: * Chris@16: * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the Chris@16: * Simple System concept. Chris@16: * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. Chris@16: * \param t The value of the time, at which the step should be performed. Chris@16: * \param dt The step size. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn void adams_bashforth::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) Chris@16: * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. Chris@16: * Chris@16: * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the Chris@16: * Simple System concept. Chris@16: * \param in The state of the ODE which should be solved. in is not modified in this method Chris@16: * \param t The value of the time, at which the step should be performed. Chris@16: * \param out The result of the step is written in out. Chris@16: * \param dt The step size. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn void adams_bashforth::adjust_size( const StateType &x ) Chris@16: * \brief Adjust the size of all temporaries in the stepper manually. Chris@16: * \param x A state from which the size of the temporaries to be resized is deduced. Chris@16: */ Chris@16: Chris@16: Chris@16: /** Chris@16: * \fn const step_storage_type& adams_bashforth::step_storage( void ) const Chris@16: * \brief Returns the storage of intermediate results. Chris@16: * \return The storage of intermediate results. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn step_storage_type& adams_bashforth::step_storage( void ) Chris@16: * \brief Returns the storage of intermediate results. Chris@16: * \return The storage of intermediate results. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn void adams_bashforth::initialize( ExplicitStepper explicit_stepper , System system , StateIn &x , time_type &t , time_type dt ) Chris@16: * \brief Initialized the stepper. Does Steps-1 steps with the explicit_stepper to fill the buffer. Chris@16: * \param explicit_stepper the stepper used to fill the buffer of previous step results Chris@16: * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the Chris@16: * Simple System concept. Chris@16: * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. Chris@16: * \param t The value of the time, at which the step should be performed. Chris@16: * \param dt The step size. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn void adams_bashforth::initialize( System system , StateIn &x , time_type &t , time_type dt ) Chris@16: * \brief Initialized the stepper. Does Steps-1 steps with an internal instance of InitializingStepper to fill the buffer. Chris@16: * \note The state x and time t are updated to the values after Steps-1 initial steps. Chris@16: * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the Chris@16: * Simple System concept. Chris@16: * \param x The initial state of the ODE which should be solved, updated in this method. Chris@16: * \param t The initial value of the time, updated in this method. Chris@16: * \param dt The step size. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn void adams_bashforth::reset( void ) Chris@16: * \brief Resets the internal buffer of the stepper. Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn bool adams_bashforth::is_initialized( void ) const Chris@16: * \brief Returns true if the stepper has been initialized. Chris@16: * \return bool true if stepper is initialized, false otherwise Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn const initializing_stepper_type& adams_bashforth::initializing_stepper( void ) const Chris@16: * \brief Returns the internal initializing stepper instance. Chris@16: * \return initializing_stepper Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn const initializing_stepper_type& adams_bashforth::initializing_stepper( void ) const Chris@16: * \brief Returns the internal initializing stepper instance. Chris@16: * \return initializing_stepper Chris@16: */ Chris@16: Chris@16: /** Chris@16: * \fn initializing_stepper_type& adams_bashforth::initializing_stepper( void ) Chris@16: * \brief Returns the internal initializing stepper instance. Chris@16: * \return initializing_stepper Chris@16: */ Chris@16: Chris@16: } // odeint Chris@16: } // numeric Chris@16: } // boost Chris@16: Chris@16: Chris@16: Chris@16: #endif // BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_BASHFORTH_HPP_INCLUDED