]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/numeric/odeint/stepper/modified_midpoint.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / numeric / odeint / stepper / modified_midpoint.hpp
1 /*
2 [auto_generated]
3 boost/numeric/odeint/stepper/modified_midpoint.hpp
4
5 [begin_description]
6 Modified midpoint method for the use in Burlish-Stoer stepper.
7 [end_description]
8
9 Copyright 2011-2013 Mario Mulansky
10 Copyright 2011-2013 Karsten Ahnert
11 Copyright 2012 Christoph Koke
12
13 Distributed under the Boost Software License, Version 1.0.
14 (See accompanying file LICENSE_1_0.txt or
15 copy at http://www.boost.org/LICENSE_1_0.txt)
16 */
17
18
19 #ifndef BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED
20 #define BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED
21
22 #include <vector>
23
24 #include <boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp>
25 #include <boost/numeric/odeint/util/resizer.hpp>
26 #include <boost/numeric/odeint/util/is_resizeable.hpp>
27 #include <boost/numeric/odeint/algebra/range_algebra.hpp>
28 #include <boost/numeric/odeint/algebra/default_operations.hpp>
29 #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
30 #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
31 #include <boost/numeric/odeint/util/copy.hpp>
32
33 namespace boost {
34 namespace numeric {
35 namespace odeint {
36
37 template<
38 class State ,
39 class Value = double ,
40 class Deriv = State ,
41 class Time = Value ,
42 class Algebra = typename algebra_dispatcher< State >::algebra_type ,
43 class Operations = typename operations_dispatcher< State >::operations_type ,
44 class Resizer = initially_resizer
45 >
46 #ifndef DOXYGEN_SKIP
47 class modified_midpoint
48 : public explicit_stepper_base<
49 modified_midpoint< State , Value , Deriv , Time , Algebra , Operations , Resizer > ,
50 2 , State , Value , Deriv , Time , Algebra , Operations , Resizer >
51 #else
52 class modified_midpoint : public explicit_stepper_base
53 #endif
54 {
55
56 public :
57
58 typedef explicit_stepper_base<
59 modified_midpoint< State , Value , Deriv , Time , Algebra , Operations , Resizer > ,
60 2 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type;
61
62 typedef typename stepper_base_type::state_type state_type;
63 typedef typename stepper_base_type::wrapped_state_type wrapped_state_type;
64 typedef typename stepper_base_type::value_type value_type;
65 typedef typename stepper_base_type::deriv_type deriv_type;
66 typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type;
67 typedef typename stepper_base_type::time_type time_type;
68 typedef typename stepper_base_type::algebra_type algebra_type;
69 typedef typename stepper_base_type::operations_type operations_type;
70 typedef typename stepper_base_type::resizer_type resizer_type;
71 typedef typename stepper_base_type::stepper_type stepper_type;
72
73
74 modified_midpoint( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() )
75 : stepper_base_type( algebra ) , m_steps( steps )
76 { }
77
78 template< class System , class StateIn , class DerivIn , class StateOut >
79 void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt )
80 {
81 static const value_type val1 = static_cast< value_type >( 1 );
82 static const value_type val05 = static_cast< value_type >( 1 ) / static_cast< value_type >( 2 );
83
84 m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) );
85
86 const time_type h = dt / static_cast<value_type>( m_steps );
87 const time_type h2 = static_cast<value_type>(2) * h;
88
89 typename odeint::unwrap_reference< System >::type &sys = system;
90
91 time_type th = t + h;
92
93 // m_x1 = x + h*dxdt
94 stepper_base_type::m_algebra.for_each3( m_x1.m_v , in , dxdt ,
95 typename operations_type::template scale_sum2< value_type , time_type >( val1 , h ) );
96
97 sys( m_x1.m_v , m_dxdt.m_v , th );
98
99 boost::numeric::odeint::copy( in , m_x0.m_v );
100
101 unsigned short i = 1;
102 while( i != m_steps )
103 {
104 // general step
105 //tmp = m_x1; m_x1 = m_x0 + h2*m_dxdt; m_x0 = tmp
106 stepper_base_type::m_algebra.for_each3( m_x1.m_v , m_x0.m_v , m_dxdt.m_v ,
107 typename operations_type::template scale_sum_swap2< value_type , time_type >( val1 , h2 ) );
108 th += h;
109 sys( m_x1.m_v , m_dxdt.m_v , th);
110 i++;
111 }
112
113 // last step
114 // x = 0.5*( m_x0 + m_x1 + h*m_dxdt )
115 stepper_base_type::m_algebra.for_each4( out , m_x0.m_v , m_x1.m_v , m_dxdt.m_v ,
116 typename operations_type::template scale_sum3< value_type , value_type , time_type >( val05 , val05 , val05*h ) );
117 }
118
119
120 void set_steps( unsigned short steps )
121 { m_steps = steps; }
122
123
124 unsigned short steps( void ) const
125 { return m_steps; }
126
127
128 template< class StateIn >
129 void adjust_size( const StateIn &x )
130 {
131 resize_impl( x );
132 stepper_base_type::adjust_size( x );
133 }
134
135 private:
136
137 template< class StateIn >
138 bool resize_impl( const StateIn &x )
139 {
140 bool resized( false );
141 resized |= adjust_size_by_resizeability( m_x0 , x , typename is_resizeable<state_type>::type() );
142 resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() );
143 resized |= adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() );
144 return resized;
145 }
146
147
148 unsigned short m_steps;
149
150 resizer_type m_resizer;
151
152 wrapped_state_type m_x0;
153 wrapped_state_type m_x1;
154 wrapped_deriv_type m_dxdt;
155
156 };
157
158
159 /* Modified midpoint which stores derivatives and state at dt/2 in some external storage for later usage in dense output calculation
160 * This Stepper is for use in Bulirsch Stoer only. It DOES NOT meet any stepper concept.
161 */
162 template<
163 class State ,
164 class Value = double ,
165 class Deriv = State ,
166 class Time = Value ,
167 class Algebra = typename algebra_dispatcher< State >::algebra_type ,
168 class Operations = typename operations_dispatcher< State >::operations_type ,
169 class Resizer = initially_resizer
170 >
171 class modified_midpoint_dense_out
172 {
173
174 public :
175
176 typedef State state_type;
177 typedef Value value_type;
178 typedef Deriv deriv_type;
179 typedef Time time_type;
180 typedef Algebra algebra_type;
181 typedef Operations operations_type;
182 typedef Resizer resizer_type;
183 typedef state_wrapper< state_type > wrapped_state_type;
184 typedef state_wrapper< deriv_type > wrapped_deriv_type;
185
186 typedef modified_midpoint_dense_out< State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_type;
187 typedef std::vector< wrapped_deriv_type > deriv_table_type;
188
189 modified_midpoint_dense_out( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() )
190 : m_algebra( algebra ) , m_steps( steps )
191 { }
192
193 /*
194 * performs a modified midpoint step with m_steps intermediate points
195 * stores approximation for x(t+dt/2) in x_mp and all evaluated function results in derivs
196 *
197 */
198
199 template< class System , class StateIn , class DerivIn , class StateOut >
200 void do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ,
201 state_type &x_mp , deriv_table_type &derivs )
202 {
203
204 static const value_type val1 = static_cast< value_type >( 1 );
205 static const value_type val05 = static_cast< value_type >( 1 ) / static_cast< value_type >( 2 );
206
207 m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize< StateIn > , detail::ref( *this ) , detail::_1 ) );
208
209 const time_type h = dt / static_cast<value_type>( m_steps );
210 const time_type h2 = static_cast<value_type>( 2 ) * h;
211
212 typename odeint::unwrap_reference< System >::type &sys = system;
213
214 time_type th = t + h;
215
216 // m_x1 = x + h*dxdt
217 m_algebra.for_each3( m_x1.m_v , in , dxdt ,
218 typename operations_type::template scale_sum2< value_type , time_type >( val1 , h ) );
219
220 if( m_steps == 2 )
221 // result of first step already gives approximation at the center of the interval
222 boost::numeric::odeint::copy( m_x1.m_v , x_mp );
223
224 sys( m_x1.m_v , derivs[0].m_v , th );
225
226 boost::numeric::odeint::copy( in , m_x0.m_v );
227
228 unsigned short i = 1;
229 while( i != m_steps )
230 {
231 // general step
232 //tmp = m_x1; m_x1 = m_x0 + h2*m_dxdt; m_x0 = tmp
233 m_algebra.for_each3( m_x1.m_v , m_x0.m_v , derivs[i-1].m_v ,
234 typename operations_type::template scale_sum_swap2< value_type , time_type >( val1 , h2 ) );
235 if( i == m_steps/2-1 )
236 // save approximation at the center of the interval
237 boost::numeric::odeint::copy( m_x1.m_v , x_mp );
238
239 th += h;
240 sys( m_x1.m_v , derivs[i].m_v , th);
241 i++;
242 }
243
244 // last step
245 // x = 0.5*( m_x0 + m_x1 + h*m_dxdt )
246 m_algebra.for_each4( out , m_x0.m_v , m_x1.m_v , derivs[m_steps-1].m_v ,
247 typename operations_type::template scale_sum3< value_type , value_type , time_type >( val05 , val05 , val05*h ) );
248 }
249
250
251 void set_steps( unsigned short steps )
252 { m_steps = steps; }
253
254
255 unsigned short steps( void ) const
256 { return m_steps; }
257
258
259 template< class StateIn >
260 bool resize( const StateIn &x )
261 {
262 bool resized( false );
263 resized |= adjust_size_by_resizeability( m_x0 , x , typename is_resizeable<state_type>::type() );
264 resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() );
265 return resized;
266 }
267
268 template< class StateIn >
269 void adjust_size( const StateIn &x )
270 {
271 resize( x );
272 }
273
274 private:
275
276 algebra_type m_algebra;
277
278 unsigned short m_steps;
279
280 resizer_type m_resizer;
281
282 wrapped_state_type m_x0;
283 wrapped_state_type m_x1;
284
285 };
286
287
288
289 /********** DOXYGEN ***********/
290
291 /**
292 * \class modified_midpoint
293 *
294 * Implementation of the modified midpoint method with a configurable
295 * number of intermediate steps. This class is used by the Bulirsch-Stoer
296 * algorithm and is not meant for direct usage.
297 */
298
299
300 /**
301 * \class modified_midpoint_dense_out
302 *
303 * Implementation of the modified midpoint method with a configurable
304 * number of intermediate steps. This class is used by the dense output
305 * Bulirsch-Stoer algorithm and is not meant for direct usage.
306 * \note This stepper is for internal use only and does not meet
307 * any stepper concept.
308 */
309
310
311 }
312 }
313 }
314
315 #endif // BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED