Brian Silverman | 7c33ab2 | 2018-08-04 17:14:51 -0700 | [diff] [blame^] | 1 | [/============================================================================ |
| 2 | Boost.odeint |
| 3 | |
| 4 | Copyright 2011-2012 Karsten Ahnert |
| 5 | Copyright 2011-2012 Mario Mulansky |
| 6 | |
| 7 | Use, modification and distribution is subject to the Boost Software License, |
| 8 | Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| 9 | http://www.boost.org/LICENSE_1_0.txt) |
| 10 | =============================================================================/] |
| 11 | |
| 12 | [def _max_step_checker_ [classref boost::numeric::odeint::max_step_checker `max_step_checker`]] |
| 13 | |
| 14 | [section Integrate functions] |
| 15 | |
| 16 | Integrate functions perform the time evolution of a given ODE from some |
| 17 | starting time ['t[sub 0]] to a given end time ['t[sub 1]] and starting at state ['x[sub 0]] by subsequent calls of a given stepper's `do_step` function. |
| 18 | Additionally, the user can provide an __observer to analyze the state during time evolution, and |
| 19 | a _max_step_checker_ to throw an exception if too many steps are taken between observer calls (i.e. too |
| 20 | small step size). |
| 21 | There are five different integrate functions which have different strategies on when to call the observer function during integration. |
| 22 | All of the integrate functions except `integrate_n_steps` can be called with any stepper following one of the stepper concepts: __stepper , __error_stepper , __controlled_stepper , __dense_output_stepper. |
| 23 | Depending on the abilities of the stepper, the integrate functions make use of step-size control or dense output. |
| 24 | |
| 25 | [heading Equidistant observer calls] |
| 26 | |
| 27 | If observer calls at equidistant time intervals /dt/ are needed, the |
| 28 | `integrate_const` or `integrate_n_steps` function should be used. |
| 29 | We start with explaining `integrate_const`: |
| 30 | |
| 31 | `integrate_const( stepper , system , x0 , t0 , t1 , dt )` |
| 32 | |
| 33 | `integrate_const( stepper , system , x0 , t0 , t1 , dt , observer )` |
| 34 | |
| 35 | `integrate_const( stepper , system , x0 , t0 , t1 , dt , observer , max_step_checker )` |
| 36 | |
| 37 | These integrate the ODE given by `system` with subsequent steps from `stepper`. |
| 38 | Integration start at `t0` and `x0` and ends at some ['t' = t[sub 0] + n dt] with /n/ such that ['t[sub 1] - dt < t' <= t[sub 1]]. |
| 39 | `x0` is changed to the approximative solution ['x(t')] at the end of integration. |
| 40 | If provided, the `observer` is invoked at times ['t[sub 0]], ['t[sub 0] + dt], ['t[sub 0] + 2dt], ... ,['t']. |
| 41 | If provided, the `max_step_checker` counts the number of steps between observer calls and throws a |
| 42 | `no_progress_error` this exceeds some limit (default: 500). |
| 43 | `integrate_const` returns the number of steps performed during the integration. |
| 44 | Note that if you are using a simple __stepper or __error_stepper and want to make exactly `n` steps you should prefer the `integrate_n_steps` function below. |
| 45 | |
| 46 | * If `stepper` is a __stepper or __error_stepper then `dt` is also the step size used for integration and the observer is called just after every step. |
| 47 | * If `stepper` is a __controlled_stepper then `dt` is the initial step size. |
| 48 | The actual step size will change due to error control during time evolution. |
| 49 | However, if an observer is provided the step size will be adjusted such that the algorithm always calculates /x(t)/ at ['t = t[sub 0] + n dt] and calls the observer at that point. |
| 50 | Note that the use of __controlled_stepper is reasonable here only if `dt` is considerably larger than typical step sizes used by the stepper. |
| 51 | * If `stepper` is a __dense_output_stepper then `dt` is the initial step size. |
| 52 | The actual step size will be adjusted during integration due to error control. |
| 53 | If an observer is provided dense output is used to calculate /x(t)/ at ['t = t[sub 0] + n dt]. |
| 54 | |
| 55 | [heading Integrate a given number of steps] |
| 56 | |
| 57 | This function is very similar to `integrate_const` above. The only difference |
| 58 | is that it does not take the end time as parameter, but rather the number of |
| 59 | steps. The integration is then performed until the time `t0+n*dt`. |
| 60 | |
| 61 | `integrate_n_steps( stepper , system , x0 , t0 , dt , n )` |
| 62 | |
| 63 | `integrate_n_steps( stepper , system , x0 , t0 , dt , n , observer )` |
| 64 | |
| 65 | `integrate_n_steps( stepper , system , x0 , t0 , dt , n , observer , max_step_checker )` |
| 66 | |
| 67 | Integrates the ODE given by `system` with subsequent steps from `stepper` starting at ['x[sub 0]] and ['t[sub 0]]. |
| 68 | If provided, `observer` is called after every step and at the beginning with |
| 69 | `t0`, similar as above. |
| 70 | Again, providing a `max_step_checker` will throw a `no_progress_error` if too many steps are performed |
| 71 | between observer calls. |
| 72 | The approximate result for ['x( t[sub 0] + n dt )] is stored in `x0`. |
| 73 | This function returns the end time `t0 + n*dt`. |
| 74 | |
| 75 | |
| 76 | [heading Observer calls at each step] |
| 77 | |
| 78 | If the observer should be called at each time step then the `integrate_adaptive` function should be used. |
| 79 | Note that in the case of __controlled_stepper or __dense_output_stepper this leads to non-equidistant observer calls as the step size changes. |
| 80 | |
| 81 | `integrate_adaptive( stepper , system , x0 , t0 , t1 , dt )` |
| 82 | |
| 83 | `integrate_adaptive( stepper , system , x0 , t0 , t1 , dt , observer )` |
| 84 | |
| 85 | Integrates the ODE given by `system` with subsequent steps from `stepper`. |
| 86 | Integration start at `t0` and `x0` and ends at ['t[sub 1]]. |
| 87 | `x0` is changed to the approximative solution ['x(t[sub 1])] at the end of integration. |
| 88 | If provided, the `observer` is called after each step (and before the first step at `t0`). |
| 89 | `integrate_adaptive` returns the number of steps performed during the integration. |
| 90 | |
| 91 | [note `integrate_adaptive` by design performs an observer call after each time step. Hence |
| 92 | there is no need for a _max_step_checker_ as only exactly one step is ever performed between |
| 93 | observer calls. |
| 94 | ] |
| 95 | |
| 96 | * If `stepper` is a __stepper or __error_stepper then `dt` is the step size used for integration and `integrate_adaptive` behaves like `integrate_const` except that for the last step the step size is reduced to ensure we end exactly at `t1`. |
| 97 | If provided, the observer is called at each step. |
| 98 | * If `stepper` is a __controlled_stepper then `dt` is the initial step size. |
| 99 | The actual step size is changed according to error control of the stepper. |
| 100 | For the last step, the step size will be reduced to ensure we end exactly at `t1`. |
| 101 | If provided, the observer is called after each time step (and before the first step at `t0`). |
| 102 | * If stepper is a __dense_output_stepper then `dt` is the initial step size and `integrate_adaptive` behaves just like for __controlled_stepper above. No dense output is used. |
| 103 | |
| 104 | [heading Observer calls at given time points] |
| 105 | |
| 106 | If the observer should be called at some user given time points the `integrate_times` function should be used. |
| 107 | The times for observer calls are provided as a sequence of time values. |
| 108 | The sequence is either defined via two iterators pointing to begin and end of the sequence or in terms of a __boost_range object. |
| 109 | |
| 110 | `integrate_times( stepper , system , x0 , times_start , times_end , dt , observer )` |
| 111 | |
| 112 | `integrate_times( stepper , system , x0 , time_range , dt , observer )` |
| 113 | |
| 114 | Integrates the ODE given by `system` with subsequent steps from `stepper`. |
| 115 | Integration starts at `*times_start` and ends exactly at `*(times_end-1)`. |
| 116 | `x0` contains the approximate solution at the end point of integration. |
| 117 | This function requires an observer which is invoked at the subsequent times `*times_start++` until `times_start == times_end`. |
| 118 | If called with a __boost_range `time_range` the function behaves the same with `times_start = boost::begin( time_range )` and `times_end = boost::end( time_range )`. |
| 119 | Additionally, a _max_step_checker_ can be provided, e.g.: |
| 120 | |
| 121 | `integrate_times( stepper , system , x0 , times_start , times_end , dt , observer , max_step_checker)` |
| 122 | |
| 123 | As above, this will throw a `no_progress_error` if too many steps are performed between observer calls. |
| 124 | |
| 125 | `integrate_times` returns the number of steps performed during the integration. |
| 126 | |
| 127 | * If `stepper` is a __stepper or __error_stepper `dt` is the step size used for integration. |
| 128 | However, whenever a time point from the sequence is approached the step size `dt` will be reduced to obtain the state /x(t)/ exactly at the time point. |
| 129 | * If `stepper` is a __controlled_stepper then `dt` is the initial step size. |
| 130 | The actual step size is adjusted during integration according to error control. |
| 131 | However, if a time point from the sequence is approached the step size is reduced to obtain the state /x(t)/ exactly at the time point. |
| 132 | * If `stepper` is a __dense_output_stepper then `dt` is the initial step size. |
| 133 | The actual step size is adjusted during integration according to error control. |
| 134 | Dense output is used to obtain the states /x(t)/ at the time points from the sequence. |
| 135 | |
| 136 | [heading Convenience integrate function] |
| 137 | |
| 138 | Additionally to the sophisticated integrate function above odeint also provides a simple `integrate` routine which uses a dense output stepper based on `runge_kutta_dopri5` with standard error bounds ['10[super -6]] for the steps. |
| 139 | |
| 140 | `integrate( system , x0 , t0 , t1 , dt )` |
| 141 | |
| 142 | `integrate( system , x0 , t0 , t1 , dt , observer )` |
| 143 | |
| 144 | This function behaves exactly like `integrate_adaptive` above but no stepper has to be provided. |
| 145 | It also returns the number of steps performed during the integration. |
| 146 | |
| 147 | [endsect] |