Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/general/autodiff.hpp
3206 views
1
#ifndef FILE_AUTODIFF
2
#define FILE_AUTODIFF
3
4
/**************************************************************************/
5
/* File: autodiff.hpp */
6
/* Author: Joachim Schoeberl */
7
/* Date: 24. Oct. 02 */
8
/**************************************************************************/
9
10
// Automatic differentiation datatype
11
12
13
/**
14
Datatype for automatic differentiation.
15
Contains function value and D derivatives. Algebraic
16
operations are overloaded by using product-rule etc. etc.
17
**/
18
template <int D, typename SCAL = double>
19
class AutoDiff
20
{
21
SCAL val;
22
SCAL dval[D];
23
public:
24
25
typedef AutoDiff<D,SCAL> TELEM;
26
typedef SCAL TSCAL;
27
28
29
/// elements are undefined
30
AutoDiff () throw() { };
31
// { val = 0; for (int i = 0; i < D; i++) dval[i] = 0; } // !
32
33
/// copy constructor
34
AutoDiff (const AutoDiff & ad2) throw()
35
{
36
val = ad2.val;
37
for (int i = 0; i < D; i++)
38
dval[i] = ad2.dval[i];
39
}
40
41
/// initial object with constant value
42
AutoDiff (SCAL aval) throw()
43
{
44
val = aval;
45
for (int i = 0; i < D; i++)
46
dval[i] = 0;
47
}
48
49
/// init object with (val, e_diffindex)
50
AutoDiff (SCAL aval, int diffindex) throw()
51
{
52
val = aval;
53
for (int i = 0; i < D; i++)
54
dval[i] = 0;
55
dval[diffindex] = 1;
56
}
57
58
/// assign constant value
59
AutoDiff & operator= (SCAL aval) throw()
60
{
61
val = aval;
62
for (int i = 0; i < D; i++)
63
dval[i] = 0;
64
return *this;
65
}
66
67
/// returns value
68
SCAL Value() const throw() { return val; }
69
70
/// returns partial derivative
71
SCAL DValue (int i) const throw() { return dval[i]; }
72
73
/// access value
74
SCAL & Value() throw() { return val; }
75
76
/// accesses partial derivative
77
SCAL & DValue (int i) throw() { return dval[i]; }
78
79
///
80
AutoDiff<D,SCAL> & operator+= (const AutoDiff<D,SCAL> & y) throw()
81
{
82
val += y.val;
83
for (int i = 0; i < D; i++)
84
dval[i] += y.dval[i];
85
return *this;
86
}
87
88
///
89
AutoDiff<D,SCAL> & operator-= (const AutoDiff<D,SCAL> & y) throw()
90
{
91
val -= y.val;
92
for (int i = 0; i < D; i++)
93
dval[i] -= y.dval[i];
94
return *this;
95
96
}
97
98
///
99
AutoDiff<D,SCAL> & operator*= (const AutoDiff<D,SCAL> & y) throw()
100
{
101
for (int i = 0; i < D; i++)
102
{
103
// dval[i] *= y.val;
104
// dval[i] += val * y.dval[i];
105
dval[i] = dval[i] * y.val + val * y.dval[i];
106
}
107
val *= y.val;
108
return *this;
109
}
110
111
///
112
AutoDiff<D,SCAL> & operator*= (const SCAL & y) throw()
113
{
114
val *= y;
115
for (int i = 0; i < D; i++)
116
dval[i] *= y;
117
return *this;
118
}
119
120
///
121
AutoDiff<D,SCAL> & operator/= (const SCAL & y) throw()
122
{
123
SCAL iy = 1.0 / y;
124
val *= iy;
125
for (int i = 0; i < D; i++)
126
dval[i] *= iy;
127
return *this;
128
}
129
130
///
131
bool operator== (SCAL val2) throw()
132
{
133
return val == val2;
134
}
135
136
///
137
bool operator!= (SCAL val2) throw()
138
{
139
return val != val2;
140
}
141
142
///
143
bool operator< (SCAL val2) throw()
144
{
145
return val < val2;
146
}
147
148
///
149
bool operator> (SCAL val2) throw()
150
{
151
return val > val2;
152
}
153
};
154
155
156
//@{ AutoDiff helper functions.
157
158
/// prints AutoDiff
159
template<int D, typename SCAL>
160
inline ostream & operator<< (ostream & ost, const AutoDiff<D,SCAL> & x)
161
{
162
ost << x.Value() << ", D = ";
163
for (int i = 0; i < D; i++)
164
ost << x.DValue(i) << " ";
165
return ost;
166
}
167
168
/// AutoDiff plus AutoDiff
169
template<int D, typename SCAL>
170
inline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()
171
{
172
AutoDiff<D,SCAL> res;
173
res.Value () = x.Value()+y.Value();
174
// AutoDiff<D,SCAL> res(x.Value()+y.Value());
175
for (int i = 0; i < D; i++)
176
res.DValue(i) = x.DValue(i) + y.DValue(i);
177
return res;
178
}
179
180
181
/// AutoDiff minus AutoDiff
182
template<int D, typename SCAL>
183
inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()
184
{
185
AutoDiff<D,SCAL> res;
186
res.Value() = x.Value()-y.Value();
187
// AutoDiff<D,SCAL> res (x.Value()-y.Value());
188
for (int i = 0; i < D; i++)
189
res.DValue(i) = x.DValue(i) - y.DValue(i);
190
return res;
191
}
192
193
/// double plus AutoDiff
194
template<int D, typename SCAL>
195
inline AutoDiff<D,SCAL> operator+ (double x, const AutoDiff<D,SCAL> & y) throw()
196
{
197
AutoDiff<D,SCAL> res;
198
res.Value() = x+y.Value();
199
for (int i = 0; i < D; i++)
200
res.DValue(i) = y.DValue(i);
201
return res;
202
}
203
204
/// AutoDiff plus double
205
template<int D, typename SCAL>
206
inline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & y, double x) throw()
207
{
208
AutoDiff<D,SCAL> res;
209
res.Value() = x+y.Value();
210
for (int i = 0; i < D; i++)
211
res.DValue(i) = y.DValue(i);
212
return res;
213
}
214
215
216
/// minus AutoDiff
217
template<int D, typename SCAL>
218
inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x) throw()
219
{
220
AutoDiff<D,SCAL> res;
221
res.Value() = -x.Value();
222
for (int i = 0; i < D; i++)
223
res.DValue(i) = -x.DValue(i);
224
return res;
225
}
226
227
/// AutoDiff minus double
228
template<int D, typename SCAL>
229
inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, double y) throw()
230
{
231
AutoDiff<D,SCAL> res;
232
res.Value() = x.Value()-y;
233
for (int i = 0; i < D; i++)
234
res.DValue(i) = x.DValue(i);
235
return res;
236
}
237
238
///
239
template<int D, typename SCAL>
240
inline AutoDiff<D,SCAL> operator- (double x, const AutoDiff<D,SCAL> & y) throw()
241
{
242
AutoDiff<D,SCAL> res;
243
res.Value() = x-y.Value();
244
for (int i = 0; i < D; i++)
245
res.DValue(i) = -y.DValue(i);
246
return res;
247
}
248
249
250
/// double times AutoDiff
251
template<int D, typename SCAL>
252
inline AutoDiff<D,SCAL> operator* (double x, const AutoDiff<D,SCAL> & y) throw()
253
{
254
AutoDiff<D,SCAL> res;
255
res.Value() = x*y.Value();
256
for (int i = 0; i < D; i++)
257
res.DValue(i) = x*y.DValue(i);
258
return res;
259
}
260
261
/// AutoDiff times double
262
template<int D, typename SCAL>
263
inline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & y, double x) throw()
264
{
265
AutoDiff<D,SCAL> res;
266
res.Value() = x*y.Value();
267
for (int i = 0; i < D; i++)
268
res.DValue(i) = x*y.DValue(i);
269
return res;
270
}
271
272
/// AutoDiff times AutoDiff
273
template<int D, typename SCAL>
274
inline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()
275
{
276
AutoDiff<D,SCAL> res;
277
SCAL hx = x.Value();
278
SCAL hy = y.Value();
279
280
res.Value() = hx*hy;
281
for (int i = 0; i < D; i++)
282
res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i);
283
284
return res;
285
}
286
287
/// AutoDiff times AutoDiff
288
template<int D, typename SCAL>
289
inline AutoDiff<D,SCAL> sqr (const AutoDiff<D,SCAL> & x) throw()
290
{
291
AutoDiff<D,SCAL> res;
292
SCAL hx = x.Value();
293
res.Value() = hx*hx;
294
hx *= 2;
295
for (int i = 0; i < D; i++)
296
res.DValue(i) = hx*x.DValue(i);
297
return res;
298
}
299
300
/// Inverse of AutoDiff
301
template<int D, typename SCAL>
302
inline AutoDiff<D,SCAL> Inv (const AutoDiff<D,SCAL> & x)
303
{
304
AutoDiff<D,SCAL> res(1.0 / x.Value());
305
for (int i = 0; i < D; i++)
306
res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value());
307
return res;
308
}
309
310
311
/// AutoDiff div AutoDiff
312
template<int D, typename SCAL>
313
inline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y)
314
{
315
return x * Inv (y);
316
}
317
318
/// AutoDiff div double
319
template<int D, typename SCAL>
320
inline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, double y)
321
{
322
return (1/y) * x;
323
}
324
325
/// double div AutoDiff
326
template<int D, typename SCAL>
327
inline AutoDiff<D,SCAL> operator/ (double x, const AutoDiff<D,SCAL> & y)
328
{
329
return x * Inv(y);
330
}
331
332
333
334
335
template<int D, typename SCAL>
336
inline AutoDiff<D,SCAL> fabs (const AutoDiff<D,SCAL> & x)
337
{
338
double abs = fabs (x.Value());
339
AutoDiff<D,SCAL> res( abs );
340
if (abs != 0.0)
341
for (int i = 0; i < D; i++)
342
res.DValue(i) = x.DValue(i) / abs;
343
else
344
for (int i = 0; i < D; i++)
345
res.DValue(i) = 0.0;
346
return res;
347
}
348
349
//@}
350
351
#endif
352
353