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