7#ifndef GMATTENSOR_CARTESIAN3D_H
8#define GMATTENSOR_CARTESIAN3D_H
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>
26namespace Cartesian3d {
61inline int dsyevj3(
double A[3][3],
double Q[3][3],
double w[3])
82 double g, h, z, theta;
86 for (
int i = 0; i < n; i++) {
88 for (
int j = 0; j < i; j++)
89 Q[i][j] = Q[j][i] = 0.0;
93 for (
int i = 0; i < n; i++)
98 for (
int i = 0; i < n; i++)
103 for (
int nIter = 0; nIter < 50; nIter++) {
106 for (
int p = 0; p < n; p++)
107 for (
int q = p + 1; q < n; q++)
113 thresh = 0.2 * so / (n * n);
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])) {
124 else if (fabs(A[p][q]) > thresh) {
127 if (fabs(h) + g == fabs(h)) {
131 theta = 0.5 * h / A[p][q];
133 t = -1.0 / (sqrt(1.0 + theta * theta) - theta);
135 t = 1.0 / (sqrt(1.0 + theta * theta) + theta);
137 c = 1.0 / sqrt(1.0 + t * t);
145 for (
int r = 0; r < p; r++) {
147 A[r][p] = c * t - s * A[r][q];
148 A[r][q] = s * t + c * A[r][q];
150 for (
int r = p + 1; r < q; r++) {
152 A[p][r] = c * t - s * A[r][q];
153 A[r][q] = s * t + c * A[r][q];
155 for (
int r = q + 1; r < n; r++) {
157 A[p][r] = c * t - s * A[q][r];
158 A[q][r] = s * t + c * A[q][r];
162 for (
int r = 0; r < n; r++) {
164 Q[r][p] = c * t - s * Q[r][q];
165 Q[r][q] = s * t + c * Q[r][q];
183inline void O2(T* ret)
185 std::fill(ret, ret + 9, T(0));
194inline void O4(T* ret)
196 std::fill(ret, ret + 81, T(0));
205inline void I2(T* ret)
224inline void II(T* ret)
226 std::fill(ret, ret + 81, T(0));
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;
247inline void I4(T* ret)
249 std::fill(ret, ret + 81, T(0));
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;
272 std::fill(ret, ret + 81, T(0));
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;
297 std::array<double, 81> i4rt;
300 std::transform(ret, ret + 81, &i4rt[0], ret, std::plus<T>());
302 std::transform(ret, ret + 81, ret, std::bind(std::multiplies<T>(), std::placeholders::_1, 0.5));
315 std::array<double, 81> ii;
319 &ii[0], &ii[0] + 81, &ii[0], std::bind(std::divides<T>(), std::placeholders::_1, 3.0));
321 std::transform(ret, ret + 81, &ii[0], ret, std::minus<T>());
333 return A[0] + A[4] + A[8];
345 return Trace(A) / T(3);
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]);
368inline void sym(
const T* A, T* ret)
371 ret[1] = 0.5 * (A[1] + A[3]);
372 ret[2] = 0.5 * (A[2] + A[6]);
375 ret[5] = 0.5 * (A[5] + A[7]);
389inline T
Inv(
const T* A, T* ret)
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;
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];
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];
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] +
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];
514 std::fill(ret, ret + 81, T(0));
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];
540 std::fill(ret, ret + 9, T(0));
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];
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];
581 std::fill(ret, ret + 9, T(0));
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];
611 std::fill(ret, ret + 81, T(0));
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];
652 std::fill(ret, ret + 9, T(0));
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];
678void eigs(
const T* A, T* vec, T* val)
684 std::copy(&A[0], &A[0] + 9, &a[0][0]);
688 auto succes = detail::dsyevj3(a, Q, w);
692 std::copy(&Q[0][0], &Q[0][0] + 3 * 3, vec);
693 std::copy(&w[0], &w[0] + 3, val);
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];
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]);
767 return xt::zeros<double>({3, 3});
777 return xt::zeros<double>({3, 3, 3, 3});
939 return detail::impl_A2<T, 3>::ret0(A, [](
const auto& a) {
return pointer::Trace(a); });
948template <
class T,
class R>
949inline void trace(
const T& A, R& ret)
951 detail::impl_A2<T, 3>::ret0(A, ret, [](
const auto& a) {
return pointer::Trace(a); });
977template <
class T,
class R>
991inline auto Det(
const T& A)
993 return detail::impl_A2<T, 3>::ret0(A, [](
const auto& a) {
return pointer::Det(a); });
1002template <
class T,
class R>
1003inline void det(
const T& A, R& ret)
1005 detail::impl_A2<T, 3>::ret0(A, ret, [](
const auto& a) {
return pointer::Det(a); });
1026 return detail::impl_A2<T, 3>::B2_ret0(
1037template <
class T,
class R>
1040 detail::impl_A2<T, 3>::B2_ret0(
1057 return detail::impl_A2<T, 3>::B2_ret0(
1068template <
class T,
class R>
1071 detail::impl_A2<T, 3>::B2_ret0(
1088 return detail::impl_A2<T, 3>::ret0(
1098template <
class T,
class R>
1118 return detail::impl_A2<T, 3>::ret2(
1128template <
class T,
class R>
1131 detail::impl_A2<T, 3>::ret2(
1152 return detail::impl_A2<T, 3>::ret2(
1153 A, [](
const auto& a,
const auto& r) {
return pointer::sym(a, r); });
1162template <
class T,
class R>
1163inline void sym(
const T& A, R& ret)
1165 detail::impl_A2<T, 3>::ret2(
1166 A, ret, [](
const auto& a,
const auto& r) {
return pointer::sym(a, r); });
1179 return detail::impl_A2<T, 3>::ret2(
1180 A, [](
const auto& a,
const auto& r) {
return pointer::Inv(a, r); });
1189template <
class T,
class R>
1190inline void inv(
const T& A, R& ret)
1192 detail::impl_A2<T, 3>::ret2(
1193 A, ret, [](
const auto& a,
const auto& r) {
return pointer::Inv(a, r); });
1207 return detail::impl_A2<T, 3>::ret2(
1208 A, [](
const auto& a,
const auto& r) {
return pointer::logs(a, r); });
1217template <
class T,
class R>
1218inline void logs(
const T& A, R& ret)
1220 detail::impl_A2<T, 3>::ret2(
1221 A, ret, [](
const auto& a,
const auto& r) {
return pointer::logs(a, r); });
1241 return detail::impl_A2<T, 3>::ret2(
1251template <
class T,
class R>
1254 detail::impl_A2<T, 3>::ret2(
1276 return detail::impl_A2<T, 3>::B2_ret2(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
1288template <
class T,
class R>
1291 detail::impl_A2<T, 3>::B2_ret2(A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
1314 return detail::impl_A2<T, 3>::B2_ret4(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
1326template <
class T,
class R>
1329 detail::impl_A2<T, 3>::B2_ret4(A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
1349template <
class T,
class U>
1352 return detail::impl_A4<T, 3>::B2_ret2(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
1364template <
class T,
class U,
class R>
1367 detail::impl_A4<T, 3>::B2_ret2(A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
1387template <
class T,
class U>
1390 return detail::impl_A4<T, 3>::B2_ret4(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
1402template <
class T,
class U,
class R>
1405 detail::impl_A4<T, 3>::B2_ret4(A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
1419 return detail::impl_A2<T, 3>::toSizeT0(A.shape());
1431 return detail::impl_A4<T, 3>::toSizeT0(A.shape());
1443 return detail::impl_A2<T, 3>::toShapeT0(A.shape());
1455 return detail::impl_A4<T, 3>::toShapeT0(A.shape());
1472 constexpr static std::size_t
rank = N;
1476 virtual ~Array() =
default;
1493 const std::array<size_t, N>&
shape()
const
1547#pragma omp parallel for
1548 for (
size_t i = 0; i <
m_size; ++i) {
1564#pragma omp parallel for
1565 for (
size_t i = 0; i <
m_size; ++i) {
1581#pragma omp parallel for
1582 for (
size_t i = 0; i <
m_size; ++i) {
1598#pragma omp parallel for
1599 for (
size_t i = 0; i <
m_size; ++i) {
1615#pragma omp parallel for
1616 for (
size_t i = 0; i <
m_size; ++i) {
1632#pragma omp parallel for
1633 for (
size_t i = 0; i <
m_size; ++i) {
array_type::tensor< double, N+4 > I4d() const
Array of Cartesian3d::I4d()
const std::array< size_t, N+2 > & shape_tensor2() const
Shape of the array of second-order tensors.
std::array< size_t, N+4 > m_shape_tensor4
Shape of an array of 4th-order tensors == [m_shape, 3, 3, 3, 3].
Array(const std::array< size_t, N > &shape)
Constructor.
array_type::tensor< double, N+4 > I4s() const
Array of Cartesian3d::I4s()
array_type::tensor< double, N+4 > I4() const
Array of Cartesian3d::I4()
static constexpr size_t m_stride_tensor4
Storage stride for 4th-order tensors ( ).
static constexpr size_t m_ndim
Number of dimensions of tensors.
std::array< size_t, N > m_shape
Shape of the array (of scalars).
const std::array< size_t, N > & shape() const
Shape of the array (of scalars).
array_type::tensor< double, N+4 > II() const
Array of Cartesian3d::II()
void init(const std::array< size_t, N > &shape)
Constructor 'alias'.
array_type::tensor< double, N+4 > O4() const
Array of Cartesian3d::O4()
std::array< size_t, N+2 > m_shape_tensor2
Shape of an array of 2nd-order tensors == [m_shape, 3, 3].
static constexpr std::size_t rank
Rank of the array (the actual rank is increased with the tensor-rank).
size_t m_size
Size of the array (of scalars) == prod(m_shape).
array_type::tensor< double, N+2 > O2() const
Array of Cartesian3d::O2()
const std::array< size_t, N+4 > & shape_tensor4() const
Shape of the array of fourth-order tensors.
array_type::tensor< double, N+2 > I2() const
Array of Cartesian3d::I2()
array_type::tensor< double, N+4 > I4rt() const
Array of Cartesian3d::I4rt()
static constexpr size_t m_stride_tensor2
Storage stride for 2nd-order tensors ( ).
Macros used in the library.
#define GMATTENSOR_ASSERT(expr)
All assertions are implementation as:
void I4d(T *ret)
See Cartesian3d::I4d()
void logs(const T *A, T *ret)
See Cartesian3d::Logs()
void A2_dyadic_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A2_dyadic_B2()
void from_eigs(const T *vec, const T *val, T *ret)
Reconstruct tensor from eigenvalues/-vectors (reverse operation of eigs()) Symmetric tensors only,...
void I4rt(T *ret)
See Cartesian3d::I4rt()
void A2_dot_B2_dot_C2T(const T *A, const T *B, const T *C, T *ret)
Product.
T Inv(const T *A, T *ret)
See Cartesian3d::Inv(), returns Cartesian3d::Det()
void eigs(const T *A, T *vec, T *val)
Get eigenvalues/-vectors such that.
T A2s_ddot_B2s(const T *A, const T *B)
See Cartesian3d::A2s_ddot_B2s()
void A4_dot_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A4_dot_B2()
T Det(const T *A)
See Cartesian3d::Det()
T Trace(const T *A)
See Cartesian3d::Trace()
void I2(T *ret)
See Cartesian3d::I2()
void I4(T *ret)
See Cartesian3d::I4()
void I4s(T *ret)
See Cartesian3d::I4s()
T Hydrostatic(const T *A)
See Cartesian3d::Hydrostatic()
T Deviatoric_ddot_deviatoric(const T *A)
Double tensor contraction of the tensor's deviator.
void A2_dot_A2T(const T *A, T *ret)
See Cartesian3d::A2_dot_A2T()
T Norm_deviatoric(const T *A)
See Cartesian3d::Norm_deviatoric()
void II(T *ret)
See Cartesian3d::II()
void A2_dot_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A2_dot_B2()
T A2_ddot_B2(const T *A, const T *B)
See Cartesian3d::A2_ddot_B2()
void A4_ddot_B2(const T *A, const T *B, T *ret)
See Cartesian3d::A4_ddot_B2()
void sym(const T *A, T *ret)
See Cartesian3d::Sym()
T Hydrostatic_deviatoric(const T *A, T *ret)
Returns Cartesian3d::Hydrostatic() and computes Cartesian3d::Deviatoric()
void A4_ddot_B4_ddot_C4(const T *A, const T *B, const T *C, T *ret)
Product.
void hydrostatic(const T &A, R &ret)
Same as Hydrostatic() but writes to externally allocated output.
auto Deviatoric(const T &A)
Deviatoric part of a tensor:
auto A2_dyadic_B2(const T &A, const T &B)
Dyadic product.
size_t underlying_size_A2(const T &A)
Size of the underlying array.
auto Sym(const T &A)
Symmetric part of a tensor:
auto underlying_shape_A2(const T &A) -> std::array< size_t, detail::impl_A2< T, 3 >::rank >
Shape of the underlying array.
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.
void trace(const T &A, R &ret)
Same as Trace() but writes to externally allocated output.
auto Logs(const T &A)
Logarithm.
array_type::tensor< double, 2 > I2()
2nd-order identity tensor.
array_type::tensor< double, 2 > O2()
2nd-order null tensor (all components equal to zero).
auto A2_dot_B2(const T &A, const T &B)
Dot-product (single tensor contraction)
void deviatoric(const T &A, R &ret)
Same as Deviatoric() but writes to externally allocated output.
array_type::tensor< double, 4 > I4()
Fourth order unit tensor.
array_type::tensor< double, 4 > II()
Result of the dyadic product of two 2nd-order identity tensors (see I2()).
auto A2_ddot_B2(const T &A, const T &B)
Double tensor contraction.
array_type::tensor< double, 4 > I4rt()
Right-transposed fourth order unit tensor.
array_type::tensor< double, 4 > I4d()
Fourth order deviatoric projection.
void det(const T &A, R &ret)
Same as Det() but writes to externally allocated output.
void logs(const T &A, R &ret)
Same as Logs() but writes to externally allocated output.
array_type::tensor< double, 4 > Random4()
Random 4th-order tensor (for example for use in testing).
void sym(const T &A, R &ret)
Same as Sym() but writes to externally allocated output.
array_type::tensor< double, 4 > I4s()
Fourth order symmetric projection.
auto Det(const T &A)
Determinant.
auto underlying_shape_A4(const T &A) -> std::array< size_t, detail::impl_A4< T, 3 >::rank >
Shape of the underlying array.
array_type::tensor< double, 4 > O4()
4th-order null tensor (all components equal to zero).
auto Inv(const T &A)
Inverse.
void inv(const T &A, R &ret)
Same as Inv() but writes to externally allocated output.
auto Norm_deviatoric(const T &A)
Norm of the tensor's deviator:
size_t underlying_size_A4(const T &A)
Size of the underlying array.
auto Trace(const T &A)
Trace or 2nd-order tensor.
auto A4_dot_B2(const T &A, const U &B)
Tensor contraction.
void norm_deviatoric(const T &A, R &ret)
Same as Norm_deviatoric() but writes to externally allocated output.
auto A4_ddot_B2(const T &A, const U &B)
Double tensor contraction.
auto Hydrostatic(const T &A)
Hydrostatic part of a tensor.
array_type::tensor< double, 2 > Random2()
Random 2nd-order tensor (for example for use in testing).
auto A2_dot_A2T(const T &A)
Dot-product (single tensor contraction)
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Tensor products / operations.