adaptive_iterator_impl.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. [auto_generated]
  3. boost/numeric/odeint/iterator/detail/adaptive_iterator_impl.hpp
  4. [begin_description]
  5. tba.
  6. [end_description]
  7. Copyright 2009-2012 Karsten Ahnert
  8. Copyright 2009-2012 Mario Mulansky
  9. Distributed under the Boost Software License, Version 1.0.
  10. (See accompanying file LICENSE_1_0.txt or
  11. copy at http://www.boost.org/LICENSE_1_0.txt)
  12. */
  13. #ifndef BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED
  14. #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED
  15. #include <boost/utility/enable_if.hpp>
  16. #include <boost/type_traits/is_same.hpp>
  17. #include <boost/throw_exception.hpp>
  18. #include <boost/numeric/odeint/util/unit_helper.hpp>
  19. #include <boost/numeric/odeint/util/copy.hpp>
  20. #include <boost/numeric/odeint/stepper/controlled_step_result.hpp>
  21. #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp>
  22. namespace boost {
  23. namespace numeric {
  24. namespace odeint {
  25. template< class Iterator , class Stepper , class System , class State , typename Tag , typename StepperTag >
  26. class adaptive_iterator_impl;
  27. /*
  28. * Specilization for controlled steppers
  29. */
  30. /**
  31. * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper.
  32. *
  33. * Implements an ODE iterator with adaptive step size control. Uses controlled steppers. adaptive_iterator is a model
  34. * of single-pass iterator.
  35. *
  36. * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time.
  37. *
  38. * \tparam Stepper The stepper type which should be used during the iteration.
  39. * \tparam System The type of the system function (ODE) which should be solved.
  40. */
  41. template< class Iterator , class Stepper , class System , class State , typename Tag >
  42. class adaptive_iterator_impl< Iterator , Stepper , System , State , Tag , controlled_stepper_tag >
  43. : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
  44. {
  45. private:
  46. typedef Stepper stepper_type;
  47. typedef System system_type;
  48. typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
  49. typedef State state_type;
  50. typedef typename traits::time_type< stepper_type >::type time_type;
  51. typedef typename traits::value_type< stepper_type >::type ode_value_type;
  52. #ifndef DOXYGEN_SKIP
  53. typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
  54. #endif
  55. public:
  56. /**
  57. * \brief Constructs an adaptive_iterator. This constructor should be used to construct the begin iterator.
  58. *
  59. * \param stepper The stepper to use during the iteration.
  60. * \param sys The system function (ODE) to solve.
  61. * \param s The initial state. adaptive_iterator stores a reference of s and changes its value during the iteration.
  62. * \param t The initial time.
  63. * \param t_end The end time, at which the iteration should stop.
  64. * \param dt The initial time step.
  65. */
  66. adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt )
  67. : base_type( stepper , sys , t , dt ) , m_t_end( t_end ) , m_state( &s )
  68. {
  69. if( detail::less_with_sign( this->m_t_end , this->m_t , this->m_dt ) )
  70. this->m_at_end = true;
  71. }
  72. /**
  73. * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator.
  74. *
  75. * \param stepper The stepper to use during the iteration.
  76. * \param sys The system function (ODE) to solve.
  77. * \param s The initial state. adaptive_iterator store a reference of s and changes its value during the iteration.
  78. */
  79. adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
  80. : base_type( stepper , sys ) , m_state( &s ) { }
  81. protected:
  82. friend class boost::iterator_core_access;
  83. void increment()
  84. {
  85. if( detail::less_with_sign( this->m_t , this->m_t_end , this->m_dt) )
  86. {
  87. if( detail::less_with_sign( this->m_t_end ,
  88. static_cast<time_type>(this->m_t + this->m_dt) ,
  89. this->m_dt ) )
  90. {
  91. this->m_dt = this->m_t_end - this->m_t;
  92. }
  93. unwrapped_stepper_type &stepper = this->m_stepper;
  94. const size_t max_attempts = 1000;
  95. size_t trials = 0;
  96. controlled_step_result res = success;
  97. do
  98. {
  99. res = stepper.try_step( this->m_system , *( this->m_state ) , this->m_t , this->m_dt );
  100. ++trials;
  101. }
  102. while( ( res == fail ) && ( trials < max_attempts ) );
  103. if( trials == max_attempts )
  104. {
  105. BOOST_THROW_EXCEPTION( std::overflow_error( "Adaptive iterator : Maximal number of iterations reached. A step size could not be found." ));
  106. }
  107. } else {
  108. this->m_at_end = true;
  109. }
  110. }
  111. public:
  112. const state_type& get_state() const
  113. {
  114. return *this->m_state;
  115. }
  116. private:
  117. time_type m_t_end;
  118. state_type* m_state;
  119. };
  120. /*
  121. * Specilization for dense outputer steppers
  122. */
  123. /**
  124. * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper.
  125. *
  126. * Implements an ODE iterator with adaptive step size control. Uses dense-output steppers. adaptive_iterator is a model
  127. * of single-pass iterator.
  128. *
  129. * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time.
  130. *
  131. * \tparam Stepper The stepper type which should be used during the iteration.
  132. * \tparam System The type of the system function (ODE) which should be solved.
  133. */
  134. template< class Iterator , class Stepper , class System , class State , typename Tag >
  135. class adaptive_iterator_impl< Iterator , Stepper , System , State , Tag , dense_output_stepper_tag >
  136. : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
  137. {
  138. private:
  139. typedef Stepper stepper_type;
  140. typedef System system_type;
  141. typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
  142. typedef State state_type;
  143. typedef typename traits::time_type< stepper_type >::type time_type;
  144. typedef typename traits::value_type< stepper_type >::type ode_value_type;
  145. #ifndef DOXYGEN_SKIP
  146. typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
  147. #endif
  148. public:
  149. /**
  150. * \brief Constructs an adaptive_iterator. This constructor should be used to construct the begin iterator.
  151. *
  152. * \param stepper The stepper to use during the iteration.
  153. * \param sys The system function (ODE) to solve.
  154. * \param s The initial state.
  155. * \param t The initial time.
  156. * \param t_end The end time, at which the iteration should stop.
  157. * \param dt The initial time step.
  158. */
  159. adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt )
  160. : base_type( stepper , sys , t , dt ) , m_t_end( t_end )
  161. {
  162. if( detail::less_eq_with_sign( this->m_t , this->m_t_end , this->m_dt ) )
  163. {
  164. unwrapped_stepper_type &st = this->m_stepper;
  165. st.initialize( s , this->m_t , this->m_dt );
  166. } else {
  167. this->m_at_end = true;
  168. }
  169. }
  170. /**
  171. * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator.
  172. *
  173. * \param stepper The stepper to use during the iteration.
  174. * \param sys The system function (ODE) to solve.
  175. * \param s The initial state.
  176. */
  177. adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type& /* s */ )
  178. : base_type( stepper , sys ) { }
  179. protected:
  180. friend class boost::iterator_core_access;
  181. void increment()
  182. {
  183. unwrapped_stepper_type &stepper = this->m_stepper;
  184. if( detail::less_with_sign( this->m_t ,
  185. this->m_t_end ,
  186. stepper.current_time_step() ) )
  187. {
  188. if( detail::less_with_sign( this->m_t_end ,
  189. static_cast<time_type>(this->m_t + stepper.current_time_step()) ,
  190. stepper.current_time_step() ) )
  191. {
  192. // make stpper to end exactly at t_end
  193. stepper.initialize( stepper.current_state() , stepper.current_time() ,
  194. static_cast<time_type>(this->m_t_end-this->m_t) );
  195. }
  196. stepper.do_step( this->m_system );
  197. this->m_t = stepper.current_time();
  198. } else { // we have reached t_end
  199. this->m_at_end = true;
  200. }
  201. }
  202. public:
  203. const state_type& get_state() const
  204. {
  205. const unwrapped_stepper_type &stepper = this->m_stepper;
  206. return stepper.current_state();
  207. }
  208. private:
  209. time_type m_t_end;
  210. };
  211. } // namespace odeint
  212. } // namespace numeric
  213. } // namespace boost
  214. #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED