/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/model/ad.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/model/ad.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
ad.hh
Go to the documentation of this file.
1#pragma once
2
3// DiFfRG
6
7// external libraries
8#include <autodiff/forward/dual.hpp>
9#include <autodiff/forward/real.hpp>
10#include <deal.II/base/point.h>
11#include <deal.II/base/tensor.h>
12#include <deal.II/lac/full_matrix.h>
13#include <deal.II/lac/vector.h>
14#include <tbb/tbb.h>
15
16namespace DiFfRG
17{
18 namespace def
19 {
20 using namespace dealii;
21 using std::get;
22
23 namespace internal
24 {
25 template <typename AD_type> struct AD_tools;
26
27 template <> struct AD_tools<autodiff::dual> {
28 template <uint n, typename Vector> static std::array<autodiff::dual, n> vector_to_AD(const Vector &v)
29 {
30 std::array<autodiff::dual, n> x;
31 for (uint i = 0; i < n; ++i) {
32 x[i] = v[i];
33 }
34 return x;
35 }
36
37 // Any indexable container of dealii::Tensor works: CG hands in a std::vector, the KT-FV
38 // assembler a std::array. Rank and dimension are read off the element type.
39 template <uint n, typename Container> static auto ten_to_AD(const Container &v)
40 {
41 using TensorType = std::decay_t<decltype(v[0])>;
42 constexpr int r = static_cast<int>(TensorType::rank);
43 constexpr int dim = static_cast<int>(TensorType::dimension);
44 static_assert(r >= 1 && r <= 2, "Only rank 1 and 2 tensors are supported.");
45 std::array<dealii::Tensor<r, dim, autodiff::dual>, n> x;
46 for (uint i = 0; i < n; ++i) {
47 if constexpr (r == 1)
48 for (uint d = 0; d < dim; ++d)
49 x[i][d] = v[i][d];
50 else if constexpr (r == 2)
51 for (uint d1 = 0; d1 < dim; ++d1)
52 for (uint d2 = 0; d2 < dim; ++d2) {
53 x[i][d1][d2] = v[i][d1][d2];
54 }
55 }
56 return x;
57 }
58 };
59
60 template <> struct AD_tools<autodiff::real> {
61 template <uint n, typename Vector> static std::array<autodiff::real, n> vector_to_AD(const Vector &v)
62 {
63 std::array<autodiff::real, n> x;
64 for (uint i = 0; i < n; ++i)
65 x[i] = v[i];
66 return x;
67 }
68
69 // Any indexable container of dealii::Tensor works: CG hands in a std::vector, the KT-FV
70 // assembler a std::array. Rank and dimension are read off the element type.
71 template <uint n, typename Container> static auto ten_to_AD(const Container &v)
72 {
73 using TensorType = std::decay_t<decltype(v[0])>;
74 constexpr int r = static_cast<int>(TensorType::rank);
75 constexpr int dim = static_cast<int>(TensorType::dimension);
76 static_assert(r >= 1 && r <= 2, "Only rank 1 and 2 tensors are supported.");
77 std::array<dealii::Tensor<r, dim, autodiff::real>, n> x;
78 for (uint i = 0; i < n; ++i) {
79 if constexpr (r == 1) {
80 for (uint d = 0; d < dim; ++d)
81 x[i][d] = v[i][d];
82 } else if constexpr (r == 2) {
83 for (uint d1 = 0; d1 < dim; ++d1)
84 for (uint d2 = 0; d2 < dim; ++d2) {
85 x[i][d1][d2] = v[i][d1][d2];
86 }
87 }
88 }
89 return x;
90 }
91 };
92 } // namespace internal
93
94 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_flux
95 {
96 Model &asImp() { return static_cast<Model &>(*this); }
97 const Model &asImp() const { return static_cast<const Model &>(*this); }
99
100 public:
101 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
102 void jacobian_flux_grad(SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from> &jF, const Point<dim> &p,
103 const Vector &sol) const
104 {
105 using Components = typename Model::Components;
106 static_assert(n_to == Components::count_fe_functions(),
107 "jacobian_flux_grad: n_to must equal count_fe_functions()");
108 static_assert(n_from == Components::count_fe_functions(),
109 "jacobian_flux_grad: n_from must equal count_fe_functions()");
110
111 const auto &u = get<tup_idx>(sol);
112 auto du = AD_tools::template ten_to_AD<n_from>(u);
113 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
115 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
116 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
117 for (uint d = 0; d < dim; ++d) {
118 res = {};
119 seed(du[j][d]);
120 asImp().flux(res, p, Vector::as(ad_sol));
121 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
122 for (uint dd = 0; dd < dim; ++dd) {
123 jF(i, j)[dd][d] = grad(res[i][dd]);
124 }
125 }
126 unseed(du[j][d]);
127 }
128 }
129 }
130
131 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
132 void jacobian_flux_hess(SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from> &jF, const Point<dim> &p,
133 const Vector &sol) const
134 {
135 using Components = typename Model::Components;
136 static_assert(n_to == Components::count_fe_functions(),
137 "jacobian_flux_hess: n_to must equal count_fe_functions()");
138 static_assert(n_from == Components::count_fe_functions(),
139 "jacobian_flux_hess: n_from must equal count_fe_functions()");
140
141 const auto &u = get<tup_idx>(sol);
142 auto du = AD_tools::template ten_to_AD<n_from>(u);
143 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
145 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
146 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
147 for (uint d1 = 0; d1 < dim; ++d1)
148 for (uint d2 = 0; d2 < dim; ++d2) {
149 res = {};
150 seed(du[j][d1][d2]);
151 asImp().flux(res, p, Vector::as(ad_sol));
152 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
153 for (uint d = 0; d < dim; ++d) {
154 jF(i, j)[d][d1][d2] = grad(res[i][d]);
155 }
156 }
157 unseed(du[j][d1][d2]);
158 }
159 }
160 }
161
162 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
163 void jacobian_flux_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jF, const Point<dim> &p,
164 const Vector &sol) const
165 {
166 using Components = typename Model::Components;
167 static_assert(n_to == Components::count_fe_functions(),
168 "jacobian_flux_extr: n_to must equal count_fe_functions()");
169 static_assert(n_from == Components::count_extractors(),
170 "jacobian_flux_extr: n_from must equal count_extractors()");
171
172 const auto &e = get<tup_idx>(sol);
173 auto de = AD_tools::template vector_to_AD<n_from>(e);
174 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(de),
176 for (uint j = 0; j < Components::count_extractors(); ++j) {
177 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
178 seed(de[j]);
179 asImp().flux(res, p, Vector::as(ad_sol));
180 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
181 for (uint d = 0; d < dim; ++d) {
182 jF(i, j)[d] = grad(res[i][d]);
183 }
184 }
185 unseed(de[j]);
186 }
187 }
188
189 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
190 void jacobian_flux(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jF, const Point<dim> &p,
191 const Vector &sol) const
192 {
193 using Components = typename Model::Components;
194 static_assert(n_to == Components::count_fe_functions(to),
195 "jacobian_flux: n_to must equal count_fe_functions(to)");
196 static_assert(n_from == Components::count_fe_functions(from),
197 "jacobian_flux: n_from must equal count_fe_functions(from)");
198
199 if constexpr (to == 0) {
200 const auto &u = get<from>(sol);
201 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(u);
202 auto ad_sol = std::tuple_cat(tuple_first<from>(sol), std::tie(du),
204 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
205 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
206 seed(du[j]);
207 asImp().flux(res, p, Vector::as(ad_sol));
208 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
209 for (uint d = 0; d < dim; ++d) {
210 jF(i, j)[d] = grad(res[i][d]);
211 }
212 }
213 unseed(du[j]);
214 }
215 } else {
216 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(sol);
217 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
218 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
219 // take derivative with respect to jth variable
220 seed(du[j]);
221 asImp().template ldg_flux<to>(res, p, du);
222 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
223 for (uint d = 0; d < dim; ++d) {
224 jF(i, j)[d] = grad(res[i][d]);
225 }
226 }
227 unseed(du[j]);
228 }
229 }
230 }
231 };
232
233 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_source
234 {
235 Model &asImp() { return static_cast<Model &>(*this); }
236 const Model &asImp() const { return static_cast<const Model &>(*this); }
238
239 public:
240 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
241 void jacobian_source_grad(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jS, const Point<dim> &p,
242 const Vector &sol) const
243 {
244 using Components = typename Model::Components;
245 static_assert(n_to == Components::count_fe_functions(),
246 "jacobian_source_grad: n_to must equal count_fe_functions()");
247 static_assert(n_from == Components::count_fe_functions(),
248 "jacobian_source_grad: n_from must equal count_fe_functions()");
249
250 const auto &u = get<tup_idx>(sol);
251 auto du = AD_tools::template ten_to_AD<n_from>(u);
252 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
254 std::array<AD_type, Components::count_fe_functions()> res{{}};
255 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
256 for (uint d = 0; d < dim; ++d) {
257 res = {};
258 seed(du[j][d]);
259 asImp().source(res, p, Vector::as(ad_sol));
260 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
261 jS(i, j)[d] = grad(res[i]);
262 }
263 unseed(du[j][d]);
264 }
265 }
266 }
267
268 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
269 void jacobian_source_hess(SimpleMatrix<Tensor<2, dim, NT>, n_to, n_from> &jS, const Point<dim> &p,
270 const Vector &sol) const
271 {
272 using Components = typename Model::Components;
273 static_assert(n_to == Components::count_fe_functions(),
274 "jacobian_source_hess: n_to must equal count_fe_functions()");
275 static_assert(n_from == Components::count_fe_functions(),
276 "jacobian_source_hess: n_from must equal count_fe_functions()");
277
278 const auto &u = get<tup_idx>(sol);
279 auto du = AD_tools::template ten_to_AD<n_from>(u);
280 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
282 std::array<AD_type, Components::count_fe_functions()> res{{}};
283 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
284 for (uint d1 = 0; d1 < dim; ++d1) {
285 for (uint d2 = 0; d2 < dim; ++d2) {
286 res = {};
287 seed(du[j][d1][d2]);
288 asImp().source(res, p, Vector::as(ad_sol));
289 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
290 jS(i, j)[d1][d2] = grad(res[i]);
291 }
292 unseed(du[j][d1][d2]);
293 }
294 }
295 }
296 }
297
298 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
299 void jacobian_source_extr(SimpleMatrix<NT, n_to, n_from> &jS, const Point<dim> &p, const Vector &sol) const
300 {
301 using Components = typename Model::Components;
302 static_assert(n_to == Components::count_fe_functions(),
303 "jacobian_source_extr: n_to must equal count_fe_functions()");
304 static_assert(n_from == Components::count_extractors(),
305 "jacobian_source_extr: n_from must equal count_extractors()");
306
307 const auto &e = get<tup_idx>(sol);
308 auto de = AD_tools::template vector_to_AD<n_from>(e);
309 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(de),
311 for (uint j = 0; j < n_from; ++j) {
312 std::array<AD_type, Components::count_fe_functions()> res{{}};
313 seed(de[j]);
314 asImp().source(res, p, Vector::as(ad_sol));
315 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
316 jS(i, j) = grad(res[i]);
317 }
318 unseed(de[j]);
319 }
320 }
321
322 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
323 void jacobian_source(SimpleMatrix<NT, n_to, n_from> &jS, const Point<dim> &p, const Vector &sol) const
324 {
325 using Components = typename Model::Components;
326 static_assert(n_to == Components::count_fe_functions(to),
327 "jacobian_source: n_to must equal count_fe_functions(to)");
328 static_assert(n_from == Components::count_fe_functions(from),
329 "jacobian_source: n_from must equal count_fe_functions(from)");
330
331 if constexpr (to == 0) {
332 const auto &u = get<from>(sol);
333 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(u);
334 auto ad_sol = std::tuple_cat(tuple_first<from>(sol), std::tie(du),
336 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
337 std::array<AD_type, Components::count_fe_functions(to)> res{{}};
338 seed(du[j]);
339 asImp().source(res, p, Vector::as(ad_sol));
340 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
341 jS(i, j) = grad(res[i]);
342 }
343 unseed(du[j]);
344 }
345 } else {
346 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(sol);
347 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
348 std::array<AD_type, Components::count_fe_functions(to)> res{{}};
349 // take derivative with respect to jth variable
350 seed(du[j]);
351 asImp().template ldg_source<to>(res, p, du);
352 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
353 jS(i, j) = grad(res[i]);
354 }
355 unseed(du[j]);
356 }
357 }
358 }
359 };
360
361 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_flux_source
362 {
363 Model &asImp() { return static_cast<Model &>(*this); }
364 const Model &asImp() const { return static_cast<const Model &>(*this); }
366
367 public:
368 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
369 void jacobian_flux_source(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jF, SimpleMatrix<NT, n_to, n_from> &jS,
370 const Point<dim> &p, const Vector &sol) const
371 {
372 using Components = typename Model::Components;
373 static_assert(n_to == Components::count_fe_functions(to),
374 "jacobian_flux_source: n_to must equal count_fe_functions(to)");
375 static_assert(n_from == Components::count_fe_functions(from),
376 "jacobian_flux_source: n_from must equal count_fe_functions(from)");
377
378 if constexpr (to == 0) {
379 const auto &u = get<from>(sol);
380 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(u);
381 auto ad_sol = std::tuple_cat(tuple_first<from>(sol), std::tie(du),
383 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
384 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res_flux{{}};
385 std::array<AD_type, Components::count_fe_functions(to)> res_source{{}};
386 seed(du[j]);
387 asImp().flux(res_flux, p, Vector::as(ad_sol));
388 asImp().source(res_source, p, Vector::as(ad_sol));
389 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
390 for (uint d = 0; d < dim; ++d)
391 jF(i, j)[d] = grad(res_flux[i][d]);
392 jS(i, j) = grad(res_source[i]);
393 }
394 unseed(du[j]);
395 }
396 } else {
397 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(sol);
398 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
399 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res_flux{{}};
400 std::array<AD_type, Components::count_fe_functions(to)> res_source{{}};
401 seed(du[j]);
402 asImp().template ldg_flux<to>(res_flux, p, du);
403 asImp().template ldg_source<to>(res_source, p, du);
404 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
405 for (uint d = 0; d < dim; ++d)
406 jF(i, j)[d] = grad(res_flux[i][d]);
407 jS(i, j) = grad(res_source[i]);
408 }
409 unseed(du[j]);
410 }
411 }
412 }
413
414 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
415 void jacobian_flux_source_grad(SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from> &jF,
416 SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jS, const Point<dim> &p,
417 const Vector &sol) const
418 {
419 using Components = typename Model::Components;
420 static_assert(n_to == Components::count_fe_functions(),
421 "jacobian_flux_source_grad: n_to must equal count_fe_functions()");
422 static_assert(n_from == Components::count_fe_functions(),
423 "jacobian_flux_source_grad: n_from must equal count_fe_functions()");
424
425 const auto &u = get<tup_idx>(sol);
426 auto du = AD_tools::template ten_to_AD<n_from>(u);
427 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
429 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res_flux{{}};
430 std::array<AD_type, Components::count_fe_functions()> res_source{{}};
431 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
432 for (uint d = 0; d < dim; ++d) {
433 res_flux = {};
434 res_source = {};
435 seed(du[j][d]);
436 asImp().flux(res_flux, p, Vector::as(ad_sol));
437 asImp().source(res_source, p, Vector::as(ad_sol));
438 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
439 for (uint dd = 0; dd < dim; ++dd)
440 jF(i, j)[dd][d] = grad(res_flux[i][dd]);
441 jS(i, j)[d] = grad(res_source[i]);
442 }
443 unseed(du[j][d]);
444 }
445 }
446 }
447
448 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
449 void jacobian_flux_source_hess(SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from> &jF,
450 SimpleMatrix<Tensor<2, dim, NT>, n_to, n_from> &jS, const Point<dim> &p,
451 const Vector &sol) const
452 {
453 using Components = typename Model::Components;
454 static_assert(n_to == Components::count_fe_functions(),
455 "jacobian_flux_source_hess: n_to must equal count_fe_functions()");
456 static_assert(n_from == Components::count_fe_functions(),
457 "jacobian_flux_source_hess: n_from must equal count_fe_functions()");
458
459 const auto &u = get<tup_idx>(sol);
460 auto du = AD_tools::template ten_to_AD<n_from>(u);
461 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
463 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res_flux{{}};
464 std::array<AD_type, Components::count_fe_functions()> res_source{{}};
465 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
466 for (uint d1 = 0; d1 < dim; ++d1) {
467 for (uint d2 = 0; d2 < dim; ++d2) {
468 res_flux = {};
469 res_source = {};
470 seed(du[j][d1][d2]);
471 asImp().flux(res_flux, p, Vector::as(ad_sol));
472 asImp().source(res_source, p, Vector::as(ad_sol));
473 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
474 for (uint d = 0; d < dim; ++d)
475 jF(i, j)[d][d1][d2] = grad(res_flux[i][d]);
476 jS(i, j)[d1][d2] = grad(res_source[i]);
477 }
478 unseed(du[j][d1][d2]);
479 }
480 }
481 }
482 }
483
484 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
485 void jacobian_flux_source_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jF,
486 SimpleMatrix<NT, n_to, n_from> &jS, const Point<dim> &p,
487 const Vector &sol) const
488 {
489 using Components = typename Model::Components;
490 static_assert(n_to == Components::count_fe_functions(),
491 "jacobian_flux_source_extr: n_to must equal count_fe_functions()");
492 static_assert(n_from == Components::count_extractors(),
493 "jacobian_flux_source_extr: n_from must equal count_extractors()");
494
495 const auto &e = get<tup_idx>(sol);
496 auto de = AD_tools::template vector_to_AD<n_from>(e);
497 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(de),
499 for (uint j = 0; j < Components::count_extractors(); ++j) {
500 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res_flux{{}};
501 std::array<AD_type, Components::count_fe_functions()> res_source{{}};
502 seed(de[j]);
503 asImp().flux(res_flux, p, Vector::as(ad_sol));
504 asImp().source(res_source, p, Vector::as(ad_sol));
505 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
506 for (uint d = 0; d < dim; ++d)
507 jF(i, j)[d] = grad(res_flux[i][d]);
508 jS(i, j) = grad(res_source[i]);
509 }
510 unseed(de[j]);
511 }
512 }
513 };
514
515 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_numflux
516 {
517 Model &asImp() { return static_cast<Model &>(*this); }
518 const Model &asImp() const { return static_cast<const Model &>(*this); }
520
521 public:
522 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
523 void jacobian_numflux_grad(std::array<SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from>, 2> &jNF,
524 const Tensor<1, dim> &normal, const Point<dim> &p, const Vector_s &sol_s,
525 const Vector_n &sol_n) const
526 {
527 using Components = typename Model::Components;
528 static_assert(n_to == Components::count_fe_functions(),
529 "jacobian_numflux_grad: n_to must equal count_fe_functions()");
530 static_assert(n_from == Components::count_fe_functions(),
531 "jacobian_numflux_grad: n_from must equal count_fe_functions()");
532
533 const auto &u_s = get<tup_idx>(sol_s);
534 const auto &u_n = get<tup_idx>(sol_n);
535
536 auto du_s = AD_tools::template ten_to_AD<n_from>(u_s);
537 auto ad_sol_s = std::tuple_cat(tuple_first<tup_idx>(sol_s), std::tie(du_s),
539 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
540 for (uint d = 0; d < dim; ++d) {
541 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
542 seed(du_s[j][d]);
543 asImp().numflux(res, normal, p, Vector_s::as(ad_sol_s), sol_n);
544 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
545 for (uint dd = 0; dd < dim; ++dd) {
546 jNF[0](i, j)[dd][d] = grad(res[i][dd]);
547 }
548 }
549 unseed(du_s[j][d]);
550 }
551 }
552 auto du_n = AD_tools::template ten_to_AD<n_from>(u_n);
553 auto ad_sol_n = std::tuple_cat(tuple_first<tup_idx>(sol_n), std::tie(du_n),
555 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
556 for (uint d = 0; d < dim; ++d) {
557 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
558 seed(du_n[j][d]);
559 asImp().numflux(res, normal, p, sol_s, Vector_n::as(ad_sol_n));
560 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
561 for (uint dd = 0; dd < dim; ++dd) {
562 jNF[1](i, j)[dd][d] = grad(res[i][dd]);
563 }
564 }
565 unseed(du_n[j][d]);
566 }
567 }
568 }
569
570 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
571 void jacobian_numflux_hess(std::array<SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from>, 2> &jNF,
572 const Tensor<1, dim> &normal, const Point<dim> &p, const Vector_s &sol_s,
573 const Vector_n &sol_n) const
574 {
575 using Components = typename Model::Components;
576 static_assert(n_to == Components::count_fe_functions(),
577 "jacobian_numflux_hess: n_to must equal count_fe_functions()");
578 static_assert(n_from == Components::count_fe_functions(),
579 "jacobian_numflux_hess: n_from must equal count_fe_functions()");
580
581 const auto &u_s = get<tup_idx>(sol_s);
582 const auto &u_n = get<tup_idx>(sol_n);
583
584 auto du_s = AD_tools::template ten_to_AD<n_from>(u_s);
585 auto ad_sol_s = std::tuple_cat(tuple_first<tup_idx>(sol_s), std::tie(du_s),
587 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
588 for (uint d1 = 0; d1 < dim; ++d1)
589 for (uint d2 = 0; d2 < dim; ++d2) {
590 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
591 seed(du_s[j][d1][d2]);
592 asImp().numflux(res, normal, p, Vector_s::as(ad_sol_s), sol_n);
593 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
594 for (uint d = 0; d < dim; ++d) {
595 jNF[0](i, j)[d][d1][d2] = grad(res[i][d]);
596 }
597 }
598 unseed(du_s[j][d1][d2]);
599 }
600 }
601 auto du_n = AD_tools::template ten_to_AD<n_from>(u_n);
602 auto ad_sol_n = std::tuple_cat(tuple_first<tup_idx>(sol_n), std::tie(du_n),
604 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
605 for (uint d1 = 0; d1 < dim; ++d1)
606 for (uint d2 = 0; d2 < dim; ++d2) {
607 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
608 seed(du_n[j][d1][d2]);
609 asImp().numflux(res, normal, p, sol_s, Vector_n::as(ad_sol_n));
610 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
611 for (uint d = 0; d < dim; ++d) {
612 jNF[1](i, j)[d][d1][d2] = grad(res[i][d]);
613 }
614 }
615 unseed(du_n[j][d1][d2]);
616 }
617 }
618 }
619
620 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
621 void jacobian_numflux_extr(std::array<SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from>, 2> &jNF,
622 const Tensor<1, dim> &normal, const Point<dim> &p, const Vector_s &sol_s,
623 const Vector_n &sol_n) const
624 {
625 using Components = typename Model::Components;
626 static_assert(n_to == Components::count_fe_functions(),
627 "jacobian_numflux_extr: n_to must equal count_fe_functions()");
628 static_assert(n_from == Components::count_extractors(),
629 "jacobian_numflux_extr: n_from must equal count_extractors()");
630
631 const auto &e = get<tup_idx>(sol_s);
632 auto de = AD_tools::template vector_to_AD<n_from>(e);
633 auto ad_sol_s = std::tuple_cat(tuple_first<tup_idx>(sol_s), std::tie(de),
635 auto ad_sol_n = std::tuple_cat(tuple_first<tup_idx>(sol_n), std::tie(de),
637 for (uint j = 0; j < n_from; ++j) {
638 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res_s{{}};
639 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res_n{{}};
640 seed(de[j]);
641 asImp().numflux(res_s, normal, p, Vector_s::as(ad_sol_s), sol_n);
642 asImp().numflux(res_n, normal, p, sol_s, Vector_n::as(ad_sol_n));
643 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
644 for (uint d = 0; d < dim; ++d) {
645 jNF[0](i, j)[d] = grad(res_s[i][d]);
646 jNF[1](i, j)[d] = grad(res_n[i][d]);
647 }
648 }
649 unseed(de[j]);
650 }
651 }
652
653 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
654 void jacobian_numflux(std::array<SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from>, 2> &jNF,
655 const Tensor<1, dim> &normal, const Point<dim> &p, const Vector_s &sol_s,
656 const Vector_n &sol_n) const
657 {
658 using Components = typename Model::Components;
659 static_assert(n_to == Components::count_fe_functions(to),
660 "jacobian_numflux: n_to must equal count_fe_functions(to)");
661 static_assert(n_from == Components::count_fe_functions(from),
662 "jacobian_numflux: n_from must equal count_fe_functions(from)");
663
664 if constexpr (to == 0) {
665 const auto &u_s = get<from>(sol_s);
666 const auto &u_n = get<from>(sol_n);
667
668 auto du_s = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(u_s);
669 auto ad_sol_s = std::tuple_cat(tuple_first<from>(sol_s), std::tie(du_s),
671 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
672 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
673 seed(du_s[j]);
674 asImp().numflux(res, normal, p, Vector_s::as(ad_sol_s), sol_n);
675 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
676 for (uint d = 0; d < dim; ++d) {
677 jNF[0](i, j)[d] = grad(res[i][d]);
678 }
679 }
680 unseed(du_s[j]);
681 }
682 auto du_n = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(u_n);
683 auto ad_sol_n = std::tuple_cat(tuple_first<from>(sol_n), std::tie(du_n),
685 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
686 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
687 seed(du_n[j]);
688 asImp().numflux(res, normal, p, sol_s, Vector_n::as(ad_sol_n));
689 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
690 for (uint d = 0; d < dim; ++d) {
691 jNF[1](i, j)[d] = grad(res[i][d]);
692 }
693 }
694 unseed(du_n[j]);
695 }
696 } else {
697 auto du_s = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(sol_s);
698 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
699 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
700 // take derivative with respect to jth variable
701 seed(du_s[j]);
702 asImp().template ldg_numflux<to>(res, normal, p, du_s, sol_n);
703 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
704 for (uint d = 0; d < dim; ++d) {
705 jNF[0](i, j)[d] = grad(res[i][d]);
706 }
707 }
708 unseed(du_s[j]);
709 }
710 auto du_n = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(sol_n);
711 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
712 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
713 // take derivative with respect to jth variable
714 seed(du_n[j]);
715 asImp().template ldg_numflux<to>(res, normal, p, sol_s, du_n);
716 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
717 for (uint d = 0; d < dim; ++d) {
718 jNF[1](i, j)[d] = grad(res[i][d]);
719 }
720 }
721 unseed(du_n[j]);
722 }
723 }
724 }
725 };
726
727 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_boundary_numflux
728 {
729 Model &asImp() { return static_cast<Model &>(*this); }
730 const Model &asImp() const { return static_cast<const Model &>(*this); }
732
733 public:
734 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
735 void jacobian_boundary_numflux_grad(SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from> &jBNF,
736 const Tensor<1, dim> &normal, const Point<dim> &p, const Vector &sol) const
737 {
738 using Components = typename Model::Components;
739 static_assert(n_to == Components::count_fe_functions(),
740 "jacobian_boundary_numflux_grad: n_to must equal count_fe_functions()");
741 static_assert(n_from == Components::count_fe_functions(),
742 "jacobian_boundary_numflux_grad: n_from must equal count_fe_functions()");
743
744 const auto &u = get<tup_idx>(sol);
745 auto du = AD_tools::template ten_to_AD<n_from>(u);
746 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
748 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
749 for (uint d = 0; d < dim; ++d) {
750 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
751 seed(du[j][d]);
752 asImp().boundary_numflux(res, normal, p, Vector::as(ad_sol));
753 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
754 for (uint dd = 0; dd < dim; ++dd) {
755 jBNF(i, j)[dd][d] = grad(res[i][dd]);
756 }
757 }
758 unseed(du[j][d]);
759 }
760 }
761 }
762
763 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
764 void jacobian_boundary_numflux_hess(SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from> &jBNF,
765 const Tensor<1, dim> &normal, const Point<dim> &p, const Vector &sol) const
766 {
767 using Components = typename Model::Components;
768 static_assert(n_to == Components::count_fe_functions(),
769 "jacobian_boundary_numflux_hess: n_to must equal count_fe_functions()");
770 static_assert(n_from == Components::count_fe_functions(),
771 "jacobian_boundary_numflux_hess: n_from must equal count_fe_functions()");
772
773 const auto &u = get<tup_idx>(sol);
774 auto du = AD_tools::template ten_to_AD<n_from>(u);
775 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(du),
777 for (uint j = 0; j < Components::count_fe_functions(); ++j) {
778 for (uint d1 = 0; d1 < dim; ++d1)
779 for (uint d2 = 0; d2 < dim; ++d2) {
780 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
781 seed(du[j][d1][d2]);
782 asImp().boundary_numflux(res, normal, p, Vector::as(ad_sol));
783 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
784 for (uint d = 0; d < dim; ++d) {
785 jBNF(i, j)[d][d1][d2] = grad(res[i][d]);
786 }
787 }
788 unseed(du[j][d1][d2]);
789 }
790 }
791 }
792
793 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
794 void jacobian_boundary_numflux_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jBNF,
795 const Tensor<1, dim> &normal, const Point<dim> &p, const Vector &sol) const
796 {
797 using Components = typename Model::Components;
798 static_assert(n_to == Components::count_fe_functions(),
799 "jacobian_boundary_numflux_extr: n_to must equal count_fe_functions()");
800 static_assert(n_from == Components::count_extractors(),
801 "jacobian_boundary_numflux_extr: n_from must equal count_extractors()");
802
803 const auto &e = get<tup_idx>(sol);
804 auto de = AD_tools::template vector_to_AD<n_from>(e);
805 auto ad_sol = std::tuple_cat(tuple_first<tup_idx>(sol), std::tie(de),
807 for (uint j = 0; j < n_from; ++j) {
808 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions()> res{{}};
809 seed(de[j]);
810 asImp().boundary_numflux(res, normal, p, Vector::as(ad_sol));
811 for (uint i = 0; i < Components::count_fe_functions(); ++i) {
812 for (uint d = 0; d < dim; ++d) {
813 jBNF(i, j)[d] = grad(res[i][d]);
814 }
815 }
816 unseed(de[j]);
817 }
818 }
819
820 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
821 void jacobian_boundary_numflux(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &jBNF, const Tensor<1, dim> &normal,
822 const Point<dim> &p, const Vector &sol) const
823 {
824 using Components = typename Model::Components;
825 static_assert(n_to == Components::count_fe_functions(to),
826 "jacobian_boundary_numflux: n_to must equal count_fe_functions(to)");
827 static_assert(n_from == Components::count_fe_functions(from),
828 "jacobian_boundary_numflux: n_from must equal count_fe_functions(from)");
829
830 if constexpr (to == 0) {
831 const auto &u = get<from>(sol);
832 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(u);
833 auto ad_sol = std::tuple_cat(tuple_first<from>(sol), std::tie(du),
835 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
836 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
837 seed(du[j]);
838 asImp().boundary_numflux(res, normal, p, Vector::as(ad_sol));
839 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
840 for (uint d = 0; d < dim; ++d) {
841 jBNF(i, j)[d] = grad(res[i][d]);
842 }
843 }
844 unseed(du[j]);
845 }
846 } else {
847 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(from)>(sol);
848 for (uint j = 0; j < Components::count_fe_functions(from); ++j) {
849 std::array<Tensor<1, dim, AD_type>, Components::count_fe_functions(to)> res{{}};
850 // take derivative with respect to jth variable
851 seed(du[j]);
852 asImp().template ldg_boundary_numflux<to>(res, normal, p, du);
853 for (uint i = 0; i < Components::count_fe_functions(to); ++i) {
854 for (uint d = 0; d < dim; ++d) {
855 jBNF(i, j)[d] = grad(res[i][d]);
856 }
857 }
858 unseed(du[j]);
859 }
860 }
861 }
862 };
863
864 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_mass
865 {
866 Model &asImp() { return static_cast<Model &>(*this); }
867 const Model &asImp() const { return static_cast<const Model &>(*this); }
869
870 public:
871 template <uint dot, uint n_from, uint n_to, int dim, typename NT, typename Vector>
872 void jacobian_mass(SimpleMatrix<NT, n_to, n_from> &jM, const Point<dim> &p, const Vector &u,
873 const Vector &u_dot) const
874 {
875 using Components = typename Model::Components;
876 static_assert(n_from == Components::count_fe_functions() && n_to == Components::count_fe_functions(),
877 "jacobian_mass: n_from and n_to must both equal count_fe_functions()");
878
879 if constexpr (dot == 0) {
880 auto du = AD_tools::template vector_to_AD<Components::count_fe_functions(0)>(u);
881 for (uint j = 0; j < Components::count_fe_functions(0); ++j) {
882 std::array<AD_type, Components::count_fe_functions(0)> res{{}};
883 // take derivative with respect to jth variable
884 seed(du[j]);
885 asImp().mass(res, p, du, u_dot);
886 for (uint i = 0; i < Components::count_fe_functions(0); ++i) {
887 jM(i, j) = grad(res[i]);
888 }
889 unseed(du[j]);
890 }
891 } else {
892 auto du_dot = AD_tools::template vector_to_AD<Components::count_fe_functions(0)>(u_dot);
893 for (uint j = 0; j < Components::count_fe_functions(0); ++j) {
894 std::array<AD_type, Components::count_fe_functions(0)> res{{}};
895 // take derivative with respect to jth variable
896 seed(du_dot[j]);
897 asImp().mass(res, p, u, du_dot);
898 for (uint i = 0; i < Components::count_fe_functions(0); ++i) {
899 jM(i, j) = grad(res[i]);
900 }
901 unseed(du_dot[j]);
902 }
903 }
904 }
905 };
906
907 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_variables
908 {
909 Model &asImp() { return static_cast<Model &>(*this); }
910 const Model &asImp() const { return static_cast<const Model &>(*this); }
912
913 public:
914 template <uint to, typename NT, typename Solution>
915 void jacobian_variables(FullMatrix<NT> &jac, const Solution &sol) const
916 {
917 const auto &variables = get<0>(sol);
918 const auto &extractors = get<1>(sol);
919 if constexpr (to == 0) {
920 AssertThrow(jac.m() == variables.size() && jac.n() == variables.size(),
921 ExcMessage("Assure that the jacobian has the right dimension!"));
922 } else if constexpr (to == 1) {
923 AssertThrow(jac.m() == variables.size() && jac.n() == extractors.size(),
924 ExcMessage("Assure that the jacobian has the right dimension!"));
925 }
926
927 if constexpr (to == 0) {
928 auto du = AD_tools::template vector_to_AD<Model::Components::count_variables()>(variables);
929 auto ad_sol = std::tuple_cat(tuple_first<to>(sol), std::tie(du),
931 for (uint j = 0; j < Model::Components::count_variables(); ++j) {
932 std::array<AD_type, Model::Components::count_variables()> res{{}};
933 seed(du[j]);
934 asImp().dt_variables(res, Solution::as(ad_sol));
935 for (uint i = 0; i < Model::Components::count_variables(); ++i) {
936 jac(i, j) = grad(res[i]);
937 }
938 unseed(du[j]);
939 }
940 } else if constexpr (to == 1) {
941 auto du = AD_tools::template vector_to_AD<Model::Components::count_extractors()>(extractors);
942 auto ad_sol = std::tuple_cat(tuple_first<to>(sol), std::tie(du),
944 for (uint j = 0; j < Model::Components::count_extractors(); ++j) {
945 std::array<AD_type, Model::Components::count_variables()> res{{}};
946 seed(du[j]);
947 asImp().dt_variables(res, Solution::as(ad_sol));
948 for (uint i = 0; i < Model::Components::count_extractors(); ++i) {
949 jac(i, j) = grad(res[i]);
950 }
951 unseed(du[j]);
952 }
953 }
954 }
955 };
956
957 template <typename Model, typename AD_type = autodiff::real> class ADjacobian_extractors
958 {
959 Model &asImp() { return static_cast<Model &>(*this); }
960 const Model &asImp() const { return static_cast<const Model &>(*this); }
962
963 public:
964 template <uint to, int dim, typename NT, typename Solution>
965 void jacobian_extractors(FullMatrix<NT> &jac, const Point<dim> &x, const Solution &sol) const
966 {
967 static_assert(std::is_same_v<NT, double>, "Only double is supported for now!");
968 const auto &fe_functions = get<0>(sol);
969 const auto &fe_derivatives = get<1>(sol);
970 const auto &fe_hessians = get<2>(sol);
971
972 if constexpr (to == 0) {
973 AssertThrow(jac.m() == Model::Components::count_extractors() && jac.n() == fe_functions.size(),
974 ExcMessage("Assure that the jacobian has the right dimension!"));
975 } else if constexpr (to == 1) {
976 AssertThrow(jac.m() == Model::Components::count_extractors() && jac.n() == fe_derivatives.size() * dim,
977 ExcMessage("Assure that the jacobian has the right dimension!"));
978 } else if constexpr (to == 2) {
979 AssertThrow(jac.m() == Model::Components::count_extractors() && jac.n() == fe_derivatives.size() * dim * dim,
980 ExcMessage("Assure that the jacobian has the right dimension!"));
981 }
982
983 if constexpr (to == 0) {
984 auto du = AD_tools::template vector_to_AD<Model::Components::count_fe_functions()>(fe_functions);
985 auto ad_sol = std::tuple_cat(tuple_first<to>(sol), std::tie(du),
987 for (uint j = 0; j < Model::Components::count_fe_functions(); ++j) {
988 std::array<AD_type, Model::Components::count_extractors()> res{{}};
989 seed(du[j]);
990 asImp().extract(res, x, Solution::as(ad_sol));
991 for (uint i = 0; i < Model::Components::count_extractors(); ++i) {
992 jac(i, j) = grad(res[i]);
993 }
994 unseed(du[j]);
995 }
996 } else if constexpr (to == 1) {
997 auto du = AD_tools::template ten_to_AD<Model::Components::count_fe_functions()>(fe_derivatives);
998 auto ad_sol = std::tuple_cat(tuple_first<to>(sol), std::tie(du),
1000 for (uint j = 0; j < Model::Components::count_fe_functions(); ++j) {
1001 for (uint d1 = 0; d1 < dim; ++d1) {
1002 std::array<AD_type, Model::Components::count_extractors()> res{{}};
1003 seed(du[j][d1]);
1004 asImp().extract(res, x, Solution::as(ad_sol));
1005 for (uint i = 0; i < Model::Components::count_extractors(); ++i) {
1006 jac(i, j * dim + d1) = grad(res[i]);
1007 }
1008 unseed(du[j][d1]);
1009 }
1010 }
1011 } else if constexpr (to == 2) {
1012 auto du = AD_tools::template ten_to_AD<Model::Components::count_fe_functions()>(fe_hessians);
1013 auto ad_sol = std::tuple_cat(tuple_first<to>(sol), std::tie(du),
1015 for (uint j = 0; j < Model::Components::count_fe_functions(); ++j) {
1016 for (uint d1 = 0; d1 < dim; ++d1)
1017 for (uint d2 = 0; d2 < dim; ++d2) {
1018 std::array<AD_type, Model::Components::count_extractors()> res{{}};
1019 seed(du[j][d1][d2]);
1020 asImp().extract(res, x, Solution::as(ad_sol));
1021 for (uint i = 0; i < Model::Components::count_extractors(); ++i) {
1022 jac(i, j * dim * dim + d1 * dim + d2) = grad(res[i]);
1023 }
1024 unseed(du[j][d1][d2]);
1025 }
1026 }
1027 }
1028 }
1029 };
1030
1031 template <typename Model>
1032 class AD_real : public ADjacobian_flux<Model, autodiff::real>,
1033 public ADjacobian_source<Model, autodiff::real>,
1034 public ADjacobian_flux_source<Model, autodiff::real>,
1035 public ADjacobian_numflux<Model, autodiff::real>,
1036 public ADjacobian_boundary_numflux<Model, autodiff::real>,
1037 public ADjacobian_mass<Model, autodiff::real>,
1038 public ADjacobian_variables<Model, autodiff::real>,
1039 public ADjacobian_extractors<Model, autodiff::real>
1040 {
1041 };
1042
1043 template <typename Model>
1044 class AD_dual : public ADjacobian_flux<Model, autodiff::dual>,
1045 public ADjacobian_source<Model, autodiff::dual>,
1046 public ADjacobian_flux_source<Model, autodiff::dual>,
1047 public ADjacobian_numflux<Model, autodiff::dual>,
1048 public ADjacobian_boundary_numflux<Model, autodiff::dual>,
1049 public ADjacobian_mass<Model, autodiff::dual>,
1050 public ADjacobian_variables<Model, autodiff::dual>,
1051 public ADjacobian_extractors<Model, autodiff::dual>
1052 {
1053 };
1054
1055 template <typename Model> using AD = AD_real<Model>;
1056
1057 template <typename Model>
1058 class FE_AD : public ADjacobian_flux<Model, autodiff::real>,
1059 public ADjacobian_source<Model, autodiff::real>,
1060 public ADjacobian_flux_source<Model, autodiff::real>,
1061 public ADjacobian_numflux<Model, autodiff::real>,
1062 public ADjacobian_boundary_numflux<Model, autodiff::real>,
1063 public ADjacobian_mass<Model, autodiff::real>
1064 {
1065 public:
1066 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1067 void jacobian_flux_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Point<dim> &,
1068 const Vector &) const
1069 {
1070 }
1071 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1072 void jacobian_source_extr(SimpleMatrix<NT, n_to, n_from> &, const Point<dim> &, const Vector &) const
1073 {
1074 }
1075 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1076 void jacobian_flux_source_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &,
1077 SimpleMatrix<NT, n_to, n_from> &, const Point<dim> &, const Vector &) const
1078 {
1079 }
1080 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
1081 void jacobian_numflux_extr(std::array<SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from>, 2> &,
1082 const Tensor<1, dim> &, const Point<dim> &, const Vector_s &, const Vector_n &) const
1083 {
1084 }
1085 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1086 void jacobian_boundary_numflux_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Tensor<1, dim> &,
1087 const Point<dim> &, const Vector &) const
1088 {
1089 }
1090 template <uint to, int dim, typename NT, typename Solution>
1091 void jacobian_extractors(FullMatrix<NT> &, const Point<dim> &, const Solution &) const
1092 {
1093 }
1094 template <uint to, typename NT, typename Solution>
1095 void jacobian_variables(FullMatrix<NT> &, const Solution &) const
1096 {
1097 }
1098 };
1099
1101 {
1102 public:
1103 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1104 void jacobian_flux_grad(SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from> &, const Point<dim> &,
1105 const Vector &) const
1106 {
1107 }
1108 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1109 void jacobian_flux_hess(SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from> &, const Point<dim> &,
1110 const Vector &) const
1111 {
1112 }
1113 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1114 void jacobian_flux_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Point<dim> &,
1115 const Vector &) const
1116 {
1117 }
1118 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1119 void jacobian_flux(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Point<dim> &, const Vector &) const
1120 {
1121 }
1122 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1123 void jacobian_source_grad(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Point<dim> &,
1124 const Vector &) const
1125 {
1126 }
1127 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1128 void jacobian_source_hess(SimpleMatrix<Tensor<2, dim, NT>, n_to, n_from> &, const Point<dim> &,
1129 const Vector &) const
1130 {
1131 }
1132 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1133 void jacobian_source_extr(SimpleMatrix<NT, n_to, n_from> &, const Point<dim> &, const Vector &) const
1134 {
1135 }
1136 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1137 void jacobian_source(SimpleMatrix<NT, n_to, n_from> &, const Point<dim> &, const Vector &) const
1138 {
1139 }
1140 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1141 void jacobian_flux_source(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, SimpleMatrix<NT, n_to, n_from> &,
1142 const Point<dim> &, const Vector &) const
1143 {
1144 }
1145 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1146 void jacobian_flux_source_grad(SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from> &,
1147 SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Point<dim> &,
1148 const Vector &) const
1149 {
1150 }
1151 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1152 void jacobian_flux_source_hess(SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from> &,
1153 SimpleMatrix<Tensor<2, dim, NT>, n_to, n_from> &, const Point<dim> &,
1154 const Vector &) const
1155 {
1156 }
1157 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1158 void jacobian_flux_source_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &,
1159 SimpleMatrix<NT, n_to, n_from> &, const Point<dim> &, const Vector &) const
1160 {
1161 }
1162 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
1163 void jacobian_numflux_grad(std::array<SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from>, 2> &,
1164 const Tensor<1, dim> &, const Point<dim> &, const Vector_s &, const Vector_n &) const
1165 {
1166 }
1167 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
1168 void jacobian_numflux_hess(std::array<SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from>, 2> &,
1169 const Tensor<1, dim> &, const Point<dim> &, const Vector_s &, const Vector_n &) const
1170 {
1171 }
1172 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
1173 void jacobian_numflux_extr(std::array<SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from>, 2> &,
1174 const Tensor<1, dim> &, const Point<dim> &, const Vector_s &, const Vector_n &) const
1175 {
1176 }
1177 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector_s, typename Vector_n>
1178 void jacobian_numflux(std::array<SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from>, 2> &, const Tensor<1, dim> &,
1179 const Point<dim> &, const Vector_s &, const Vector_n &) const
1180 {
1181 }
1182 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1183 void jacobian_boundary_numflux_grad(SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NT>>, n_to, n_from> &,
1184 const Tensor<1, dim> &, const Point<dim> &, const Vector &) const
1185 {
1186 }
1187 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1188 void jacobian_boundary_numflux_hess(SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NT>>, n_to, n_from> &,
1189 const Tensor<1, dim> &, const Point<dim> &, const Vector &) const
1190 {
1191 }
1192 template <uint tup_idx, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1193 void jacobian_boundary_numflux_extr(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Tensor<1, dim> &,
1194 const Point<dim> &, const Vector &) const
1195 {
1196 }
1197 template <uint from, uint to, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1198 void jacobian_boundary_numflux(SimpleMatrix<Tensor<1, dim, NT>, n_to, n_from> &, const Tensor<1, dim> &,
1199 const Point<dim> &, const Vector &) const
1200 {
1201 }
1202 template <uint dot, uint n_from, uint n_to, int dim, typename NT, typename Vector>
1203 void jacobian_mass(SimpleMatrix<NT, n_to, n_from> &, const Point<dim> &, const Vector &, const Vector &) const
1204 {
1205 }
1206
1207 template <uint to, int dim, typename NT, typename Solution>
1208 void jacobian_extractors(FullMatrix<NT> &, const Point<dim> &, const Solution &) const
1209 {
1210 }
1211 template <uint to, typename NT, typename Solution>
1212 void jacobian_variables(FullMatrix<NT> &, const Solution &) const
1213 {
1214 }
1215 };
1216
1217 } // namespace def
1218} // namespace DiFfRG
A simple NxM-matrix class, which is used for cell-wise Jacobians.
Definition tuples.hh:170
Definition ad.hh:1052
Definition ad.hh:1040
void jacobian_boundary_numflux_grad(SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from > &jBNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:735
void jacobian_boundary_numflux_hess(SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from > &jBNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:764
const Model & asImp() const
Definition ad.hh:730
void jacobian_boundary_numflux_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jBNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:794
Model & asImp()
Definition ad.hh:729
void jacobian_boundary_numflux(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jBNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:821
Model & asImp()
Definition ad.hh:959
void jacobian_extractors(FullMatrix< NT > &jac, const Point< dim > &x, const Solution &sol) const
Definition ad.hh:965
const Model & asImp() const
Definition ad.hh:960
Model & asImp()
Definition ad.hh:363
void jacobian_flux_source_hess(SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from > &jF, SimpleMatrix< Tensor< 2, dim, NT >, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:449
void jacobian_flux_source(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jF, SimpleMatrix< NT, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:369
void jacobian_flux_source_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jF, SimpleMatrix< NT, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:485
void jacobian_flux_source_grad(SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from > &jF, SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:415
const Model & asImp() const
Definition ad.hh:364
Definition ad.hh:95
void jacobian_flux_grad(SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from > &jF, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:102
void jacobian_flux_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jF, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:163
void jacobian_flux(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jF, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:190
void jacobian_flux_hess(SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from > &jF, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:132
const Model & asImp() const
Definition ad.hh:97
Model & asImp()
Definition ad.hh:96
Definition ad.hh:865
void jacobian_mass(SimpleMatrix< NT, n_to, n_from > &jM, const Point< dim > &p, const Vector &u, const Vector &u_dot) const
Definition ad.hh:872
Model & asImp()
Definition ad.hh:866
const Model & asImp() const
Definition ad.hh:867
const Model & asImp() const
Definition ad.hh:518
void jacobian_numflux_extr(std::array< SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from >, 2 > &jNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector_s &sol_s, const Vector_n &sol_n) const
Definition ad.hh:621
Model & asImp()
Definition ad.hh:517
void jacobian_numflux(std::array< SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from >, 2 > &jNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector_s &sol_s, const Vector_n &sol_n) const
Definition ad.hh:654
void jacobian_numflux_grad(std::array< SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from >, 2 > &jNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector_s &sol_s, const Vector_n &sol_n) const
Definition ad.hh:523
void jacobian_numflux_hess(std::array< SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from >, 2 > &jNF, const Tensor< 1, dim > &normal, const Point< dim > &p, const Vector_s &sol_s, const Vector_n &sol_n) const
Definition ad.hh:571
Definition ad.hh:234
void jacobian_source_grad(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:241
void jacobian_source(SimpleMatrix< NT, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:323
Model & asImp()
Definition ad.hh:235
void jacobian_source_extr(SimpleMatrix< NT, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:299
const Model & asImp() const
Definition ad.hh:236
void jacobian_source_hess(SimpleMatrix< Tensor< 2, dim, NT >, n_to, n_from > &jS, const Point< dim > &p, const Vector &sol) const
Definition ad.hh:269
Model & asImp()
Definition ad.hh:909
void jacobian_variables(FullMatrix< NT > &jac, const Solution &sol) const
Definition ad.hh:915
const Model & asImp() const
Definition ad.hh:910
Definition ad.hh:1064
void jacobian_boundary_numflux_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1086
void jacobian_extractors(FullMatrix< NT > &, const Point< dim > &, const Solution &) const
Definition ad.hh:1091
void jacobian_flux_source_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, SimpleMatrix< NT, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1076
void jacobian_flux_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1067
void jacobian_variables(FullMatrix< NT > &, const Solution &) const
Definition ad.hh:1095
void jacobian_source_extr(SimpleMatrix< NT, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1072
void jacobian_numflux_extr(std::array< SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from >, 2 > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector_s &, const Vector_n &) const
Definition ad.hh:1081
Definition ad.hh:1101
void jacobian_boundary_numflux_hess(SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1188
void jacobian_boundary_numflux(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1198
void jacobian_flux_hess(SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1109
void jacobian_mass(SimpleMatrix< NT, n_to, n_from > &, const Point< dim > &, const Vector &, const Vector &) const
Definition ad.hh:1203
void jacobian_numflux_hess(std::array< SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from >, 2 > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector_s &, const Vector_n &) const
Definition ad.hh:1168
void jacobian_flux_source_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, SimpleMatrix< NT, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1158
void jacobian_source(SimpleMatrix< NT, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1137
void jacobian_flux_source_hess(SimpleMatrix< Tensor< 1, dim, Tensor< 2, dim, NT > >, n_to, n_from > &, SimpleMatrix< Tensor< 2, dim, NT >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1152
void jacobian_source_grad(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1123
void jacobian_variables(FullMatrix< NT > &, const Solution &) const
Definition ad.hh:1212
void jacobian_source_hess(SimpleMatrix< Tensor< 2, dim, NT >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1128
void jacobian_boundary_numflux_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1193
void jacobian_flux_extr(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1114
void jacobian_extractors(FullMatrix< NT > &, const Point< dim > &, const Solution &) const
Definition ad.hh:1208
void jacobian_numflux_grad(std::array< SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from >, 2 > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector_s &, const Vector_n &) const
Definition ad.hh:1163
void jacobian_flux_grad(SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1104
void jacobian_source_extr(SimpleMatrix< NT, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1133
void jacobian_numflux_extr(std::array< SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from >, 2 > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector_s &, const Vector_n &) const
Definition ad.hh:1173
void jacobian_flux(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1119
void jacobian_boundary_numflux_grad(SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1183
void jacobian_flux_source(SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, SimpleMatrix< NT, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1141
void jacobian_numflux(std::array< SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from >, 2 > &, const Tensor< 1, dim > &, const Point< dim > &, const Vector_s &, const Vector_n &) const
Definition ad.hh:1178
void jacobian_flux_source_grad(SimpleMatrix< Tensor< 1, dim, Tensor< 1, dim, NT > >, n_to, n_from > &, SimpleMatrix< Tensor< 1, dim, NT >, n_to, n_from > &, const Point< dim > &, const Vector &) const
Definition ad.hh:1146
Definition complex_math.hh:10
constexpr auto tuple_first(const std::tuple< Head, Tail... > &t)
Definition tuples.hh:261
NT dot(const A1 &a1, const A2 &a2)
A dot product which takes the dot product between a1 and a2, assuming each has n entries which can be...
Definition math.hh:220
constexpr auto & get(named_tuple< tuple_type, strSet > &ob)
get a reference to the element with the given name
Definition tuples.hh:125
unsigned int uint
Definition utils.hh:24
KOKKOS_FORCEINLINE_FUNCTION auto real(const autodiff::Real< N, T > &a)
Definition complex_math.hh:96
constexpr auto tuple_last(const std::tuple< Head, Tail... > &t)
Definition tuples.hh:247
Definition complex_math.hh:19
static auto ten_to_AD(const Container &v)
Definition ad.hh:39
static std::array< autodiff::dual, n > vector_to_AD(const Vector &v)
Definition ad.hh:28
static auto ten_to_AD(const Container &v)
Definition ad.hh:71
static std::array< autodiff::real, n > vector_to_AD(const Vector &v)
Definition ad.hh:61