CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
romberg_mul.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_UTILITY_ROMBERG_MUL_HPP
2 # define CPPAD_UTILITY_ROMBERG_MUL_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 $begin RombergMul$$
16 $spell
17  cppad.hpp
18  bool
19  const
20  Cpp
21  RombergMulMul
22 $$
23 
24 $section Multi-dimensional Romberg Integration$$
25 $mindex integrate multi dimensional dimension$$
26 
27 
28 $head Syntax$$
29 $codei%# include <cppad/utility/romberg_mul.hpp>
30 %$$
31 $codei%RombergMul<%Fun%, %SizeVector%, %FloatVector%, %m%> %R%$$
32 $pre
33 $$
34 $icode%r% = %R%(%F%, %a%, %b%, %n%, %p%, %e%)%$$
35 
36 
37 $head Description$$
38 Returns the Romberg integration estimate
39 $latex r$$ for the multi-dimensional integral
40 $latex \[
41 r =
42 \int_{a[0]}^{b[0]} \cdots \int_{a[m-1]}^{b[m-1]}
43 \; F(x) \;
44 {\bf d} x_0 \cdots {\bf d} x_{m-1}
45 \; + \;
46 \sum_{i=0}^{m-1}
47 O \left[ ( b[i] - a[i] ) / 2^{n[i]-1} \right]^{2(p[i]+1)}
48 \] $$
49 
50 $head Include$$
51 The file $code cppad/romberg_mul.hpp$$ is included by $code cppad/cppad.hpp$$
52 but it can also be included separately with out the rest of
53 the $code CppAD$$ routines.
54 
55 $head m$$
56 The template parameter $icode m$$ must be convertible to a $code size_t$$
57 object with a value that can be determined at compile time; for example
58 $code 2$$.
59 It determines the dimension of the domain space for the integration.
60 
61 $head r$$
62 The return value $icode r$$ has prototype
63 $codei%
64  %Float% %r%
65 %$$
66 It is the estimate computed by $code RombergMul$$ for the integral above
67 (see description of $cref/Float/RombergMul/Float/$$ below).
68 
69 $head F$$
70 The object $icode F$$ has the prototype
71 $codei%
72  %Fun% &%F%
73 %$$
74 It must support the operation
75 $codei%
76  %F%(%x%)
77 %$$
78 The argument $icode x$$ to $icode F$$ has prototype
79 $codei%
80  const %Float% &%x%
81 %$$
82 The return value of $icode F$$ is a $icode Float$$ object
83 
84 $head a$$
85 The argument $icode a$$ has prototype
86 $codei%
87  const %FloatVector% &%a%
88 %$$
89 It specifies the lower limit for the integration
90 (see description of $cref/FloatVector/RombergMul/FloatVector/$$ below).
91 
92 $head b$$
93 The argument $icode b$$ has prototype
94 $codei%
95  const %FloatVector% &%b%
96 %$$
97 It specifies the upper limit for the integration.
98 
99 $head n$$
100 The argument $icode n$$ has prototype
101 $codei%
102  const %SizeVector% &%n%
103 %$$
104 A total number of $latex 2^{n[i]-1} + 1$$
105 evaluations of $icode%F%(%x%)%$$ are used to estimate the integral
106 with respect to $latex {\bf d} x_i$$.
107 
108 $head p$$
109 The argument $icode p$$ has prototype
110 $codei%
111  const %SizeVector% &%p%
112 %$$
113 For $latex i = 0 , \ldots , m-1$$,
114 $latex n[i]$$ determines the accuracy order in the
115 approximation for the integral
116 that is returned by $code RombergMul$$.
117 The values in $icode p$$ must be less than or equal $icode n$$; i.e.,
118 $icode%p%[%i%] <= %n%[%i%]%$$.
119 
120 $head e$$
121 The argument $icode e$$ has prototype
122 $codei%
123  %Float% &%e%
124 %$$
125 The input value of $icode e$$ does not matter
126 and its output value is an approximation for the absolute error in
127 the integral estimate.
128 
129 $head Float$$
130 The type $icode Float$$ is defined as the type of the elements of
131 $cref/FloatVector/RombergMul/FloatVector/$$.
132 The type $icode Float$$ must satisfy the conditions
133 for a $cref NumericType$$ type.
134 The routine $cref CheckNumericType$$ will generate an error message
135 if this is not the case.
136 In addition, if $icode x$$ and $icode y$$ are $icode Float$$ objects,
137 $codei%
138  %x% < %y%
139 %$$
140 returns the $code bool$$ value true if $icode x$$ is less than
141 $icode y$$ and false otherwise.
142 
143 $head FloatVector$$
144 The type $icode FloatVector$$ must be a $cref SimpleVector$$ class.
145 The routine $cref CheckSimpleVector$$ will generate an error message
146 if this is not the case.
147 
148 
149 $children%
150  example/utility/romberg_mul.cpp
151 %$$
152 $head Example$$
153 $comment%
154  example/utility/romberg_mul.cpp
155 %$$
156 The file
157 $cref Rombergmul.cpp$$
158 contains an example and test a test of using this routine.
159 It returns true if it succeeds and false otherwise.
160 
161 $head Source Code$$
162 The source code for this routine is in the file
163 $code cppad/romberg_mul.hpp$$.
164 
165 $end
166 */
167 
171 
172 namespace CppAD { // BEGIN CppAD namespace
173 
174 template <class Fun, class FloatVector>
175 class SliceLast {
176  typedef typename FloatVector::value_type Float;
177 private:
178  Fun *F;
179  size_t last;
180  FloatVector x;
181 public:
182  SliceLast( Fun *F_, size_t last_, const FloatVector &x_ )
183  : F(F_) , last(last_), x(last + 1)
184  { size_t i;
185  for(i = 0; i < last; i++)
186  x[i] = x_[i];
187  }
188  double operator()(const Float &xlast)
189  { x[last] = xlast;
190  return (*F)(x);
191  }
192 };
193 
194 template <class Fun, class SizeVector, class FloatVector, class Float>
196 private:
197  Fun *F;
198  const size_t last;
199  const FloatVector a;
200  const FloatVector b;
201  const SizeVector n;
202  const SizeVector p;
203  Float esum;
204  size_t ecount;
205 
206 public:
208  Fun *F_ ,
209  size_t last_ ,
210  const FloatVector &a_ ,
211  const FloatVector &b_ ,
212  const SizeVector &n_ ,
213  const SizeVector &p_ )
214  : F(F_) , last(last_), a(a_) , b(b_) , n(n_) , p(p_)
215  { }
216  Float operator()(const FloatVector &x)
217  { Float r, e;
219  r = CppAD::RombergOne(
220  S, a[last], b[last], n[last], p[last], e
221  );
222  esum = esum + e;
223  ecount++;
224  return r;
225  }
226  void ClearEsum(void)
227  { esum = 0.; }
228  Float GetEsum(void)
229  { return esum; }
230 
231  void ClearEcount(void)
232  { ecount = 0; }
233  size_t GetEcount(void)
234  { return ecount; }
235 };
236 
237 template <class Fun, class SizeVector, class FloatVector, size_t m>
238 class RombergMul {
239  typedef typename FloatVector::value_type Float;
240 public:
242  { }
244  Fun &F ,
245  const FloatVector &a ,
246  const FloatVector &b ,
247  const SizeVector &n ,
248  const SizeVector &p ,
249  Float &e )
250  { Float r;
251 
252  typedef IntegrateLast<
253  Fun ,
254  SizeVector ,
255  FloatVector ,
256  Float > IntegrateOne;
257 
258  IntegrateOne Fm1(&F, m-1, a, b, n, p);
259  RombergMul<
260  IntegrateOne,
261  SizeVector ,
262  FloatVector ,
263  m-1 > RombergMulM1;
264 
265  Fm1.ClearEsum();
266  Fm1.ClearEcount();
267 
268  r = RombergMulM1(Fm1, a, b, n, p, e);
269 
270  size_t i, j;
271  Float prod = 1;
272  size_t pow2 = 1;
273  for(i = 0; i < m-1; i++)
274  { prod *= (b[i] - a[i]);
275  for(j = 0; j < (n[i] - 1); j++)
276  pow2 *= 2;
277  }
278  assert( Fm1.GetEcount() == (pow2+1) );
279 
280  e = e + Fm1.GetEsum() * prod / Float( double(Fm1.GetEcount()) );
281 
282  return r;
283  }
284 };
285 
286 template <class Fun, class SizeVector, class FloatVector>
287 class RombergMul <Fun, SizeVector, FloatVector, 1> {
288  typedef typename FloatVector::value_type Float;
289 public:
291  Fun &F ,
292  const FloatVector &a ,
293  const FloatVector &b ,
294  const SizeVector &n ,
295  const SizeVector &p ,
296  Float &e )
297  { Float r;
298  typedef IntegrateLast<
299  Fun ,
300  SizeVector ,
301  FloatVector ,
302  Float > IntegrateOne;
303 
304  // check simple vector class specifications
305  CheckSimpleVector<Float, FloatVector>();
306 
307  // check numeric type specifications
308  CheckNumericType<Float>();
309 
310  IntegrateOne F0(&F, 0, a, b, n, p);
311 
312  F0.ClearEsum();
313  F0.ClearEcount();
314 
315  r = F0(a);
316 
317  assert( F0.GetEcount() == 1 );
318  e = F0.GetEsum();
319 
320  return r;
321  }
322 };
323 
324 } // END CppAD namespace
325 
326 # endif
size_t GetEcount(void)
const SizeVector p
FloatVector::value_type Float
SliceLast(Fun *F_, size_t last_, const FloatVector &x_)
const FloatVector a
double operator()(const Float &xlast)
Float operator()(const FloatVector &x)
Float operator()(Fun &F, const FloatVector &a, const FloatVector &b, const SizeVector &n, const SizeVector &p, Float &e)
Float RombergOne(Fun &F, const Float &a, const Float &b, size_t n, size_t p, Float &e)
const SizeVector n
const FloatVector b
IntegrateLast(Fun *F_, size_t last_, const FloatVector &a_, const FloatVector &b_, const SizeVector &n_, const SizeVector &p_)
Scalar value_type
FloatVector::value_type Float