v0.16.0
Loading...
Searching...
No Matches
MatrixFunctionTemplate.hpp
Go to the documentation of this file.
1/** \file FunctionMatrix.hpp
2 \brief Get function from matrix
3 \ingroup ftensor
4
5 For reference see \cite miehe2001algorithms
6
7 Usage:
8
9 To calculate exponent of matrix, first and second derivatives
10 \code
11 auto f = [](double v) { return exp(v); };
12 auto d_f = [](double v) { return exp(v); };
13 auto dd_f = [](double v) { return exp(v); };
14 \endcode
15
16 Calculate matrix here t_L are vector of eigen values, and t_N is matrix of
17 eigen vectors.
18 \code
19 auto t_A = EigenMatrixImp<double, double, 3, 3>::getMat(t_L, t_N, f);
20 \endcode
21 Return t_A is symmetric tensor rank two.
22
23 Calculate derivarive
24 \code
25 auto t_P = EigenMatrixImp<double, double, 3, 3>::getDiffMat(t_L, t_N, f, d_f);
26 \endcode
27 where return t_SL is 4th order tensor (symmetry on first two and
28 second to indices, i.e. minor symmetrise)
29
30 Calculate second derivative, L, such that S:L, for given S,
31 \code
32 FTensor::Tensor2<double, 3, 3> t_S{
33
34 1., 0., 0.,
35
36 0., 1., 0.,
37
38 0., 0., 1.};
39
40 auto t_SL = EigenMatrixImp<double, double, 3, 3>::getDiffDiffMat(
41 t_L, t_N, f, d_f, dd_f, t_S)
42 \endcode
43 where return t_SL is 4th order tensor (symmetry on first two and
44 second to indices, i.e. minor symmetrise)
45
46 You can calculate eigen values using lapack.
47
48 *
49 */
50
51namespace EigenMatrix {
52
53template <int N> using Number = FTensor::Number<N>;
54
55template <int N1, int N2, int Dim>
56inline auto get_sym_index(const Number<N1> &, const Number<N2> &,
57 const Number<Dim> &) {
58 if constexpr (N1 > N2)
59 return N1 + (N2 * (2 * Dim - N2 - 1)) / 2;
60 else
61 return N2 + (N1 * (2 * Dim - N1 - 1)) / 2;
62}
63
64inline auto get_sym_index(const int N1, const int N2, const int Dim) {
65 if (N1 > N2)
66 return N1 + (N2 * (2 * Dim - N2 - 1)) / 2;
67 else
68 return N2 + (N1 * (2 * Dim - N1 - 1)) / 2;
69}
70
71template <int N1, int N2, int Dim>
72inline auto get_nodiag_index(const Number<N1> &, const Number<N2> &,
73 const Number<Dim> &) {
74 static_assert(N1 != N2, "Bad index");
75 if constexpr (N2 > N1)
76 return (Dim - 1) * N1 + N2 - 1;
77 else
78 return (Dim - 1) * N1 + N2;
79}
80
81inline auto get_nodiag_index(const int N1, const int N2, int Dim) {
82 if (N2 > N1)
83 return (Dim - 1) * N1 + N2 - 1;
84 else
85 return (Dim - 1) * N1 + N2;
86}
87
88template <typename E, typename C> struct d2MCoefficients {
89 using Val = typename E::Val;
90 using Vec = typename E::Vec;
91 using Fun = typename E::Fun;
92
93 using NumberNb = typename E::NumberNb;
94 using NumberDim = typename E::NumberDim;
95
96 template <int N> using Number = FTensor::Number<N>;
97
99 E &e;
100
101 template <int a, int b>
102 inline auto get(const Number<a> &, const Number<b> &, const int i,
103 const int j, const int k, const int l,
104 const Number<3> &) const {
105 return e.aS[get_sym_index(Number<a>(), Number<b>(), NumberDim())](i, j, k,
106 l) *
107 e.fVal(a) * e.aF(a, b);
108 }
109
110 template <int a, int b>
111 inline auto get(const Number<a> &, const Number<b> &, const int i,
112 const int j, const int k, const int l,
113 const Number<2> &) const {
114 if constexpr (a == 1 || b == 1)
115 return get(Number<a>(), Number<b>(), i, j, k, l, Number<3>());
116 else
117 return get(Number<a>(), Number<b>(), i, j, k, l, Number<1>());
118 }
119
120 template <int a, int b>
121 inline auto get(const Number<a> &, const Number<b> &, const int i,
122 const int j, const int k, const int l,
123 const Number<1>) const {
124 return e.aS[get_sym_index(Number<a>(), Number<b>(), NumberDim())](i, j, k,
125 l) *
126 e.dfVal(a) / static_cast<C>(2);
127 }
128};
129
130template <typename E, typename C, typename G> struct d2MImpl {
131 using Val = typename E::Val;
132 using Vec = typename E::Vec;
133 using Fun = typename E::Fun;
134
135 template <int N> using Number = FTensor::Number<N>;
136 d2MImpl(E &e) : g(e), e(e) {}
138 E &e;
139
140 template <int b, int a>
141 inline C term(const int i, const int j, const int k, const int l) const {
142 if constexpr (a != b) {
143 return g.get(Number<a>(), Number<b>(), i, j, k, l,
144 typename E::NumberNb());
145 }
146 return 0;
147 }
148
149 template <int nb, int a>
150 inline C eval(const Number<nb> &, const Number<a> &, const int i, const int j,
151 const int k, const int l) const {
152 return term<nb - 1, a>(i, j, k, l) +
153 eval(Number<nb - 1>(), Number<a>(), i, j, k, l);
154 }
155
156 template <int a>
157 inline C eval(const Number<1> &, const Number<a> &, const int i, const int j,
158 const int k, const int l) const {
159 return term<0, a>(i, j, k, l);
160 }
161};
162
163template <typename E, typename C> struct Fdd4MImpl {
164 using Val = typename E::Val;
165 using Vec = typename E::Vec;
166 using Fun = typename E::Fun;
167
168 Fdd4MImpl(E &e) : e(e) {}
169 E &e;
170
171 using NumberNb = typename E::NumberNb;
172 using NumberDim = typename E::NumberDim;
173
174 template <int A, int a, int b, int I, int J, int K, int L>
175 inline auto fd2M() const {
176 return e.d2MType1[b][get_sym_index(Number<A>(), Number<a>(), NumberDim())](
178 }
179
180 template <int a, int b, int i, int j, int k, int l, int m, int n>
181 inline auto term_fd2S(const Number<a> &, const Number<b> &, const Number<i> &,
182 const Number<j> &, const Number<k> &, const Number<l> &,
183 const Number<m> &, const Number<n> &) const {
184 if constexpr (i == j && k == l) {
185 return 4 *
186 (
187
188 fd2M<a, a, b, i, k, m, n>() * e.aM[b](Number<j>(), Number<l>())
189
190 +
191
192 fd2M<b, a, b, i, k, m, n>() * e.aM[a](Number<j>(), Number<l>())
193
194 );
195
196 } else if constexpr (i == j)
197 return 2 *
198 (
199
200 fd2M<a, a, b, i, k, m, n>() *
201 e.aM[b](Number<j>(), Number<l>()) +
202 fd2M<b, a, b, j, l, m, n>() * e.aM[a](Number<i>(), Number<k>())
203
204 +
205
206 fd2M<b, a, b, i, k, m, n>() *
207 e.aM[a](Number<j>(), Number<l>()) +
208 fd2M<a, a, b, j, l, m, n>() * e.aM[b](Number<i>(), Number<k>())
209
210 );
211 else if constexpr (k == l)
212 return 2 *
213 (
214
215 fd2M<a, a, b, i, k, m, n>() *
216 e.aM[b](Number<j>(), Number<l>()) +
217 fd2M<b, a, b, j, l, m, n>() *
218 e.aM[a](Number<i>(), Number<k>()) +
219
220 +
221
222 fd2M<b, a, b, i, k, m, n>() *
223 e.aM[a](Number<j>(), Number<l>()) +
224 fd2M<a, a, b, j, l, m, n>() * e.aM[b](Number<i>(), Number<k>())
225
226 );
227 else
228 return fd2M<a, a, b, i, k, m, n>() * e.aM[b](Number<j>(), Number<l>()) +
229 fd2M<b, a, b, j, l, m, n>() * e.aM[a](Number<i>(), Number<k>()) +
230 fd2M<a, a, b, i, l, m, n>() * e.aM[b](Number<j>(), Number<k>()) +
231 fd2M<b, a, b, j, k, m, n>() * e.aM[a](Number<i>(), Number<l>())
232
233 +
234
235 fd2M<b, a, b, i, k, m, n>() * e.aM[a](Number<j>(), Number<l>()) +
236 fd2M<a, a, b, j, l, m, n>() * e.aM[b](Number<i>(), Number<k>()) +
237 fd2M<b, a, b, i, l, m, n>() * e.aM[a](Number<j>(), Number<k>()) +
238 fd2M<a, a, b, j, k, m, n>() * e.aM[b](Number<i>(), Number<l>());
239 }
240
241 template <int NB, int a, int b, int i, int j, int k, int l, int m, int n>
242 inline C term_SM(const Number<a> &, const Number<b> &, const Number<NB> &,
243 const Number<i> &, const Number<j> &, const Number<k> &,
244 const Number<l> &, const Number<m> &,
245 const Number<n> &) const {
246
247 if constexpr (NB == 1) {
248 return 0;
249
250 } else if constexpr (NB == 2) {
251
252 if constexpr (a == 1 || b == 1) {
253 return
254
255 e.aF2(Number<a>(), Number<b>()) *
262
263 } else {
264 return 0;
265 }
266
267 } else {
268
269 return
270
271 e.aF2(Number<a>(), Number<b>()) *
278 }
279
280 return 0;
281 }
282
283 template <int nb, int a, int i, int j, int k, int l, int m, int n>
284 inline C eval_fdS2(const Number<nb> &, const Number<a> &, const Number<i> &,
285 const Number<j> &, const Number<k> &, const Number<l> &,
286 const Number<m> &, const Number<n> &) const {
287 if constexpr (a != nb - 1)
288 return term_fd2S(Number<a>(), Number<nb - 1>(), Number<i>(), Number<j>(),
292 else
295 }
296
297 template <int a, int i, int j, int k, int l, int m, int n>
298 inline C eval_fdS2(const Number<1> &, const Number<a> &, const Number<i> &,
299 const Number<j> &, const Number<k> &, const Number<l> &,
300 const Number<m> &, const Number<n> &) const {
301 if constexpr (a != 0)
304 else
305 return 0;
306 }
307
308 template <int nb, int a, int i, int j, int k, int l, int m, int n>
309 inline C eval_SM(const Number<nb> &, const Number<a> &, const Number<i> &,
310 const Number<j> &, const Number<k> &, const Number<l> &,
311 const Number<m> &, const Number<n> &) const {
312 if constexpr (a != nb - 1)
313 return term_SM(Number<a>(), Number<nb - 1>(), NumberNb(), Number<i>(),
315 Number<n>()) +
318
319 else
322 }
323
324 template <int a, int i, int j, int k, int l, int m, int n>
325 inline C eval_SM(const Number<1> &, const Number<a> &, const Number<i> &,
326 const Number<j> &, const Number<k> &, const Number<l> &,
327 const Number<m> &, const Number<n> &) const {
328 if constexpr (a != 0)
329 return term_SM(Number<a>(), Number<0>(), NumberNb(), Number<i>(),
331 Number<n>());
332 else
333 return 0;
334 }
335
336 template <int nb, int a, int i, int j, int k, int l, int m, int n>
337 inline C eval(const Number<nb> &, const Number<a> &, const Number<i> &,
338 const Number<j> &, const Number<k> &, const Number<l> &,
339 const Number<m> &, const Number<n> &) const {
340 return
341
342 (2 * e.fVal(a)) * eval_SM(NumberDim(), Number<a>(), Number<i>(),
344 Number<m>(), Number<n>())
345
346 +
347
350 }
351};
352
353template <typename E, typename C> struct ReconstructMatImpl {
354 using Val = typename E::Val;
355 using Vec = typename E::Vec;
356 using Fun = typename E::Fun;
357
358 template <int N> using Number = FTensor::Number<N>;
359
361 E &e;
362
363 template <int a, int i, int j> inline C term() const {
364 return e.aM[a](Number<i>(), Number<j>()) * e.fVal(a);
365 }
366
367 template <int nb, int i, int j>
368 inline C eval(const Number<nb> &, const Number<i> &,
369 const Number<j> &) const {
370 return term<nb - 1, i, j>() +
372 }
373
374 template <int i, int j>
375 inline C eval(const Number<1> &, const Number<i> &, const Number<j> &) const {
376 return term<0, i, j>();
377 }
378};
379
380template <typename E, typename C> struct FirstMatrixDirectiveImpl {
381 using Val = typename E::Val;
382 using Vec = typename E::Vec;
383 using Fun = typename E::Fun;
384
385 template <int N> using Number = FTensor::Number<N>;
386
389 E &e;
390
391 template <int a, int i, int j, int k, int l> inline C term() const {
392 return
393
394 e.aMM[a][a](i, j, k, l) * e.dfVal(a)
395
396 +
397
398 r.eval(typename E::NumberDim(), Number<a>(), i, j, k, l) * 0.5;
399 }
400
401 template <int nb, int i, int j, int k, int l>
402 inline C eval(const Number<nb> &, const Number<i> &, const Number<j> &,
403 const Number<k> &, const Number<l> &) const {
404 return term<nb - 1, i, j, k, l>() + eval(Number<nb - 1>(), Number<i>(),
405 Number<j>(), Number<k>(),
406 Number<l>());
407 }
408
409 template <int i, int j, int k, int l>
410 inline C eval(const Number<1> &, const Number<i> &, const Number<j> &,
411 const Number<k> &, const Number<l> &) const {
412 return term<0, i, j, k, l>();
413 }
414};
415
416template <typename E, typename C> struct SecondMatrixDirectiveImpl {
417 using Val = typename E::Val;
418 using Vec = typename E::Vec;
419 using Fun = typename E::Fun;
420
421 using NumberDim = typename E::NumberDim;
422
423 template <int N> using Number = FTensor::Number<N>;
424
427 E &e;
428
429 template <int a, int i, int j, int k, int l, int m, int n>
430 inline C term1() const {
431 return e.d2MType0[a][get_sym_index(Number<k>(), Number<l>(), NumberDim())](
433 };
434
435 template <int a, int i, int j, int k, int l, int m, int n>
436 inline C term2() const {
437 return e.d2MType0[a][get_sym_index(Number<i>(), Number<j>(), NumberDim())](
439 }
440
441 template <int a, int i, int j, int k, int l, int m, int n>
442 inline C term3() const {
443 return e.d2MType0[a][get_sym_index(Number<n>(), Number<m>(), NumberDim())](
445 }
446
447 template <int a, int i, int j, int k, int l, int m, int n>
448 inline C term() const {
449
450 return
451
452 (term1<a, i, j, k, l, m, n>() + term2<a, i, j, k, l, m, n>() +
453 term3<a, i, j, k, l, m, n>()) *
454 0.5
455
456 +
457
458 (e.aMM[a][a](Number<i>(), Number<j>(), Number<k>(), Number<l>()) *
459 e.aM[a](Number<m>(), Number<n>())) *
460 e.ddfVal(a)
461
462 +
463
464 r.eval(typename E::NumberDim(), Number<a>(), Number<i>(), Number<j>(),
466 0.25;
467 }
468
469 template <int nb, int i, int j, int k, int l, int m, int n>
470 inline C eval(const Number<nb> &, const Number<i> &, const Number<j> &,
471 const Number<k> &, const Number<l> &, const Number<m> &,
472 const Number<n> &) const {
473 return term<nb - 1, i, j, k, l, m, n>()
474
475 +
476
479 }
480
481 template <int i, int j, int k, int l, int m, int n>
482 inline C eval(const Number<1> &, const Number<i> &, const Number<j> &,
483 const Number<k> &, const Number<l> &, const Number<m> &,
484 const Number<n> &) const {
485 return term<0, i, j, k, l, m, n>();
486 }
487};
488
489template <typename E, typename C, typename T> struct GetMatImpl {
490 using Val = typename E::Val;
491 using Vec = typename E::Vec;
492 using Fun = typename E::Fun;
493
494 using NumberNb = typename E::NumberNb;
495 using NumberDim = typename E::NumberDim;
496
497 template <int N> using Number = FTensor::Number<N>;
498
499 GetMatImpl(E &e, T &t_a) : r(e), tA(t_a) {}
501 T &tA;
502
503 template <int i, int j>
504 inline void set(const Number<i> &, const Number<j> &) {
505
507
510 }
511
512 template <int i> inline void set(const Number<i> &, const Number<1> &) {
513
515
517 r.eval(NumberDim(), Number<i - 1>(), Number<0>());
518 }
519
520 inline void set(const Number<1> &, const Number<1> &) {
521 tA(Number<0>(), Number<0>()) =
522 r.eval(NumberDim(), Number<0>(), Number<0>());
523 }
524};
525
526template <typename E, typename C, typename T> struct GetDiffMatImpl {
527 using Val = typename E::Val;
528 using Vec = typename E::Vec;
529 using Fun = typename E::Fun;
530
531 using NumberNb = typename E::NumberNb;
532 using NumberDim = typename E::NumberDim;
533
534 template <int N> using Number = FTensor::Number<N>;
535
536 GetDiffMatImpl(E &e, T &t_a) : r(e), tA(t_a) {}
538 T &tA;
539
540 template <int i, int j, int k, int l>
541 inline void set(const Number<i> &, const Number<j> &, const Number<k> &,
542 const Number<l> &) {
543
546 Number<l - 1>());
547
549 }
550
551 template <int j, int k, int l>
552 inline void set(const Number<1> &, const Number<j> &, const Number<k> &,
553 const Number<l> &) {
554
557 Number<l - 1>());
558
560 }
561
562 template <int k, int l>
563 inline void set(const Number<1> &, const Number<1> &, const Number<k> &,
564 const Number<l> &) {
565
568 Number<l - 1>());
569
571 }
572
573 template <int l>
574 inline void set(const Number<1> &, const Number<1> &, const Number<1> &,
575 const Number<l> &) {
576
577 tA(Number<0>(), Number<0>(), Number<0>(), Number<l - 1>()) = r.eval(
579
581 }
582
583 inline void set(const Number<1> &, const Number<1> &, const Number<1> &,
584 const Number<1> &) {
585
587 r.eval(NumberDim(), Number<0>(), Number<0>(), Number<0>(), Number<0>());
588 }
589};
590
591template <typename E, typename C, typename T1, typename T2>
593 using Val = typename E::Val;
594 using Vec = typename E::Vec;
595 using Fun = typename E::Fun;
596
597 using NumberNb = typename E::NumberNb;
598 using NumberDim = typename E::NumberDim;
599
600 template <int N> using Number = FTensor::Number<N>;
601
602 GetDiffDiffMatImpl(E &e, T1 &t_a, T2 &t_S) : r(e), e(e), tA(t_a), tS(t_S) {}
604 E &e;
605 T1 &tA;
606 T2 &tS;
607
608 template <int I, int J, int K, int L, int M, int N>
609 inline auto add(const Number<I> &, const Number<J> &, const Number<K> &,
610 const Number<L> &, const Number<M> &, const Number<N> &) {
611 if constexpr (N != M)
612 return (tS(M - 1, N - 1) + tS(N - 1, M - 1)) *
613 r.eval(NumberDim(), Number<M - 1>(), Number<N - 1>(),
614 Number<I - 1>(), Number<J - 1>(), Number<K - 1>(),
616
617 +
618
620 Number<M>(), Number<N - 1>());
621 else
622 return tS(M - 1, N - 1) * r.eval(NumberDim(), Number<M - 1>(),
626
627 +
628
631 }
632
633 template <int I, int J, int K, int L, int M>
634 inline auto add(const Number<I> &, const Number<J> &, const Number<K> &,
635 const Number<L> &, const Number<M> &, const Number<1> &) {
636 return (tS(M - 1, 0) + tS(0, M - 1)) *
637 r.eval(NumberDim(), Number<M - 1>(), Number<0>(),
640
641 +
642
645
646 ;
647 }
648
649 template <int I, int J, int K, int L>
650 inline auto add(const Number<I> &, const Number<J> &, const Number<K> &,
651 const Number<L> &, const Number<1> &, const Number<1> &) {
652 return tS(0, 0) * r.eval(NumberDim(), Number<0>(), Number<0>(),
654 Number<L - 1>());
655 }
656
657 template <int I, int J, int K, int L>
658 inline void set(const Number<I> &, const Number<J> &, const Number<K> &,
659 const Number<L> &) {
661 tA(I - 1, J - 1, K - 1, L - 1) = add(Number<I>(), Number<J>(), Number<K>(),
663 // Major symmetry
664 if constexpr (K != I || L != J)
665 tA(K - 1, L - 1, I - 1, J - 1) = tA(I - 1, J - 1, K - 1, L - 1);
666 }
667
668 template <int I, int J, int K>
669 inline void set(const Number<I> &, const Number<J> &, const Number<K> &,
670 const Number<0> &) {
672 }
673
674 template <int I, int J>
675 inline void set(const Number<I> &, const Number<J> &, const Number<0> &,
676 const Number<0> &) {
678 }
679
680 template <int I, int K>
681 inline void set(const Number<I> &, const Number<0> &, const Number<K> &,
682 const Number<0> &) {
684 }
685
686 inline void set(const Number<0> &, const Number<0> &, const Number<0> &,
687 const Number<0> &) {}
688};
689
690template <typename E, typename C, typename T1, typename VT2, int DimT2>
691struct GetDiffDiffMatImpl<E, C, T1, FTensor::Tensor2_symmetric<VT2, DimT2>> {
692 using Val = typename E::Val;
693 using Vec = typename E::Vec;
694 using Fun = typename E::Fun;
695
696 using NumberNb = typename E::NumberNb;
697 using NumberDim = typename E::NumberDim;
698
699 template <int N> using Number = FTensor::Number<N>;
700
702 : r(e), e(e), tA(t_a), tS(t_S) {}
704 E &e;
705 T1 &tA;
707
708 template <int I, int J, int K, int L, int M, int N>
709 inline auto add(const Number<I> &, const Number<J> &, const Number<K> &,
710 const Number<L> &, const Number<M> &, const Number<N> &) {
711
712 if constexpr (N != M)
713 return (2 * tS(Number<M - 1>(), Number<N - 1>())) *
714 r.eval(NumberDim(), Number<M - 1>(), Number<N - 1>(),
715 Number<I - 1>(), Number<J - 1>(), Number<K - 1>(),
717
718 +
719
721 Number<M>(), Number<N - 1>());
722 else
723 return tS(Number<M - 1>(), Number<N - 1>()) *
727
728 +
729
732 }
733
734 template <int I, int J, int K, int L, int M>
735 inline auto add(const Number<I> &, const Number<J> &, const Number<K> &,
736 const Number<L> &, const Number<M> &, const Number<1> &) {
737 return (2 * tS(Number<M - 1>(), Number<0>())) *
738 r.eval(NumberDim(), Number<M - 1>(), Number<0>(),
741
742 +
743
746 }
747
748 template <int I, int J, int K, int L>
749 inline auto add(const Number<I> &, const Number<J> &, const Number<K> &,
750 const Number<L> &, const Number<1> &, const Number<1> &) {
751 return tS(Number<0>(), Number<0>()) *
754 }
755
756 template <int I, int J, int K, int L>
757 inline void set(const Number<I> &, const Number<J> &, const Number<K> &,
758 const Number<L> &) {
759
761
764 NumberDim());
765
766 // Major symmetry
767 if constexpr (K != I || L != J)
768 tA(Number<K - 1>(), Number<L - 1>(), Number<I - 1>(), Number<J - 1>()) =
770 Number<L - 1>());
771 }
772
773 template <int I, int J, int K>
774 inline void set(const Number<I> &, const Number<J> &, const Number<K> &,
775 const Number<0> &) {
777 }
778
779 template <int I, int J>
780 inline void set(const Number<I> &, const Number<J> &, const Number<0> &,
781 const Number<0> &) {
783 }
784
785 template <int I, int K>
786 inline void set(const Number<I> &, const Number<0> &, const Number<K> &,
787 const Number<0> &) {
789 }
790
791 inline void set(const Number<0> &, const Number<0> &, const Number<0> &,
792 const Number<0> &) {}
793};
794
795/** Compute S:D2f(A) directly, without materialising sixth-order derivatives. */
796template <typename T1, typename T2, int Dim>
798
801 using Fun = boost::function<double(const double)>;
802 using V = double;
803
804 static constexpr int sizeSymm = (Dim * (Dim + 1)) / 2;
805
807 : tVal(t_val), tVec(t_vec) {}
808
809 template <typename T>
810 inline auto getDiffDiffMat(Fun f, Fun d_f, Fun dd_f, T &t_S) {
811 // Coalesce only eigenvalues equal within the same tolerance as getUniqNb.
812 V group_ref[Dim];
813 V group_val[Dim]{};
814 int group_size[Dim]{};
815 int group_of[Dim];
816 int nb_groups = 0;
817
818 auto is_equal = [](const V a, const V b) {
819 const V eps = 100 * std::numeric_limits<V>::epsilon();
820 const V scale = std::max(V(1), std::max(std::abs(a), std::abs(b)));
821 return std::abs(a - b) <= eps * scale;
822 };
823
824 for (int aa = 0; aa != Dim; ++aa) {
825 int gg = 0;
826 for (; gg != nb_groups; ++gg)
827 if (is_equal(tVal(aa), group_ref[gg]))
828 break;
829
830 if (gg == nb_groups) {
831 group_ref[gg] = tVal(aa);
832 ++nb_groups;
833 }
834 group_of[aa] = gg;
835 group_val[gg] += tVal(aa);
836 ++group_size[gg];
837 }
838
839 V f_val[Dim];
840 V df_val[Dim];
841 V ddf_val[Dim];
842 for (int aa = 0; aa != nb_groups; ++aa) {
843 group_val[aa] /= group_size[aa];
844 f_val[aa] = f(group_val[aa]);
845 df_val[aa] = d_f(group_val[aa]);
846 ddf_val[aa] = dd_f(group_val[aa]);
847 }
848
849 auto first_divided_difference = [&](const int aa, const int bb) {
850 if (aa == bb)
851 return df_val[aa];
852 return (f_val[aa] - f_val[bb]) / (group_val[aa] - group_val[bb]);
853 };
854
855 auto second_divided_difference = [&](const int aa, const int bb,
856 const int cc) {
857 if (aa == bb && bb == cc)
858 return ddf_val[aa] / 2;
859
860 if (aa == bb) {
861 const V d1 = first_divided_difference(aa, cc);
862 return (df_val[aa] - d1) / (group_val[aa] - group_val[cc]);
863 }
864 if (aa == cc) {
865 const V d1 = first_divided_difference(aa, bb);
866 return (df_val[aa] - d1) / (group_val[aa] - group_val[bb]);
867 }
868 if (bb == cc) {
869 const V d1 = first_divided_difference(aa, bb);
870 return (d1 - df_val[bb]) / (group_val[aa] - group_val[bb]);
871 }
872
873 const V d1_ab = first_divided_difference(aa, bb);
874 const V d1_bc = first_divided_difference(bb, cc);
875 return (d1_ab - d1_bc) / (group_val[aa] - group_val[cc]);
876 };
877
878 V ddf[Dim][Dim][Dim];
879 for (int aa = 0; aa != Dim; ++aa)
880 for (int bb = 0; bb != Dim; ++bb)
881 for (int cc = 0; cc != Dim; ++cc)
882 ddf[aa][bb][cc] = second_divided_difference(
883 group_of[aa], group_of[bb], group_of[cc]);
884
885 V s_hat[Dim][Dim]{};
886 for (int aa = 0; aa != Dim; ++aa)
887 for (int cc = 0; cc != Dim; ++cc)
888 for (int ii = 0; ii != Dim; ++ii)
889 for (int jj = 0; jj != Dim; ++jj)
890 s_hat[aa][cc] += tVec(aa, ii) * t_S(ii, jj) * tVec(cc, jj);
891
892 int pair_0[sizeSymm];
893 int pair_1[sizeSymm];
894 V basis_hat[sizeSymm][Dim][Dim];
895 // Off-diagonal directions carry 1/2 to recover Cartesian Ddg components.
896 for (int ii = 0; ii != Dim; ++ii)
897 for (int jj = ii; jj != Dim; ++jj) {
898 const int LL = get_sym_index(ii, jj, Dim);
899 pair_0[LL] = ii;
900 pair_1[LL] = jj;
901 for (int aa = 0; aa != Dim; ++aa)
902 for (int bb = 0; bb != Dim; ++bb)
903 basis_hat[LL][aa][bb] =
904 (tVec(aa, ii) * tVec(bb, jj) + tVec(aa, jj) * tVec(bb, ii)) / 2;
905 }
906
908 for (int LL = 0; LL != sizeSymm; ++LL)
909 for (int JJ = 0; JJ <= LL; ++JJ) {
910 V v = 0;
911 for (int aa = 0; aa != Dim; ++aa)
912 for (int bb = 0; bb != Dim; ++bb)
913 for (int cc = 0; cc != Dim; ++cc)
914 v += s_hat[aa][cc] * ddf[aa][bb][cc] *
915 (basis_hat[LL][aa][bb] * basis_hat[JJ][bb][cc] +
916 basis_hat[JJ][aa][bb] * basis_hat[LL][bb][cc]);
917
918 t_diff_A(pair_0[LL], pair_1[LL], pair_0[JJ], pair_1[JJ]) = v;
919 if (JJ != LL)
920 t_diff_A(pair_0[JJ], pair_1[JJ], pair_0[LL], pair_1[LL]) = v;
921 }
922
923 return t_diff_A;
924 }
925
926private:
929};
930
931template <typename T1, typename T2, int NB, int Dim> struct EigenMatrixImp {
932
935 using Fun = boost::function<double(const double)>;
936 using V = double; // typename FTensor::promote<T1, T2>::V;
937
938 template <int N> using Number = FTensor::Number<N>;
939 template <char c> using I = typename FTensor::Index<c, Dim>;
940
943
944 EigenMatrixImp(Val &t_val, Vec &t_vec) : tVal(t_val), tVec(t_vec) {
945
946 FTensor::Index<'i', Dim> i;
947 FTensor::Index<'j', Dim> j;
948 FTensor::Index<'k', Dim> k;
949 FTensor::Index<'l', Dim> l;
950
951 for (auto aa = 0; aa != Dim; ++aa) {
952 auto &M = aM[aa];
953 for (auto ii = 0; ii != Dim; ++ii)
954 for (auto jj = 0; jj <= ii; ++jj)
955 M(ii, jj) = tVec(aa, ii) * tVec(aa, jj);
956 }
957
958 for (auto aa = 0; aa != Dim; ++aa) {
959 for (auto bb = 0; bb != Dim; ++bb) {
960 auto &Ma = aM[aa];
961 auto &Mb = aM[bb];
962 auto &MM = aMM[aa][bb];
963 MM(i, j, k, l) = Ma(i, j) * Mb(k, l);
964 }
965 }
966
967 for (auto aa = 0; aa != Dim; ++aa) {
968 for (auto bb = 0; bb != Dim; ++bb) {
969 if (aa != bb) {
970 auto &MM = aMM[aa][bb];
971 auto &G = aG[aa][bb];
972 G(i, j, k, l) = MM(i, k, j, l) || MM(i, l, j, k);
973 }
974 }
975 }
976
977 for (auto aa = 0; aa != Dim; ++aa) {
978 for (auto bb = 0; bb != Dim; ++bb) {
979 if (aa != bb) {
980 auto &Gab = aG[aa][bb];
981 auto &Gba = aG[bb][aa];
982 auto &S = aS[get_sym_index(aa, bb, Dim)];
983 S(i, j, k, l) = Gab(i, j, k, l) + Gba(i, j, k, l);
984 }
985 }
986 }
987 }
988
989 /**
990 * @brief Get matrix
991 *
992 * \f[
993 * \mathbf{B} = f(\mathbf{A})
994 * \f]
995 *
996 * \f[
997 * B_{ij} = \sum_{a}^3 f(\lambda^a) n^a_i n^a_j
998 * \f]
999 * where \f$a\f$ is eigen value number.
1000 *
1001 * @param t_val eiegn values vector
1002 * @param t_vec eigen vectors matrix
1003 * @param f function
1004 * @return auto function symmetric tensor rank two
1005 */
1006 inline auto getMat(Fun f) {
1007
1008 for (auto aa = 0; aa != Dim; ++aa)
1009 fVal(aa) = f(tVal(aa));
1010
1011 using T3 =
1013 T3 t_A;
1015 .set(NumberDim(), NumberDim());
1016 return t_A;
1017 }
1018
1019 /**
1020 * @brief Get derivative of matrix
1021 *
1022 * \f[
1023 * P_{ijkl} = \frac{\partial B_{ij}}{\partial A_{kl}}
1024 * \f]
1025 *
1026 * @param t_val eiegn values vector
1027 * @param t_vec eiegn vectors matrix
1028 * @param f function
1029 * @param d_f directive of function
1030 * @return auto derivatives, forth order tensor with minor simetries
1031 */
1032 inline auto getDiffMat(Fun f, Fun d_f) {
1033
1034 for (auto aa = 0; aa != Dim; ++aa)
1035 fVal(aa) = f(tVal(aa));
1036
1037 for (auto aa = 0; aa != Dim; ++aa)
1038 dfVal(aa) = d_f(tVal(aa));
1039
1040 for (auto aa = 0; aa != Dim; ++aa)
1041 for (auto bb = 0; bb != aa; ++bb) {
1042 aF(aa, bb) = 1 / (tVal(aa) - tVal(bb));
1043 aF(bb, aa) = -aF(aa, bb);
1044 aF2(aa, bb) = aF(aa, bb) * aF(aa, bb);
1045 }
1046
1047 using T3 = FTensor::Ddg<V, Dim, Dim>;
1048 T3 t_diff_A;
1050 .set(NumberDim(), NumberDim(), NumberDim(), NumberDim());
1051 return t_diff_A;
1052 }
1053
1054 /**
1055 * @brief Get second directive of matrix
1056 *
1057 * \f[
1058 * LS_{klmn} =
1059 * S_{ij} \frac{\partial^2 B_{ij}}{\partial A_{kl} \partial A_{mn} }
1060 * \f]
1061 *
1062 * @tparam T
1063 * @param t_val eigen values vector
1064 * @param t_vec eigen vectors matrix
1065 * @param f function
1066 * @param d_f derivative of function
1067 * @param dd_f second derivative of function
1068 * @param t_S second rank tensor S
1069 * @return auto second derivatives, forth order tensor with minor symmetries
1070 */
1071 template <typename T>
1072 inline auto getDiffDiffMat(Fun f, Fun d_f, Fun dd_f, T &t_S) {
1073
1074 for (auto aa = 0; aa != Dim; ++aa)
1075 fVal(aa) = f(tVal(aa));
1076
1077 for (auto aa = 0; aa != Dim; ++aa)
1078 dfVal(aa) = d_f(tVal(aa));
1079
1080 for (auto aa = 0; aa != Dim; ++aa)
1081 ddfVal(aa) = dd_f(tVal(aa));
1082
1083 for (auto aa = 0; aa != Dim; ++aa)
1084 for (auto bb = 0; bb != aa; ++bb) {
1085 aF(aa, bb) = 1 / (tVal(aa) - tVal(bb));
1086 aF(bb, aa) = -aF(aa, bb);
1087 aF2(aa, bb) = aF(aa, bb) * aF(aa, bb);
1088 }
1089
1090 FTensor::Index<'i', Dim> i;
1091 FTensor::Index<'j', Dim> j;
1092 FTensor::Index<'k', Dim> k;
1093 FTensor::Index<'l', Dim> l;
1094
1095 for (auto aa = 0; aa != Dim; ++aa) {
1096 for (auto bb = 0; bb != Dim; ++bb) {
1097 if (aa != bb) {
1098 const auto &S = aS[get_sym_index(aa, bb, Dim)];
1099 const auto &M = aM[aa];
1100 auto &SMmn = aSM[get_nodiag_index(aa, bb, Dim)];
1101 for (auto mm = 0; mm != Dim; ++mm) {
1102 for (auto nn = mm; nn != Dim; ++nn) {
1103 SMmn[get_sym_index(mm, nn, Dim)](i, j, k, l) =
1104 S(i, j, k, l) * M(mm, nn);
1105 }
1106 }
1107 }
1108 }
1109 }
1110
1111 for (auto aa = 0; aa != Dim; ++aa) {
1112 for (auto mm = 0; mm != Dim; ++mm) {
1113 for (auto nn = mm; nn != Dim; ++nn) {
1114 d2MType0[aa][get_sym_index(mm, nn, Dim)](i, j, k, l) = 0;
1115 }
1116 }
1117 }
1118
1119 if constexpr (NB == 3)
1120 for (auto aa = 0; aa != Dim; ++aa) {
1121 for (auto bb = 0; bb != Dim; ++bb) {
1122 if (aa != bb) {
1123 const V v = dfVal(aa) * aF(aa, bb);
1124 for (auto mm = 0; mm != Dim; ++mm) {
1125 for (auto nn = mm; nn != Dim; ++nn) {
1126 d2MType0[aa][get_sym_index(mm, nn, Dim)](i, j, k, l) +=
1127 v * aSM[get_nodiag_index(aa, bb, Dim)]
1128 [get_sym_index(mm, nn, Dim)](i, j, k, l);
1129 }
1130 }
1131 }
1132 }
1133 }
1134
1135 if constexpr (NB == 2)
1136 for (auto aa = 0; aa != Dim; ++aa) {
1137 for (auto bb = 0; bb != Dim; ++bb) {
1138 if (aa != bb) {
1139 V v;
1140 if (aa == 1 || bb == 1)
1141 v = dfVal(aa) * aF(aa, bb);
1142 else
1143 v = ddfVal(aa) / 2;
1144 for (auto mm = 0; mm != Dim; ++mm) {
1145 for (auto nn = mm; nn != Dim; ++nn) {
1146 d2MType0[aa][get_sym_index(mm, nn, Dim)](i, j, k, l) +=
1147 v * aSM[get_nodiag_index(aa, bb, Dim)]
1148 [get_sym_index(mm, nn, Dim)](i, j, k, l);
1149 }
1150 }
1151 }
1152 }
1153 }
1154
1155 if constexpr (NB == 1)
1156 for (auto aa = 0; aa != Dim; ++aa) {
1157 for (auto bb = 0; bb != Dim; ++bb) {
1158 if (aa != bb) {
1159 const V v = ddfVal(aa) / 2;
1160 for (auto mm = 0; mm != Dim; ++mm) {
1161 for (auto nn = mm; nn != Dim; ++nn) {
1162 d2MType0[aa][get_sym_index(mm, nn, Dim)](i, j, k, l) +=
1163 v * aSM[get_nodiag_index(aa, bb, Dim)]
1164 [get_sym_index(mm, nn, Dim)](i, j, k, l);
1165 }
1166 }
1167 }
1168 }
1169 }
1170
1171 for (auto aa = 0; aa != Dim; ++aa) {
1172 for (auto mm = 0; mm != Dim; ++mm) {
1173 for (auto nn = 0; nn != Dim; ++nn) {
1174 if (nn != mm)
1175 d2MType1[mm][get_sym_index(aa, nn, Dim)](i, j, k, l) = 0;
1176 }
1177 }
1178 }
1179
1180 if constexpr (NB == 3)
1181 for (auto aa = 0; aa != Dim; ++aa) {
1182 for (auto bb = 0; bb != Dim; ++bb) {
1183 if (aa != bb) {
1184 const auto &S = aS[get_sym_index(aa, bb, Dim)];
1185 const auto v0 = aF(aa, bb);
1186 for (auto cc = 0; cc != Dim; ++cc) {
1187 for (auto dd = 0; dd != Dim; ++dd) {
1188 if (cc != dd) {
1189 const double v1 = fVal(cc) * aF(cc, dd);
1190 d2MType1[dd][get_sym_index(aa, cc, Dim)](i, j, k, l) +=
1191 (v1 * v0) * S(i, j, k, l);
1192 }
1193 }
1194 }
1195 }
1196 }
1197 }
1198
1199 if constexpr (NB == 2)
1200 for (auto aa = 0; aa != Dim; ++aa) {
1201 for (auto bb = 0; bb != Dim; ++bb) {
1202 if (aa != bb)
1203 for (auto cc = 0; cc != Dim; ++cc) {
1204 for (auto dd = 0; dd != Dim; ++dd)
1205 if (cc != dd) {
1206
1207 V r;
1208
1209 if ((cc == 1 || dd == 1) && (aa == 1 || bb == 1))
1210 r = fVal(cc) * aF(cc, dd) * aF(aa, bb);
1211 else if (cc != 1 && dd != 1 && aa != 1 && bb != 1) {
1212
1213 if ((aa != bb && bb != dd) && (aa != dd && bb != cc))
1214 r = ddfVal(cc) / 4;
1215 else
1216 r = 0;
1217
1218 } else if ((cc != 1 && dd != 1) && (aa == 1 || bb == 1))
1219 r = dfVal(cc) * aF(aa, bb) / 2;
1220 else if ((cc == 1 || dd == 1) && (aa != 1 && bb != 1)) {
1221
1222 if ((cc == 2 && dd == 1) || (cc == 1 && dd == 2))
1223 r = (
1224
1225 dfVal(cc)
1226
1227 - (fVal(cc) - fVal(dd)) * aF(cc, dd)
1228
1229 ) *
1230 aF(cc, dd);
1231
1232 else
1233 r = 0;
1234
1235 } else
1236 r = 0;
1237
1238 if (r)
1239 d2MType1[dd][get_sym_index(aa, cc, Dim)](i, j, k, l) +=
1240 r * aS[get_sym_index(aa, bb, Dim)](i, j, k, l);
1241 }
1242 }
1243 }
1244 }
1245
1246 if constexpr (NB == 1)
1247 for (auto aa = 0; aa != Dim; ++aa) {
1248 for (auto bb = 0; bb != Dim; ++bb) {
1249 if (aa != bb) {
1250 for (auto cc = 0; cc != Dim; ++cc) {
1251 for (auto dd = 0; dd != Dim; ++dd) {
1252 if (cc != dd) {
1253 if ((bb != dd) && (aa != dd && bb != cc)) {
1254 const double r = ddfVal(cc) / 4;
1255 d2MType1[dd][get_sym_index(aa, cc, Dim)](i, j, k, l) +=
1256 r * aS[get_sym_index(aa, bb, Dim)](i, j, k, l);
1257 }
1258 }
1259 }
1260 }
1261 }
1262 }
1263 }
1264
1266 using T3 = FTensor::Ddg<V, Dim, Dim>;
1267
1268 T3 t_diff_A;
1269 GetDiffDiffMatImpl<THIS, V, T3, T>(*this, t_diff_A, t_S)
1271 return t_diff_A;
1272 }
1273
1274private:
1280 FTensor::Ddg<V, Dim, Dim> aS[(Dim * (Dim + 1)) / 2];
1281 FTensor::Ddg<V, Dim, Dim> aSM[(Dim - 1) * Dim][(Dim * (Dim + 1)) / 2];
1282 FTensor::Ddg<V, Dim, Dim> d2MType0[Dim][(Dim * (Dim + 1)) / 2];
1283 FTensor::Ddg<V, Dim, Dim> d2MType1[Dim][(Dim * (Dim + 1)) / 2];
1289
1290 template <typename E, typename C> friend struct d2MCoefficients;
1291 template <typename E, typename C, typename G> friend struct d2MImpl;
1292 template <typename E, typename C> friend struct Fdd4MImpl;
1293 template <typename E, typename C> friend struct ReconstructMatImpl;
1294 template <typename E, typename C> friend struct FirstMatrixDirectiveImpl;
1295 template <typename E, typename C> friend struct SecondMatrixDirectiveImpl;
1296 template <typename E, typename C, typename T> friend struct GetDiffMatImpl;
1297 template <typename E, typename C, typename T3, typename T4>
1298 friend struct GetDiffDiffMatImpl;
1299
1300}; // namespace EigenMatrix
1301} // namespace EigenMatrix
constexpr double a
static const double eps
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
constexpr IntegrationType G
Definition level_set.cpp:33
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
auto get_sym_index(const Number< N1 > &, const Number< N2 > &, const Number< Dim > &)
auto get_nodiag_index(const Number< N1 > &, const Number< N2 > &, const Number< Dim > &)
Tensors class implemented by Walter Landry.
Definition FTensor.hpp:51
constexpr IntegrationType I
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
boost::function< double(const double)> Fun
auto getDiffDiffMat(Fun f, Fun d_f, Fun dd_f, T &t_S)
FTensor::Ddg< V, Dim, Dim > d2MType0[Dim][(Dim *(Dim+1))/2]
FTensor::Ddg< V, Dim, Dim > aMM[Dim][Dim]
FTensor::Tensor2_symmetric< V, Dim > aF2
FTensor::Ddg< V, Dim, Dim > aS[(Dim *(Dim+1))/2]
boost::function< double(const double)> Fun
FTensor::Ddg< V, Dim, Dim > d2MType1[Dim][(Dim *(Dim+1))/2]
auto getDiffMat(Fun f, Fun d_f)
Get derivative of matrix.
EigenMatrixImp(Val &t_val, Vec &t_vec)
typename FTensor::Index< c, Dim > I
FTensor::Tensor1< V, Dim > ddfVal
FTensor::Tensor2_symmetric< V, Dim > aM[Dim]
FTensor::Ddg< V, Dim, Dim > aSM[(Dim - 1) *Dim][(Dim *(Dim+1))/2]
FTensor::Ddg< V, Dim, Dim > aG[Dim][Dim]
FTensor::Tensor2< V, Dim, Dim > aF
auto getDiffDiffMat(Fun f, Fun d_f, Fun dd_f, T &t_S)
Get second directive of matrix.
typename E::NumberDim NumberDim
C eval(const Number< nb > &, const Number< a > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
C eval_SM(const Number< nb > &, const Number< a > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
C eval_SM(const Number< 1 > &, const Number< a > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
auto term_fd2S(const Number< a > &, const Number< b > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
C term_SM(const Number< a > &, const Number< b > &, const Number< NB > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
C eval_fdS2(const Number< 1 > &, const Number< a > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
C eval_fdS2(const Number< nb > &, const Number< a > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
C eval(const Number< nb > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &) const
C eval(const Number< 1 > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &) const
d2MImpl< E, C, d2MCoefficients< E, C > > r
void set(const Number< I > &, const Number< J > &, const Number< 0 > &, const Number< 0 > &)
auto add(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &, const Number< M > &, const Number< N > &)
void set(const Number< 0 > &, const Number< 0 > &, const Number< 0 > &, const Number< 0 > &)
void set(const Number< I > &, const Number< J > &, const Number< K > &, const Number< 0 > &)
auto add(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &, const Number< M > &, const Number< 1 > &)
void set(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &)
auto add(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &, const Number< 1 > &, const Number< 1 > &)
GetDiffDiffMatImpl(E &e, T1 &t_a, FTensor::Tensor2_symmetric< VT2, DimT2 > &t_S)
void set(const Number< I > &, const Number< 0 > &, const Number< K > &, const Number< 0 > &)
void set(const Number< I > &, const Number< J > &, const Number< 0 > &, const Number< 0 > &)
void set(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &)
auto add(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &, const Number< M > &, const Number< N > &)
auto add(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &, const Number< M > &, const Number< 1 > &)
void set(const Number< I > &, const Number< J > &, const Number< K > &, const Number< 0 > &)
void set(const Number< 0 > &, const Number< 0 > &, const Number< 0 > &, const Number< 0 > &)
auto add(const Number< I > &, const Number< J > &, const Number< K > &, const Number< L > &, const Number< 1 > &, const Number< 1 > &)
SecondMatrixDirectiveImpl< E, C > r
void set(const Number< I > &, const Number< 0 > &, const Number< K > &, const Number< 0 > &)
void set(const Number< 1 > &, const Number< 1 > &, const Number< k > &, const Number< l > &)
FirstMatrixDirectiveImpl< E, C > r
void set(const Number< 1 > &, const Number< 1 > &, const Number< 1 > &, const Number< l > &)
void set(const Number< 1 > &, const Number< j > &, const Number< k > &, const Number< l > &)
void set(const Number< 1 > &, const Number< 1 > &, const Number< 1 > &, const Number< 1 > &)
void set(const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &)
void set(const Number< 1 > &, const Number< 1 > &)
ReconstructMatImpl< E, C > r
void set(const Number< i > &, const Number< j > &)
void set(const Number< i > &, const Number< 1 > &)
C eval(const Number< 1 > &, const Number< i > &, const Number< j > &) const
C eval(const Number< nb > &, const Number< i > &, const Number< j > &) const
C eval(const Number< 1 > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
C eval(const Number< nb > &, const Number< i > &, const Number< j > &, const Number< k > &, const Number< l > &, const Number< m > &, const Number< n > &) const
auto get(const Number< a > &, const Number< b > &, const int i, const int j, const int k, const int l, const Number< 2 > &) const
auto get(const Number< a > &, const Number< b > &, const int i, const int j, const int k, const int l, const Number< 3 > &) const
auto get(const Number< a > &, const Number< b > &, const int i, const int j, const int k, const int l, const Number< 1 >) const
C term(const int i, const int j, const int k, const int l) const
C eval(const Number< nb > &, const Number< a > &, const int i, const int j, const int k, const int l) const
C eval(const Number< 1 > &, const Number< a > &, const int i, const int j, const int k, const int l) const
double scale
Definition plastic.cpp:124