]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | */ | |
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 | */ | |
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 | ||
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: | |
125 | 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 | */ | |
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 | */ | |
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 | ||
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: | |
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: | |
246 | 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 | */ | |
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 | */ | |
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 | ||
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: | |
353 | 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 |