Theoretica
Scientific Computing
Loading...
Searching...
No Matches
autodiff.h
Go to the documentation of this file.
1
5
6#ifndef THEORETICA_AUTODIFF_H
7#define THEORETICA_AUTODIFF_H
8
9#include "dual.h"
10#include "dual2.h"
11#include "multidual.h"
12#include "../algebra/vec.h"
13#include "../algebra/mat.h"
14#include "../core/error.h"
15#include "../core/core_traits.h"
16#include "./autodiff_types.h"
17
18#include <functional>
19
20
21namespace theoretica {
22
24 namespace autodiff {
25
26
27 // Univariate automatic differentiation
28
29
37 template <
38 typename DualFunction = std::function<dual(dual)>,
40 >
41 inline real deriv(DualFunction f, real x) {
42 return f(dual(x, 1.0)).Dual();
43 }
44
45
54 template <
55 typename DualFunction = std::function<dual(dual)>,
57 >
58 inline auto deriv(DualFunction f) {
59
60 return [f](real x) -> real {
61 return autodiff::deriv(f, x);
62 };
63 }
64
65
73 template <
74 typename Dual2Function = std::function<dual2(dual2)>,
76 >
78 return f(dual2(x, 1.0, 0.0)).Dual2();
79 }
80
81
90 template <
91 typename Dual2Function = std::function<dual2(dual2)>,
93 >
94 inline auto deriv2(Dual2Function f) {
95
96 return [f](real x) -> real {
97 return autodiff::deriv2(f, x);
98 };
99 }
100
101
102 // Differential operators
103
104
117 template <
118 typename Function, typename Vector = vec<real>,
120 enable_vector<Vector> = true
121 >
122 inline auto gradient(Function f, const Vector& x) {
123
124 // Extract the return type of the function
125 using MultidualType = return_type_t<Function>;
126
127 constexpr size_t N = MultidualType::size_argument;
129 arg.resize(x.size());
130
131 // Iterate over each element, setting the dual part to
132 // the i-th element of the canonical base
133 for (unsigned int i = 0; i < x.size(); ++i) {
134 arg[i] = MultidualType(
135 x[i], vec<real, N>::euclidean_base(i, x.size())
136 );
137 }
138
139 return f(arg).Dual();
140 }
141
142
154 template <
155 typename Function,
157 >
158 inline auto gradient(Function f) {
159
160 constexpr size_t N = return_type_t<Function>::size_argument;
161
162 return [f](const vec<real, N>& x) {
163 return gradient(f, x);
164 };
165 }
166
167
179 template <
180 typename Function, typename Vector = vec<real>,
182 enable_vector<Vector> = true
183 >
184 inline real divergence(Function V, const Vector& x) {
185
186 using MultidualT = return_type_t<Function>;
187 const size_t N = MultidualT::size_argument;
188
189 // Sum the diagonal elements of the jacobian
191
192 real div = 0.0;
193 for (unsigned int i = 0; i < res.size(); ++i) {
194
195 // dreal numbers initialized to a scalar
196 // have an empty dual part, check the size before summing
197 if (res[i].v.size() > i)
198 div += res[i].Dual()[i];
199 }
200
201 return div;
202 }
203
204
215 template <
216 typename Function,
218 >
219 inline auto divergence(Function V) {
220
221 constexpr size_t N = return_type_t<Function>::size_argument;
222 using Vector = vec<real, N>;
223
224 return [V](const Vector& x) {
225 return divergence(V, x);
226 };
227 }
228
229
237 template <
238 typename MultidualFunction, typename Vector,
239 enable_vector<Vector> = true,
241 >
242 inline auto jacobian(MultidualFunction f, const Vector& x) {
243
244 constexpr size_t M = return_type_t<MultidualFunction>::size_argument;
245 constexpr size_t N = _internal::func_helper<MultidualFunction>::first_arg_type::size_argument;
246
248
249 // Construct the jacobian matrix
251 J.resize(res.size(), x.size());
252
253 for (unsigned int j = 0; j < J.rows(); ++j) {
254
255 const unsigned int dual_size = res[j].v.size();
256
257 if (dual_size > J.cols()) {
258 TH_MATH_ERROR("autodiff::jacobian", dual_size, MathError::InvalidArgument);
259 return algebra::mat_error(J);
260 }
261
262 unsigned int i = 0;
263 for (; i < dual_size; ++i)
264 J(j, i) = res[j].v[i];
265
266 for (; i < J.cols(); ++i)
267 J(j, i) = 0.0;
268 }
269
270 return J;
271 }
272
273
281 template<
282 typename MultidualFunction,
284 >
286
287 constexpr size_t N = return_type_t<MultidualFunction>::size_argument;
288 using Vector = vec<real, N>;
289
290 return [f](const Vector& x) {
291 return jacobian(f, x);
292 };
293 }
294
295
304 template <
305 typename MultidualFunction, typename Vector,
306 enable_vector<Vector> = true,
308 >
309 inline auto curl(MultidualFunction f, const Vector& x) {
310
311 Vector res;
312 res.resize(3);
313
314 if(x.size() != 3) {
315 TH_MATH_ERROR("th::curl", x.size(), MathError::InvalidArgument);
316 return algebra::vec_error(res);
317 }
318
319 constexpr size_t N = return_type_t<MultidualFunction>::size_argument;
320 const mat<real, N, N> J = jacobian(f, x);
321
322 res[0] = J(2, 1) - J(1, 2);
323 res[1] = J(0, 2) - J(2, 0);
324 res[2] = J(1, 0) - J(0, 1);
325
326 return res;
327 }
328
329
338 template<
339 typename MultidualFunction,
341 >
342 inline auto curl(MultidualFunction f) {
343
344 constexpr size_t N = return_type_t<MultidualFunction>::size_argument;
345 using Vector = vec<real, N>;
346
347 return [f](const Vector& x) {
348 return curl(f, x);
349 };
350 }
351
352
361 template <
362 typename Dual2Function, typename Vector,
363 enable_vector<Vector> = true
364 >
365 inline real laplacian(Dual2Function f, const Vector& x) {
366
367 // Extract size template argument of the input vector
368 constexpr size_t N = _internal::func_helper<Dual2Function>
369 ::first_arg_type::size_argument;
370
372 d.resize(x.size());
373
374 for (unsigned int i = 0; i < d.size(); ++i)
375 d[i].a = x[i];
376
377 // Accumulate second derivatives
378 real res = 0;
379 for (unsigned int i = 0; i < d.size(); ++i) {
380 d[i].b = 1;
381 res += f(d).Dual2();
382 d[i].b = 0;
383 }
384
385 return res;
386 }
387
388
397 template <typename Dual2Function>
398 inline auto laplacian(Dual2Function f) {
399
400 constexpr size_t N = _internal::func_helper<Dual2Function>
401 ::first_arg_type::size_argument;
402
403 return [f](const vec<real, N>& x) {
404 return laplacian(f, x);
405 };
406 }
407
408 }
409}
410
411#endif
Types and traits for automatic differentiation.
Second order dual number class.
Definition dual2.h:29
real Dual2() const
Return second order dual part.
Definition dual2.h:95
Dual number class.
Definition dual.h:28
A generic matrix with a fixed number of rows and columns.
Definition mat.h:136
mat< Type, N, K > resize(unsigned int n, unsigned int k)
Compatibility function to allow for allocation or resizing of dynamic matrices.
Definition mat.h:730
Multidual number algebra for functions of the form .
Definition multidual.h:26
A statically allocated N-dimensional vector with elements of the given type.
Definition vec.h:92
void resize(size_t n) const
Compatibility function to allow for allocation or resizing of dynamic vectors.
Definition vec.h:459
TH_CONSTEXPR unsigned int size() const
Returns the size of the vector (N)
Definition vec.h:449
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compilation op...
Definition error.h:219
Second order dual number class.
Dual number class.
Multidual numbers.
Matrix & mat_error(Matrix &m)
Overwrite the given matrix with the error matrix with NaN values on the diagonal and zeroes everywher...
Definition algebra.h:40
Vector & vec_error(Vector &v)
Overwrite the given vector with the error vector with NaN values.
Definition algebra.h:58
real laplacian(Dual2Function f, const Vector &x)
Compute the Laplacian differential operator for a generic function of the form at a given $\vec x$.
Definition autodiff.h:365
auto jacobian(MultidualFunction f, const Vector &x)
Compute the jacobian of a vector field of the form .
Definition autodiff.h:242
real deriv(DualFunction f, real x)
Compute the derivative of a function at the given point using univariate automatic differentiation.
Definition autodiff.h:41
auto curl(MultidualFunction f, const Vector &x)
Compute the curl for a given of a vector field defined by using automatic differentiation.
Definition autodiff.h:309
real divergence(Function V, const Vector &x)
Compute the divergence for a given of a vector field of the form using automatic differentiation.
Definition autodiff.h:184
real deriv2(Dual2Function f, real x)
Compute the second derivative of a function at the given point using univariate automatic differentia...
Definition autodiff.h:77
auto gradient(Function f, const Vector &x)
Compute the gradient for a given of a scalar field of the form using automatic differentiation.
Definition autodiff.h:122
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
double real
A real number, defined as a floating point type.
Definition constants.h:207
Vector make_error()
Create a vector representing an error state, with all NaN values.
Definition algebra.h:103
@ InvalidArgument
Invalid argument.