CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ode_err_control.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_UTILITY_ODE_ERR_CONTROL_HPP
2 # define CPPAD_UTILITY_ODE_ERR_CONTROL_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 
15 /*
16 $begin OdeErrControl$$
17 $spell
18  cppad.hpp
19  nstep
20  maxabs
21  exp
22  scur
23  CppAD
24  xf
25  tf
26  xi
27  smin
28  smax
29  eabs
30  erel
31  ef
32  ta
33  tb
34  xa
35  xb
36  const
37  eb
38 $$
39 
40 
41 
42 $section An Error Controller for ODE Solvers$$
43 $mindex OdeErrControl differential equation$$
44 
45 $head Syntax$$
46 $codei%# include <cppad/utility/ode_err_control.hpp>
47 %$$
48 $icode%xf% = OdeErrControl(%method%, %ti%, %tf%, %xi%,
49  %smin%, %smax%, %scur%, %eabs%, %erel%, %ef% , %maxabs%, %nstep% )%$$
50 
51 
52 $head Description$$
53 Let $latex \B{R}$$ denote the real numbers
54 and let $latex F : \B{R} \times \B{R}^n \rightarrow \B{R}^n$$ be a smooth function.
55 We define $latex X : [ti , tf] \rightarrow \B{R}^n$$ by
56 the following initial value problem:
57 $latex \[
58 \begin{array}{rcl}
59  X(ti) & = & xi \\
60  X'(t) & = & F[t , X(t)]
61 \end{array}
62 \] $$
63 The routine $code OdeErrControl$$ can be used to adjust the step size
64 used an arbitrary integration methods in order to be as fast as possible
65 and still with in a requested error bound.
66 
67 $head Include$$
68 The file $code cppad/ode_err_control.hpp$$ is included by
69 $code cppad/cppad.hpp$$
70 but it can also be included separately with out the rest of
71 the $code CppAD$$ routines.
72 
73 $head Notation$$
74 The template parameter types $cref/Scalar/OdeErrControl/Scalar/$$ and
75 $cref/Vector/OdeErrControl/Vector/$$ are documented below.
76 
77 $head xf$$
78 The return value $icode xf$$ has the prototype
79 $codei%
80  %Vector% %xf%
81 %$$
82 (see description of $cref/Vector/OdeErrControl/Vector/$$ below).
83 and the size of $icode xf$$ is equal to $icode n$$.
84 If $icode xf$$ contains not a number $cref nan$$,
85 see the discussion of $cref/step/OdeErrControl/Method/Nan/$$.
86 
87 $head Method$$
88 The class $icode Method$$
89 and the object $icode method$$ satisfy the following syntax
90 $codei%
91  %Method% &%method%
92 %$$
93 The object $icode method$$ must support $code step$$ and
94 $code order$$ member functions defined below:
95 
96 $subhead step$$
97 The syntax
98 $codei%
99  %method%.step(%ta%, %tb%, %xa%, %xb%, %eb%)
100 %$$
101 executes one step of the integration method.
102 $codei%
103 
104 %ta%
105 %$$
106 The argument $icode ta$$ has prototype
107 $codei%
108  const %Scalar% &%ta%
109 %$$
110 It specifies the initial time for this step in the
111 ODE integration.
112 (see description of $cref/Scalar/OdeErrControl/Scalar/$$ below).
113 $codei%
114 
115 %tb%
116 %$$
117 The argument $icode tb$$ has prototype
118 $codei%
119  const %Scalar% &%tb%
120 %$$
121 It specifies the final time for this step in the
122 ODE integration.
123 $codei%
124 
125 %xa%
126 %$$
127 The argument $icode xa$$ has prototype
128 $codei%
129  const %Vector% &%xa%
130 %$$
131 and size $icode n$$.
132 It specifies the value of $latex X(ta)$$.
133 (see description of $cref/Vector/OdeErrControl/Vector/$$ below).
134 $codei%
135 
136 %xb%
137 %$$
138 The argument value $icode xb$$ has prototype
139 $codei%
140  %Vector% &%xb%
141 %$$
142 and size $icode n$$.
143 The input value of its elements does not matter.
144 On output,
145 it contains the approximation for $latex X(tb)$$ that the method obtains.
146 $codei%
147 
148 %eb%
149 %$$
150 The argument value $icode eb$$ has prototype
151 $codei%
152  %Vector% &%eb%
153 %$$
154 and size $icode n$$.
155 The input value of its elements does not matter.
156 On output,
157 it contains an estimate for the error in the approximation $icode xb$$.
158 It is assumed (locally) that the error bound in this approximation
159 nearly equal to $latex K (tb - ta)^m$$
160 where $icode K$$ is a fixed constant and $icode m$$
161 is the corresponding argument to $code CodeControl$$.
162 
163 $subhead Nan$$
164 If any element of the vector $icode eb$$ or $icode xb$$ are
165 not a number $code nan$$,
166 the current step is considered to large.
167 If this happens with the current step size equal to $icode smin$$,
168 $code OdeErrControl$$ returns with $icode xf$$ and $icode ef$$ as vectors
169 of $code nan$$.
170 
171 $subhead order$$
172 If $icode m$$ is $code size_t$$,
173 the object $icode method$$ must also support the following syntax
174 $codei%
175  %m% = %method%.order()
176 %$$
177 The return value $icode m$$ is the order of the error estimate;
178 i.e., there is a constant K such that if $latex ti \leq ta \leq tb \leq tf$$,
179 $latex \[
180  | eb(tb) | \leq K | tb - ta |^m
181 \] $$
182 where $icode ta$$, $icode tb$$, and $icode eb$$ are as in
183 $icode%method%.step(%ta%, %tb%, %xa%, %xb%, %eb%)%$$
184 
185 
186 $head ti$$
187 The argument $icode ti$$ has prototype
188 $codei%
189  const %Scalar% &%ti%
190 %$$
191 It specifies the initial time for the integration of
192 the differential equation.
193 
194 
195 $head tf$$
196 The argument $icode tf$$ has prototype
197 $codei%
198  const %Scalar% &%tf%
199 %$$
200 It specifies the final time for the integration of
201 the differential equation.
202 
203 $head xi$$
204 The argument $icode xi$$ has prototype
205 $codei%
206  const %Vector% &%xi%
207 %$$
208 and size $icode n$$.
209 It specifies value of $latex X(ti)$$.
210 
211 $head smin$$
212 The argument $icode smin$$ has prototype
213 $codei%
214  const %Scalar% &%smin%
215 %$$
216 The step size during a call to $icode method$$ is defined as
217 the corresponding value of $latex tb - ta$$.
218 If $latex tf - ti \leq smin$$,
219 the integration will be done in one step of size $icode tf - ti$$.
220 Otherwise,
221 the minimum value of $icode tb - ta$$ will be $latex smin$$
222 except for the last two calls to $icode method$$ where it may be
223 as small as $latex smin / 2$$.
224 
225 $head smax$$
226 The argument $icode smax$$ has prototype
227 $codei%
228  const %Scalar% &%smax%
229 %$$
230 It specifies the maximum step size to use during the integration;
231 i.e., the maximum value for $latex tb - ta$$ in a call to $icode method$$.
232 The value of $icode smax$$ must be greater than or equal $icode smin$$.
233 
234 $head scur$$
235 The argument $icode scur$$ has prototype
236 $codei%
237  %Scalar% &%scur%
238 %$$
239 The value of $icode scur$$ is the suggested next step size,
240 based on error criteria, to try in the next call to $icode method$$.
241 On input it corresponds to the first call to $icode method$$,
242 in this call to $code OdeErrControl$$ (where $latex ta = ti$$).
243 On output it corresponds to the next call to $icode method$$,
244 in a subsequent call to $code OdeErrControl$$ (where $icode ta = tf$$).
245 
246 $head eabs$$
247 The argument $icode eabs$$ has prototype
248 $codei%
249  const %Vector% &%eabs%
250 %$$
251 and size $icode n$$.
252 Each of the elements of $icode eabs$$ must be
253 greater than or equal zero.
254 It specifies a bound for the absolute
255 error in the return value $icode xf$$ as an approximation for $latex X(tf)$$.
256 (see the
257 $cref/error criteria discussion/OdeErrControl/Error Criteria Discussion/$$
258 below).
259 
260 $head erel$$
261 The argument $icode erel$$ has prototype
262 $codei%
263  const %Scalar% &%erel%
264 %$$
265 and is greater than or equal zero.
266 It specifies a bound for the relative
267 error in the return value $icode xf$$ as an approximation for $latex X(tf)$$
268 (see the
269 $cref/error criteria discussion/OdeErrControl/Error Criteria Discussion/$$
270 below).
271 
272 $head ef$$
273 The argument value $icode ef$$ has prototype
274 $codei%
275  %Vector% &%ef%
276 %$$
277 and size $icode n$$.
278 The input value of its elements does not matter.
279 On output,
280 it contains an estimated bound for the
281 absolute error in the approximation $icode xf$$; i.e.,
282 $latex \[
283  ef_i > | X( tf )_i - xf_i |
284 \] $$
285 If on output $icode ef$$ contains not a number $code nan$$,
286 see the discussion of $cref/step/OdeErrControl/Method/Nan/$$.
287 
288 $head maxabs$$
289 The argument $icode maxabs$$ is optional in the call to $code OdeErrControl$$.
290 If it is present, it has the prototype
291 $codei%
292  %Vector% &%maxabs%
293 %$$
294 and size $icode n$$.
295 The input value of its elements does not matter.
296 On output,
297 it contains an estimate for the
298 maximum absolute value of $latex X(t)$$; i.e.,
299 $latex \[
300  maxabs[i] \approx \max \left\{
301  | X( t )_i | \; : \; t \in [ti, tf]
302  \right\}
303 \] $$
304 
305 $head nstep$$
306 The argument $icode nstep$$ is optional in the call to $code OdeErrControl$$.
307 If it is present, it has the prototype
308 $codei%
309  %size_t% &%nstep%
310 %$$
311 Its input value does not matter and its output value
312 is the number of calls to $icode%method%.step%$$
313 used by $code OdeErrControl$$.
314 
315 $head Error Criteria Discussion$$
316 The relative error criteria $icode erel$$ and
317 absolute error criteria $icode eabs$$ are enforced during each step of the
318 integration of the ordinary differential equations.
319 In addition, they are inversely scaled by the step size so that
320 the total error bound is less than the sum of the error bounds.
321 To be specific, if $latex \tilde{X} (t)$$ is the approximate solution
322 at time $latex t$$,
323 $icode ta$$ is the initial step time,
324 and $icode tb$$ is the final step time,
325 $latex \[
326 \left| \tilde{X} (tb)_j - X (tb)_j \right|
327 \leq
328 \frac{tf - ti}{tb - ta}
329 \left[ eabs[j] + erel \; | \tilde{X} (tb)_j | \right]
330 \] $$
331 If $latex X(tb)_j$$ is near zero for some $latex tb \in [ti , tf]$$,
332 and one uses an absolute error criteria $latex eabs[j]$$ of zero,
333 the error criteria above will force $code OdeErrControl$$
334 to use step sizes equal to
335 $cref/smin/OdeErrControl/smin/$$
336 for steps ending near $latex tb$$.
337 In this case, the error relative to $icode maxabs$$ can be judged after
338 $code OdeErrControl$$ returns.
339 If $icode ef$$ is to large relative to $icode maxabs$$,
340 $code OdeErrControl$$ can be called again
341 with a smaller value of $icode smin$$.
342 
343 $head Scalar$$
344 The type $icode Scalar$$ must satisfy the conditions
345 for a $cref NumericType$$ type.
346 The routine $cref CheckNumericType$$ will generate an error message
347 if this is not the case.
348 In addition, the following operations must be defined for
349 $icode Scalar$$ objects $icode a$$ and $icode b$$:
350 
351 $table
352 $bold Operation$$ $cnext $bold Description$$ $rnext
353 $icode%a% <= %b%$$ $cnext
354  returns true (false) if $icode a$$ is less than or equal
355  (greater than) $icode b$$.
356 $rnext
357 $icode%a% == %b%$$ $cnext
358  returns true (false) if $icode a$$ is equal to $icode b$$.
359 $rnext
360 $codei%log(%a%)%$$ $cnext
361  returns a $icode Scalar$$ equal to the logarithm of $icode a$$
362 $rnext
363 $codei%exp(%a%)%$$ $cnext
364  returns a $icode Scalar$$ equal to the exponential of $icode a$$
365 $tend
366 
367 
368 $head Vector$$
369 The type $icode Vector$$ must be a $cref SimpleVector$$ class with
370 $cref/elements of type Scalar/SimpleVector/Elements of Specified Type/$$.
371 The routine $cref CheckSimpleVector$$ will generate an error message
372 if this is not the case.
373 
374 $head Example$$
375 $children%
376  example/utility/ode_err_control.cpp%
377  example/utility/ode_err_maxabs.cpp
378 %$$
379 The files
380 $cref ode_err_control.cpp$$
381 and
382 $cref ode_err_maxabs.cpp$$
383 contain examples and tests of using this routine.
384 They return true if they succeed and false otherwise.
385 
386 $head Theory$$
387 Let $latex e(s)$$ be the error as a function of the
388 step size $latex s$$ and suppose that there is a constant
389 $latex K$$ such that $latex e(s) = K s^m$$.
390 Let $latex a$$ be our error bound.
391 Given the value of $latex e(s)$$, a step of size $latex \lambda s$$
392 would be ok provided that
393 $latex \[
394 \begin{array}{rcl}
395  a & \geq & e( \lambda s ) (tf - ti) / ( \lambda s ) \\
396  a & \geq & K \lambda^m s^m (tf - ti) / ( \lambda s ) \\
397  a & \geq & \lambda^{m-1} s^{m-1} (tf - ti) e(s) / s^m \\
398  a & \geq & \lambda^{m-1} (tf - ti) e(s) / s \\
399  \lambda^{m-1} & \leq & \frac{a}{e(s)} \frac{s}{tf - ti}
400 \end{array}
401 \] $$
402 Thus if the right hand side of the last inequality is greater
403 than or equal to one, the step of size $latex s$$ is ok.
404 
405 $head Source Code$$
406 The source code for this routine is in the file
407 $code cppad/ode_err_control.hpp$$.
408 
409 $end
410 --------------------------------------------------------------------------
411 */
412 
413 // link exp and log for float and double
414 # include <cppad/base_require.hpp>
415 
416 # include <cppad/core/cppad_assert.hpp>
418 # include <cppad/utility/nan.hpp>
419 
420 namespace CppAD { // Begin CppAD namespace
421 
422 template <typename Scalar, typename Vector, typename Method>
424  Method &method,
425  const Scalar &ti ,
426  const Scalar &tf ,
427  const Vector &xi ,
428  const Scalar &smin ,
429  const Scalar &smax ,
430  Scalar &scur ,
431  const Vector &eabs ,
432  const Scalar &erel ,
433  Vector &ef ,
434  Vector &maxabs,
435  size_t &nstep )
436 {
437  // check simple vector class specifications
438  CheckSimpleVector<Scalar, Vector>();
439 
440  size_t n = size_t(xi.size());
441 
443  smin <= smax,
444  "Error in OdeErrControl: smin > smax"
445  );
447  size_t(eabs.size()) == n,
448  "Error in OdeErrControl: size of eabs is not equal to n"
449  );
451  size_t(maxabs.size()) == n,
452  "Error in OdeErrControl: size of maxabs is not equal to n"
453  );
454  size_t m = method.order();
456  m > 1,
457  "Error in OdeErrControl: m is less than or equal one"
458  );
459 
460  bool ok;
461  bool minimum_step;
462  size_t i;
463  Vector xa(n), xb(n), eb(n), nan_vec(n);
464 
465  // initialization
466  Scalar zero(0.0);
467  Scalar one(1.0);
468  Scalar two(2.0);
469  Scalar three(3.0);
470  Scalar m1(double(m-1));
471  Scalar ta = ti;
472  for(i = 0; i < n; i++)
473  { nan_vec[i] = nan(zero);
474  ef[i] = zero;
475  xa[i] = xi[i];
476  if( zero <= xi[i] )
477  maxabs[i] = xi[i];
478  else maxabs[i] = - xi[i];
479 
480  }
481  nstep = 0;
482 
483  Scalar tb, step, lambda, axbi, a, r, root;
484  while( ! (ta == tf) )
485  { // start with value suggested by error criteria
486  step = scur;
487 
488  // check maximum
489  if( smax <= step )
490  step = smax;
491 
492  // check minimum
493  minimum_step = step <= smin;
494  if( minimum_step )
495  step = smin;
496 
497  // check if near the end
498  if( tf <= ta + step * three / two )
499  tb = tf;
500  else tb = ta + step;
501 
502  // try using this step size
503  nstep++;
504  method.step(ta, tb, xa, xb, eb);
505  step = tb - ta;
506 
507  // check if this steps error estimate is ok
508  ok = ! (hasnan(xb) || hasnan(eb));
509  if( (! ok) && minimum_step )
510  { ef = nan_vec;
511  return nan_vec;
512  }
513 
514  // compute value of lambda for this step
515  lambda = Scalar(10) * scur / step;
516  for(i = 0; i < n; i++)
517  { if( zero <= xb[i] )
518  axbi = xb[i];
519  else axbi = - xb[i];
520  a = eabs[i] + erel * axbi;
521  if( ! (eb[i] == zero) )
522  { r = ( a / eb[i] ) * step / (tf - ti);
523  root = exp( log(r) / m1 );
524  if( root <= lambda )
525  lambda = root;
526  }
527  }
528  if( ok && ( one <= lambda || step <= smin * three / two) )
529  { // this step is within error limits or
530  // close to the minimum size
531  ta = tb;
532  for(i = 0; i < n; i++)
533  { xa[i] = xb[i];
534  ef[i] = ef[i] + eb[i];
535  if( zero <= xb[i] )
536  axbi = xb[i];
537  else axbi = - xb[i];
538  if( axbi > maxabs[i] )
539  maxabs[i] = axbi;
540  }
541  }
542  if( ! ok )
543  { // decrease step an see if method will work this time
544  scur = step / two;
545  }
546  else if( ! (ta == tf) )
547  { // step suggested by the error criteria is not used
548  // on the last step because it may be very small.
549  scur = lambda * step / two;
550  }
551  }
552  return xa;
553 }
554 
555 template <typename Scalar, typename Vector, typename Method>
557  Method &method,
558  const Scalar &ti ,
559  const Scalar &tf ,
560  const Vector &xi ,
561  const Scalar &smin ,
562  const Scalar &smax ,
563  Scalar &scur ,
564  const Vector &eabs ,
565  const Scalar &erel ,
566  Vector &ef )
567 { Vector maxabs(xi.size());
568  size_t nstep;
569  return OdeErrControl(
570  method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep
571  );
572 }
573 
574 template <typename Scalar, typename Vector, typename Method>
576  Method &method,
577  const Scalar &ti ,
578  const Scalar &tf ,
579  const Vector &xi ,
580  const Scalar &smin ,
581  const Scalar &smax ,
582  Scalar &scur ,
583  const Vector &eabs ,
584  const Scalar &erel ,
585  Vector &ef ,
586  Vector &maxabs)
587 { size_t nstep;
588  return OdeErrControl(
589  method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep
590  );
591 }
592 
593 } // End CppAD namespace
594 
595 # endif
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
AD< Base > log(const AD< Base > &x)
Scalar nan(const Scalar &zero)
Definition: nan.hpp:187
Define the CppAD error checking macros (all of which begin with CPPAD_ASSERT_)
AD< Base > exp(const AD< Base > &x)
bool hasnan(const Vector &v)
Definition: nan.hpp:174
Vector OdeErrControl(Method &method, const Scalar &ti, const Scalar &tf, const Vector &xi, const Scalar &smin, const Scalar &smax, Scalar &scur, const Vector &eabs, const Scalar &erel, Vector &ef, Vector &maxabs, size_t &nstep)