21#ifndef __B2_TENSOR_CALCULUS_H__
22#define __B2_TENSOR_CALCULUS_H__
60 return mat_a[0][0] * (mat_a[1][1] * mat_a[2][2] - mat_a[1][2] * mat_a[2][1])
61 + mat_a[1][0] * (mat_a[0][2] * mat_a[2][1] - mat_a[0][1] * mat_a[2][2])
62 + mat_a[2][0] * (mat_a[0][1] * mat_a[1][2] - mat_a[0][2] * mat_a[1][1]);
72 return mat_a[0][0] * mat_a[1][1] - mat_a[0][1] * mat_a[1][0];
87 const std::array<std::array<T, 3>, 3>& mat_a, std::array<std::array<T, 3>, 3>& mat_b) {
89 if (determinant == T(0)) {
90 mat_b.fill({T(0), T(0), T(0)});
93 const T inv_det = T(1) / determinant;
94 mat_b[0][0] = (mat_a[1][1] * mat_a[2][2] - mat_a[1][2] * mat_a[2][1]) * inv_det;
95 mat_b[0][1] = (mat_a[0][2] * mat_a[2][1] - mat_a[0][1] * mat_a[2][2]) * inv_det;
96 mat_b[0][2] = (mat_a[0][1] * mat_a[1][2] - mat_a[0][2] * mat_a[1][1]) * inv_det;
97 mat_b[1][0] = (mat_a[1][2] * mat_a[2][0] - mat_a[1][0] * mat_a[2][2]) * inv_det;
98 mat_b[1][1] = (mat_a[0][0] * mat_a[2][2] - mat_a[0][2] * mat_a[2][0]) * inv_det;
99 mat_b[1][2] = (mat_a[0][2] * mat_a[1][0] - mat_a[0][0] * mat_a[1][2]) * inv_det;
100 mat_b[2][0] = (mat_a[1][0] * mat_a[2][1] - mat_a[1][1] * mat_a[2][0]) * inv_det;
101 mat_b[2][1] = (mat_a[0][1] * mat_a[2][0] - mat_a[0][0] * mat_a[2][1]) * inv_det;
102 mat_b[2][2] = (mat_a[0][0] * mat_a[1][1] - mat_a[0][1] * mat_a[1][0]) * inv_det;
118 const std::array<std::array<T, 2>, 2>& mat_a, std::array<std::array<T, 2>, 2>& mat_b) {
120 if (determinant == T(0)) {
121 mat_b.fill({T(0), T(0)});
124 const T inv_det = T(1) / determinant;
125 mat_b[0][0] = +mat_a[1][1] * inv_det;
126 mat_b[0][1] = -mat_a[0][1] * inv_det;
127 mat_b[1][0] = -mat_a[1][0] * inv_det;
128 mat_b[1][1] = +mat_a[0][0] * inv_det;
142inline std::array<T, 2>
eigenvalues_2(
const std::array<std::array<T, 2>, 2>& matrix) {
143 const T trace = matrix[0][0] + matrix[1][1];
144 const T determinant = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
145 const T discriminant = trace * trace / 4 - determinant;
148 std::array<T, 2> eigenvalues;
153 if constexpr (std::is_floating_point<T>::value) {
154 if (discriminant >= 0) {
155 s = std::sqrt(discriminant);
156 }
else if (std::fabs(discriminant) <= 4096 * std::numeric_limits<T>::epsilon()) {
162 s = std::sqrt(discriminant);
165 eigenvalues[0] = trace / 2 + s;
166 eigenvalues[1] = trace / 2 - s;
182 const std::array<std::array<T, 2>, 2>& matrix, std::array<T, 2>& eigenvalues,
183 std::array<std::array<T, 2>, 2>& eigenvector) {
186 if (std::abs(matrix[0][1]) > std::numeric_limits<T>::epsilon()) {
187 eigenvector[0][0] = eigenvalues[0] - matrix[1][1];
188 eigenvector[1][0] = eigenvalues[1] - matrix[1][1];
189 eigenvector[0][1] = eigenvector[1][1] = matrix[0][1];
190 }
else if (std::abs(matrix[1][0]) > std::numeric_limits<T>::epsilon()) {
191 eigenvector[0][0] = eigenvector[1][0] = matrix[1][0];
192 eigenvector[0][1] = eigenvalues[0] - matrix[0][0];
193 eigenvector[1][1] = eigenvalues[1] - matrix[0][0];
195 eigenvector[0][0] = eigenvector[1][1] = 1;
196 eigenvector[1][0] = eigenvector[0][1] = 0;
201template <
typename T1>
203 std::fill_n(a, 3, T1(0));
207template <
typename T1>
209 std::fill_n(a, 2, T1(0));
213template <
typename T1>
214inline void copy_3(
const T1 a[3], T1 b[3]) {
215 std::copy(a, a + 3, b);
219template <
typename T1,
typename T2>
220inline void copy_3(
const T1 a[3], T2 b[3]) {
221 for (
int i = 0; i != 3; ++i) { b[i] = a[i]; }
225template <
typename T1>
226inline void copy_2(
const T1 a[2], T1 b[2]) {
227 std::copy(a, a + 2, b);
231template <
typename T1,
typename T2>
232inline void copy_2(
const T1 a[2], T2 b[2]) {
233 for (
int i = 0; i != 2; ++i) { b[i] = a[i]; }
238template <
typename T1,
typename T2,
typename T3>
239inline void sub_3(
const T1 v1[3],
const T2 v2[3], T3 dest[3]) {
240 dest[0] = v1[0] - v2[0];
241 dest[1] = v1[1] - v2[1];
242 dest[2] = v1[2] - v2[2];
247template <
typename T1,
typename T2,
typename T3>
248inline void sub_2(
const T1 v1[2],
const T2 v2[2], T3 dest[2]) {
249 dest[0] = v1[0] - v2[0];
250 dest[1] = v1[1] - v2[1];
255template <
typename T1,
typename T2,
typename T3>
256inline void add_3(
const T1 v1[3],
const T2 v2[3], T3 dest[3]) {
257 dest[0] = v1[0] + v2[0];
258 dest[1] = v1[1] + v2[1];
259 dest[2] = v1[2] + v2[2];
264template <
typename T1,
typename T2,
typename T3>
265inline void add_2(
const T1 v1[2],
const T2 v2[2], T3 dest[2]) {
266 dest[0] = v1[0] + v2[0];
267 dest[1] = v1[1] + v2[1];
272template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
273inline void add_scale_3(
const T1 s1,
const T2 v1[3],
const T3 s2,
const T4 v2[3], T5 dest[3]) {
274 dest[0] = s1 * v1[0] + s2 * v2[0];
275 dest[1] = s1 * v1[1] + s2 * v2[1];
276 dest[2] = s1 * v1[2] + s2 * v2[2];
281template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
282inline void add_scale_2(
const T1 s1,
const T2 v1[2],
const T3 s2,
const T4 v2[2], T5 dest[2]) {
283 dest[0] = s1 * v1[0] + s2 * v2[0];
284 dest[1] = s1 * v1[1] + s2 * v2[1];
288template <
typename T1,
typename T2>
296template <
typename T1,
typename T2>
303template <
typename T1,
typename T2>
304inline void add_3(T1 a[3],
const T2 b[3]) {
305 for (
int i = 0; i != 3; ++i) { a[i] += b[i]; }
309template <
typename T1,
typename T2>
310inline void add_2(T1 a[2],
const T2 b[2]) {
311 for (
int i = 0; i != 2; ++i) { a[i] += b[i]; }
315template <
typename T1,
typename T2,
typename T3>
317 for (
int i = 0; i != 3; ++i) { a[i] += s * b[i]; }
321template <
typename T1,
typename T2,
typename T3>
323 for (
int i = 0; i != 2; ++i) { a[i] += s * b[i]; }
328inline T
dot_3(
const T a[3],
const T b[3]) {
329 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
334inline std::complex<T>
dot_3(
const std::complex<T> a[3],
const std::complex<T> b[3]) {
335 return a[0] * std::conj(b[0]) + a[1] * std::conj(b[1]) + a[2] * std::conj(b[2]);
340inline b2000::csda<T>
dot_3(
const b2000::csda<T> a[3],
const b2000::csda<T> b[3]) {
341 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
346inline T
dot_2(
const T a[2],
const T b[2]) {
347 return a[0] * b[0] + a[1] * b[1];
352inline std::complex<T>
dot_2(
const std::complex<T> a[2],
const std::complex<T> b[2]) {
353 return a[0] * std::conj(b[0]) + a[1] * std::conj(b[1]);
358inline b2000::csda<T>
dot_2(
const b2000::csda<T> a[2],
const b2000::csda<T> b[2]) {
359 return a[0] * b[0] + a[1] * b[1];
365 return std::sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
371 return std::sqrt(std::norm(a[0]) + std::norm(a[1]) + std::norm(a[2]));
377 return std::sqrt(a[0] * a[0] + a[1] * a[1]);
383 return std::sqrt(std::norm(a[0]) + std::norm(a[1]));
388template <
typename T1,
typename T2,
typename T3>
390 c[0] = a[1] * b[2] - a[2] * b[1];
391 c[1] = a[2] * b[0] - a[0] * b[2];
392 c[2] = a[0] * b[1] - a[1] * b[0];
397template <
typename T1,
typename T2,
typename T3>
399 c[0] += a[1] * b[2] - a[2] * b[1];
400 c[1] += a[2] * b[0] - a[0] * b[2];
401 c[2] += a[0] * b[1] - a[1] * b[0];
409 c[0] = a[1] * b[2] - a[2] * b[1];
410 c[1] = a[2] * b[0] - a[0] * b[2];
411 c[2] = a[0] * b[1] - a[1] * b[0];
447 const b2000::csda<T> n =
norm_3(a);
449 b2000::csda<T> s = b2000::csda<T>(1) / n;
487 const b2000::csda<T> n =
norm_2(a);
489 b2000::csda<T> s = b2000::csda<T>(1) / n;
497template <
typename T1>
499 std::fill_n(&a[0][0], 9, T1(0));
503template <
typename T1>
505 a[0][0] = a[0][1] = T1(0);
506 a[1][0] = a[1][1] = T1(0);
510template <
typename T1>
512 std::fill_n(&a[0][0], 9, T1(0));
513 a[0][0] = a[1][1] = a[2][2] = T1(1);
517template <
typename T1>
519 a[0][0] = a[1][1] = T1(1);
520 a[0][1] = a[1][0] = T1(0);
524template <
typename T1>
525inline void copy_3_3(
const T1 a[3][3], T1 b[3][3]) {
526 std::copy(&a[0][0], &a[0][0] + 9, &b[0][0]);
530template <
typename T1,
typename T2>
531inline void copy_3_3(
const T1 a[3][3], T2 b[3][3]) {
532 for (
int i = 0; i != 3; ++i) {
533 for (
int j = 0; j != 3; ++j) { b[i][j] = a[i][j]; }
538template <
typename T1>
539inline void copy_2_2(
const T1 a[2][2], T1 b[2][2]) {
540 std::copy(&a[0][0], &a[0][0] + 4, &b[0][0]);
544template <
typename T1,
typename T2>
545inline void copy_2_2(
const T1 a[2][2], T2 b[2][2]) {
546 for (
int i = 0; i != 2; ++i) {
547 for (
int j = 0; j != 2; ++j) { b[i][j] = a[i][j]; }
553inline void scale_3_3(
const T a,
const T b[3][3], T c[3][3]) {
554 c[0][0] = a * b[0][0];
555 c[0][1] = a * b[0][1];
556 c[0][2] = a * b[0][2];
557 c[1][0] = a * b[1][0];
558 c[1][1] = a * b[1][1];
559 c[1][2] = a * b[1][2];
560 c[2][0] = a * b[2][0];
561 c[2][1] = a * b[2][1];
562 c[2][2] = a * b[2][2];
567inline void scale_2_2(
const T a,
const T b[2][2], T c[2][2]) {
568 c[0][0] = a * b[0][0];
569 c[0][1] = a * b[0][1];
570 c[1][0] = a * b[1][0];
571 c[1][1] = a * b[1][1];
575template <
typename T1,
typename T2>
576inline void add_3_3(T1 a[3][3],
const T2 b[3][3]) {
579 for (
int i = 0; i != 9; ++i) { aa[i] += bb[i]; }
583template <
typename T1,
typename T2>
584inline void add_2_2(T1 a[2][2],
const T2 b[2][2]) {
587 for (
int i = 0; i != 4; ++i) { aa[i] += bb[i]; }
593 c[0][0] += a * b[0][0];
594 c[0][1] += a * b[0][1];
595 c[0][2] += a * b[0][2];
596 c[1][0] += a * b[1][0];
597 c[1][1] += a * b[1][1];
598 c[1][2] += a * b[1][2];
599 c[2][0] += a * b[2][0];
600 c[2][1] += a * b[2][1];
601 c[2][2] += a * b[2][2];
607 c[0][0] += a * b[0][0];
608 c[0][1] += a * b[0][1];
609 c[1][0] += a * b[1][0];
610 c[1][1] += a * b[1][1];
614template <
typename T1>
616 std::swap(a[0][1], a[1][0]);
617 std::swap(a[0][2], a[2][0]);
618 std::swap(a[1][2], a[2][1]);
622template <
typename T1>
624 std::swap(a[0][1], a[1][0]);
628template <
typename T1>
630 for (
int i = 0; i != 3; ++i) {
631 for (
int j = 0; j != 3; ++j) { b[i][j] = a[j][i]; }
636template <
typename T1>
638 for (
int i = 0; i != 2; ++i) {
639 for (
int j = 0; j != 2; ++j) { b[i][j] = a[j][i]; }
644template <
typename T1>
648 for (
int i = 0; i < 9; i++) { res = std::max(res, aa[i]); }
653template <
typename T1>
657 for (
int i = 0; i < 4; i++) { res = std::max(res, aa[i]); }
670 return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1])
671 + a[1][0] * (a[0][2] * a[2][1] - a[0][1] * a[2][2])
672 + a[2][0] * (a[0][1] * a[1][2] - a[0][2] * a[1][1]);
684 return a[0][0] * a[1][1] - a[0][1] * a[1][0];
702 std::fill(b[0], b[3], T(0));
705 const T inv_det = T(1) / det;
706 b[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) * inv_det;
707 b[0][1] = (a[0][2] * a[2][1] - a[0][1] * a[2][2]) * inv_det;
708 b[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) * inv_det;
709 b[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) * inv_det;
710 b[1][1] = (a[0][0] * a[2][2] - a[0][2] * a[2][0]) * inv_det;
711 b[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) * inv_det;
712 b[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) * inv_det;
713 b[2][1] = (a[0][1] * a[2][0] - a[0][0] * a[2][1]) * inv_det;
714 b[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) * inv_det;
732 const T inv_det = T(1) / det;
733 b[0][0] = +a[1][1] * inv_det;
734 b[0][1] = -a[0][1] * inv_det;
735 b[1][0] = -a[1][0] * inv_det;
736 b[1][1] = +a[0][0] * inv_det;
767 std::fill(b[0], b[3], T(0));
770 const T inv_det = T(1) / det;
771 b[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) * inv_det;
772 b[1][0] = (a[0][2] * a[2][1] - a[0][1] * a[2][2]) * inv_det;
773 b[2][0] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) * inv_det;
774 b[0][1] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) * inv_det;
775 b[1][1] = (a[0][0] * a[2][2] - a[0][2] * a[2][0]) * inv_det;
776 b[2][1] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) * inv_det;
777 b[0][2] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) * inv_det;
778 b[1][2] = (a[0][1] * a[2][0] - a[0][0] * a[2][1]) * inv_det;
779 b[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) * inv_det;
797 const T inv_det = T(1) / det;
798 b[0][0] = +a[1][1] * inv_det;
799 b[1][0] = -a[0][1] * inv_det;
800 b[0][1] = -a[1][0] * inv_det;
801 b[1][1] = +a[0][0] * inv_det;
809 c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
810 c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
811 c[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
812 c[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
813 c[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
814 c[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
815 c[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
816 c[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
817 c[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
824 c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[0][1] + a[0][2] * b[0][2];
825 c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[0][1] + a[1][2] * b[0][2];
826 c[0][2] = a[2][0] * b[0][0] + a[2][1] * b[0][1] + a[2][2] * b[0][2];
827 c[1][0] = a[0][0] * b[1][0] + a[0][1] * b[1][1] + a[0][2] * b[1][2];
828 c[1][1] = a[1][0] * b[1][0] + a[1][1] * b[1][1] + a[1][2] * b[1][2];
829 c[1][2] = a[2][0] * b[1][0] + a[2][1] * b[1][1] + a[2][2] * b[1][2];
830 c[2][0] = a[0][0] * b[2][0] + a[0][1] * b[2][1] + a[0][2] * b[2][2];
831 c[2][1] = a[1][0] * b[2][0] + a[1][1] * b[2][1] + a[1][2] * b[2][2];
832 c[2][2] = a[2][0] * b[2][0] + a[2][1] * b[2][1] + a[2][2] * b[2][2];
839 c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1];
840 c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1];
841 c[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1];
842 c[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1];
849 c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[1][0] + a[2][0] * b[2][0];
850 c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[1][0] + a[2][1] * b[2][0];
851 c[0][2] = a[0][2] * b[0][0] + a[1][2] * b[1][0] + a[2][2] * b[2][0];
852 c[1][0] = a[0][0] * b[0][1] + a[1][0] * b[1][1] + a[2][0] * b[2][1];
853 c[1][1] = a[0][1] * b[0][1] + a[1][1] * b[1][1] + a[2][1] * b[2][1];
854 c[1][2] = a[0][2] * b[0][1] + a[1][2] * b[1][1] + a[2][2] * b[2][1];
855 c[2][0] = a[0][0] * b[0][2] + a[1][0] * b[1][2] + a[2][0] * b[2][2];
856 c[2][1] = a[0][1] * b[0][2] + a[1][1] * b[1][2] + a[2][1] * b[2][2];
857 c[2][2] = a[0][2] * b[0][2] + a[1][2] * b[1][2] + a[2][2] * b[2][2];
864 c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[1][0];
865 c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[1][0];
866 c[1][0] = a[0][0] * b[0][1] + a[1][0] * b[1][1];
867 c[1][1] = a[0][1] * b[0][1] + a[1][1] * b[1][1];
874 c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0];
875 c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0];
876 c[0][2] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0];
877 c[1][0] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1];
878 c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1];
879 c[1][2] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1];
880 c[2][0] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2];
881 c[2][1] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2];
882 c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2];
889 c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0];
890 c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[1][0];
891 c[1][0] = a[0][0] * b[0][1] + a[0][1] * b[1][1];
892 c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1];
900 c[0] = a[0][0] * b[0] + a[1][0] * b[1];
901 c[1] = a[0][1] * b[0] + a[1][1] * b[1];
909 c[0] = a[0][0] * b[0] + a[0][1] * b[1];
910 c[1] = a[1][0] * b[0] + a[1][1] * b[1];
917 c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
918 c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
919 c[0][2] += a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
920 c[1][0] += a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
921 c[1][1] += a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
922 c[1][2] += a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
923 c[2][0] += a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
924 c[2][1] += a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
925 c[2][2] += a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
932 c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[0][1];
933 c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[0][1];
934 c[1][0] += a[0][0] * b[1][0] + a[1][0] * b[1][1];
935 c[1][1] += a[0][1] * b[1][0] + a[1][1] * b[1][1];
942 c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[0][1] + a[0][2] * b[0][2];
943 c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[0][1] + a[1][2] * b[0][2];
944 c[0][2] += a[2][0] * b[0][0] + a[2][1] * b[0][1] + a[2][2] * b[0][2];
945 c[1][0] += a[0][0] * b[1][0] + a[0][1] * b[1][1] + a[0][2] * b[1][2];
946 c[1][1] += a[1][0] * b[1][0] + a[1][1] * b[1][1] + a[1][2] * b[1][2];
947 c[1][2] += a[2][0] * b[1][0] + a[2][1] * b[1][1] + a[2][2] * b[1][2];
948 c[2][0] += a[0][0] * b[2][0] + a[0][1] * b[2][1] + a[0][2] * b[2][2];
949 c[2][1] += a[1][0] * b[2][0] + a[1][1] * b[2][1] + a[1][2] * b[2][2];
950 c[2][2] += a[2][0] * b[2][0] + a[2][1] * b[2][1] + a[2][2] * b[2][2];
957 c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[0][1];
958 c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[0][1];
959 c[1][0] += a[0][0] * b[1][0] + a[0][1] * b[1][1];
960 c[1][1] += a[1][0] * b[1][0] + a[1][1] * b[1][1];
967 c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[1][0] + a[2][0] * b[2][0];
968 c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[1][0] + a[2][1] * b[2][0];
969 c[0][2] += a[0][2] * b[0][0] + a[1][2] * b[1][0] + a[2][2] * b[2][0];
970 c[1][0] += a[0][0] * b[0][1] + a[1][0] * b[1][1] + a[2][0] * b[2][1];
971 c[1][1] += a[0][1] * b[0][1] + a[1][1] * b[1][1] + a[2][1] * b[2][1];
972 c[1][2] += a[0][2] * b[0][1] + a[1][2] * b[1][1] + a[2][2] * b[2][1];
973 c[2][0] += a[0][0] * b[0][2] + a[1][0] * b[1][2] + a[2][0] * b[2][2];
974 c[2][1] += a[0][1] * b[0][2] + a[1][1] * b[1][2] + a[2][1] * b[2][2];
975 c[2][2] += a[0][2] * b[0][2] + a[1][2] * b[1][2] + a[2][2] * b[2][2];
982 c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[1][0];
983 c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[1][0];
984 c[1][0] += a[0][0] * b[0][1] + a[1][0] * b[1][1];
985 c[1][1] += a[0][1] * b[0][1] + a[1][1] * b[1][1];
992 c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[0][1];
993 c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[0][1];
994 c[1][0] = a[0][0] * b[1][0] + a[0][1] * b[1][1];
995 c[1][1] = a[1][0] * b[1][0] + a[1][1] * b[1][1];
1000template <
typename T>
1002 c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0];
1003 c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0];
1004 c[0][2] += a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0];
1005 c[1][0] += a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1];
1006 c[1][1] += a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1];
1007 c[1][2] += a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1];
1008 c[2][0] += a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2];
1009 c[2][1] += a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2];
1010 c[2][2] += a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2];
1015template <
typename T>
1017 c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[1][0];
1018 c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[1][0];
1019 c[1][0] += a[0][0] * b[0][1] + a[0][1] * b[1][1];
1020 c[1][1] += a[1][0] * b[0][1] + a[1][1] * b[1][1];
1026template <
typename T>
1028 c[0] = a[0][0] * b[0] + a[1][0] * b[1] + a[2][0] * b[2];
1029 c[1] = a[0][1] * b[0] + a[1][1] * b[1] + a[2][1] * b[2];
1030 c[2] = a[0][2] * b[0] + a[1][2] * b[1] + a[2][2] * b[2];
1036template <
typename T>
1038 c[0] = a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2];
1039 c[1] = a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2];
1040 c[2] = a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2];
1046template <
typename T>
1048 c[0] += a[0][0] * b[0] + a[1][0] * b[1] + a[2][0] * b[2];
1049 c[1] += a[0][1] * b[0] + a[1][1] * b[1] + a[2][1] * b[2];
1050 c[2] += a[0][2] * b[0] + a[1][2] * b[1] + a[2][2] * b[2];
1055template <
typename T>
1057 c[0] += a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2];
1058 c[1] += a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2];
1059 c[2] += a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2];
1074template <
typename T>
1075inline bool solve_2_2(
const T a[2][2],
const T y[2], T x[2]) {
1078 std::fill(x, x + 2, T(0));
1081 const T inv_det = T(1) / det;
1082 x[0] = (y[0] * a[1][1] - y[1] * a[1][0]) * inv_det;
1083 x[1] = (y[1] * a[0][0] - y[0] * a[0][1]) * inv_det;
1096template <
typename T>
1098 const T t = m[0][0] + m[1][1];
1099 const T d = m[0][0] * m[1][1] - m[0][1] * m[1][0];
1100 const T s = std::sqrt(t * t / 4 - d);
1101 value[0] = t / 2 + s;
1102 value[1] = t / 2 - s;
1104 if (std::abs(m[0][1]) > std::numeric_limits<T>::epsilon()) {
1105 vector[0][0] = value[0] - m[1][1];
1106 vector[1][0] = value[1] - m[1][1];
1107 vector[0][1] = vector[1][1] = m[0][1];
1108 }
else if (std::abs(m[1][0]) > std::numeric_limits<T>::epsilon()) {
1109 vector[0][0] = vector[1][0] = m[1][0];
1110 vector[0][1] = value[0] - m[0][0];
1111 vector[1][1] = value[1] - m[0][0];
1113 vector[0][0] = vector[1][1] = 1;
1114 vector[1][0] = vector[0][1] = 0;
1121template <
typename T>
1123 i1 = t[0] + t[1] + t[2];
1124 i2 = t[0] * t[1] + t[1] * t[2] + t[0] * t[2] - t[3] * t[3] - t[4] * t[4] - t[5] * t[5];
1125 i3 = t[0] * t[1] * t[2] + 2 * t[3] * t[4] * t[5] - t[0] * t[4] * t[4] - t[1] * t[5] * t[5]
1126 - t[2] * t[3] * t[3];
1130template <
typename T>
1140 if (nsol == T(2)) { s3 = i1 - s1 - s2; }
1141 if (s1 < s2) { std::swap(s1, s2); }
1142 if (s1 < s3) { std::swap(s1, s3); }
1143 if (s2 < s3) { std::swap(s2, s3); }
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
void inner_product_3_3_TT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:873
void set_zero_3_3(T1 a[3][3])
Definition b2tensor_calculus.H:498
void add_2(const T1 v1[2], const T2 v2[2], T3 dest[2])
Definition b2tensor_calculus.H:265
void set_identity_3_3(T1 a[3][3])
Definition b2tensor_calculus.H:511
bool solve_2_2(const T a[2][2], const T y[2], T x[2])
Definition b2tensor_calculus.H:1075
void add_3(const T1 v1[3], const T2 v2[3], T3 dest[3])
Definition b2tensor_calculus.H:256
void inner_product_2_2_NT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:863
void inner_product_2_2_TT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:888
void inner_product_add_2_2_TN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:956
T invert_2_2(const T a[2][2], T b[2][2])
Definition b2tensor_calculus.H:730
void inner_product_add_2_2_NT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:981
void sub_2(const T1 v1[2], const T2 v2[2], T3 dest[2])
Definition b2tensor_calculus.H:248
T norm_outer_product_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:407
void add_scale_2_2(const T a, const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:606
T norm_3(T a[3])
Definition b2tensor_calculus.H:364
void copy_3(const T1 a[3], T1 b[3])
Definition b2tensor_calculus.H:214
void inner_product_3_3_NN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:808
void set_zero_2(T1 a[2])
Definition b2tensor_calculus.H:208
void inner_product_2_1_TN(const T a[2][2], const T b[2], T c[2])
Definition b2tensor_calculus.H:908
void inner_product_add_3_3_TT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:1001
void inner_product_add_3_3_NT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:966
T determinant_3x3(const std::array< std::array< T, 3 >, 3 > &mat_a)
Definition b2tensor_calculus.H:59
T determinant_3_3(const T a[3][3])
Definition b2tensor_calculus.H:669
void inner_product_3_1_TN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1037
T invert_x_x(const T a[2][2], T b[2][2])
Definition b2tensor_calculus.H:742
void add_scale_3_3(const T a, const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:592
void sub_3(const T1 v1[3], const T2 v2[3], T3 dest[3])
Definition b2tensor_calculus.H:239
void set_identity_2_2(T1 a[2][2])
Definition b2tensor_calculus.H:518
void add_scale_3(const T1 s1, const T2 v1[3], const T3 s2, const T4 v2[3], T5 dest[3])
Definition b2tensor_calculus.H:273
void set_zero_2_2(T1 a[2][2])
Definition b2tensor_calculus.H:504
void eigenvector_2(const std::array< std::array< T, 2 >, 2 > &matrix, std::array< T, 2 > &eigenvalues, std::array< std::array< T, 2 >, 2 > &eigenvector)
Definition b2tensor_calculus.H:181
T transposed_invert_3_3(const T a[3][3], T b[3][3])
Definition b2tensor_calculus.H:764
T normalise_3(T a[3])
Definition b2tensor_calculus.H:418
std::array< T, 2 > eigenvalues_2(const std::array< std::array< T, 2 >, 2 > &matrix)
Definition b2tensor_calculus.H:142
void add_scale_2(const T1 s1, const T2 v1[2], const T3 s2, const T4 v2[2], T5 dest[2])
Definition b2tensor_calculus.H:282
void outer_product_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:389
void transpose_2_2(T1 a[2][2])
Definition b2tensor_calculus.H:623
T determinant_2x2(const std::array< std::array< T, 2 >, 2 > &mat_a)
Definition b2tensor_calculus.H:71
void copy_2_2(const T1 a[2][2], T1 b[2][2])
Definition b2tensor_calculus.H:539
void inner_product_add_3_3_NN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:916
void inner_product_add_2_2_NN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:931
void solve_cubic_equation(const T a, const T b, const T c, const T d, int &nsol, T &x1, T &x2, T &x3)
Definition b2util.H:770
void inner_product_add_3_3_TN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:941
void stress_invariants(const T t[6], T &i1, T &i2, T &i3)
Definition b2tensor_calculus.H:1122
void inner_product_3_3_NT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:848
void add_3_3(T1 a[3][3], const T2 b[3][3])
Definition b2tensor_calculus.H:576
void inner_product_add_3_1_TN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1056
void inner_product_2_2_NN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:838
void inner_product_3_1_NN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1027
void add_2_2(T1 a[2][2], const T2 b[2][2])
Definition b2tensor_calculus.H:584
void copy_2(const T1 a[2], T1 b[2])
Definition b2tensor_calculus.H:226
void set_zero_3(T1 a[3])
Definition b2tensor_calculus.H:202
T transposed_invert_2_2(const T a[2][2], T b[2][2])
Definition b2tensor_calculus.H:795
T invert_3_3(const T a[3][3], T b[3][3])
Definition b2tensor_calculus.H:699
T norm_2(T a[2])
Definition b2tensor_calculus.H:376
T1 norm_inf_3_3(const T1 a[3][3])
Definition b2tensor_calculus.H:645
T normalise_2(T a[2])
Definition b2tensor_calculus.H:460
void outer_product_add_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:398
void copy_3_3(const T1 a[3][3], T1 b[3][3])
Definition b2tensor_calculus.H:525
T1 norm_inf_2_2(const T1 a[3][3])
Definition b2tensor_calculus.H:654
void scale_2(T1 v[2], const T2 s)
Definition b2tensor_calculus.H:297
T dot_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:328
void inner_product_3_3_TN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:823
void inner_product_add_2_2_TT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:1016
void scale_3(T1 v[3], const T2 s)
Definition b2tensor_calculus.H:289
T invert_3x3(const std::array< std::array< T, 3 >, 3 > &mat_a, std::array< std::array< T, 3 >, 3 > &mat_b)
Definition b2tensor_calculus.H:86
void inner_product_2_2_TN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:991
void scale_2_2(const T a, const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:567
T invert_2x2(const std::array< std::array< T, 2 >, 2 > &mat_a, std::array< std::array< T, 2 >, 2 > &mat_b)
Definition b2tensor_calculus.H:117
T determinant_2_2(const T a[2][2])
Definition b2tensor_calculus.H:683
T dot_2(const T a[2], const T b[2])
Definition b2tensor_calculus.H:346
void transpose_3_3(T1 a[3][3])
Definition b2tensor_calculus.H:615
void inner_product_add_3_1_NN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1047
void inner_product_2_1_NN(const T a[2][2], const T b[2], T c[2])
Definition b2tensor_calculus.H:899
void scale_3_3(const T a, const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:553
void stress_principals(const T i1, const T i2, const T i3, T &s1, T &s2, T &s3)
Calculate the stress principals from the stress invariants.
Definition b2tensor_calculus.H:1131