times_iterator_impl.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  2. [auto_generated]
  3. boost/numeric/odeint/iterator/detail/times_iterator_impl.hpp
  4. [begin_description]
  5. tba.
  6. [end_description]
  7. Copyright 2009-2013 Karsten Ahnert
  8. Copyright 2009-2013 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_TIMES_ITERATOR_IMPL_HPP_DEFINED
  14. #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_TIMES_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 , class TimeIterator ,
  26. typename Tag , typename StepperTag >
  27. class times_iterator_impl;
  28. /*
  29. * Specilization for basic steppers
  30. */
  31. /**
  32. * \brief ODE Iterator with constant step size.
  33. *
  34. * Implements an ODE iterator with observer calls at predefined times.
  35. * Uses controlled steppers. times_iterator is a model of single-pass iterator.
  36. *
  37. * 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.
  38. *
  39. * \tparam Stepper The stepper type which should be used during the iteration.
  40. * \tparam System The type of the system function (ODE) which should be solved.
  41. */
  42. template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag >
  43. class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , stepper_tag >
  44. : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
  45. {
  46. private:
  47. typedef Stepper stepper_type;
  48. typedef System system_type;
  49. typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
  50. typedef State state_type;
  51. typedef TimeIterator time_iterator_type;
  52. typedef typename traits::time_type< stepper_type >::type time_type;
  53. typedef typename traits::value_type< stepper_type >::type ode_value_type;
  54. #ifndef DOXYGEN_SKIP
  55. typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
  56. #endif
  57. public:
  58. /**
  59. * \brief Constructs a times_iterator. This constructor should be used to construct the begin iterator.
  60. *
  61. * \param stepper The stepper to use during the iteration.
  62. * \param sys The system function (ODE) to solve.
  63. * \param s The initial state. adaptive_iterator stores a reference of s and changes its value during the iteration.
  64. * \param t_start Iterator to the begin of a sequence of time values.
  65. * \param t_end Iterator to the begin of a sequence of time values.
  66. * \param dt The (initial) time step.
  67. */
  68. times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ,
  69. time_iterator_type t_start , time_iterator_type t_end , time_type dt )
  70. : base_type( stepper , sys , *t_start , dt ) ,
  71. m_t_start( t_start ) , m_t_end( t_end ) , m_state( &s )
  72. {
  73. if( t_start == t_end )
  74. this->m_at_end = true;
  75. }
  76. /**
  77. * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator.
  78. *
  79. * \param stepper The stepper to use during the iteration.
  80. * \param sys The system function (ODE) to solve.
  81. * \param s The initial state. adaptive_iterator store a reference of s and changes its value during the iteration.
  82. */
  83. times_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
  84. : base_type( stepper , sys ) , m_state( &s ) { }
  85. protected:
  86. friend class boost::iterator_core_access;
  87. void increment()
  88. {
  89. unwrapped_stepper_type &stepper = this->m_stepper;
  90. if( ++m_t_start != m_t_end )
  91. {
  92. while( detail::less_with_sign( this->m_t , static_cast<time_type>(*m_t_start) , this->m_dt ) )
  93. {
  94. const time_type current_dt = detail::min_abs( this->m_dt , static_cast<time_type>(*m_t_start) - this->m_t );
  95. stepper.do_step( this->m_system , *( this->m_state ) , this->m_t , current_dt );
  96. this->m_t += current_dt;
  97. }
  98. } else {
  99. this->m_at_end = true;
  100. }
  101. }
  102. public:
  103. const state_type& get_state() const
  104. {
  105. return *m_state;
  106. }
  107. private:
  108. time_iterator_type m_t_start;
  109. time_iterator_type m_t_end;
  110. state_type* m_state;
  111. };
  112. /*
  113. * Specilization for controlled steppers
  114. */
  115. /**
  116. * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper.
  117. *
  118. * Implements an ODE iterator with observer calls at predefined times.
  119. * Uses controlled steppers. times_iterator is a model of single-pass iterator.
  120. *
  121. * 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.
  122. *
  123. * \tparam Stepper The stepper type which should be used during the iteration.
  124. * \tparam System The type of the system function (ODE) which should be solved.
  125. */
  126. template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag >
  127. class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , controlled_stepper_tag >
  128. : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
  129. {
  130. private:
  131. typedef Stepper stepper_type;
  132. typedef System system_type;
  133. typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
  134. typedef State state_type;
  135. typedef TimeIterator time_iterator_type;
  136. typedef typename traits::time_type< stepper_type >::type time_type;
  137. typedef typename traits::value_type< stepper_type >::type ode_value_type;
  138. #ifndef DOXYGEN_SKIP
  139. typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
  140. #endif
  141. public:
  142. /**
  143. * \brief Constructs a times_iterator. This constructor should be used to construct the begin iterator.
  144. *
  145. * \param stepper The stepper to use during the iteration.
  146. * \param sys The system function (ODE) to solve.
  147. * \param s The initial state. adaptive_iterator stores a reference of s and changes its value during the iteration.
  148. * \param t_start Iterator to the begin of a sequence of time values.
  149. * \param t_end Iterator to the begin of a sequence of time values.
  150. * \param dt The (initial) time step.
  151. */
  152. times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ,
  153. time_iterator_type t_start , time_iterator_type t_end , time_type dt )
  154. : base_type( stepper , sys , *t_start , dt ) ,
  155. m_t_start( t_start ) , m_t_end( t_end ) , m_state( &s )
  156. {
  157. if( t_start == t_end )
  158. this->m_at_end = true;
  159. }
  160. /**
  161. * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator.
  162. *
  163. * \param stepper The stepper to use during the iteration.
  164. * \param sys The system function (ODE) to solve.
  165. * \param s The initial state. adaptive_iterator store a reference of s and changes its value during the iteration.
  166. */
  167. times_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
  168. : base_type( stepper , sys ) , m_state( &s ) { }
  169. protected:
  170. friend class boost::iterator_core_access;
  171. void increment()
  172. {
  173. if( ++m_t_start != m_t_end )
  174. {
  175. while( detail::less_with_sign( this->m_t , static_cast<time_type>(*m_t_start) , this->m_dt ) )
  176. {
  177. if( detail::less_with_sign( static_cast<time_type>(*m_t_start) - this->m_t , this->m_dt , this->m_dt ) )
  178. {
  179. // we want to end exactly at the time point
  180. time_type current_dt = static_cast<time_type>(*m_t_start) - this->m_t;
  181. step_loop( current_dt );
  182. } else {
  183. step_loop( this->m_dt );
  184. }
  185. }
  186. } else {
  187. this->m_at_end = true;
  188. }
  189. }
  190. private:
  191. void step_loop( time_type &dt )
  192. {
  193. unwrapped_stepper_type &stepper = this->m_stepper;
  194. const size_t max_attempts = 1000;
  195. size_t trials = 0;
  196. controlled_step_result res = success;
  197. do
  198. {
  199. res = stepper.try_step( this->m_system , *( this->m_state ) , this->m_t , dt );
  200. ++trials;
  201. }
  202. while( ( res == fail ) && ( trials < max_attempts ) );
  203. if( trials == max_attempts )
  204. {
  205. BOOST_THROW_EXCEPTION( std::overflow_error( "Adaptive iterator : Maximal number of iterations reached. A step size could not be found." ) );
  206. }
  207. }
  208. public:
  209. const state_type& get_state() const
  210. {
  211. return *m_state;
  212. }
  213. private:
  214. time_iterator_type m_t_start;
  215. time_iterator_type m_t_end;
  216. state_type* m_state;
  217. };
  218. /*
  219. * Specilization for dense outputer steppers
  220. */
  221. /**
  222. * \brief ODE Iterator with step size control and dense output.
  223. * Implements an ODE iterator with adaptive step size control. Uses dense-output steppers.
  224. * times_iterator is a model of single-pass iterator.
  225. *
  226. * \tparam Stepper The stepper type which should be used during the iteration.
  227. * \tparam System The type of the system function (ODE) which should be solved.
  228. */
  229. template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag >
  230. class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , dense_output_stepper_tag >
  231. : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
  232. {
  233. private:
  234. typedef Stepper stepper_type;
  235. typedef System system_type;
  236. typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
  237. typedef State state_type;
  238. typedef TimeIterator time_iterator_type;
  239. typedef typename traits::time_type< stepper_type >::type time_type;
  240. typedef typename traits::value_type< stepper_type >::type ode_value_type;
  241. #ifndef DOXYGEN_SKIP
  242. typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
  243. #endif
  244. public:
  245. /**
  246. * \brief Constructs a times_iterator. This constructor should be used to construct the begin iterator.
  247. *
  248. * \param stepper The stepper to use during the iteration.
  249. * \param sys The system function (ODE) to solve.
  250. * \param s The initial state.
  251. * \param t_start Iterator to the begin of a sequence of time values.
  252. * \param t_end Iterator to the begin of a sequence of time values.
  253. * \param dt The (initial) time step.
  254. */
  255. times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ,
  256. time_iterator_type t_start , time_iterator_type t_end , time_type dt )
  257. : base_type( stepper , sys , *t_start , dt ) ,
  258. m_t_start( t_start ) , m_t_end( t_end ) , m_final_time( *(t_end-1) ) ,
  259. m_state( &s )
  260. {
  261. if( t_start != t_end )
  262. {
  263. unwrapped_stepper_type &st = this->m_stepper;
  264. st.initialize( *( this->m_state ) , this->m_t , this->m_dt );
  265. } else {
  266. this->m_at_end = true;
  267. }
  268. }
  269. /**
  270. * \brief Constructs a times_iterator. This constructor should be used to construct the end iterator.
  271. *
  272. * \param stepper The stepper to use during the iteration.
  273. * \param sys The system function (ODE) to solve.
  274. * \param s The initial state.
  275. */
  276. times_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
  277. : base_type( stepper , sys ) , m_state( &s ) { }
  278. protected:
  279. friend class boost::iterator_core_access;
  280. void increment()
  281. {
  282. unwrapped_stepper_type &st = this->m_stepper;
  283. if( ++m_t_start != m_t_end )
  284. {
  285. this->m_t = static_cast<time_type>(*m_t_start);
  286. while( detail::less_with_sign( st.current_time() , this->m_t , this->m_dt ) )
  287. {
  288. // make sure we don't go beyond the last point
  289. if( detail::less_with_sign( m_final_time-st.current_time() , st.current_time_step() , st.current_time_step() ) )
  290. {
  291. st.initialize( st.current_state() , st.current_time() , m_final_time-st.current_time() );
  292. }
  293. st.do_step( this->m_system );
  294. }
  295. st.calc_state( this->m_t , *( this->m_state ) );
  296. } else {
  297. this->m_at_end = true;
  298. }
  299. }
  300. public:
  301. const state_type& get_state() const
  302. {
  303. return *m_state;
  304. }
  305. private:
  306. time_iterator_type m_t_start;
  307. time_iterator_type m_t_end;
  308. time_type m_final_time;
  309. state_type* m_state;
  310. };
  311. } // namespace odeint
  312. } // namespace numeric
  313. } // namespace boost
  314. #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_TIMES_ITERATOR_IMPL_HPP_DEFINED