• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  [auto_generated]
3   boost/numeric/odeint/iterator/detail/adaptive_iterator_impl.hpp
4 
5   [begin_description]
6   tba.
7   [end_description]
8 
9   Copyright 2009-2012 Karsten Ahnert
10   Copyright 2009-2012 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_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED
19 #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ADAPTIVE_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 , typename Tag , typename StepperTag >
37     class adaptive_iterator_impl;
38 
39     /*
40      * Specilization for controlled steppers
41      */
42     /**
43      * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper.
44      *
45      * Implements an ODE iterator with adaptive step size control. Uses controlled steppers. adaptive_iterator is a model
46      * of single-pass iterator.
47      *
48      * 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.
49      *
50      * \tparam Stepper The stepper type which should be used during the iteration.
51      * \tparam System The type of the system function (ODE) which should be solved.
52      */
53     template< class Iterator , class Stepper , class System , class State , typename Tag >
54     class adaptive_iterator_impl< Iterator , Stepper , System , State , Tag , controlled_stepper_tag >
55         : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
56     {
57     private:
58 
59 
60         typedef Stepper stepper_type;
61         typedef System system_type;
62         typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
63         typedef State state_type;
64         typedef typename traits::time_type< stepper_type >::type time_type;
65         typedef typename traits::value_type< stepper_type >::type ode_value_type;
66         #ifndef DOXYGEN_SKIP
67         typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
68         #endif
69 
70     public:
71 
72         /**
73          * \brief Constructs an adaptive_iterator. This constructor should be used to construct the begin 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 stores a reference of s and changes its value during the iteration.
78          * \param t The initial time.
79          * \param t_end The end time, at which the iteration should stop.
80          * \param dt The initial time step.
81          */
adaptive_iterator_impl(stepper_type stepper,system_type sys,state_type & s,time_type t,time_type t_end,time_type dt)82         adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt )
83             : base_type( stepper , sys , t , dt ) , m_t_end( t_end ) , m_state( &s )
84         {
85             if( detail::less_with_sign( this->m_t_end , this->m_t , this->m_dt ) )
86                 this->m_at_end = true;
87         }
88 
89         /**
90          * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator.
91          *
92          * \param stepper The stepper to use during the iteration.
93          * \param sys The system function (ODE) to solve.
94          * \param s The initial state. adaptive_iterator store a reference of s and changes its value during the iteration.
95          */
adaptive_iterator_impl(stepper_type stepper,system_type sys,state_type & s)96         adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s )
97             : base_type( stepper , sys ) , m_state( &s ) { }
98 
99     protected:
100 
101         friend class boost::iterator_core_access;
102 
increment()103         void increment()
104         {
105             if( detail::less_with_sign( this->m_t , this->m_t_end , this->m_dt) )
106             {
107                 if( detail::less_with_sign( this->m_t_end ,
108                                             static_cast<time_type>(this->m_t + this->m_dt) ,
109                                             this->m_dt ) )
110                 {
111                     this->m_dt = this->m_t_end - this->m_t;
112                 }
113                 unwrapped_stepper_type &stepper = this->m_stepper;
114                 const size_t max_attempts = 1000;
115                 size_t trials = 0;
116                 controlled_step_result res = success;
117                 do
118                 {
119                     res = stepper.try_step( this->m_system , *( this->m_state ) , this->m_t , this->m_dt );
120                     ++trials;
121                 }
122                 while( ( res == fail ) && ( trials < max_attempts ) );
123                 if( trials == max_attempts )
124                 {
125                     BOOST_THROW_EXCEPTION( std::overflow_error( "Adaptive iterator : Maximal number of iterations reached. A step size could not be found." ));
126                 }
127             } else {
128                 this->m_at_end = true;
129             }
130         }
131     public:
get_state() const132         const state_type& get_state() const
133         {
134             return *this->m_state;
135         }
136 
137     private:
138         time_type m_t_end;
139         state_type* m_state;
140     };
141 
142 
143 
144     /*
145      * Specilization for dense outputer steppers
146      */
147     /**
148      * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper.
149      *
150      * Implements an ODE iterator with adaptive step size control. Uses dense-output steppers. adaptive_iterator is a model
151      * of single-pass iterator.
152      *
153      * 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.
154      *
155      * \tparam Stepper The stepper type which should be used during the iteration.
156      * \tparam System The type of the system function (ODE) which should be solved.
157      */
158     template< class Iterator , class Stepper , class System , class State , typename Tag >
159     class adaptive_iterator_impl< Iterator , Stepper , System , State , Tag , dense_output_stepper_tag >
160         : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag >
161     {
162     private:
163 
164 
165         typedef Stepper stepper_type;
166         typedef System system_type;
167         typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type;
168         typedef State state_type;
169         typedef typename traits::time_type< stepper_type >::type time_type;
170         typedef typename traits::value_type< stepper_type >::type ode_value_type;
171         #ifndef DOXYGEN_SKIP
172         typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type;
173         #endif
174 
175 
176    public:
177 
178 
179         /**
180          * \brief Constructs an adaptive_iterator. This constructor should be used to construct the begin iterator.
181          *
182          * \param stepper The stepper to use during the iteration.
183          * \param sys The system function (ODE) to solve.
184          * \param s The initial state.
185          * \param t The initial time.
186          * \param t_end The end time, at which the iteration should stop.
187          * \param dt The initial time step.
188          */
adaptive_iterator_impl(stepper_type stepper,system_type sys,state_type & s,time_type t,time_type t_end,time_type dt)189         adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt )
190             : base_type( stepper , sys , t , dt ) , m_t_end( t_end )
191         {
192             if( detail::less_eq_with_sign( this->m_t , this->m_t_end , this->m_dt ) )
193             {
194                 unwrapped_stepper_type &st = this->m_stepper;
195                 st.initialize( s , this->m_t , this->m_dt );
196             } else {
197                 this->m_at_end = true;
198             }
199         }
200 
201         /**
202          * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator.
203          *
204          * \param stepper The stepper to use during the iteration.
205          * \param sys The system function (ODE) to solve.
206          * \param s The initial state.
207          */
adaptive_iterator_impl(stepper_type stepper,system_type sys,state_type &)208         adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type& /* s */ )
209             : base_type( stepper , sys ) { }
210 
211     protected:
212 
213         friend class boost::iterator_core_access;
214 
increment()215         void increment()
216         {
217             unwrapped_stepper_type &stepper = this->m_stepper;
218             if( detail::less_with_sign( this->m_t ,
219                                         this->m_t_end ,
220                                         stepper.current_time_step() ) )
221             {
222                 if( detail::less_with_sign( this->m_t_end ,
223                                             static_cast<time_type>(this->m_t + stepper.current_time_step()) ,
224                                             stepper.current_time_step() ) )
225                 {
226                     // make stpper to end exactly at t_end
227                     stepper.initialize( stepper.current_state() , stepper.current_time() ,
228                                         static_cast<time_type>(this->m_t_end-this->m_t) );
229                 }
230                 stepper.do_step( this->m_system );
231                 this->m_t = stepper.current_time();
232             } else { // we have reached t_end
233                 this->m_at_end = true;
234             }
235         }
236 
237     public:
get_state() const238         const state_type& get_state() const
239         {
240             const unwrapped_stepper_type &stepper = this->m_stepper;
241             return stepper.current_state();
242         }
243 
244     private:
245         time_type m_t_end;
246     };
247 
248 } // namespace odeint
249 } // namespace numeric
250 } // namespace boost
251 
252 
253 #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED
254