File indexing completed on 2025-01-18 09:42:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_TIMES_ITERATOR_IMPL_HPP_DEFINED
0019 #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_TIMES_ITERATOR_IMPL_HPP_DEFINED
0020
0021 #include <boost/utility/enable_if.hpp>
0022 #include <boost/type_traits/is_same.hpp>
0023 #include <boost/throw_exception.hpp>
0024
0025 #include <boost/numeric/odeint/util/unit_helper.hpp>
0026 #include <boost/numeric/odeint/util/copy.hpp>
0027 #include <boost/numeric/odeint/stepper/controlled_step_result.hpp>
0028 #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp>
0029
0030
0031 namespace boost {
0032 namespace numeric {
0033 namespace odeint {
0034
0035
0036 template< class Iterator , class Stepper , class System , class State , class TimeIterator ,
0037 typename Tag , typename StepperTag >
0038 class times_iterator_impl;
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag >
0055 class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , stepper_tag >
0056 : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
0057 {
0058 private:
0059
0060
0061 typedef Stepper stepper_type;
0062 typedef System system_type;
0063 typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
0064 typedef State state_type;
0065 typedef TimeIterator time_iterator_type;
0066 typedef typename traits::time_type< stepper_type >::type time_type;
0067 typedef typename traits::value_type< stepper_type >::type ode_value_type;
0068 #ifndef DOXYGEN_SKIP
0069 typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
0070 #endif
0071
0072 public:
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ,
0085 time_iterator_type t_start , time_iterator_type t_end , time_type dt )
0086 : base_type( stepper , sys , *t_start , dt ) ,
0087 m_t_start( t_start ) , m_t_end( t_end ) , m_state( &s )
0088 {
0089 if( t_start == t_end )
0090 this->m_at_end = true;
0091 }
0092
0093
0094
0095
0096
0097
0098
0099
0100 times_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
0101 : base_type( stepper , sys ) , m_state( &s ) { }
0102
0103 protected:
0104
0105 friend class boost::iterator_core_access;
0106
0107 void increment()
0108 {
0109 unwrapped_stepper_type &stepper = this->m_stepper;
0110 if( ++m_t_start != m_t_end )
0111 {
0112 while( detail::less_with_sign( this->m_t , static_cast<time_type>(*m_t_start) , this->m_dt ) )
0113 {
0114 const time_type current_dt = detail::min_abs( this->m_dt , static_cast<time_type>(*m_t_start) - this->m_t );
0115 stepper.do_step( this->m_system , *( this->m_state ) , this->m_t , current_dt );
0116 this->m_t += current_dt;
0117 }
0118
0119 } else {
0120 this->m_at_end = true;
0121 }
0122 }
0123
0124 public:
0125 const state_type& get_state() const
0126 {
0127 return *m_state;
0128 }
0129
0130 private:
0131 time_iterator_type m_t_start;
0132 time_iterator_type m_t_end;
0133 state_type* m_state;
0134 };
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152 template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag >
0153 class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , controlled_stepper_tag >
0154 : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
0155 {
0156 private:
0157
0158
0159 typedef Stepper stepper_type;
0160 typedef System system_type;
0161 typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
0162 typedef State state_type;
0163 typedef TimeIterator time_iterator_type;
0164 typedef typename traits::time_type< stepper_type >::type time_type;
0165 typedef typename traits::value_type< stepper_type >::type ode_value_type;
0166 #ifndef DOXYGEN_SKIP
0167 typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
0168 #endif
0169
0170 public:
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ,
0183 time_iterator_type t_start , time_iterator_type t_end , time_type dt )
0184 : base_type( stepper , sys , *t_start , dt ) ,
0185 m_t_start( t_start ) , m_t_end( t_end ) , m_state( &s )
0186 {
0187 if( t_start == t_end )
0188 this->m_at_end = true;
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198 times_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
0199 : base_type( stepper , sys ) , m_state( &s ) { }
0200
0201 protected:
0202
0203 friend class boost::iterator_core_access;
0204
0205 void increment()
0206 {
0207 if( ++m_t_start != m_t_end )
0208 {
0209 while( detail::less_with_sign( this->m_t , static_cast<time_type>(*m_t_start) , this->m_dt ) )
0210 {
0211 if( detail::less_with_sign( static_cast<time_type>(*m_t_start) - this->m_t , this->m_dt , this->m_dt ) )
0212 {
0213
0214 time_type current_dt = static_cast<time_type>(*m_t_start) - this->m_t;
0215 step_loop( current_dt );
0216 } else {
0217 step_loop( this->m_dt );
0218 }
0219 }
0220
0221 } else {
0222 this->m_at_end = true;
0223 }
0224 }
0225
0226 private:
0227 void step_loop( time_type &dt )
0228 {
0229 unwrapped_stepper_type &stepper = this->m_stepper;
0230 const size_t max_attempts = 1000;
0231 size_t trials = 0;
0232 controlled_step_result res = success;
0233 do
0234 {
0235 res = stepper.try_step( this->m_system , *( this->m_state ) , this->m_t , dt );
0236 ++trials;
0237 }
0238 while( ( res == fail ) && ( trials < max_attempts ) );
0239 if( trials == max_attempts )
0240 {
0241 BOOST_THROW_EXCEPTION( std::overflow_error( "Adaptive iterator : Maximal number of iterations reached. A step size could not be found." ) );
0242 }
0243 }
0244
0245 public:
0246 const state_type& get_state() const
0247 {
0248 return *m_state;
0249 }
0250
0251
0252 private:
0253 time_iterator_type m_t_start;
0254 time_iterator_type m_t_end;
0255 state_type* m_state;
0256 };
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag >
0271 class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , dense_output_stepper_tag >
0272 : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
0273 {
0274 private:
0275
0276
0277 typedef Stepper stepper_type;
0278 typedef System system_type;
0279 typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
0280 typedef State state_type;
0281 typedef TimeIterator time_iterator_type;
0282 typedef typename traits::time_type< stepper_type >::type time_type;
0283 typedef typename traits::value_type< stepper_type >::type ode_value_type;
0284 #ifndef DOXYGEN_SKIP
0285 typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
0286 #endif
0287
0288
0289 public:
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302 times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ,
0303 time_iterator_type t_start , time_iterator_type t_end , time_type dt )
0304 : base_type( stepper , sys , *t_start , dt ) ,
0305 m_t_start( t_start ) , m_t_end( t_end ) , m_final_time( *(t_end-1) ) ,
0306 m_state( &s )
0307 {
0308 if( t_start != t_end )
0309 {
0310 unwrapped_stepper_type &st = this->m_stepper;
0311 st.initialize( *( this->m_state ) , this->m_t , this->m_dt );
0312 } else {
0313 this->m_at_end = true;
0314 }
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324 times_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
0325 : base_type( stepper , sys ) , m_state( &s ) { }
0326
0327 protected:
0328
0329 friend class boost::iterator_core_access;
0330
0331 void increment()
0332 {
0333 unwrapped_stepper_type &st = this->m_stepper;
0334 if( ++m_t_start != m_t_end )
0335 {
0336 this->m_t = static_cast<time_type>(*m_t_start);
0337 while( detail::less_with_sign( st.current_time() , this->m_t , this->m_dt ) )
0338 {
0339
0340 if( detail::less_with_sign( m_final_time-st.current_time() , st.current_time_step() , st.current_time_step() ) )
0341 {
0342 st.initialize( st.current_state() , st.current_time() , m_final_time-st.current_time() );
0343 }
0344 st.do_step( this->m_system );
0345 }
0346 st.calc_state( this->m_t , *( this->m_state ) );
0347 } else {
0348 this->m_at_end = true;
0349 }
0350 }
0351
0352 public:
0353 const state_type& get_state() const
0354 {
0355 return *m_state;
0356 }
0357
0358
0359 private:
0360 time_iterator_type m_t_start;
0361 time_iterator_type m_t_end;
0362 time_type m_final_time;
0363 state_type* m_state;
0364 };
0365
0366 }
0367 }
0368 }
0369
0370
0371 #endif