GMatElastic 0.5.3
Loading...
Searching...
No Matches
Cartesian3d.hpp
Go to the documentation of this file.
1
9#ifndef GMATTENSOR_CARTESIAN3D_HPP
10#define GMATTENSOR_CARTESIAN3D_HPP
11
12#include "Cartesian3d.h"
13#include "detail.hpp"
14
15namespace GMatTensor {
16namespace Cartesian3d {
17
18namespace detail {
19using GMatTensor::detail::impl_A2;
20using GMatTensor::detail::impl_A4;
21} // namespace detail
22
24{
25 array_type::tensor<double, 2> ret = xt::random::randn<double>({3, 3});
26 return ret;
27}
28
30{
31 array_type::tensor<double, 4> ret = xt::random::randn<double>({3, 3, 3, 3});
32 return ret;
33}
34
36{
37 array_type::tensor<double, 2> ret = xt::zeros<double>({3, 3});
38 return ret;
39}
40
42{
43 array_type::tensor<double, 4> ret = xt::zeros<double>({3, 3, 3, 3});
44 return ret;
45}
46
48{
49 array_type::tensor<double, 2> ret = xt::empty<double>({3, 3});
50 pointer::I2(ret.data());
51 return ret;
52}
53
55{
56 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
57 pointer::II(ret.data());
58 return ret;
59}
60
62{
63 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
64 pointer::I4(ret.data());
65 return ret;
66}
67
69{
70 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
71 pointer::I4rt(ret.data());
72 return ret;
73}
74
76{
77 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
78 pointer::I4s(ret.data());
79 return ret;
80}
81
83{
84 array_type::tensor<double, 4> ret = xt::empty<double>({3, 3, 3, 3});
85 pointer::I4d(ret.data());
86 return ret;
87}
88
89template <class T, class R>
90inline void trace(const T& A, R& ret)
91{
92 return detail::impl_A2<T, 3>::ret0(A, ret, [](const auto& a) { return pointer::Trace(a); });
93}
94
95template <class T>
96inline auto Trace(const T& A)
97{
98 return detail::impl_A2<T, 3>::ret0(A, [](const auto& a) { return pointer::Trace(a); });
99}
100
101template <class T, class R>
102inline void hydrostatic(const T& A, R& ret)
103{
104 return detail::impl_A2<T, 3>::ret0(
105 A, ret, [](const auto& a) { return pointer::Hydrostatic(a); });
106}
107
108template <class T>
109inline auto Hydrostatic(const T& A)
110{
111 return detail::impl_A2<T, 3>::ret0(A, [](const auto& a) { return pointer::Hydrostatic(a); });
112}
113
114template <class T, class R>
115inline void det(const T& A, R& ret)
116{
117 return detail::impl_A2<T, 3>::ret0(A, ret, [](const auto& a) { return pointer::Det(a); });
118}
119
120template <class T>
121inline auto Det(const T& A)
122{
123 return detail::impl_A2<T, 3>::ret0(A, [](const auto& a) { return pointer::Det(a); });
124}
125
126template <class T, class R>
127inline void A2_ddot_B2(const T& A, const T& B, R& ret)
128{
129 return detail::impl_A2<T, 3>::B2_ret0(
130 A, B, ret, [](const auto& a, const auto& b) { return pointer::A2_ddot_B2(a, b); });
131}
132
133template <class T>
134inline auto A2_ddot_B2(const T& A, const T& B)
135{
136 return detail::impl_A2<T, 3>::B2_ret0(
137 A, B, [](const auto& a, const auto& b) { return pointer::A2_ddot_B2(a, b); });
138}
139
140template <class T, class R>
141inline void A2s_ddot_B2s(const T& A, const T& B, R& ret)
142{
143 return detail::impl_A2<T, 3>::B2_ret0(
144 A, B, ret, [](const auto& a, const auto& b) { return pointer::A2s_ddot_B2s(a, b); });
145}
146
147template <class T>
148inline auto A2s_ddot_B2s(const T& A, const T& B)
149{
150 return detail::impl_A2<T, 3>::B2_ret0(
151 A, B, [](const auto& a, const auto& b) { return pointer::A2s_ddot_B2s(a, b); });
152}
153
154template <class T, class R>
155inline void norm_deviatoric(const T& A, R& ret)
156{
157 return detail::impl_A2<T, 3>::ret0(
158 A, ret, [](const auto& a) { return pointer::Norm_deviatoric(a); });
159}
160
161template <class T>
162inline auto Norm_deviatoric(const T& A)
163{
164 return detail::impl_A2<T, 3>::ret0(
165 A, [](const auto& a) { return pointer::Norm_deviatoric(a); });
166}
167
168template <class T, class R>
169inline void deviatoric(const T& A, R& ret)
170{
171 return detail::impl_A2<T, 3>::ret2(
172 A, ret, [](const auto& a, const auto& r) { return pointer::Hydrostatic_deviatoric(a, r); });
173}
174
175template <class T>
176inline auto Deviatoric(const T& A)
177{
178 return detail::impl_A2<T, 3>::ret2(
179 A, [](const auto& a, const auto& r) { return pointer::Hydrostatic_deviatoric(a, r); });
180}
181
182template <class T, class R>
183inline void sym(const T& A, R& ret)
184{
185 return detail::impl_A2<T, 3>::ret2(
186 A, ret, [](const auto& a, const auto& r) { return pointer::sym(a, r); });
187}
188
189template <class T>
190inline auto Sym(const T& A)
191{
192 return detail::impl_A2<T, 3>::ret2(
193 A, [](const auto& a, const auto& r) { return pointer::sym(a, r); });
194}
195
196template <class T, class R>
197inline void inv(const T& A, R& ret)
198{
199 return detail::impl_A2<T, 3>::ret2(
200 A, ret, [](const auto& a, const auto& r) { return pointer::Inv(a, r); });
201}
202
203template <class T>
204inline auto Inv(const T& A)
205{
206 return detail::impl_A2<T, 3>::ret2(
207 A, [](const auto& a, const auto& r) { return pointer::Inv(a, r); });
208}
209
210template <class T, class R>
211inline void logs(const T& A, R& ret)
212{
213 return detail::impl_A2<T, 3>::ret2(
214 A, ret, [](const auto& a, const auto& r) { return pointer::logs(a, r); });
215}
216
217template <class T>
218inline auto Logs(const T& A)
219{
220 return detail::impl_A2<T, 3>::ret2(
221 A, [](const auto& a, const auto& r) { return pointer::logs(a, r); });
222}
223
224template <class T, class R>
225inline void A2_dot_A2T(const T& A, R& ret)
226{
227 return detail::impl_A2<T, 3>::ret2(
228 A, ret, [](const auto& a, const auto& r) { return pointer::A2_dot_A2T(a, r); });
229}
230
231template <class T>
232inline auto A2_dot_A2T(const T& A)
233{
234 return detail::impl_A2<T, 3>::ret2(
235 A, [](const auto& a, const auto& r) { return pointer::A2_dot_A2T(a, r); });
236}
237
238template <class T, class R>
239inline void A2_dot_B2(const T& A, const T& B, R& ret)
240{
241 return detail::impl_A2<T, 3>::B2_ret2(
242 A, B, ret, [](const auto& a, const auto& b, const auto& r) {
243 return pointer::A2_dot_B2(a, b, r);
244 });
245}
246
247template <class T>
248inline auto A2_dot_B2(const T& A, const T& B)
249{
250 return detail::impl_A2<T, 3>::B2_ret2(A, B, [](const auto& a, const auto& b, const auto& r) {
251 return pointer::A2_dot_B2(a, b, r);
252 });
253}
254
255template <class T, class R>
256inline void A2_dyadic_B2(const T& A, const T& B, R& ret)
257{
258 return detail::impl_A2<T, 3>::B2_ret4(
259 A, B, ret, [](const auto& a, const auto& b, const auto& r) {
260 return pointer::A2_dyadic_B2(a, b, r);
261 });
262}
263
264template <class T>
265inline auto A2_dyadic_B2(const T& A, const T& B)
266{
267 return detail::impl_A2<T, 3>::B2_ret4(A, B, [](const auto& a, const auto& b, const auto& r) {
268 return pointer::A2_dyadic_B2(a, b, r);
269 });
270}
271
272template <class T, class U, class R>
273inline void A4_ddot_B2(const T& A, const U& B, R& ret)
274{
275 return detail::impl_A4<T, 3>::B2_ret2(
276 A, B, ret, [](const auto& a, const auto& b, const auto& r) {
277 return pointer::A4_ddot_B2(a, b, r);
278 });
279}
280
281template <class T, class U>
282inline auto A4_ddot_B2(const T& A, const U& B)
283{
284 return detail::impl_A4<T, 3>::B2_ret2(A, B, [](const auto& a, const auto& b, const auto& r) {
285 return pointer::A4_ddot_B2(a, b, r);
286 });
287}
288
289template <class T, class U, class R>
290inline void A4_dot_B2(const T& A, const U& B, R& ret)
291{
292 return detail::impl_A4<T, 3>::B2_ret4(
293 A, B, ret, [](const auto& a, const auto& b, const auto& r) {
294 return pointer::A4_dot_B2(a, b, r);
295 });
296}
297
298template <class T, class U>
299inline auto A4_dot_B2(const T& A, const U& B)
300{
301 return detail::impl_A4<T, 3>::B2_ret4(A, B, [](const auto& a, const auto& b, const auto& r) {
302 return pointer::A4_dot_B2(a, b, r);
303 });
304}
305
306namespace pointer {
307
308namespace detail {
309
310// ----------------------------------------------------------------------------
311// Numerical diagonalization of 3x3 matrices
312// Copyright (C) 2006 Joachim Kopp
313// ----------------------------------------------------------------------------
314// This library is free software; you can redistribute it and/or
315// modify it under the terms of the GNU Lesser General Public
316// License as published by the Free Software Foundation; either
317// version 2.1 of the License, or (at your option) any later version.
318//
319// This library is distributed in the hope that it will be useful,
320// but WITHOUT ANY WARRANTY; without even the implied warranty of
321// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
322// Lesser General Public License for more details.
323//
324// You should have received a copy of the GNU Lesser General Public
325// License along with this library; if not, write to the Free Software
326// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
327// ----------------------------------------------------------------------------
328
329// ----------------------------------------------------------------------------
330inline int dsyevj3(double A[3][3], double Q[3][3], double w[3])
331// ----------------------------------------------------------------------------
332// Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3
333// matrix A using the Jacobi algorithm.
334// The upper triangular part of A is destroyed during the calculation,
335// the diagonal elements are read but not destroyed, and the lower
336// triangular elements are not referenced at all.
337// ----------------------------------------------------------------------------
338// Parameters:
339// A: The symmetric input matrix
340// Q: Storage buffer for eigenvectors
341// w: Storage buffer for eigenvalues
342// ----------------------------------------------------------------------------
343// Return value:
344// 0: Success
345// -1: Error (no convergence)
346// ----------------------------------------------------------------------------
347{
348 const int n = 3;
349 double sd, so; // Sums of diagonal resp. off-diagonal elements
350 double s, c, t; // sin(phi), cos(phi), tan(phi) and temporary storage
351 double g, h, z, theta; // More temporary storage
352 double thresh;
353
354 // Initialize Q to the identity matrix
355 for (int i = 0; i < n; i++) {
356 Q[i][i] = 1.0;
357 for (int j = 0; j < i; j++)
358 Q[i][j] = Q[j][i] = 0.0;
359 }
360
361 // Initialize w to diag(A)
362 for (int i = 0; i < n; i++)
363 w[i] = A[i][i];
364
365 // Calculate SQR(tr(A))
366 sd = 0.0;
367 for (int i = 0; i < n; i++)
368 sd += fabs(w[i]);
369 sd = sd * sd;
370
371 // Main iteration loop
372 for (int nIter = 0; nIter < 50; nIter++) {
373 // Test for convergence
374 so = 0.0;
375 for (int p = 0; p < n; p++)
376 for (int q = p + 1; q < n; q++)
377 so += fabs(A[p][q]);
378 if (so == 0.0)
379 return 0;
380
381 if (nIter < 4)
382 thresh = 0.2 * so / (n * n);
383 else
384 thresh = 0.0;
385
386 // Do sweep
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])) {
391 A[p][q] = 0.0;
392 }
393 else if (fabs(A[p][q]) > thresh) {
394 // Calculate Jacobi transformation
395 h = w[q] - w[p];
396 if (fabs(h) + g == fabs(h)) {
397 t = A[p][q] / h;
398 }
399 else {
400 theta = 0.5 * h / A[p][q];
401 if (theta < 0.0)
402 t = -1.0 / (sqrt(1.0 + theta * theta) - theta);
403 else
404 t = 1.0 / (sqrt(1.0 + theta * theta) + theta);
405 }
406 c = 1.0 / sqrt(1.0 + t * t);
407 s = t * c;
408 z = t * A[p][q];
409
410 // Apply Jacobi transformation
411 A[p][q] = 0.0;
412 w[p] -= z;
413 w[q] += z;
414 for (int r = 0; r < p; r++) {
415 t = A[r][p];
416 A[r][p] = c * t - s * A[r][q];
417 A[r][q] = s * t + c * A[r][q];
418 }
419 for (int r = p + 1; r < q; r++) {
420 t = A[p][r];
421 A[p][r] = c * t - s * A[r][q];
422 A[r][q] = s * t + c * A[r][q];
423 }
424 for (int r = q + 1; r < n; r++) {
425 t = A[p][r];
426 A[p][r] = c * t - s * A[q][r];
427 A[q][r] = s * t + c * A[q][r];
428 }
429
430 // Update eigenvectors
431 for (int r = 0; r < n; r++) {
432 t = Q[r][p];
433 Q[r][p] = c * t - s * Q[r][q];
434 Q[r][q] = s * t + c * Q[r][q];
435 }
436 }
437 }
438 }
439
440 return -1;
441}
442// ----------------------------------------------------------------------------
443
444} // namespace detail
445
446template <class T>
447inline void O2(T* ret)
448{
449 std::fill(ret, ret + 9, T(0));
450}
451
452template <class T>
453inline void O4(T* ret)
454{
455 std::fill(ret, ret + 81, T(0));
456}
457
458template <class T>
459inline void I2(T* ret)
460{
461 ret[0] = 1.0;
462 ret[1] = 0.0;
463 ret[2] = 0.0;
464 ret[3] = 0.0;
465 ret[4] = 1.0;
466 ret[5] = 0.0;
467 ret[6] = 0.0;
468 ret[7] = 0.0;
469 ret[8] = 1.0;
470}
471
472template <class T>
473inline void II(T* ret)
474{
475 std::fill(ret, ret + 81, T(0));
476
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;
483 }
484 }
485 }
486 }
487 }
488}
489
490template <class T>
491inline void I4(T* ret)
492{
493 std::fill(ret, ret + 81, T(0));
494
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;
501 }
502 }
503 }
504 }
505 }
506}
507
508template <class T>
509inline void I4rt(T* ret)
510{
511 std::fill(ret, ret + 81, T(0));
512
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;
519 }
520 }
521 }
522 }
523 }
524}
525
526template <class T>
527inline void I4s(T* ret)
528{
529 I4(ret);
530
531 std::array<double, 81> i4rt;
532 I4rt(&i4rt[0]);
533
534 std::transform(ret, ret + 81, &i4rt[0], ret, std::plus<T>());
535
536 std::transform(ret, ret + 81, ret, std::bind(std::multiplies<T>(), std::placeholders::_1, 0.5));
537}
538
539template <class T>
540inline void I4d(T* ret)
541{
542 I4s(ret);
543
544 std::array<double, 81> ii;
545 II(&ii[0]);
546
547 std::transform(
548 &ii[0], &ii[0] + 81, &ii[0], std::bind(std::divides<T>(), std::placeholders::_1, 3.0));
549
550 std::transform(ret, ret + 81, &ii[0], ret, std::minus<T>());
551}
552
553template <class T>
554inline T Trace(const T* A)
555{
556 return A[0] + A[4] + A[8];
557}
558
559template <class T>
560inline T Hydrostatic(const T* A)
561{
562 return Trace(A) / T(3);
563}
564
565template <class T>
566inline T Det(const T* A)
567{
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]);
570}
571
572template <class T>
573inline void sym(const T* A, T* ret)
574{
575 ret[0] = A[0];
576 ret[1] = 0.5 * (A[1] + A[3]);
577 ret[2] = 0.5 * (A[2] + A[6]);
578 ret[3] = ret[1];
579 ret[4] = A[4];
580 ret[5] = 0.5 * (A[5] + A[7]);
581 ret[6] = ret[2];
582 ret[7] = ret[5];
583 ret[8] = A[8];
584}
585
586template <class T>
587inline T Inv(const T* A, T* ret)
588{
589 T D = Det(A);
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;
599 return D;
600}
601
602template <class T>
603inline T Hydrostatic_deviatoric(const T* A, T* ret)
604{
605 T m = Hydrostatic(A);
606 ret[0] = A[0] - m;
607 ret[1] = A[1];
608 ret[2] = A[2];
609 ret[3] = A[3];
610 ret[4] = A[4] - m;
611 ret[5] = A[5];
612 ret[6] = A[6];
613 ret[7] = A[7];
614 ret[8] = A[8] - m;
615 return m;
616}
617
618template <class T>
619inline T Deviatoric_ddot_deviatoric(const T* A)
620{
621 T m = Hydrostatic(A);
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];
624}
625
626template <class T>
627inline T Norm_deviatoric(const T* A)
628{
629 return std::sqrt(Deviatoric_ddot_deviatoric(A));
630}
631
632template <class T>
633inline T A2_ddot_B2(const T* A, const T* B)
634{
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];
637}
638
639template <class T>
640inline T A2s_ddot_B2s(const T* A, const T* B)
641{
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] +
643 T(2) * A[5] * B[5];
644}
645
646template <class T>
647inline void A2_dyadic_B2(const T* A, const T* B, T* ret)
648{
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];
654 }
655 }
656 }
657 }
658}
659
660template <class T>
661inline void A4_dot_B2(const T* A, const T* B, T* ret)
662{
663 std::fill(ret, ret + 81, T(0));
664
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];
672 }
673 }
674 }
675 }
676 }
677}
678
679template <class T>
680inline void A2_dot_B2(const T* A, const T* B, T* ret)
681{
682 std::fill(ret, ret + 9, T(0));
683
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];
688 }
689 }
690 }
691}
692
693template <class T>
694inline void A2_dot_A2T(const T* A, T* ret)
695{
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];
702 ret[3] = ret[1];
703 ret[6] = ret[2];
704 ret[7] = ret[5];
705}
706
707template <class T>
708inline void A4_ddot_B2(const T* A, const T* B, T* ret)
709{
710 std::fill(ret, ret + 9, T(0));
711
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];
717 }
718 }
719 }
720 }
721}
722
723template <class T>
724inline void A4_ddot_B4_ddot_C4(const T* A, const T* B, const T* C, T* ret)
725{
726 std::fill(ret, ret + 81, T(0));
727
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];
740 }
741 }
742 }
743 }
744 }
745 }
746 }
747 }
748}
749
750template <class T>
751inline void A2_dot_B2_dot_C2T(const T* A, const T* B, const T* C, T* ret)
752{
753 std::fill(ret, ret + 9, T(0));
754
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];
760 }
761 }
762 }
763 }
764}
765
766template <class T>
767void eigs(const T* A, T* vec, T* val)
768{
769 double a[3][3];
770 double Q[3][3];
771 double w[3];
772
773 std::copy(&A[0], &A[0] + 9, &a[0][0]);
774
775 // use the 'Jacobi' algorithm, which is accurate but not very fast
776 // (in practice the faster 'hybrid' "dsyevh3" is too inaccurate for finite elements)
777 auto succes = detail::dsyevj3(a, Q, w);
778 (void)(succes);
779 GMATTENSOR_ASSERT(succes == 0);
780
781 std::copy(&Q[0][0], &Q[0][0] + 3 * 3, vec);
782 std::copy(&w[0], &w[0] + 3, val);
783}
784
785template <class T>
786void from_eigs(const T* vec, const T* val, T* ret)
787{
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];
794 ret[3] = ret[1];
795 ret[6] = ret[2];
796 ret[7] = ret[5];
797}
798
799template <class T>
800inline void logs(const T* A, T* ret)
801{
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]);
807 }
808 from_eigs(&vec[0], &val[0], &ret[0]);
809}
810
811} // namespace pointer
812
813} // namespace Cartesian3d
814} // namespace GMatTensor
815
816#endif
#define GMATTENSOR_ASSERT(expr)
All assertions are implementation as:
Definition: config.h:59
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.
Definition: Cartesian3d.hpp:90
auto Logs(const T &A)
Logarithm.
array_type::tensor< double, 2 > I2()
2nd-order identity tensor.
Definition: Cartesian3d.hpp:47
array_type::tensor< double, 2 > O2()
2nd-order null tensor (all components equal to zero).
Definition: Cartesian3d.hpp:35
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.
Definition: Cartesian3d.hpp:61
array_type::tensor< double, 4 > II()
Result of the dyadic product of two 2nd-order identity tensors (see I2()).
Definition: Cartesian3d.hpp:54
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.
Definition: Cartesian3d.hpp:68
array_type::tensor< double, 4 > I4d()
Fourth order deviatoric projection.
Definition: Cartesian3d.hpp:82
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).
Definition: Cartesian3d.hpp:29
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.
Definition: Cartesian3d.hpp:75
auto Det(const T &A)
Determinant.
array_type::tensor< double, 4 > O4()
4th-order null tensor (all components equal to zero).
Definition: Cartesian3d.hpp:41
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.
Definition: Cartesian3d.hpp:96
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).
Definition: Cartesian3d.hpp:23
auto A2_dot_A2T(const T &A)
Dot-product (single tensor contraction)
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition: config.h:86
Tensor products / operations.
Definition: Cartesian2d.h:20