Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ad_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 // Brief demo of Fad and Rad for computing first derivatives
11 
12 #include <Sacado_No_Kokkos.hpp> // for FAD and RAD
13 #include <cstdio> // nicer than streams in some respects
14 using std::printf;
15 
16 using namespace std;
17 
18 // Typedefs reduce gobbledygook below
19 
20 typedef Sacado::Fad::DFad<double> F; // FAD with # of ind. vars given later
21 typedef Sacado::Fad::SFad<double,2> F2; // FAD with # of ind. vars fixed at 2
22 typedef Sacado::Rad::ADvar<double> R; // for RAD
23 
24 template <typename T>
25 const T func2(T &a, T &b) // sample function of 2 variables
26 { return sqrt(a*a + 2*b*b); }
27 
28 template <typename T>
29 const T func(int n, T *x) // sample function of n variables
30  // == func2 when n == 2
31 {
32  int i;
33  T t = 0;
34  for(i = 1; i < n; i++)
35  t += i*x[i]*x[i];
36  return sqrt(t);
37  }
38 
39 // demo of FAD (forward-mode AD), with general number of ind. vars
40 
41  void
43 {
44  F a, b, x[5], y;
45  int i, n;
46 
47  printf("Fad_demo...\n\n");
48 
49  // first try n == 2
50  a = 1.;
51  b = 2.;
52  // indicate the independent variables, and initialize their partials to 1:
53  a.diff(0,2); // 0 ==> this is the first independent var., of 2
54  b.diff(1,2); // 1 ==> this is the second ind. var.
55 
56  y = func2(a,b);
57 
58  printf("func2(%g,%g) = %g\n", a.val(), b.val(), y.val());
59 
60  printf("partials of func2 = %g, %g\n", y.dx(0), y.dx(1));
61 
62  // When we know the result was not constant (i.e., did involve ind. vars)
63  // or when hasFastAccess() is true, we access partials more quickly
64  // by using member function fastAccessDx rather than dx
65 
66  if (y.hasFastAccess())
67  printf("Repeat with fastAccess: partials of func2 = %g, %g\n",
68  y.fastAccessDx(0), y.fastAccessDx(1));
69 
70  // Similar exercise with general n, in this case n == 5
71  n = 5;
72  for(i = 0; i < n; i++) {
73  x[i] = i;
74  x[i].diff(i, n);
75  }
76  y = func(n, x);
77  printf("\nfunc(5,x) for x = (0,1,2,3,4) = %g\n", y.val());
78  for(i = 0; i < n; i++)
79  printf("d func / d x[%d] = %g == %g\n", i, y.dx(i), y.fastAccessDx(i));
80  }
81 
82 // Fad_demo2 == repeat first part of Fad_Demo with type F2 instead of F
83 // i.e., with fixed-size allocations
84 
85  void
87 {
88  F2 a, b, y;
89 
90  printf("\n\nFad2_demo...\n\n");
91 
92  a = 1.;
93  b = 2.;
94  // indicate the independent variables, and initialize their partials to 1:
95  a.diff(0,2); // 0 ==> this is the first independent var., of 2
96  b.diff(1,2); // 1 ==> this is the second ind. var.
97 
98  y = func2(a,b);
99 
100  printf("func2(%g,%g) = %g\n", a.val(), b.val(), y.val());
101 
102  printf("partials of func2 = %g, %g\n", y.dx(0), y.dx(1));
103 
104  if (y.hasFastAccess())
105  printf("Repeat with fastAccess: partials of func2 = %g, %g\n",
106  y.fastAccessDx(0), y.fastAccessDx(1));
107  }
108 
109 // Fad_demo3 == repeat of Fad_Demo2 with a different constructor, one that
110 // indicates the independent variables and their initial values
111 // and removes the need to invoke .diff()
112 
113  void
115 {
116  F2 a(2,0,1.), b(2,1,2.), y;
117 
118  printf("\n\nFad3_demo...\n\n");
119 
120  y = func2(a,b);
121 
122  printf("func2(%g,%g) = %g\n", a.val(), b.val(), y.val());
123 
124  printf("partials of func2 = %g, %g\n", y.dx(0), y.dx(1));
125 
126  if (y.hasFastAccess())
127  printf("Repeat with fastAccess: partials of func2 = %g, %g\n",
128  y.fastAccessDx(0), y.fastAccessDx(1));
129  }
130 
131 // Rad_demo == repeat of Fad_Demo with type R instead of F,
132 // i.e., with reverse-mode rather than forward-mode AD
133 
134  void
136 {
137  R a, b, x[5], y;
138  int i, n;
139 
140  printf("\n\nRad_demo...\n\n");
141 
142  // first try n == 2
143  a = 1.;
144  b = 2.;
145 
146  y = func2(a,b);
147 
148  R::Gradcomp(); // do the reverse sweep
149 
150  printf("func2(%g,%g) = %g\n", a.val(), b.val(), y.val());
151 
152  printf("partials of func2 = %g, %g\n", a.adj(), b.adj());
153 
154  // Similar exercise with general n, in this case n == 5
155  n = 5;
156  for(i = 0; i < n; i++)
157  x[i] = i;
158  y = func(n, x);
159  printf("\nfunc(5,x) for x = (0,1,2,3,4) = %g\n", y.val());
160 
161  // the .val() values are always available; we must call Gradcomp
162  // before accessing the adjoints, i.e., the .adj() values...
163 
164  R::Gradcomp();
165 
166  for(i = 0; i < n; i++)
167  printf("d func / d x[%d] = %g\n", i, x[i].adj());
168  }
169 
170  int
172 {
173  Fad_demo();
174  Fad2_demo();
175  Fad3_demo();
176  Rad_demo();
177  return 0;
178  }
Sacado::Fad::DFad< double > F
Definition: ad_example.cpp:20
void Fad_demo()
Definition: ad_example.cpp:42
const T func2(T &a, T &b)
Definition: ad_example.cpp:25
void Fad3_demo()
Definition: ad_example.cpp:114
void Fad2_demo()
Definition: ad_example.cpp:86
Sacado::Rad::ADvar< double > R
Definition: ad_example.cpp:22
#define T
Definition: Sacado_rad.hpp:553
int main()
Definition: ad_example.cpp:171
sqrt(expr.val())
Sacado::Fad::SFad< double, 2 > F2
Definition: ad_example.cpp:21
const T func(int n, T *x)
Definition: ad_example.cpp:29
void Rad_demo()
Definition: ad_example.cpp:135
int n
const double y