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
31namespace boost {
32namespace numeric {
33namespace 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 */
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 */
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
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:
132 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 */
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 */
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
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:
238 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

source code of boost/boost/numeric/odeint/iterator/impl/adaptive_iterator_impl.hpp