Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
high_order_example.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Sacado Package
4 //
5 // Copyright 2006 NTESS and the Sacado contributors.
6 // SPDX-License-Identifier: LGPL-2.1-or-later
7 // *****************************************************************************
8 // @HEADER
9 
10 // high_order_example
11 //
12 // usage:
13 // high_order_example
14 //
15 // output:
16 // computes a high-order derivative of a simple function along a small set
17 // of directions/modes using DFad, and then computes the same thing through
18 // the multivariate chain rule.
19 
20 #include <iostream>
21 
22 #include "Sacado.hpp"
23 
25 
26 // Function to compute derivatives of
27 template <typename Scalar>
28 Scalar func(const int m, const Scalar x[]) {
29  using std::exp;
30  Scalar z = 1.0;
31  for (int i=0; i<m; ++i)
32  z *= x[i];
33  return exp(z);
34 }
35 
36 // Build nested Fad type for computing derivatives up to order N
37 template <int N>
38 struct MakeFad {
39  // Replace double in FadType with MakeFad<N-1>::type
40  typedef typename MakeFad<N-1>::type nested_type;
42 
43  // Initialize Fad for computation of full derivative
44  static type apply(const int n, const int i, const double x) {
45  return type(n,i,MakeFad<N-1>::apply(n,i,x));
46  }
47 
48  // Initialize Fad object for derivative-matrix product
49  static type apply(const int n, const double x, const double v[]) {
50  type x_fad(n,MakeFad<N-1>::apply(n,x,v));
51  for (int i=0; i<n; ++i)
52  x_fad.fastAccessDx(i) = v[i];
53  return x_fad;
54  }
55 };
56 template <>
57 struct MakeFad<1> {
58  typedef FadType type;
59 
60  // Initialize Fad for computation of full derivative
61  static type apply(const int n, const int i, const double x) {
62  return type(n,i,x);
63  }
64 
65  // Initialize Fad object for derivative-matrix product
66  static type apply(const int n, const double x, const double v[]) {
67  type x_fad(n,x);
68  for (int i=0; i<n; ++i)
69  x_fad.fastAccessDx(i) = v[i];
70  return x_fad;
71  }
72 };
73 
74 // Extract d^r/(dx_k_1 ... dx_k_r) where the sequence k_1 ... k_r is indicated
75 // by the passed iterator (e.g., iterator into a std::vector)
76 template <typename TermIterator>
77 double
78 extract_derivative(const double& x, TermIterator term, TermIterator term_end)
79 {
80  return x;
81 }
82 template <typename T, typename TermIterator>
83 double
84 extract_derivative(const T& x, TermIterator term, TermIterator term_end)
85 {
86  // If there are no terms, return value
87  if (term == term_end)
89 
90  // Get the first term
91  auto k = *term;
92 
93  // Extract remaining terms
94  return extract_derivative(x.fastAccessDx(k), ++term, term_end);
95 }
96 
97 int main(int argc, char **argv)
98 {
99  const int deg = 6; // Order of derivative to compute
100  const int m = 3; // Number of coordinates
101  const int n = 2; // Number of modes
102  const double x0[m] = { 1.0, 1.0, 1.0 }; // Expansion point
103  const double V[m][n] = { {0.1, 0.2},
104  {0.3, 0.4},
105  {0.5, 0.6} }; // Mode coordinates
106 
107  // Derivative term we wish to extract. This corresponds to the derivative
108  // d^6/(ds_0 ds_0 ds_0 ds_1 ds_1 ds_1) = d^6/(ds_0^3 ds_1^3)
109  std::vector<int> term = { 0, 0, 0, 1, 1, 1 };
110 
111  // For y = f(x(s)), x(s) = x0 + V*s, compute
112  // d^r y / (ds_i_1 ... ds_i_r) where (i_1,...,i_r) is indicated by term
113  typedef typename MakeFad<deg>::type NestedFadType;
114  NestedFadType x_fad[m];
115  for (int i=0; i<m; ++i)
116  x_fad[i] = MakeFad<deg>::apply(n,x0[i],V[i]);
117  const NestedFadType f_fad = func(m,x_fad);
118  const double z1 = extract_derivative(f_fad, term.begin(), term.end());
119 
120  // Now compute the same thing by first computing
121  // d^k y / (dx_j_1 .. dx_j_k) for 0 <= k <= deg and j_1,...,j_k = 0,...,m-1
122  NestedFadType x_fad2[m];
123  for (int i=0; i<m; ++i)
124  x_fad2[i] = MakeFad<deg>::apply(m,i,x0[i]);
125  const NestedFadType f_fad2 = func(m,x_fad2);
126 
127  // Now compute multivariate chain-rule:
128  // d^r y / (ds_i_1 ... ds_i_r) =
129  // \sum_{j_1,...,j_r=0}^{m-1} d^r y/(dx_j_1 .. dx_j_r) *
130  // V[j_1][i_1]...V[j_r][i_r].
131  // This requires iterating (j_1,...,j_r) over the m^r-dimensional tensor
132  // product space [0,m-1] x ... x [0,m-1]
133  double z2 = 0.0;
134  const int r = term.size();
135  std::vector<int> t(r, 0);
136  bool finished = false;
137  while (!finished) {
138  const double z = extract_derivative(f_fad2, t.begin(), t.end());
139  double c = 1.0;
140  for (int i=0; i<r; ++i) {
141  c *= V[t[i]][term[i]];
142  }
143  z2 += z*c;
144 
145  // Increment t to next term in tensor product space
146  ++t[0];
147  int j=0;
148  while (j<r-1 && t[j] >= m) {
149  t[j] = 0;
150  ++j;
151  ++t[j];
152  }
153  if (t[r-1] == m)
154  finished = true;
155  }
156 
157  const double error = std::abs(z1-z2)/std::abs(z2);
158  std::cout << "z (reduced) = " << z1 << " z (full) = " << z2
159  << " error = " << error << std::endl;
160 
161  const double tol = 1.0e-14;
162  if (error < tol) {
163  std::cout << "\nExample passed!" << std::endl;
164  return 0;
165  }
166 
167  std::cout <<"\nSomething is wrong, example failed!" << std::endl;
168  return 1;
169 }
static SACADO_INLINE_FUNCTION const T & eval(const T &x)
static type apply(const int n, const double x, const double v[])
abs(expr.val())
static type apply(const int n, const int i, const double x)
MakeFad< N-1 >::type nested_type
Sacado::Fad::DFad< double > FadType
F::template apply< A1, A2, A3, A4, A5 >::type type
static type apply(const int n, const double x, const double v[])
#define T
Definition: Sacado_rad.hpp:553
expr expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c *expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr2 expr1 expr1 expr1 c
int main()
Definition: ad_example.cpp:171
const int N
std::string error
Definition: GTestSuite.cpp:13
Uncopyable z
double extract_derivative(const double &x, TermIterator term, TermIterator term_end)
const double tol
const T func(int n, T *x)
Definition: ad_example.cpp:29
Sacado::mpl::apply< FadType, nested_type >::type type
static type apply(const int n, const int i, const double x)
exp(expr.val())
int n