9#ifndef GMATTENSOR_CARTESIAN3D_HPP
10#define GMATTENSOR_CARTESIAN3D_HPP
16namespace Cartesian3d {
19using GMatTensor::detail::impl_A2;
20using GMatTensor::detail::impl_A4;
89template <
class T,
class R>
90inline void trace(
const T& A, R& ret)
92 return detail::impl_A2<T, 3>::ret0(A, ret, [](
const auto& a) {
return pointer::Trace(a); });
98 return detail::impl_A2<T, 3>::ret0(A, [](
const auto& a) {
return pointer::Trace(a); });
101template <
class T,
class R>
104 return detail::impl_A2<T, 3>::ret0(
114template <
class T,
class R>
115inline void det(
const T& A, R& ret)
117 return detail::impl_A2<T, 3>::ret0(A, ret, [](
const auto& a) {
return pointer::Det(a); });
121inline auto Det(
const T& A)
123 return detail::impl_A2<T, 3>::ret0(A, [](
const auto& a) {
return pointer::Det(a); });
126template <
class T,
class R>
129 return detail::impl_A2<T, 3>::B2_ret0(
136 return detail::impl_A2<T, 3>::B2_ret0(
140template <
class T,
class R>
143 return detail::impl_A2<T, 3>::B2_ret0(
150 return detail::impl_A2<T, 3>::B2_ret0(
154template <
class T,
class R>
157 return detail::impl_A2<T, 3>::ret0(
164 return detail::impl_A2<T, 3>::ret0(
168template <
class T,
class R>
171 return detail::impl_A2<T, 3>::ret2(
178 return detail::impl_A2<T, 3>::ret2(
182template <
class T,
class R>
183inline void sym(
const T& A, R& ret)
185 return detail::impl_A2<T, 3>::ret2(
186 A, ret, [](
const auto& a,
const auto& r) {
return pointer::sym(a, r); });
190inline auto Sym(
const T& A)
192 return detail::impl_A2<T, 3>::ret2(
193 A, [](
const auto& a,
const auto& r) {
return pointer::sym(a, r); });
196template <
class T,
class R>
197inline void inv(
const T& A, R& ret)
199 return detail::impl_A2<T, 3>::ret2(
200 A, ret, [](
const auto& a,
const auto& r) {
return pointer::Inv(a, r); });
204inline auto Inv(
const T& A)
206 return detail::impl_A2<T, 3>::ret2(
207 A, [](
const auto& a,
const auto& r) {
return pointer::Inv(a, r); });
210template <
class T,
class R>
211inline void logs(
const T& A, R& ret)
213 return detail::impl_A2<T, 3>::ret2(
214 A, ret, [](
const auto& a,
const auto& r) {
return pointer::logs(a, r); });
220 return detail::impl_A2<T, 3>::ret2(
221 A, [](
const auto& a,
const auto& r) {
return pointer::logs(a, r); });
224template <
class T,
class R>
227 return detail::impl_A2<T, 3>::ret2(
234 return detail::impl_A2<T, 3>::ret2(
238template <
class T,
class R>
241 return detail::impl_A2<T, 3>::B2_ret2(
242 A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
250 return detail::impl_A2<T, 3>::B2_ret2(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
255template <
class T,
class R>
258 return detail::impl_A2<T, 3>::B2_ret4(
259 A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
267 return detail::impl_A2<T, 3>::B2_ret4(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
272template <
class T,
class U,
class R>
275 return detail::impl_A4<T, 3>::B2_ret2(
276 A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
281template <
class T,
class U>
284 return detail::impl_A4<T, 3>::B2_ret2(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
289template <
class T,
class U,
class R>
292 return detail::impl_A4<T, 3>::B2_ret4(
293 A, B, ret, [](
const auto& a,
const auto& b,
const auto& r) {
298template <
class T,
class U>
301 return detail::impl_A4<T, 3>::B2_ret4(A, B, [](
const auto& a,
const auto& b,
const auto& r) {
330inline int dsyevj3(
double A[3][3],
double Q[3][3],
double w[3])
351 double g, h, z, theta;
355 for (
int i = 0; i < n; i++) {
357 for (
int j = 0; j < i; j++)
358 Q[i][j] = Q[j][i] = 0.0;
362 for (
int i = 0; i < n; i++)
367 for (
int i = 0; i < n; i++)
372 for (
int nIter = 0; nIter < 50; nIter++) {
375 for (
int p = 0; p < n; p++)
376 for (
int q = p + 1; q < n; q++)
382 thresh = 0.2 * so / (n * n);
387 for (
int p = 0; p < n; p++)
388 for (
int q = p + 1; q < n; q++) {
389 g = 100.0 * fabs(A[p][q]);
390 if (nIter > 4 && fabs(w[p]) + g == fabs(w[p]) && fabs(w[q]) + g == fabs(w[q])) {
393 else if (fabs(A[p][q]) > thresh) {
396 if (fabs(h) + g == fabs(h)) {
400 theta = 0.5 * h / A[p][q];
402 t = -1.0 / (sqrt(1.0 + theta * theta) - theta);
404 t = 1.0 / (sqrt(1.0 + theta * theta) + theta);
406 c = 1.0 / sqrt(1.0 + t * t);
414 for (
int r = 0; r < p; r++) {
416 A[r][p] = c * t - s * A[r][q];
417 A[r][q] = s * t + c * A[r][q];
419 for (
int r = p + 1; r < q; r++) {
421 A[p][r] = c * t - s * A[r][q];
422 A[r][q] = s * t + c * A[r][q];
424 for (
int r = q + 1; r < n; r++) {
426 A[p][r] = c * t - s * A[q][r];
427 A[q][r] = s * t + c * A[q][r];
431 for (
int r = 0; r < n; r++) {
433 Q[r][p] = c * t - s * Q[r][q];
434 Q[r][q] = s * t + c * Q[r][q];
447inline void O2(T* ret)
449 std::fill(ret, ret + 9, T(0));
453inline void O4(T* ret)
455 std::fill(ret, ret + 81, T(0));
459inline void I2(T* ret)
473inline void II(T* ret)
475 std::fill(ret, ret + 81, T(0));
477 for (
size_t i = 0; i < 3; ++i) {
478 for (
size_t j = 0; j < 3; ++j) {
479 for (
size_t k = 0; k < 3; ++k) {
480 for (
size_t l = 0; l < 3; ++l) {
481 if (i == j && k == l) {
482 ret[i * 27 + j * 9 + k * 3 + l] = 1.0;
491inline void I4(T* ret)
493 std::fill(ret, ret + 81, T(0));
495 for (
size_t i = 0; i < 3; ++i) {
496 for (
size_t j = 0; j < 3; ++j) {
497 for (
size_t k = 0; k < 3; ++k) {
498 for (
size_t l = 0; l < 3; ++l) {
499 if (i == l && j == k) {
500 ret[i * 27 + j * 9 + k * 3 + l] = 1.0;
511 std::fill(ret, ret + 81, T(0));
513 for (
size_t i = 0; i < 3; ++i) {
514 for (
size_t j = 0; j < 3; ++j) {
515 for (
size_t k = 0; k < 3; ++k) {
516 for (
size_t l = 0; l < 3; ++l) {
517 if (i == k && j == l) {
518 ret[i * 27 + j * 9 + k * 3 + l] = 1.0;
531 std::array<double, 81> i4rt;
534 std::transform(ret, ret + 81, &i4rt[0], ret, std::plus<T>());
536 std::transform(ret, ret + 81, ret, std::bind(std::multiplies<T>(), std::placeholders::_1, 0.5));
544 std::array<double, 81> ii;
548 &ii[0], &ii[0] + 81, &ii[0], std::bind(std::divides<T>(), std::placeholders::_1, 3.0));
550 std::transform(ret, ret + 81, &ii[0], ret, std::minus<T>());
556 return A[0] + A[4] + A[8];
562 return Trace(A) / T(3);
568 return (A[0] * A[4] * A[8] + A[1] * A[5] * A[6] + A[2] * A[3] * A[7]) -
569 (A[2] * A[4] * A[6] + A[1] * A[3] * A[8] + A[0] * A[5] * A[7]);
573inline void sym(
const T* A, T* ret)
576 ret[1] = 0.5 * (A[1] + A[3]);
577 ret[2] = 0.5 * (A[2] + A[6]);
580 ret[5] = 0.5 * (A[5] + A[7]);
587inline T
Inv(
const T* A, T* ret)
590 ret[0] = (A[4] * A[8] - A[5] * A[7]) / D;
591 ret[1] = (A[2] * A[7] - A[1] * A[8]) / D;
592 ret[2] = (A[1] * A[5] - A[2] * A[4]) / D;
593 ret[3] = (A[5] * A[6] - A[3] * A[8]) / D;
594 ret[4] = (A[0] * A[8] - A[2] * A[6]) / D;
595 ret[5] = (A[2] * A[3] - A[0] * A[5]) / D;
596 ret[6] = (A[3] * A[7] - A[4] * A[6]) / D;
597 ret[7] = (A[1] * A[6] - A[0] * A[7]) / D;
598 ret[8] = (A[0] * A[4] - A[1] * A[3]) / D;
622 return (A[0] - m) * (A[0] - m) + (A[4] - m) * (A[4] - m) + (A[8] - m) * (A[8] - m) +
623 T(2) * A[1] * A[3] + T(2) * A[2] * A[6] + T(2) * A[5] * A[7];
635 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] +
636 A[5] * B[7] + A[6] * B[2] + A[7] * B[5];
642 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] +
649 for (
size_t i = 0; i < 3; ++i) {
650 for (
size_t j = 0; j < 3; ++j) {
651 for (
size_t k = 0; k < 3; ++k) {
652 for (
size_t l = 0; l < 3; ++l) {
653 ret[i * 27 + j * 9 + k * 3 + l] = A[i * 3 + j] * B[k * 3 + l];
663 std::fill(ret, ret + 81, T(0));
665 for (
size_t i = 0; i < 3; ++i) {
666 for (
size_t j = 0; j < 3; ++j) {
667 for (
size_t k = 0; k < 3; ++k) {
668 for (
size_t l = 0; l < 3; ++l) {
669 for (
size_t m = 0; m < 3; ++m) {
670 ret[i * 27 + j * 9 + k * 3 + m] +=
671 A[i * 27 + j * 9 + k * 3 + l] * B[l * 3 + m];
682 std::fill(ret, ret + 9, T(0));
684 for (
size_t i = 0; i < 3; ++i) {
685 for (
size_t j = 0; j < 3; ++j) {
686 for (
size_t k = 0; k < 3; ++k) {
687 ret[i * 3 + k] += A[i * 3 + j] * B[j * 3 + k];
696 ret[0] = A[0] * A[0] + A[1] * A[1] + A[2] * A[2];
697 ret[1] = A[0] * A[3] + A[1] * A[4] + A[2] * A[5];
698 ret[2] = A[0] * A[6] + A[1] * A[7] + A[2] * A[8];
699 ret[4] = A[3] * A[3] + A[4] * A[4] + A[5] * A[5];
700 ret[5] = A[3] * A[6] + A[4] * A[7] + A[5] * A[8];
701 ret[8] = A[6] * A[6] + A[7] * A[7] + A[8] * A[8];
710 std::fill(ret, ret + 9, T(0));
712 for (
size_t i = 0; i < 3; i++) {
713 for (
size_t j = 0; j < 3; j++) {
714 for (
size_t k = 0; k < 3; k++) {
715 for (
size_t l = 0; l < 3; l++) {
716 ret[i * 3 + j] += A[i * 27 + j * 9 + k * 3 + l] * B[l * 3 + k];
726 std::fill(ret, ret + 81, T(0));
728 for (
size_t i = 0; i < 3; ++i) {
729 for (
size_t j = 0; j < 3; ++j) {
730 for (
size_t k = 0; k < 3; ++k) {
731 for (
size_t l = 0; l < 3; ++l) {
732 for (
size_t m = 0; m < 3; ++m) {
733 for (
size_t n = 0; n < 3; ++n) {
734 for (
size_t o = 0; o < 3; ++o) {
735 for (
size_t p = 0; p < 3; ++p) {
736 ret[i * 27 + j * 9 + o * 3 + p] +=
737 A[i * 27 + j * 9 + k * 3 + l] *
738 B[l * 27 + k * 9 + m * 3 + n] *
739 C[n * 27 + m * 9 + o * 3 + p];
753 std::fill(ret, ret + 9, T(0));
755 for (
size_t i = 0; i < 3; ++i) {
756 for (
size_t j = 0; j < 3; ++j) {
757 for (
size_t h = 0; h < 3; ++h) {
758 for (
size_t l = 0; l < 3; ++l) {
759 ret[i * 3 + l] += A[i * 3 + j] * B[j * 3 + h] * C[l * 3 + h];
767void eigs(
const T* A, T* vec, T* val)
773 std::copy(&A[0], &A[0] + 9, &a[0][0]);
777 auto succes = detail::dsyevj3(a, Q, w);
781 std::copy(&Q[0][0], &Q[0][0] + 3 * 3, vec);
782 std::copy(&w[0], &w[0] + 3, val);
788 ret[0] = val[0] * vec[0] * vec[0] + val[1] * vec[1] * vec[1] + val[2] * vec[2] * vec[2];
789 ret[1] = val[0] * vec[0] * vec[3] + val[1] * vec[1] * vec[4] + val[2] * vec[2] * vec[5];
790 ret[2] = val[0] * vec[0] * vec[6] + val[1] * vec[1] * vec[7] + val[2] * vec[2] * vec[8];
791 ret[4] = val[0] * vec[3] * vec[3] + val[1] * vec[4] * vec[4] + val[2] * vec[5] * vec[5];
792 ret[5] = val[0] * vec[3] * vec[6] + val[1] * vec[4] * vec[7] + val[2] * vec[5] * vec[8];
793 ret[8] = val[0] * vec[6] * vec[6] + val[1] * vec[7] * vec[7] + val[2] * vec[8] * vec[8];
800inline void logs(
const T* A, T* ret)
802 std::array<double, 3> val;
803 std::array<double, 9> vec;
804 eigs(&A[0], &vec[0], &val[0]);
805 for (
size_t j = 0; j < 3; ++j) {
806 val[j] = std::log(val[j]);
#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.
auto Sym(const T &A)
Symmetric part of a tensor:
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.
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:
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.