GMatTensor 0.10.6
Loading...
Searching...
No Matches
Cartesian3d.h
Go to the documentation of this file.
1
7#ifndef GMATTENSOR_CARTESIAN3D_H
8#define GMATTENSOR_CARTESIAN3D_H
9
10#include <xtensor/xadapt.hpp>
11#include <xtensor/xnoalias.hpp>
12#include <xtensor/xrandom.hpp>
13#include <xtensor/xtensor.hpp>
14#include <xtensor/xview.hpp>
15
16#include "config.h"
17#include "detail.hpp"
18#include "version.h"
19
20namespace GMatTensor {
21
26namespace Cartesian3d {
27
37namespace pointer {
38
39namespace detail {
40
41// ----------------------------------------------------------------------------
42// Numerical diagonalization of 3x3 matrices
43// Copyright (C) 2006 Joachim Kopp
44// ----------------------------------------------------------------------------
45// This library is free software; you can redistribute it and/or
46// modify it under the terms of the GNU Lesser General Public
47// License as published by the Free Software Foundation; either
48// version 2.1 of the License, or (at your option) any later version.
49//
50// This library is distributed in the hope that it will be useful,
51// but WITHOUT ANY WARRANTY; without even the implied warranty of
52// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53// Lesser General Public License for more details.
54//
55// You should have received a copy of the GNU Lesser General Public
56// License along with this library; if not, write to the Free Software
57// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
58// ----------------------------------------------------------------------------
59
60// ----------------------------------------------------------------------------
61inline int dsyevj3(double A[3][3], double Q[3][3], double w[3])
62// ----------------------------------------------------------------------------
63// Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3
64// matrix A using the Jacobi algorithm.
65// The upper triangular part of A is destroyed during the calculation,
66// the diagonal elements are read but not destroyed, and the lower
67// triangular elements are not referenced at all.
68// ----------------------------------------------------------------------------
69// Parameters:
70// A: The symmetric input matrix
71// Q: Storage buffer for eigenvectors
72// w: Storage buffer for eigenvalues
73// ----------------------------------------------------------------------------
74// Return value:
75// 0: Success
76// -1: Error (no convergence)
77// ----------------------------------------------------------------------------
78{
79 const int n = 3;
80 double sd, so; // Sums of diagonal resp. off-diagonal elements
81 double s, c, t; // sin(phi), cos(phi), tan(phi) and temporary storage
82 double g, h, z, theta; // More temporary storage
83 double thresh;
84
85 // Initialize Q to the identity matrix
86 for (int i = 0; i < n; i++) {
87 Q[i][i] = 1.0;
88 for (int j = 0; j < i; j++)
89 Q[i][j] = Q[j][i] = 0.0;
90 }
91
92 // Initialize w to diag(A)
93 for (int i = 0; i < n; i++)
94 w[i] = A[i][i];
95
96 // Calculate SQR(tr(A))
97 sd = 0.0;
98 for (int i = 0; i < n; i++)
99 sd += fabs(w[i]);
100 sd = sd * sd;
101
102 // Main iteration loop
103 for (int nIter = 0; nIter < 50; nIter++) {
104 // Test for convergence
105 so = 0.0;
106 for (int p = 0; p < n; p++)
107 for (int q = p + 1; q < n; q++)
108 so += fabs(A[p][q]);
109 if (so == 0.0)
110 return 0;
111
112 if (nIter < 4)
113 thresh = 0.2 * so / (n * n);
114 else
115 thresh = 0.0;
116
117 // Do sweep
118 for (int p = 0; p < n; p++)
119 for (int q = p + 1; q < n; q++) {
120 g = 100.0 * fabs(A[p][q]);
121 if (nIter > 4 && fabs(w[p]) + g == fabs(w[p]) && fabs(w[q]) + g == fabs(w[q])) {
122 A[p][q] = 0.0;
123 }
124 else if (fabs(A[p][q]) > thresh) {
125 // Calculate Jacobi transformation
126 h = w[q] - w[p];
127 if (fabs(h) + g == fabs(h)) {
128 t = A[p][q] / h;
129 }
130 else {
131 theta = 0.5 * h / A[p][q];
132 if (theta < 0.0)
133 t = -1.0 / (sqrt(1.0 + theta * theta) - theta);
134 else
135 t = 1.0 / (sqrt(1.0 + theta * theta) + theta);
136 }
137 c = 1.0 / sqrt(1.0 + t * t);
138 s = t * c;
139 z = t * A[p][q];
140
141 // Apply Jacobi transformation
142 A[p][q] = 0.0;
143 w[p] -= z;
144 w[q] += z;
145 for (int r = 0; r < p; r++) {
146 t = A[r][p];
147 A[r][p] = c * t - s * A[r][q];
148 A[r][q] = s * t + c * A[r][q];
149 }
150 for (int r = p + 1; r < q; r++) {
151 t = A[p][r];
152 A[p][r] = c * t - s * A[r][q];
153 A[r][q] = s * t + c * A[r][q];
154 }
155 for (int r = q + 1; r < n; r++) {
156 t = A[p][r];
157 A[p][r] = c * t - s * A[q][r];
158 A[q][r] = s * t + c * A[q][r];
159 }
160
161 // Update eigenvectors
162 for (int r = 0; r < n; r++) {
163 t = Q[r][p];
164 Q[r][p] = c * t - s * Q[r][q];
165 Q[r][q] = s * t + c * Q[r][q];
166 }
167 }
168 }
169 }
170
171 return -1;
172}
173// ----------------------------------------------------------------------------
174
175} // namespace detail
176
182template <class T>
183inline void O2(T* ret)
184{
185 std::fill(ret, ret + 9, T(0));
186}
187
193template <class T>
194inline void O4(T* ret)
195{
196 std::fill(ret, ret + 81, T(0));
197}
198
204template <class T>
205inline void I2(T* ret)
206{
207 ret[0] = 1.0;
208 ret[1] = 0.0;
209 ret[2] = 0.0;
210 ret[3] = 0.0;
211 ret[4] = 1.0;
212 ret[5] = 0.0;
213 ret[6] = 0.0;
214 ret[7] = 0.0;
215 ret[8] = 1.0;
216}
217
223template <class T>
224inline void II(T* ret)
225{
226 std::fill(ret, ret + 81, T(0));
227
228 for (size_t i = 0; i < 3; ++i) {
229 for (size_t j = 0; j < 3; ++j) {
230 for (size_t k = 0; k < 3; ++k) {
231 for (size_t l = 0; l < 3; ++l) {
232 if (i == j && k == l) {
233 ret[i * 27 + j * 9 + k * 3 + l] = 1.0;
234 }
235 }
236 }
237 }
238 }
239}
240
246template <class T>
247inline void I4(T* ret)
248{
249 std::fill(ret, ret + 81, T(0));
250
251 for (size_t i = 0; i < 3; ++i) {
252 for (size_t j = 0; j < 3; ++j) {
253 for (size_t k = 0; k < 3; ++k) {
254 for (size_t l = 0; l < 3; ++l) {
255 if (i == l && j == k) {
256 ret[i * 27 + j * 9 + k * 3 + l] = 1.0;
257 }
258 }
259 }
260 }
261 }
262}
263
269template <class T>
270inline void I4rt(T* ret)
271{
272 std::fill(ret, ret + 81, T(0));
273
274 for (size_t i = 0; i < 3; ++i) {
275 for (size_t j = 0; j < 3; ++j) {
276 for (size_t k = 0; k < 3; ++k) {
277 for (size_t l = 0; l < 3; ++l) {
278 if (i == k && j == l) {
279 ret[i * 27 + j * 9 + k * 3 + l] = 1.0;
280 }
281 }
282 }
283 }
284 }
285}
286
292template <class T>
293inline void I4s(T* ret)
294{
295 I4(ret);
296
297 std::array<double, 81> i4rt;
298 I4rt(&i4rt[0]);
299
300 std::transform(ret, ret + 81, &i4rt[0], ret, std::plus<T>());
301
302 std::transform(ret, ret + 81, ret, std::bind(std::multiplies<T>(), std::placeholders::_1, 0.5));
303}
304
310template <class T>
311inline void I4d(T* ret)
312{
313 I4s(ret);
314
315 std::array<double, 81> ii;
316 II(&ii[0]);
317
318 std::transform(
319 &ii[0], &ii[0] + 81, &ii[0], std::bind(std::divides<T>(), std::placeholders::_1, 3.0));
320
321 std::transform(ret, ret + 81, &ii[0], ret, std::minus<T>());
322}
323
330template <class T>
331inline T Trace(const T* A)
332{
333 return A[0] + A[4] + A[8];
334}
335
342template <class T>
343inline T Hydrostatic(const T* A)
344{
345 return Trace(A) / T(3);
346}
347
354template <class T>
355inline T Det(const T* A)
356{
357 return (A[0] * A[4] * A[8] + A[1] * A[5] * A[6] + A[2] * A[3] * A[7]) -
358 (A[2] * A[4] * A[6] + A[1] * A[3] * A[8] + A[0] * A[5] * A[7]);
359}
360
367template <class T>
368inline void sym(const T* A, T* ret)
369{
370 ret[0] = A[0];
371 ret[1] = 0.5 * (A[1] + A[3]);
372 ret[2] = 0.5 * (A[2] + A[6]);
373 ret[3] = ret[1];
374 ret[4] = A[4];
375 ret[5] = 0.5 * (A[5] + A[7]);
376 ret[6] = ret[2];
377 ret[7] = ret[5];
378 ret[8] = A[8];
379}
380
388template <class T>
389inline T Inv(const T* A, T* ret)
390{
391 T D = Det(A);
392 ret[0] = (A[4] * A[8] - A[5] * A[7]) / D;
393 ret[1] = (A[2] * A[7] - A[1] * A[8]) / D;
394 ret[2] = (A[1] * A[5] - A[2] * A[4]) / D;
395 ret[3] = (A[5] * A[6] - A[3] * A[8]) / D;
396 ret[4] = (A[0] * A[8] - A[2] * A[6]) / D;
397 ret[5] = (A[2] * A[3] - A[0] * A[5]) / D;
398 ret[6] = (A[3] * A[7] - A[4] * A[6]) / D;
399 ret[7] = (A[1] * A[6] - A[0] * A[7]) / D;
400 ret[8] = (A[0] * A[4] - A[1] * A[3]) / D;
401 return D;
402}
403
411template <class T>
412inline T Hydrostatic_deviatoric(const T* A, T* ret)
413{
414 T m = Hydrostatic(A);
415 ret[0] = A[0] - m;
416 ret[1] = A[1];
417 ret[2] = A[2];
418 ret[3] = A[3];
419 ret[4] = A[4] - m;
420 ret[5] = A[5];
421 ret[6] = A[6];
422 ret[7] = A[7];
423 ret[8] = A[8] - m;
424 return m;
425}
426
435template <class T>
436inline T Deviatoric_ddot_deviatoric(const T* A)
437{
438 T m = Hydrostatic(A);
439 return (A[0] - m) * (A[0] - m) + (A[4] - m) * (A[4] - m) + (A[8] - m) * (A[8] - m) +
440 T(2) * A[1] * A[3] + T(2) * A[2] * A[6] + T(2) * A[5] * A[7];
441}
442
449template <class T>
450inline T Norm_deviatoric(const T* A)
451{
452 return std::sqrt(Deviatoric_ddot_deviatoric(A));
453}
454
462template <class T>
463inline T A2_ddot_B2(const T* A, const T* B)
464{
465 return A[0] * B[0] + A[4] * B[4] + A[8] * B[8] + A[1] * B[3] + A[2] * B[6] + A[3] * B[1] +
466 A[5] * B[7] + A[6] * B[2] + A[7] * B[5];
467}
468
476template <class T>
477inline T A2s_ddot_B2s(const T* A, const T* B)
478{
479 return A[0] * B[0] + A[4] * B[4] + A[8] * B[8] + T(2) * A[1] * B[1] + T(2) * A[2] * B[2] +
480 T(2) * A[5] * B[5];
481}
482
490template <class T>
491inline void A2_dyadic_B2(const T* A, const T* B, T* ret)
492{
493 for (size_t i = 0; i < 3; ++i) {
494 for (size_t j = 0; j < 3; ++j) {
495 for (size_t k = 0; k < 3; ++k) {
496 for (size_t l = 0; l < 3; ++l) {
497 ret[i * 27 + j * 9 + k * 3 + l] = A[i * 3 + j] * B[k * 3 + l];
498 }
499 }
500 }
501 }
502}
503
511template <class T>
512inline void A4_dot_B2(const T* A, const T* B, T* ret)
513{
514 std::fill(ret, ret + 81, T(0));
515
516 for (size_t i = 0; i < 3; ++i) {
517 for (size_t j = 0; j < 3; ++j) {
518 for (size_t k = 0; k < 3; ++k) {
519 for (size_t l = 0; l < 3; ++l) {
520 for (size_t m = 0; m < 3; ++m) {
521 ret[i * 27 + j * 9 + k * 3 + m] +=
522 A[i * 27 + j * 9 + k * 3 + l] * B[l * 3 + m];
523 }
524 }
525 }
526 }
527 }
528}
529
537template <class T>
538inline void A2_dot_B2(const T* A, const T* B, T* ret)
539{
540 std::fill(ret, ret + 9, T(0));
541
542 for (size_t i = 0; i < 3; ++i) {
543 for (size_t j = 0; j < 3; ++j) {
544 for (size_t k = 0; k < 3; ++k) {
545 ret[i * 3 + k] += A[i * 3 + j] * B[j * 3 + k];
546 }
547 }
548 }
549}
550
557template <class T>
558inline void A2_dot_A2T(const T* A, T* ret)
559{
560 ret[0] = A[0] * A[0] + A[1] * A[1] + A[2] * A[2];
561 ret[1] = A[0] * A[3] + A[1] * A[4] + A[2] * A[5];
562 ret[2] = A[0] * A[6] + A[1] * A[7] + A[2] * A[8];
563 ret[4] = A[3] * A[3] + A[4] * A[4] + A[5] * A[5];
564 ret[5] = A[3] * A[6] + A[4] * A[7] + A[5] * A[8];
565 ret[8] = A[6] * A[6] + A[7] * A[7] + A[8] * A[8];
566 ret[3] = ret[1];
567 ret[6] = ret[2];
568 ret[7] = ret[5];
569}
570
578template <class T>
579inline void A4_ddot_B2(const T* A, const T* B, T* ret)
580{
581 std::fill(ret, ret + 9, T(0));
582
583 for (size_t i = 0; i < 3; i++) {
584 for (size_t j = 0; j < 3; j++) {
585 for (size_t k = 0; k < 3; k++) {
586 for (size_t l = 0; l < 3; l++) {
587 ret[i * 3 + j] += A[i * 27 + j * 9 + k * 3 + l] * B[l * 3 + k];
588 }
589 }
590 }
591 }
592}
593
608template <class T>
609inline void A4_ddot_B4_ddot_C4(const T* A, const T* B, const T* C, T* ret)
610{
611 std::fill(ret, ret + 81, T(0));
612
613 for (size_t i = 0; i < 3; ++i) {
614 for (size_t j = 0; j < 3; ++j) {
615 for (size_t k = 0; k < 3; ++k) {
616 for (size_t l = 0; l < 3; ++l) {
617 for (size_t m = 0; m < 3; ++m) {
618 for (size_t n = 0; n < 3; ++n) {
619 for (size_t o = 0; o < 3; ++o) {
620 for (size_t p = 0; p < 3; ++p) {
621 ret[i * 27 + j * 9 + o * 3 + p] +=
622 A[i * 27 + j * 9 + k * 3 + l] *
623 B[l * 27 + k * 9 + m * 3 + n] *
624 C[n * 27 + m * 9 + o * 3 + p];
625 }
626 }
627 }
628 }
629 }
630 }
631 }
632 }
633}
634
649template <class T>
650inline void A2_dot_B2_dot_C2T(const T* A, const T* B, const T* C, T* ret)
651{
652 std::fill(ret, ret + 9, T(0));
653
654 for (size_t i = 0; i < 3; ++i) {
655 for (size_t j = 0; j < 3; ++j) {
656 for (size_t h = 0; h < 3; ++h) {
657 for (size_t l = 0; l < 3; ++l) {
658 ret[i * 3 + l] += A[i * 3 + j] * B[j * 3 + h] * C[l * 3 + h];
659 }
660 }
661 }
662 }
663}
664
677template <class T>
678void eigs(const T* A, T* vec, T* val)
679{
680 double a[3][3];
681 double Q[3][3];
682 double w[3];
683
684 std::copy(&A[0], &A[0] + 9, &a[0][0]);
685
686 // use the 'Jacobi' algorithm, which is accurate but not very fast
687 // (in practice the faster 'hybrid' "dsyevh3" is too inaccurate for finite elements)
688 auto succes = detail::dsyevj3(a, Q, w);
689 (void)(succes);
690 GMATTENSOR_ASSERT(succes == 0);
691
692 std::copy(&Q[0][0], &Q[0][0] + 3 * 3, vec);
693 std::copy(&w[0], &w[0] + 3, val);
694}
695
704template <class T>
705void from_eigs(const T* vec, const T* val, T* ret)
706{
707 ret[0] = val[0] * vec[0] * vec[0] + val[1] * vec[1] * vec[1] + val[2] * vec[2] * vec[2];
708 ret[1] = val[0] * vec[0] * vec[3] + val[1] * vec[1] * vec[4] + val[2] * vec[2] * vec[5];
709 ret[2] = val[0] * vec[0] * vec[6] + val[1] * vec[1] * vec[7] + val[2] * vec[2] * vec[8];
710 ret[4] = val[0] * vec[3] * vec[3] + val[1] * vec[4] * vec[4] + val[2] * vec[5] * vec[5];
711 ret[5] = val[0] * vec[3] * vec[6] + val[1] * vec[4] * vec[7] + val[2] * vec[5] * vec[8];
712 ret[8] = val[0] * vec[6] * vec[6] + val[1] * vec[7] * vec[7] + val[2] * vec[8] * vec[8];
713 ret[3] = ret[1];
714 ret[6] = ret[2];
715 ret[7] = ret[5];
716}
717
724template <class T>
725void logs(const T* A, T* ret)
726{
727 std::array<double, 3> val;
728 std::array<double, 9> vec;
729 eigs(&A[0], &vec[0], &val[0]);
730 for (size_t j = 0; j < 3; ++j) {
731 val[j] = std::log(val[j]);
732 }
733 from_eigs(&vec[0], &val[0], &ret[0]);
734}
735
736} // namespace pointer
737
744{
745 array_type::tensor<double, 2> ret = xt::random::randn<double>({3, 3});
746 return ret;
747}
748
755{
756 array_type::tensor<double, 4> ret = xt::random::randn<double>({3, 3, 3, 3});
757 return ret;
758}
759
766{
767 return xt::zeros<double>({3, 3});
768}
769
776{
777 return xt::zeros<double>({3, 3, 3, 3});
778}
779
799{
800 array_type::tensor<double, 2> ret = xt::empty<double>({3, 3});
801 pointer::I2(ret.data());
802 return ret;
803}
804
824{
825 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
826 pointer::II(ret.data());
827 return ret;
828}
829
849{
850 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
851 pointer::I4(ret.data());
852 return ret;
853}
854
874{
875 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
876 pointer::I4rt(ret.data());
877 return ret;
878}
879
899{
900 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
901 pointer::I4s(ret.data());
902 return ret;
903}
904
920{
921 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
922 pointer::I4d(ret.data());
923 return ret;
924}
925
936template <class T>
937inline auto Trace(const T& A)
938{
939 return detail::impl_A2<T, 3>::ret0(A, [](const auto& a) { return pointer::Trace(a); });
940}
941
948template <class T, class R>
949inline void trace(const T& A, R& ret)
950{
951 detail::impl_A2<T, 3>::ret0(A, ret, [](const auto& a) { return pointer::Trace(a); });
952}
953
965template <class T>
966inline auto Hydrostatic(const T& A)
967{
968 return detail::impl_A2<T, 3>::ret0(A, [](const auto& a) { return pointer::Hydrostatic(a); });
969}
970
977template <class T, class R>
978inline void hydrostatic(const T& A, R& ret)
979{
980 detail::impl_A2<T, 3>::ret0(A, ret, [](const auto& a) { return pointer::Hydrostatic(a); });
981}
982
990template <class T>
991inline auto Det(const T& A)
992{
993 return detail::impl_A2<T, 3>::ret0(A, [](const auto& a) { return pointer::Det(a); });
994}
995
1002template <class T, class R>
1003inline void det(const T& A, R& ret)
1004{
1005 detail::impl_A2<T, 3>::ret0(A, ret, [](const auto& a) { return pointer::Det(a); });
1006}
1007
1023template <class T>
1024inline auto A2_ddot_B2(const T& A, const T& B)
1025{
1026 return detail::impl_A2<T, 3>::B2_ret0(
1027 A, B, [](const auto& a, const auto& b) { return pointer::A2_ddot_B2(a, b); });
1028}
1029
1037template <class T, class R>
1038inline void A2_ddot_B2(const T& A, const T& B, R& ret)
1039{
1040 detail::impl_A2<T, 3>::B2_ret0(
1041 A, B, ret, [](const auto& a, const auto& b) { return pointer::A2_ddot_B2(a, b); });
1042}
1043
1054template <class T>
1055inline auto A2s_ddot_B2s(const T& A, const T& B)
1056{
1057 return detail::impl_A2<T, 3>::B2_ret0(
1058 A, B, [](const auto& a, const auto& b) { return pointer::A2s_ddot_B2s(a, b); });
1059}
1060
1068template <class T, class R>
1069inline void A2s_ddot_B2s(const T& A, const T& B, R& ret)
1070{
1071 detail::impl_A2<T, 3>::B2_ret0(
1072 A, B, ret, [](const auto& a, const auto& b) { return pointer::A2s_ddot_B2s(a, b); });
1073}
1074
1085template <class T>
1086inline auto Norm_deviatoric(const T& A)
1087{
1088 return detail::impl_A2<T, 3>::ret0(
1089 A, [](const auto& a) { return pointer::Norm_deviatoric(a); });
1090}
1091
1098template <class T, class R>
1099inline void norm_deviatoric(const T& A, R& ret)
1100{
1101 detail::impl_A2<T, 3>::ret0(A, ret, [](const auto& a) { return pointer::Norm_deviatoric(a); });
1102}
1103
1115template <class T>
1116inline auto Deviatoric(const T& A)
1117{
1118 return detail::impl_A2<T, 3>::ret2(
1119 A, [](const auto& a, const auto& r) { return pointer::Hydrostatic_deviatoric(a, r); });
1120}
1121
1128template <class T, class R>
1129inline void deviatoric(const T& A, R& ret)
1130{
1131 detail::impl_A2<T, 3>::ret2(
1132 A, ret, [](const auto& a, const auto& r) { return pointer::Hydrostatic_deviatoric(a, r); });
1133}
1134
1149template <class T>
1150inline auto Sym(const T& A)
1151{
1152 return detail::impl_A2<T, 3>::ret2(
1153 A, [](const auto& a, const auto& r) { return pointer::sym(a, r); });
1154}
1155
1162template <class T, class R>
1163inline void sym(const T& A, R& ret)
1164{
1165 detail::impl_A2<T, 3>::ret2(
1166 A, ret, [](const auto& a, const auto& r) { return pointer::sym(a, r); });
1167}
1168
1176template <class T>
1177inline auto Inv(const T& A)
1178{
1179 return detail::impl_A2<T, 3>::ret2(
1180 A, [](const auto& a, const auto& r) { return pointer::Inv(a, r); });
1181}
1182
1189template <class T, class R>
1190inline void inv(const T& A, R& ret)
1191{
1192 detail::impl_A2<T, 3>::ret2(
1193 A, ret, [](const auto& a, const auto& r) { return pointer::Inv(a, r); });
1194}
1195
1204template <class T>
1205inline auto Logs(const T& A)
1206{
1207 return detail::impl_A2<T, 3>::ret2(
1208 A, [](const auto& a, const auto& r) { return pointer::logs(a, r); });
1209}
1210
1217template <class T, class R>
1218inline void logs(const T& A, R& ret)
1219{
1220 detail::impl_A2<T, 3>::ret2(
1221 A, ret, [](const auto& a, const auto& r) { return pointer::logs(a, r); });
1222}
1223
1238template <class T>
1239inline auto A2_dot_A2T(const T& A)
1240{
1241 return detail::impl_A2<T, 3>::ret2(
1242 A, [](const auto& a, const auto& r) { return pointer::A2_dot_A2T(a, r); });
1243}
1244
1251template <class T, class R>
1252inline void A2_dot_A2T(const T& A, R& ret)
1253{
1254 detail::impl_A2<T, 3>::ret2(
1255 A, ret, [](const auto& a, const auto& r) { return pointer::A2_dot_A2T(a, r); });
1256}
1257
1273template <class T>
1274inline auto A2_dot_B2(const T& A, const T& B)
1275{
1276 return detail::impl_A2<T, 3>::B2_ret2(A, B, [](const auto& a, const auto& b, const auto& r) {
1277 return pointer::A2_dot_B2(a, b, r);
1278 });
1279}
1280
1288template <class T, class R>
1289inline void A2_dot_B2(const T& A, const T& B, R& ret)
1290{
1291 detail::impl_A2<T, 3>::B2_ret2(A, B, ret, [](const auto& a, const auto& b, const auto& r) {
1292 return pointer::A2_dot_B2(a, b, r);
1293 });
1294}
1295
1311template <class T>
1312inline auto A2_dyadic_B2(const T& A, const T& B)
1313{
1314 return detail::impl_A2<T, 3>::B2_ret4(A, B, [](const auto& a, const auto& b, const auto& r) {
1315 return pointer::A2_dyadic_B2(a, b, r);
1316 });
1317}
1318
1326template <class T, class R>
1327inline void A2_dyadic_B2(const T& A, const T& B, R& ret)
1328{
1329 detail::impl_A2<T, 3>::B2_ret4(A, B, ret, [](const auto& a, const auto& b, const auto& r) {
1330 return pointer::A2_dyadic_B2(a, b, r);
1331 });
1332}
1333
1349template <class T, class U>
1350inline auto A4_ddot_B2(const T& A, const U& B)
1351{
1352 return detail::impl_A4<T, 3>::B2_ret2(A, B, [](const auto& a, const auto& b, const auto& r) {
1353 return pointer::A4_ddot_B2(a, b, r);
1354 });
1355}
1356
1364template <class T, class U, class R>
1365inline void A4_ddot_B2(const T& A, const U& B, R& ret)
1366{
1367 detail::impl_A4<T, 3>::B2_ret2(A, B, ret, [](const auto& a, const auto& b, const auto& r) {
1368 return pointer::A4_ddot_B2(a, b, r);
1369 });
1370}
1371
1387template <class T, class U>
1388inline auto A4_dot_B2(const T& A, const U& B)
1389{
1390 return detail::impl_A4<T, 3>::B2_ret4(A, B, [](const auto& a, const auto& b, const auto& r) {
1391 return pointer::A4_dot_B2(a, b, r);
1392 });
1393}
1394
1402template <class T, class U, class R>
1403inline void A4_dot_B2(const T& A, const U& B, R& ret)
1404{
1405 detail::impl_A4<T, 3>::B2_ret4(A, B, ret, [](const auto& a, const auto& b, const auto& r) {
1406 return pointer::A4_dot_B2(a, b, r);
1407 });
1408}
1409
1416template <class T>
1417inline size_t underlying_size_A2(const T& A)
1418{
1419 return detail::impl_A2<T, 3>::toSizeT0(A.shape());
1420}
1421
1428template <class T>
1429inline size_t underlying_size_A4(const T& A)
1430{
1431 return detail::impl_A4<T, 3>::toSizeT0(A.shape());
1432}
1433
1440template <class T>
1441inline auto underlying_shape_A2(const T& A) -> std::array<size_t, detail::impl_A2<T, 3>::rank>
1442{
1443 return detail::impl_A2<T, 3>::toShapeT0(A.shape());
1444}
1445
1452template <class T>
1453inline auto underlying_shape_A4(const T& A) -> std::array<size_t, detail::impl_A4<T, 3>::rank>
1454{
1455 return detail::impl_A4<T, 3>::toShapeT0(A.shape());
1456}
1457
1466template <size_t N>
1467class Array {
1468public:
1472 constexpr static std::size_t rank = N;
1473
1474 Array() = default;
1475
1476 virtual ~Array() = default;
1477
1483 Array(const std::array<size_t, N>& shape)
1484 {
1485 this->init(shape);
1486 }
1487
1493 const std::array<size_t, N>& shape() const
1494 {
1495 return m_shape;
1496 }
1497
1503 const std::array<size_t, N + 2>& shape_tensor2() const
1504 {
1505 return m_shape_tensor2;
1506 }
1507
1513 const std::array<size_t, N + 4>& shape_tensor4() const
1514 {
1515 return m_shape_tensor4;
1516 }
1517
1524 {
1525 return xt::zeros<double>(m_shape_tensor2);
1526 }
1527
1534 {
1535 return xt::zeros<double>(m_shape_tensor4);
1536 }
1537
1544 {
1545 array_type::tensor<double, N + 2> ret = xt::empty<double>(m_shape_tensor2);
1546
1547#pragma omp parallel for
1548 for (size_t i = 0; i < m_size; ++i) {
1550 }
1551
1552 return ret;
1553 }
1554
1561 {
1562 array_type::tensor<double, N + 4> ret = xt::empty<double>(m_shape_tensor4);
1563
1564#pragma omp parallel for
1565 for (size_t i = 0; i < m_size; ++i) {
1567 }
1568
1569 return ret;
1570 }
1571
1578 {
1579 array_type::tensor<double, N + 4> ret = xt::empty<double>(m_shape_tensor4);
1580
1581#pragma omp parallel for
1582 for (size_t i = 0; i < m_size; ++i) {
1584 }
1585
1586 return ret;
1587 }
1588
1595 {
1596 array_type::tensor<double, N + 4> ret = xt::empty<double>(m_shape_tensor4);
1597
1598#pragma omp parallel for
1599 for (size_t i = 0; i < m_size; ++i) {
1601 }
1602
1603 return ret;
1604 }
1605
1612 {
1613 array_type::tensor<double, N + 4> ret = xt::empty<double>(m_shape_tensor4);
1614
1615#pragma omp parallel for
1616 for (size_t i = 0; i < m_size; ++i) {
1618 }
1619
1620 return ret;
1621 }
1622
1629 {
1630 array_type::tensor<double, N + 4> ret = xt::empty<double>(m_shape_tensor4);
1631
1632#pragma omp parallel for
1633 for (size_t i = 0; i < m_size; ++i) {
1635 }
1636
1637 return ret;
1638 }
1639
1640protected:
1646 void init(const std::array<size_t, N>& shape)
1647 {
1648 m_shape = shape;
1649 size_t nd = m_ndim;
1650 std::copy(m_shape.begin(), m_shape.end(), m_shape_tensor2.begin());
1651 std::copy(m_shape.begin(), m_shape.end(), m_shape_tensor4.begin());
1652 std::fill(m_shape_tensor2.begin() + N, m_shape_tensor2.end(), nd);
1653 std::fill(m_shape_tensor4.begin() + N, m_shape_tensor4.end(), nd);
1654 m_size = std::accumulate(m_shape.begin(), m_shape.end(), 1, std::multiplies<size_t>());
1655 }
1656
1658 static constexpr size_t m_ndim = 3;
1659
1661 static constexpr size_t m_stride_tensor2 = 9;
1662
1664 static constexpr size_t m_stride_tensor4 = 81;
1665
1667 size_t m_size;
1668
1670 std::array<size_t, N> m_shape;
1671
1673 std::array<size_t, N + 2> m_shape_tensor2;
1674
1676 std::array<size_t, N + 4> m_shape_tensor4;
1677};
1678
1679} // namespace Cartesian3d
1680} // namespace GMatTensor
1681
1682#endif
array_type::tensor< double, N+4 > I4d() const
Array of Cartesian3d::I4d()
Definition: Cartesian3d.h:1628
const std::array< size_t, N+2 > & shape_tensor2() const
Shape of the array of second-order tensors.
Definition: Cartesian3d.h:1503
std::array< size_t, N+4 > m_shape_tensor4
Shape of an array of 4th-order tensors == [m_shape, 3, 3, 3, 3].
Definition: Cartesian3d.h:1676
Array(const std::array< size_t, N > &shape)
Constructor.
Definition: Cartesian3d.h:1483
array_type::tensor< double, N+4 > I4s() const
Array of Cartesian3d::I4s()
Definition: Cartesian3d.h:1611
array_type::tensor< double, N+4 > I4() const
Array of Cartesian3d::I4()
Definition: Cartesian3d.h:1577
static constexpr size_t m_stride_tensor4
Storage stride for 4th-order tensors ( ).
Definition: Cartesian3d.h:1664
static constexpr size_t m_ndim
Number of dimensions of tensors.
Definition: Cartesian3d.h:1658
std::array< size_t, N > m_shape
Shape of the array (of scalars).
Definition: Cartesian3d.h:1670
const std::array< size_t, N > & shape() const
Shape of the array (of scalars).
Definition: Cartesian3d.h:1493
array_type::tensor< double, N+4 > II() const
Array of Cartesian3d::II()
Definition: Cartesian3d.h:1560
void init(const std::array< size_t, N > &shape)
Constructor 'alias'.
Definition: Cartesian3d.h:1646
array_type::tensor< double, N+4 > O4() const
Array of Cartesian3d::O4()
Definition: Cartesian3d.h:1533
std::array< size_t, N+2 > m_shape_tensor2
Shape of an array of 2nd-order tensors == [m_shape, 3, 3].
Definition: Cartesian3d.h:1673
static constexpr std::size_t rank
Rank of the array (the actual rank is increased with the tensor-rank).
Definition: Cartesian3d.h:1472
size_t m_size
Size of the array (of scalars) == prod(m_shape).
Definition: Cartesian3d.h:1667
array_type::tensor< double, N+2 > O2() const
Array of Cartesian3d::O2()
Definition: Cartesian3d.h:1523
const std::array< size_t, N+4 > & shape_tensor4() const
Shape of the array of fourth-order tensors.
Definition: Cartesian3d.h:1513
array_type::tensor< double, N+2 > I2() const
Array of Cartesian3d::I2()
Definition: Cartesian3d.h:1543
array_type::tensor< double, N+4 > I4rt() const
Array of Cartesian3d::I4rt()
Definition: Cartesian3d.h:1594
static constexpr size_t m_stride_tensor2
Storage stride for 2nd-order tensors ( ).
Definition: Cartesian3d.h:1661
Macros used in the library.
#define GMATTENSOR_ASSERT(expr)
All assertions are implementation as:
Definition: config.h:59
void I4d(T *ret)
See Cartesian3d::I4d()
Definition: Cartesian3d.h:311
void logs(const T *A, T *ret)
See Cartesian3d::Logs()
Definition: Cartesian3d.h:725
void A2_dyadic_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A2_dyadic_B2()
Definition: Cartesian3d.h:491
void from_eigs(const T *vec, const T *val, T *ret)
Reconstruct tensor from eigenvalues/-vectors (reverse operation of eigs()) Symmetric tensors only,...
Definition: Cartesian3d.h:705
void I4rt(T *ret)
See Cartesian3d::I4rt()
Definition: Cartesian3d.h:270
void A2_dot_B2_dot_C2T(const T *A, const T *B, const T *C, T *ret)
Product.
Definition: Cartesian3d.h:650
T Inv(const T *A, T *ret)
See Cartesian3d::Inv(), returns Cartesian3d::Det()
Definition: Cartesian3d.h:389
void eigs(const T *A, T *vec, T *val)
Get eigenvalues/-vectors such that.
Definition: Cartesian3d.h:678
T A2s_ddot_B2s(const T *A, const T *B)
See Cartesian3d::A2s_ddot_B2s()
Definition: Cartesian3d.h:477
void A4_dot_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A4_dot_B2()
Definition: Cartesian3d.h:512
T Det(const T *A)
See Cartesian3d::Det()
Definition: Cartesian3d.h:355
T Trace(const T *A)
See Cartesian3d::Trace()
Definition: Cartesian3d.h:331
void I2(T *ret)
See Cartesian3d::I2()
Definition: Cartesian3d.h:205
void I4(T *ret)
See Cartesian3d::I4()
Definition: Cartesian3d.h:247
void I4s(T *ret)
See Cartesian3d::I4s()
Definition: Cartesian3d.h:293
T Hydrostatic(const T *A)
See Cartesian3d::Hydrostatic()
Definition: Cartesian3d.h:343
T Deviatoric_ddot_deviatoric(const T *A)
Double tensor contraction of the tensor's deviator.
Definition: Cartesian3d.h:436
void A2_dot_A2T(const T *A, T *ret)
See Cartesian3d::A2_dot_A2T()
Definition: Cartesian3d.h:558
T Norm_deviatoric(const T *A)
See Cartesian3d::Norm_deviatoric()
Definition: Cartesian3d.h:450
void II(T *ret)
See Cartesian3d::II()
Definition: Cartesian3d.h:224
void A2_dot_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A2_dot_B2()
Definition: Cartesian3d.h:538
T A2_ddot_B2(const T *A, const T *B)
See Cartesian3d::A2_ddot_B2()
Definition: Cartesian3d.h:463
void A4_ddot_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A4_ddot_B2()
Definition: Cartesian3d.h:579
void sym(const T *A, T *ret)
See Cartesian3d::Sym()
Definition: Cartesian3d.h:368
T Hydrostatic_deviatoric(const T *A, T *ret)
Returns Cartesian3d::Hydrostatic() and computes Cartesian3d::Deviatoric()
Definition: Cartesian3d.h:412
void A4_ddot_B4_ddot_C4(const T *A, const T *B, const T *C, T *ret)
Product.
Definition: Cartesian3d.h:609
void hydrostatic(const T &A, R &ret)
Same as Hydrostatic() but writes to externally allocated output.
Definition: Cartesian3d.h:978
auto Deviatoric(const T &A)
Deviatoric part of a tensor:
Definition: Cartesian3d.h:1116
auto A2_dyadic_B2(const T &A, const T &B)
Dyadic product.
Definition: Cartesian3d.h:1312
size_t underlying_size_A2(const T &A)
Size of the underlying array.
Definition: Cartesian3d.h:1417
auto Sym(const T &A)
Symmetric part of a tensor:
Definition: Cartesian3d.h:1150
auto underlying_shape_A2(const T &A) -> std::array< size_t, detail::impl_A2< T, 3 >::rank >
Shape of the underlying array.
Definition: Cartesian3d.h:1441
auto A2s_ddot_B2s(const T &A, const T &B)
Same as A2_ddot_B2(const T& A, const T& B, R& ret) but for symmetric tensors.
Definition: Cartesian3d.h:1055
void trace(const T &A, R &ret)
Same as Trace() but writes to externally allocated output.
Definition: Cartesian3d.h:949
auto Logs(const T &A)
Logarithm.
Definition: Cartesian3d.h:1205
array_type::tensor< double, 2 > I2()
2nd-order identity tensor.
Definition: Cartesian3d.h:798
array_type::tensor< double, 2 > O2()
2nd-order null tensor (all components equal to zero).
Definition: Cartesian3d.h:765
auto A2_dot_B2(const T &A, const T &B)
Dot-product (single tensor contraction)
Definition: Cartesian3d.h:1274
void deviatoric(const T &A, R &ret)
Same as Deviatoric() but writes to externally allocated output.
Definition: Cartesian3d.h:1129
array_type::tensor< double, 4 > I4()
Fourth order unit tensor.
Definition: Cartesian3d.h:848
array_type::tensor< double, 4 > II()
Result of the dyadic product of two 2nd-order identity tensors (see I2()).
Definition: Cartesian3d.h:823
auto A2_ddot_B2(const T &A, const T &B)
Double tensor contraction.
Definition: Cartesian3d.h:1024
array_type::tensor< double, 4 > I4rt()
Right-transposed fourth order unit tensor.
Definition: Cartesian3d.h:873
array_type::tensor< double, 4 > I4d()
Fourth order deviatoric projection.
Definition: Cartesian3d.h:919
void det(const T &A, R &ret)
Same as Det() but writes to externally allocated output.
Definition: Cartesian3d.h:1003
void logs(const T &A, R &ret)
Same as Logs() but writes to externally allocated output.
Definition: Cartesian3d.h:1218
array_type::tensor< double, 4 > Random4()
Random 4th-order tensor (for example for use in testing).
Definition: Cartesian3d.h:754
void sym(const T &A, R &ret)
Same as Sym() but writes to externally allocated output.
Definition: Cartesian3d.h:1163
array_type::tensor< double, 4 > I4s()
Fourth order symmetric projection.
Definition: Cartesian3d.h:898
auto Det(const T &A)
Determinant.
Definition: Cartesian3d.h:991
auto underlying_shape_A4(const T &A) -> std::array< size_t, detail::impl_A4< T, 3 >::rank >
Shape of the underlying array.
Definition: Cartesian3d.h:1453
array_type::tensor< double, 4 > O4()
4th-order null tensor (all components equal to zero).
Definition: Cartesian3d.h:775
auto Inv(const T &A)
Inverse.
Definition: Cartesian3d.h:1177
void inv(const T &A, R &ret)
Same as Inv() but writes to externally allocated output.
Definition: Cartesian3d.h:1190
auto Norm_deviatoric(const T &A)
Norm of the tensor's deviator:
Definition: Cartesian3d.h:1086
size_t underlying_size_A4(const T &A)
Size of the underlying array.
Definition: Cartesian3d.h:1429
auto Trace(const T &A)
Trace or 2nd-order tensor.
Definition: Cartesian3d.h:937
auto A4_dot_B2(const T &A, const U &B)
Tensor contraction.
Definition: Cartesian3d.h:1388
void norm_deviatoric(const T &A, R &ret)
Same as Norm_deviatoric() but writes to externally allocated output.
Definition: Cartesian3d.h:1099
auto A4_ddot_B2(const T &A, const U &B)
Double tensor contraction.
Definition: Cartesian3d.h:1350
auto Hydrostatic(const T &A)
Hydrostatic part of a tensor.
Definition: Cartesian3d.h:966
array_type::tensor< double, 2 > Random2()
Random 2nd-order tensor (for example for use in testing).
Definition: Cartesian3d.h:743
auto A2_dot_A2T(const T &A)
Dot-product (single tensor contraction)
Definition: Cartesian3d.h:1239
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition: config.h:86
Tensor products / operations.
Definition: Cartesian2d.h:20