5#ifndef __TEMPLATES_HPP__
6#define __TEMPLATES_HPP__
17 static constexpr bool isGaussByCoeffs =
true;
18 static constexpr bool isCoeffsByGauss =
false;
21 static constexpr bool isGaussByCoeffs =
false;
22 static constexpr bool isCoeffsByGauss =
true;
50 typedef typename std::remove_pointer<T1>::type T;
52 ublas::shallow_array_adaptor<T>(
n, ptr));
76 typedef typename std::remove_pointer<T1>::type T;
78 n,
m, ublas::shallow_array_adaptor<T>(
n *
m, ptr));
94template <
class KeyExtractor1,
class KeyExtractor2>
struct KeyFromKey {
99 const KeyExtractor2 &key2_ = KeyExtractor2())
111template <
typename id_type>
struct LtBit {
112 inline bool operator()(
const id_type &valueA,
const id_type &valueB)
const {
113 return valueA.to_ulong() < valueB.to_ulong();
117template <
typename id_type>
struct EqBit {
118 inline bool operator()(
const id_type &valueA,
const id_type &valueB)
const {
119 return valueA.to_ulong() == valueB.to_ulong();
125 return value.to_ulong();
129template <
class X>
inline std::string
toString(X x) {
130 std::ostringstream buffer;
141 static inline auto get(V &data) {
142 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0))>>;
168 static inline auto get(
M &data) {
171 if (data.size1() != 1 && data.size2() != 1)
172 THROW_MESSAGE(
"getFTensor0FromMat: wrong size of data matrix, number of "
173 "rows should be 1 but is " +
174 boost::lexical_cast<std::string>(data.size1()));
176 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
201template <
int S = 1,
class T,
class A>
204 if (data_ptr.expired())
214 THROW_MESSAGE(
"getFTensor0FromMat: data pointer is not available");
231template <
int Tensor_Dim,
int S,
class DL,
class M>
234template <
int Tensor_Dim,
int S,
class M>
237 static inline auto get(
M &data,
int rr,
int cc) {
239 using T = std::remove_reference_t<
decltype(data(0, 0))>;
240 constexpr int stride = S == -1 ? Tensor_Dim : S;
242 stride % Tensor_Dim == 0,
243 "getFTensor1FromMat: stride should be a multiple of Tensor_Dim");
246 if (data.size2() != Tensor_Dim)
248 "getFTensor1FromMat<" + boost::lexical_cast<std::string>(Tensor_Dim) +
249 ">: wrong size of data matrix, number of columns should be " +
250 boost::lexical_cast<std::string>(Tensor_Dim) +
" but is " +
251 boost::lexical_cast<std::string>(data.size2()));
252 auto *first = &data(rr + 0, cc + 0);
253 auto *last = &data(rr + 0, cc + 0 + Tensor_Dim - 1);
254 if (last - first != Tensor_Dim - 1)
256 boost::lexical_cast<std::string>(Tensor_Dim) +
257 ">: row slice is not contiguous");
261 &data(rr + 0, cc + 0));
265template <
int S,
class M>
268 static inline auto get(
M &data,
int rr,
int cc) {
269 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
270 constexpr int stride = S == -1 ? 1 : S;
273 if (data.size1() % 3 != 0)
275 "getFTensor1FromMat<3>: wrong size of data matrix, number of "
276 "rows modulo of 3 but is " +
277 boost::lexical_cast<std::string>(data.size1()));
280 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0));
284template <
int S,
class M>
287 static inline auto get(
M &data,
int rr,
int cc) {
288 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
289 constexpr int stride = S == -1 ? 1 : S;
291 if (data.size1() % 4 != 0)
293 "getFTensor1FromMat<4>: wrong size of data matrix, number of "
294 "rows should be 4 but is " +
295 boost::lexical_cast<std::string>(data.size1()));
298 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
299 &data(rr + 3, cc + 0));
303template <
int S,
class M>
306 static inline auto get(
M &data,
int rr,
int cc) {
307 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
308 constexpr int stride = S == -1 ? 1 : S;
310 if (data.size1() % 6 != 0)
312 "getFTensor1FromMat<6>: wrong size of data matrix, number of "
313 "rows should be 6 but is " +
314 boost::lexical_cast<std::string>(data.size1()));
317 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
318 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0));
322template <
int S,
class M>
325 static inline auto get(
M &data,
int rr,
int cc) {
326 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
327 constexpr int stride = S == -1 ? 1 : S;
329 if (data.size1() % 9 != 0)
331 "getFTensor1FromMat<9>: wrong size of data matrix, number of "
332 "rows should be 9 but is " +
333 boost::lexical_cast<std::string>(data.size1()));
336 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
337 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
338 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0));
342template <
int S,
class M>
345 static inline auto get(
M &data,
int rr,
int cc) {
346 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
347 constexpr int stride = S == -1 ? 1 : S;
349 if (data.size1() % 2 != 0)
351 "getFTensor1FromMat<2>: wrong size of data matrix, number of "
352 "row should be 2 but is " +
353 boost::lexical_cast<std::string>(data.size1()));
356 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0));
360template <
int S,
class M>
363 static inline auto get(
M &data,
int rr,
int cc) {
364 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
365 constexpr int stride = S == -1 ? 1 : S;
367 &data(rr + 0, cc + 0));
374template <
int Tensor_Dim,
int S = -1,
375 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
381template <
int Tensor_Dim,
int S = -1,
382 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
386 std::declval<M &>(), 0, 0));
388template <
int Tensor_Dim,
int S = -1,
395 "Data matrix is not available");
399 *data.lock(), rr, cc);
402template <
int Tensor_Dim,
int S = -1,
403 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
409 "Data matrix is not available");
416template <
int Tensor_Dim,
int S = Tensor_Dim,
typename T =
double>
421template <
int Tensor_Dim,
int S = Tensor_Dim>
423 return getFTensor1FromPtr<Tensor_Dim, S, std::complex<double>>(ptr);
427template <
int Tensor_Dim,
int S = Tensor_Dim>
429 return getFTensor1FromPtr<Tensor_Dim, S, adouble>(ptr);
433template <
int Tensor_Dim,
int S = Tensor_Dim,
typename T = VectorDouble>
435 static_assert(S % Tensor_Dim == 0,
436 "getFTensor1FromArray(VectorDouble&) requires S to be a "
437 "multiple of Tensor_Dim");
440 if (data.size() % S != 0) {
442 "getFTensor1FromArray: data size should be divisible by "
443 "pack stride dimension");
446 return getFTensor1FromPtr<Tensor_Dim, S>(data.data().data());
459template <
int DIM,
int S>
473 &data(rr + 0, 0), &data(rr + 1, 1), &data(rr + 2, 2)};
481template <
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class DL,
class M>
483 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
485 using T = std::remove_reference_t<
decltype(data(0, 0))>;
486 constexpr int stride =
487 S == -1 ? (DL::isGaussByCoeffs ? Tensor_Dim1 * Tensor_Dim2 : 1) : S;
488 if constexpr (DL::isGaussByCoeffs) {
489 static_assert(stride % (Tensor_Dim1 * Tensor_Dim2) == 0,
490 "getFTensor2FromMat: stride should be a multiple of "
491 "Tensor_Dim1 * Tensor_Dim2");
494 if (data.size2() != Tensor_Dim1 * Tensor_Dim2) {
496 "getFTensor2FromMat<" +
497 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
498 boost::lexical_cast<std::string>(Tensor_Dim2) +
499 ">: wrong size of columns in data matrix, should be " +
500 boost::lexical_cast<std::string>(Tensor_Dim1 * Tensor_Dim2) +
501 " but is " + boost::lexical_cast<std::string>(data.size2()));
503 auto *first = &data(rr + 0, cc + 0);
504 auto *last = &data(rr + 0, cc + 0 + Tensor_Dim1 * Tensor_Dim2 - 1);
505 if (last - first != Tensor_Dim1 * Tensor_Dim2 - 1) {
507 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
508 boost::lexical_cast<std::string>(Tensor_Dim2) +
509 ">: row slice is not contiguous");
513 Tensor_Dim2>(&data(rr + 0, cc + 0));
514 }
else if constexpr (DL::isCoeffsByGauss) {
515 std::array<T *, Tensor_Dim1 * Tensor_Dim2> ptrs;
517 if (data.size1() != Tensor_Dim1 * Tensor_Dim2) {
519 "getFTensor2FromMat<" +
520 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
521 boost::lexical_cast<std::string>(Tensor_Dim2) +
522 ">: wrong size of rows in data matrix, should be " +
523 boost::lexical_cast<std::string>(Tensor_Dim1 * Tensor_Dim2) +
524 " but is " + boost::lexical_cast<std::string>(data.size1()));
527 for (
auto i = 0;
i != Tensor_Dim1 * Tensor_Dim2; ++
i)
528 ptrs[
i] = &data(rr +
i, cc + 0);
532 static_assert(!std::is_same<M, M>::value,
533 "Unsupported data layout for getFTensor2FromMatImpl");
541template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
542 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
548template <
int Tensor_Dim0,
int Tensor_Dim1,
int S = -1,
549 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
553 std::declval<M &>(), 0, 0));
558template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
562 if (!data_ptr.lock()) {
564 "Data matrix is not available");
574template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
575 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
580 "Data matrix is not available");
587template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1>
591 Tensor_Dim1 * Tensor_Dim2);
594 decltype(matrix_data)>::get(matrix_data);
597template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
598 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
600 if constexpr (DL::isGaussByCoeffs) {
603 decltype(matrix_data)>::get(matrix_data);
604 }
else if constexpr (DL::isCoeffsByGauss) {
607 decltype(matrix_data)>::get(matrix_data);
611template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
612 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
614 if constexpr (DL::isGaussByCoeffs) {
617 decltype(matrix_data)>::get(matrix_data);
618 }
else if constexpr (DL::isCoeffsByGauss) {
621 decltype(matrix_data)>::get(matrix_data);
664 inline static auto get(
M &data,
const size_t rr,
const size_t cc = 0) {
665 return make(data, rr, cc, std::make_index_sequence<DIM1 * DIM2>{});
669 template <
size_t... Is>
670 inline static auto make(
M &data,
const size_t rr,
const size_t cc,
671 std::index_sequence<Is...>) {
672 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
674 &data(rr + Is /
DIM2, cc + Is %
DIM2)...};
693 inline static auto get(
M &data,
const size_t rr,
const size_t cc,
695 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
697 &data(rr + 0, cc + 0), &data(rr + 0, cc + 1),
699 &data(rr + 1, cc + 0), &data(rr + 1, cc + 1), ss);
705 inline static auto get(
M &data,
const size_t rr,
const size_t cc,
707 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
709 &data(rr + 0, cc + 0), &data(rr + 0, cc + 1), &data(rr + 0, cc + 2),
710 &data(rr + 1, cc + 0), &data(rr + 1, cc + 1), &data(rr + 1, cc + 2),
711 &data(rr + 2, cc + 0), &data(rr + 2, cc + 1), &data(rr + 2, cc + 2),
716template <
int DIM1,
int DIM2,
int S>
718 const size_t cc = 0) {
723template <
int DIM1,
int DIM2>
725 const size_t cc,
const int ss) {
731template <
int DIM1,
int DIM2,
int S>
742template <
int Tensor_Dim,
int S,
class DL,
class M>
745template <
int Tensor_Dim,
int S,
class M>
748 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
750 using T = std::remove_reference_t<
decltype(data(0, 0))>;
751 constexpr int symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
752 constexpr int stride = S == -1 ? symm_size : S;
753 static_assert(stride % symm_size == 0,
754 "getFTensor2SymmetricFromMat: stride should be a multiple of "
758 if (data.size2() != symm_size)
760 "getFTensor2SymmetricFromMat<" +
761 boost::lexical_cast<std::string>(Tensor_Dim) +
762 ">: wrong size of data matrix, number of columns should be " +
763 boost::lexical_cast<std::string>(symm_size) +
" but is " +
764 boost::lexical_cast<std::string>(data.size2()));
765 auto *first = &data(rr + 0, cc + 0);
766 auto *last = &data(rr + 0, cc + 0 + symm_size - 1);
767 if (last - first != symm_size - 1)
769 boost::lexical_cast<std::string>(Tensor_Dim) +
770 ">: row slice is not contiguous");
773 Tensor_Dim>(&data(rr + 0, cc + 0));
777template <
int S,
class M>
780 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
781 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
782 constexpr int stride = S == -1 ? 1 : S;
784 constexpr int symm_size = 6;
785 if (data.size1() != symm_size)
787 "getFTensor2SymmetricFromMat<3>: wrong size of data matrix, "
788 "number of rows should be 6 but is " +
789 boost::lexical_cast<std::string>(data.size1()));
792 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
793 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0));
797template <
int S,
class M>
800 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
801 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
802 constexpr int stride = S == -1 ? 1 : S;
804 constexpr int symm_size = 3;
805 if (data.size1() != symm_size)
807 "getFTensor2SymmetricFromMat<2>: wrong size of data matrix, "
808 "number of rows should be 3 but is " +
809 boost::lexical_cast<std::string>(data.size1()));
812 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0));
819template <
int Tensor_Dim,
int S = -1,
820 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
826template <
int Tensor_Dim,
int S = -1,
827 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
831 std::declval<M &>(), 0, 0));
833template <
int Tensor_Dim,
int S = -1,
838 if (data_ptr.expired()) {
840 "Data matrix is not available");
847template <
int Tensor_Dim,
int S = -1,
848 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
854 "Data matrix is not available");
866 decltype(matrix_data)>::get(matrix_data, 0, 0);
870template <
int Tensor_Dim>
876 decltype(matrix_data)>::get(matrix_data, 0, 0);
899 ptr + 0, ptr + 1, ptr + 3);
903template <
int DIM,
class T>
908 full(
i,
j) = symm(
i,
j);
917template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class DL,
921template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class M>
924 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
925 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
926 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
927 constexpr int stride = S == -1 ? tensor_size : S;
929 stride % tensor_size == 0,
930 "getFTensor3FromMat: stride should be a multiple of tensor_size");
933 if (data.size2() != tensor_size) {
935 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
936 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
937 boost::lexical_cast<std::string>(Tensor_Dim2) +
938 ">: wrong size of columns in data matrix, should be " +
939 boost::lexical_cast<std::string>(tensor_size) +
" but is " +
940 boost::lexical_cast<std::string>(data.size2()));
942 auto *first = &data(rr + 0, cc + 0);
943 auto *last = &data(rr + 0, cc + 0 + tensor_size - 1);
944 if (last - first != tensor_size - 1)
946 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
947 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
948 boost::lexical_cast<std::string>(Tensor_Dim2) +
949 ">: row slice is not contiguous");
952 Tensor_Dim1, Tensor_Dim2>{&data(rr + 0, cc + 0)};
956template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class M>
959 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
960 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
961 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
962 constexpr int stride = S == -1 ? 1 : S;
963 std::array<T *, tensor_size> ptrs;
965 if (data.size1() != tensor_size) {
967 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
968 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
969 boost::lexical_cast<std::string>(Tensor_Dim2) +
970 ">: wrong size of rows in data matrix, should be " +
971 boost::lexical_cast<std::string>(tensor_size) +
" but is " +
972 boost::lexical_cast<std::string>(data.size1()));
975 for (
auto i = 0;
i != tensor_size; ++
i)
976 ptrs[
i] = &data(rr +
i, cc + 0);
978 Tensor_Dim1, Tensor_Dim2>(ptrs);
995template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
996 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1000 M>::get(data, rr, cc);
1003template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
1004 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1008 DL,
M>::get(std::declval<M &>(), 0, 0));
1010template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
1013 int rr = 0,
int cc = 0) {
1015 if (!data_ptr.lock()) {
1017 "Data matrix is not available");
1024template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
1025 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1027 int rr = 0,
int cc = 0) {
1031 "Data matrix is not available");
1045template <
int DIM1,
int DIM2,
int DIM3>
1050 "Such getFTensor3FromPtr is not implemented");
1057 ptr + 0, ptr + 1, ptr + 2, ptr + 3, ptr + 4, ptr + 5, ptr + 6, ptr + 7,
1058 ptr + 8, ptr + 9, ptr + 10, ptr + 11);
1065 ptr + 0, ptr + 1, ptr + 2, ptr + 3, ptr + 4, ptr + 5, ptr + 6, ptr + 7,
1066 ptr + 8, ptr + 9, ptr + 10, ptr + 11, ptr + 12, ptr + 13, ptr + 14,
1067 ptr + 15, ptr + 16, ptr + 17, ptr + 18, ptr + 19, ptr + 20, ptr + 21,
1068 ptr + 22, ptr + 23, ptr + 24, ptr + 25, ptr + 26);
1076template <
int Tensor_Dim01,
int Tensor_Dim2,
int S,
class DL,
class M>
1079template <
int Tensor_Dim01,
int Tensor_Dim2,
int S,
class M>
1083 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1084 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1085 constexpr int symm_size_01 = (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2;
1086 constexpr int dg_size = symm_size_01 * Tensor_Dim2;
1087 constexpr int stride = S == -1 ? dg_size : S;
1089 stride % dg_size == 0,
1090 "getFTensor3DgFromMat: stride should be a multiple of dg_size");
1093 if (data.size2() != dg_size) {
1095 "getFTensor3DgFromMat<" +
1096 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1097 boost::lexical_cast<std::string>(Tensor_Dim2) +
1098 ">: wrong size of data matrix, number of columns should be " +
1099 boost::lexical_cast<std::string>(dg_size) +
" but is " +
1100 boost::lexical_cast<std::string>(data.size2()));
1102 auto *first = &data(rr + 0, cc + 0);
1103 auto *last = &data(rr + 0, cc + 0 + dg_size - 1);
1104 if (last - first != dg_size - 1)
1106 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1107 boost::lexical_cast<std::string>(Tensor_Dim2) +
1108 ">: row slice is not contiguous");
1111 Tensor_Dim2>{&data(rr + 0, cc + 0)};
1115template <
int S,
class M>
1118 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1119 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1120 constexpr int stride = S == -1 ? 1 : S;
1123 constexpr int dg_size = 1;
1124 if (data.size1() != dg_size)
1126 "getFTensor3DgFromMat<1, 1>: wrong size of data matrix, number "
1127 "of rows should be 1 but is " +
1128 boost::lexical_cast<std::string>(data.size1()));
1131 &data(rr + 0, cc + 0)};
1135template <
int S,
class M>
1138 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1139 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1140 constexpr int stride = S == -1 ? 1 : S;
1142 constexpr int dg_size = 6;
1143 if (data.size1() != dg_size) {
1145 "getFTensor3DgFromMat<2, 2>: wrong size of data matrix, number "
1146 "of rows should be 6 but is " +
1147 boost::lexical_cast<std::string>(data.size1()));
1151 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1152 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0)};
1156template <
int S,
class M>
1159 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1160 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1161 constexpr int stride = S == -1 ? 1 : S;
1163 constexpr int dg_size = 18;
1164 if (data.size1() != dg_size) {
1166 "getFTensor3DgFromMat<3, 3>: wrong size of data matrix, number "
1167 "of rows should be 18 but is " +
1168 boost::lexical_cast<std::string>(data.size1()));
1172 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1173 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
1174 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0),
1175 &data(rr + 9, cc + 0), &data(rr + 10, cc + 0), &data(rr + 11, cc + 0),
1176 &data(rr + 12, cc + 0), &data(rr + 13, cc + 0), &data(rr + 14, cc + 0),
1177 &data(rr + 15, cc + 0), &data(rr + 16, cc + 0), &data(rr + 17, cc + 0)};
1193template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1194 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1201template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1202 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1206 std::declval<M &>(), 0, 0));
1208template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1213 if (!data_ptr.lock()) {
1215 "Data matrix is not available");
1222template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1223 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1229 "Data matrix is not available");
1236template <
int Tensor_Dim01,
int Tensor_Dim2,
int S,
class T =
double>
1238 constexpr auto dg_size =
1239 ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) * Tensor_Dim2;
1243 decltype(matrix_data)>::get(matrix_data);
1251template <
class T,
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
1252 int Tensor_Dim3,
int S, std::size_t... Is>
1254 const std::array<T *, Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3>
1256 std::index_sequence<Is...>) {
1258 Tensor_Dim2, Tensor_Dim3>(ptrs[Is]...);
1261template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1262 int S,
class DL,
class M>
1264 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1265 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1266 constexpr int tensor_size =
1267 Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3;
1268 constexpr int stride =
1269 S == -1 ? (DL::isGaussByCoeffs ? tensor_size : 1) : S;
1270 if constexpr (DL::isGaussByCoeffs) {
1272 stride % tensor_size == 0,
1273 "getFTensor4FromMat: stride should be a multiple of tensor_size");
1276 if (data.size2() != tensor_size) {
1278 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
1279 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
1280 boost::lexical_cast<std::string>(Tensor_Dim2) +
"," +
1281 boost::lexical_cast<std::string>(Tensor_Dim3) +
1282 ">: wrong size of columns in data matrix, should be " +
1283 boost::lexical_cast<std::string>(tensor_size) +
1285 boost::lexical_cast<std::string>(data.size2()));
1287 auto *first = &data(rr + 0, cc + 0);
1288 auto *last = &data(rr + 0, cc + 0 + tensor_size - 1);
1289 if (last - first != tensor_size - 1) {
1291 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
1292 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
1293 boost::lexical_cast<std::string>(Tensor_Dim2) +
"," +
1294 boost::lexical_cast<std::string>(Tensor_Dim3) +
1295 ">: row slice is not contiguous");
1299 Tensor_Dim1, Tensor_Dim2, Tensor_Dim3>{
1300 &data(rr + 0, cc + 0)};
1301 }
else if constexpr (DL::isCoeffsByGauss) {
1302 std::array<T *, tensor_size> ptrs;
1304 if (data.size1() != tensor_size) {
1306 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
1307 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
1308 boost::lexical_cast<std::string>(Tensor_Dim2) +
"," +
1309 boost::lexical_cast<std::string>(Tensor_Dim3) +
1310 ">: wrong size of rows in data matrix, should be " +
1311 boost::lexical_cast<std::string>(tensor_size) +
1313 boost::lexical_cast<std::string>(data.size1()));
1316 for (
auto i = 0;
i != tensor_size; ++
i)
1317 ptrs[
i] = &data(rr +
i, cc + 0);
1319 Tensor_Dim3, stride>(
1320 ptrs, std::make_index_sequence<tensor_size>{});
1322 static_assert(!std::is_same<M, M>::value,
1323 "Unsupported data layout for getFTensor4FromMatImpl");
1341template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1342 int S = -1,
class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1346 Tensor_Dim3, S, DL,
M>::get(data);
1349template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1350 int S = -1,
class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1355 M>::get(std::declval<M &>(), 0, 0));
1357template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1361 if (!data_ptr.lock()) {
1363 "Data matrix is not available");
1371template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1372 int S = -1,
class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1378 "Data matrix is not available");
1386template <
int DIM1,
int DIM2,
int DIM3,
int DIM4,
int S = -1,
class T =
double>
1391 decltype(matrix_data)>::get(matrix_data);
1399template <
int Tensor_Dim01,
int Tensor_Dim23,
int S,
class DL,
class M>
1402template <
int Tensor_Dim01,
int Tensor_Dim23,
int S,
class M>
1406 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1407 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1408 constexpr int symm_size_01 = (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2;
1409 constexpr int symm_size_23 = (Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2;
1410 constexpr int ddg_size = symm_size_01 * symm_size_23;
1411 constexpr int stride = S == -1 ? ddg_size : S;
1413 stride % ddg_size == 0,
1414 "Stride should be a multiple of the size of the symmetric tensor");
1417 if (data.size2() != ddg_size) {
1419 "getFTensor4DdgFromMat<" +
1420 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1421 boost::lexical_cast<std::string>(Tensor_Dim23) +
1422 ">: wrong size of data matrix, number of columns should be " +
1423 boost::lexical_cast<std::string>(ddg_size) +
" but is " +
1424 boost::lexical_cast<std::string>(data.size2()));
1426 auto *first = &data(rr + 0, cc + 0);
1427 auto *last = &data(rr + 0, cc + 0 + ddg_size - 1);
1428 if (last - first != ddg_size - 1)
1430 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1431 boost::lexical_cast<std::string>(Tensor_Dim23) +
1432 ">: row slice is not contiguous");
1435 Tensor_Dim23>{&data(rr + 0, cc + 0)};
1439template <
int S,
class M>
1442 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1443 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1444 constexpr int stride = S == -1 ? 1 : S;
1446 constexpr int ddg_size = 1;
1447 if (data.size1() != ddg_size)
1449 "getFTensor4DdgFromMat<1, 1>: wrong size of data matrix, number "
1450 "of rows should be 1 but is " +
1451 boost::lexical_cast<std::string>(data.size1()));
1454 &data(rr + 0, cc + 0)};
1458template <
int S,
class M>
1461 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1462 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1463 constexpr int stride = S == -1 ? 1 : S;
1465 constexpr int ddg_size = 9;
1466 if (data.size1() != ddg_size) {
1468 "getFTensor4DdgFromMat<2, 2>: wrong size of data matrix, number "
1469 "of rows should be 9 but is " +
1470 boost::lexical_cast<std::string>(data.size1()));
1474 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1475 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
1476 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0)};
1480template <
int S,
class M>
1483 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1484 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1485 constexpr int stride = S == -1 ? 1 : S;
1487 constexpr int ddg_size = 36;
1488 if (data.size1() != ddg_size) {
1490 "getFTensor4DdgFromMat<3, 3>: wrong size of data matrix, number "
1491 "of rows should be 36 but is " +
1492 boost::lexical_cast<std::string>(data.size1()));
1496 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1497 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
1498 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0),
1499 &data(rr + 9, cc + 0), &data(rr + 10, cc + 0), &data(rr + 11, cc + 0),
1500 &data(rr + 12, cc + 0), &data(rr + 13, cc + 0), &data(rr + 14, cc + 0),
1501 &data(rr + 15, cc + 0), &data(rr + 16, cc + 0), &data(rr + 17, cc + 0),
1502 &data(rr + 18, cc + 0), &data(rr + 19, cc + 0), &data(rr + 20, cc + 0),
1503 &data(rr + 21, cc + 0), &data(rr + 22, cc + 0), &data(rr + 23, cc + 0),
1504 &data(rr + 24, cc + 0), &data(rr + 25, cc + 0), &data(rr + 26, cc + 0),
1505 &data(rr + 27, cc + 0), &data(rr + 28, cc + 0), &data(rr + 29, cc + 0),
1506 &data(rr + 30, cc + 0), &data(rr + 31, cc + 0), &data(rr + 32, cc + 0),
1507 &data(rr + 33, cc + 0), &data(rr + 34, cc + 0), &data(rr + 35, cc + 0)};
1522template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1523 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1530template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1531 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1535 M>::get(std::declval<M &>(), 0, 0));
1537template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1543 "Data matrix is not available");
1550template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1551 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1557 "Data matrix is not available");
1564template <
int Tensor_Dim01,
int Tensor_Dim23,
int S,
class T =
double>
1566 constexpr auto symm_size01 = (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2;
1567 constexpr auto symm_size23 = (Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2;
1568 constexpr auto symm_size = symm_size01 * symm_size23;
1572 decltype(matrix_data)>::get(matrix_data);
1583template <
class T,
int S,
int Tensor_Dim>
1588 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1589 if (
m.size1() != nb_integration_pts ||
m.size2() != Tensor_Dim) {
1590 m.resize(nb_integration_pts, Tensor_Dim,
false);
1600 [[maybe_unused]]
const size_t nb_integration_pts) {
1602 if (S == -1 || S == Tensor_Dim) {
1603 if (
m.size1() != nb_integration_pts) {
1606 "Matrix size is not compatible with the number of "
1607 "integration points: expected " +
1608 boost::lexical_cast<std::string>(nb_integration_pts) +
1609 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1621template <
class T,
int S,
int Tensor_Dim0,
int Tensor_Dim1>
1623 FTensor::Tensor2<FTensor::CursorPtr<T *, S>, Tensor_Dim0, Tensor_Dim1>,
1626 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1627 if (
m.size1() != nb_integration_pts ||
1628 m.size2() != Tensor_Dim0 * Tensor_Dim1) {
1629 m.resize(nb_integration_pts, Tensor_Dim0 * Tensor_Dim1,
false);
1639 [[maybe_unused]]
const size_t nb_integration_pts) {
1641 if (S == -1 || S == Tensor_Dim0 * Tensor_Dim1) {
1642 if (
m.size1() != nb_integration_pts) {
1645 "Matrix size is not compatible with the number of "
1646 "integration points: expected " +
1647 boost::lexical_cast<std::string>(nb_integration_pts) +
1648 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1660template <
class T,
int S,
int Tensor_Dim>
1662 FTensor::Tensor2_symmetric<FTensor::CursorPtr<T *, S>, Tensor_Dim>,
1665 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1666 constexpr int symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
1667 if (
m.size1() != nb_integration_pts ||
m.size2() != symm_size) {
1668 m.resize(nb_integration_pts, symm_size,
false);
1678 [[maybe_unused]]
const size_t nb_integration_pts) {
1680 constexpr int symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
1681 if (S == -1 || S == symm_size) {
1682 if (
m.size1() != nb_integration_pts) {
1685 "Matrix size is not compatible with the number of "
1686 "integration points: expected " +
1687 boost::lexical_cast<std::string>(nb_integration_pts) +
1688 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1700template <
class T,
int S,
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2>
1702 Tensor_Dim0, Tensor_Dim1, Tensor_Dim2>,
1705 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1706 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
1707 if (
m.size1() != nb_integration_pts ||
m.size2() != tensor_size) {
1708 m.resize(nb_integration_pts, tensor_size,
false);
1718 [[maybe_unused]]
const size_t nb_integration_pts) {
1720 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
1721 if (S == -1 || S == tensor_size) {
1722 if (
m.size1() != nb_integration_pts) {
1725 "Matrix size is not compatible with the number of "
1726 "integration points: expected " +
1727 boost::lexical_cast<std::string>(nb_integration_pts) +
1728 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1740template <
class T,
int S,
int Tensor_Dim01,
int Tensor_Dim2>
1742 FTensor::Dg<FTensor::CursorPtr<T *, S>, Tensor_Dim01, Tensor_Dim2>,
1745 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1746 constexpr int dg_size =
1747 ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) * Tensor_Dim2;
1748 if (
m.size1() != nb_integration_pts ||
m.size2() != dg_size) {
1749 m.resize(nb_integration_pts, dg_size,
false);
1753 Tensor_Dim01, Tensor_Dim2, S,
1759 [[maybe_unused]]
const size_t nb_integration_pts) {
1761 constexpr int dg_size =
1762 ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) * Tensor_Dim2;
1763 if (S == -1 || S == dg_size) {
1764 if (
m.size1() != nb_integration_pts) {
1767 "Matrix size is not compatible with the number of "
1768 "integration points: expected " +
1769 boost::lexical_cast<std::string>(nb_integration_pts) +
1770 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1776 Tensor_Dim01, Tensor_Dim2, S,
1782template <
class T,
int S,
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
1785 FTensor::Tensor4<FTensor::CursorPtr<T *, S>, Tensor_Dim0, Tensor_Dim1,
1786 Tensor_Dim2, Tensor_Dim3>,
1789 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1790 constexpr int tensor_size =
1791 Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3;
1792 if (
m.size1() != nb_integration_pts ||
m.size2() != tensor_size) {
1793 m.resize(nb_integration_pts, tensor_size,
false);
1797 Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3, S,
1803 [[maybe_unused]]
const size_t nb_integration_pts) {
1805 if (S == -1 || S == Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3) {
1806 if (
m.size1() != nb_integration_pts) {
1809 "Matrix size is not compatible with the number of "
1810 "integration points: expected " +
1811 boost::lexical_cast<std::string>(nb_integration_pts) +
1812 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1818 Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3, S,
1824template <
class T,
int S,
int Tensor_Dim01,
int Tensor_Dim23>
1826 FTensor::Ddg<FTensor::CursorPtr<T *, S>, Tensor_Dim01, Tensor_Dim23>,
1829 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1830 constexpr int ddg_size = ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) *
1831 ((Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2);
1832 if (
m.size1() != nb_integration_pts ||
m.size2() != ddg_size) {
1833 m.resize(nb_integration_pts, ddg_size,
false);
1837 Tensor_Dim01, Tensor_Dim23, S,
1843 [[maybe_unused]]
const size_t nb_integration_pts) {
1845 constexpr int ddg_size = ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) *
1846 ((Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2);
1847 if (S == -1 || S == ddg_size) {
1849 if (
m.size1() != nb_integration_pts) {
1852 "Matrix size is not compatible with the number of "
1853 "integration points: expected " +
1854 boost::lexical_cast<std::string>(nb_integration_pts) +
1855 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1861 Tensor_Dim01, Tensor_Dim23, S,
1876 if constexpr (DIM == 3) {
1877 return std::array<double, 9>{t_mat(0, 0), t_mat(1, 1), t_mat(2, 2),
1878 t_mat(0, 1), t_mat(1, 0), t_mat(0, 2),
1879 t_mat(2, 0), t_mat(1, 2), t_mat(2, 1)};
1881 return std::array<double, 5>{t_mat(0, 0), t_mat(1, 1), 1.0, t_mat(0, 1),
1887 constexpr double sqr2 = boost::math::constants::root_two<double>();
1889 if constexpr (DIM == 3) {
1890 return std::array<double, 9>{t_mat(0, 0),
1900 return std::array<double, 4>{t_mat(0, 0), t_mat(1, 1), 0.0,
1901 sqr2 * t_mat(0, 1)};
1905template <
typename T>
1907 array<double, 5> vec{t_mat(0, 0), t_mat(1, 1), 1. + hoop_term, t_mat(0, 1),
1913template <
typename T>
1915 constexpr double sqr2 = boost::math::constants::root_two<double>();
1917 array<double, 4> vec_sym{t_mat(0, 0), t_mat(1, 1), hoop_term,
1918 sqr2 * t_mat(0, 1)};
1937 const size_t M = mat.size1();
1938 const size_t N = mat.size2();
1942 "The input matrix for inverse computation is not square %zu != %zu",
1945 int *ipv =
new int[
N];
1947 double *
work =
new double[lwork];
1956 "lapack error info = %d", info);
1973 const size_t M = mat.size1();
1974 const size_t N = mat.size2();
1976 if (
M == 0 ||
M !=
N)
1978 "The input matrix for inverse computation is not square %zu != %zu",
1985 int *ipiv =
new int[
M];
1987 &*f.data().begin(),
M);
1990 "error lapack solve dgesv info = %d", info);
2008 auto mat_copy = mat;
2014template <
typename T =
double>
inline bool isEq(
const T
a,
const T b) {
2015 const double eps = 100 * std::numeric_limits<T>::epsilon();
2016 const auto abs_max =
2017 std::max(
static_cast<T
>(1), std::max(std::abs(
a), std::abs(b)));
2018 return std::abs(
a - b) <=
eps * abs_max;
2021template <
int DIM,
typename T =
double>
2026template <
int DIM1,
int DIM2,
typename T =
double>
2038template <
int DIM,
typename T =
double>
2040 std::array<double, DIM> tmp;
2041 std::copy(vec.data().begin(), vec.data().begin() + DIM, tmp.begin());
2042 std::sort(tmp.begin(), tmp.end());
2043 std::size_t n_unique = 1;
2044 for (
int i = 1;
i < DIM; ++
i) {
2045 if (!
isEq(tmp[
i], tmp[
i - 1])) {
2052template <
int DIM,
typename T =
double>
2056 if constexpr (DIM == 2) {
2059 static_assert(DIM == 2 || DIM == 3,
"That works only for DIM = 3");
2061 int i = 0,
j = 1,
k = 2;
2062 if (isEq<T>(eig(0), eig(1))) {
2066 }
else if (isEq<T>(eig(0), eig(2))) {
2070 }
else if (isEq<T>(eig(1), eig(2))) {
2075 const std::array<T, 9> eigen_vec_c{
2076 eigen_vec(
i, 0), eigen_vec(
i, 1), eigen_vec(
i, 2),
2077 eigen_vec(
j, 0), eigen_vec(
j, 1), eigen_vec(
j, 2),
2078 eigen_vec(
k, 0), eigen_vec(
k, 1), eigen_vec(
k, 2)};
2079 const std::array<T, 3> eig_c{eig(
i), eig(
j), eig(
k)};
2080 std::copy(eigen_vec_c.begin(), eigen_vec_c.end(), eigen_vec.data().begin());
2081 std::copy(eig_c.begin(), eig_c.end(), eig.data().begin());
2085template <
int DIM,
typename T =
double>
2090template <
int DIM,
typename T =
double>
2118 const size_t M = mat.size1();
2119 const size_t N = mat.size2();
2121 if (
M == 0 ||
M !=
N)
2123 "The input matrix for eigen value computation is not square %zu "
2126 if (eig.size() !=
M)
2127 eig.resize(
M,
false);
2132 const int size = (
M + 2) *
M;
2136 if (
lapack_dsyev(
'V',
'U',
n, &*eigen_vec.data().begin(), lda,
2137 &*eig.data().begin(),
work, lwork) > 0)
2139 "The algorithm failed to compute eigenvalues.");
2161template <
int DIM,
typename T1,
typename T2>
2168 const int lda = DIM;
2169 const int lwork = (DIM + 2) * DIM;
2175 "The algorithm failed to compute eigenvalues.");
2195template <
int DIM,
typename T1,
typename T2,
typename T3>
2201 for (
int ii = 0; ii != DIM; ii++)
2202 for (
int jj = 0; jj != DIM; jj++)
2203 eigen_vec(ii, jj) = mat(ii, jj);
2224 return t(0, 0) *
t(1, 1) *
t(2, 2) +
t(1, 0) *
t(2, 1) *
t(0, 2) +
2225 t(2, 0) *
t(0, 1) *
t(1, 2) -
t(0, 0) *
t(2, 1) *
t(1, 2) -
2226 t(2, 0) *
t(1, 1) *
t(0, 2) -
t(1, 0) *
t(0, 1) *
t(2, 2);
2237 return t(0, 0) *
t(1, 1) -
t(0, 1) *
t(1, 0);
2253template <
typename T,
int DIM>
2261template <
typename T,
int DIM>
2270template <
int Tensor_Dim,
class T,
class L,
class A>
2272 ublas::vector<T, A> &det_data,
2273 ublas::matrix<T, L, A> &inv_jac_data) {
2276 "Specialization for this template not yet implemented");
2289template <
class T1,
class T2>
2300template <
class T1,
class T2>
2311template <
class T1,
class T2,
class T3>
2314 const auto a =
t(0, 0), b =
t(0, 1),
c =
t(0, 2);
2315 const auto d =
t(1, 0), e =
t(1, 1), f =
t(1, 2);
2316 const auto g =
t(2, 0),
h =
t(2, 1),
i =
t(2, 2);
2317 const auto inv_det = 1.0 / det;
2318 inv_t(0, 0) = (e *
i - f *
h) * inv_det;
2319 inv_t(0, 1) = (
c *
h - b *
i) * inv_det;
2320 inv_t(0, 2) = (b * f -
c * e) * inv_det;
2321 inv_t(1, 0) = (f *
g - d *
i) * inv_det;
2322 inv_t(1, 1) = (
a *
i -
c *
g) * inv_det;
2323 inv_t(1, 2) = (
c * d -
a * f) * inv_det;
2324 inv_t(2, 0) = (d *
h - e *
g) * inv_det;
2325 inv_t(2, 1) = (b *
g -
a *
h) * inv_det;
2326 inv_t(2, 2) = (
a * e - b * d) * inv_det;
2334template <
class T1,
class T2,
class T3>
2337 const auto a =
t(0, 0);
2338 const auto b =
t(0, 1);
2339 const auto c =
t(1, 0);
2340 const auto d =
t(1, 1);
2341 inv_t(0, 0) = d / det;
2342 inv_t(0, 1) = -b / det;
2343 inv_t(1, 0) = -
c / det;
2344 inv_t(1, 1) =
a / det;
2352template <
typename T1,
typename T2,
typename T3>
2357 const auto a =
t(0, 0);
2358 const auto b =
t(0, 1);
2359 const auto c =
t(0, 2);
2360 const auto d =
t(1, 1);
2361 const auto e =
t(1, 2);
2362 const auto f =
t(2, 2);
2363 const auto inv_det = 1.0 / det;
2364 inv_t(0, 0) = (d * f - e * e) * inv_det;
2365 inv_t(0, 1) = (
c * e - b * f) * inv_det;
2366 inv_t(0, 2) = (b * e -
c * d) * inv_det;
2367 inv_t(1, 1) = (
a * f -
c *
c) * inv_det;
2368 inv_t(1, 2) = (b *
c -
a * e) * inv_det;
2369 inv_t(2, 2) = (
a * d - b * b) * inv_det;
2377template <
typename T1,
typename T2,
typename T3>
2382 const auto a =
t(0, 0);
2383 const auto b =
t(0, 1);
2384 const auto d =
t(1, 1);
2385 const auto inv_det = 1.0 / det;
2386 inv_t(0, 0) = d * inv_det;
2387 inv_t(0, 1) = -b * inv_det;
2388 inv_t(1, 1) =
a * inv_det;
2392template <
typename T1,
typename T2,
typename T3,
int DIM>
2395template <
typename T1,
typename T2,
typename T3>
2402template <
typename T1,
typename T2,
typename T3>
2409template <
typename T1,
typename T2,
typename T3,
int DIM>
2418template <
typename T1,
typename T2,
typename T3,
int DIM>
2424 DIM>::invert(
t, det, inv_t);
2437 template <
typename Iterator>
2438 static inline EntityHandle
extract(
const Iterator &it) {
2439 return (*it)->getEnt();
2461template <
typename Extractor,
typename Iterator>
2463 Iterator end_iter) {
2464 moab::Range::iterator hint = r.begin();
2465 while (begin_iter != end_iter) {
2467 auto bi = Extractor::extract(begin_iter);
2468 Iterator pj = begin_iter;
2469 while (pj != end_iter && (bi +
j) == Extractor::extract(pj)) {
2473 hint = r.insert(hint, bi, bi + (
j - 1));
2497template <
typename MI,
typename MO = Modify_change_nothing>
2501 for (
auto it = mi.begin(); it != mi.end(); ++it) {
2502 if (!
const_cast<MI &
>(mi).modify(it, mo))
2504 "Houston we have a problem");
2532 return boost::make_shared<TempMeshset>(moab);
2589template <
typename I>
2596 if (tester(first)) {
2598 auto second = first;
2601 while (second != s) {
2608 CHKERR inserter(first, second);
2634template <
typename Dest = void,
typename... Arg>
2636 if constexpr (std::is_same<void, Dest>::value)
2637 return std::array<std::common_type_t<std::decay_t<Arg>...>,
sizeof...(Arg)>{
2638 {std::forward<Arg>(arg)...}};
2640 return std::array<Dest,
sizeof...(Arg)>{{std::forward<Arg>(arg)...}};
2668#define FTENSOR_INDEX(DIM, I) I##_FTIndex<DIM> I;
2670#define FTENSOR_INDEX_DECL(r, DIM, I) FTENSOR_INDEX(DIM, I)
2672#define FTENSOR_INDEXES(DIM, ...) \
2673 BOOST_PP_SEQ_FOR_EACH(FTENSOR_INDEX_DECL, DIM, \
2674 BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
SmartPetscObj< Vec > work
#define MOAB_THROW(err)
Check error code of MoAB function and throw MoFEM exception.
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_OPERATION_UNSUCCESSFUL
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double n
refractive index of diffusive medium
static __CLPK_integer lapack_dgesv(__CLPK_integer n, __CLPK_integer nrhs, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_integer *ipiv, __CLPK_doublereal *b, __CLPK_integer ldb)
static __CLPK_integer lapack_dgetrf(__CLPK_integer m, __CLPK_integer n, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_integer *ipiv)
static __CLPK_integer lapack_dsyev(char jobz, char uplo, __CLPK_integer n, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_doublereal *w, __CLPK_doublereal *work, __CLPK_integer lwork)
static __CLPK_integer lapack_dgetri(__CLPK_integer n, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_integer *ipiv, __CLPK_doublereal *work, __CLPK_integer lwork)
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
Tensors class implemented by Walter Landry.
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITFIELDID_SIZE > BitFieldId
Field Id.
ublas::vector< T, ublas::shallow_array_adaptor< T > > VectorShallowArrayAdaptor
UBlasMatrix< double > MatrixDouble
UBlasMatrix< adouble > MatrixADouble
ublas::matrix< T, ublas::row_major, ublas::shallow_array_adaptor< T > > MatrixShallowArrayAdaptor
UBlasVector< double > VectorDouble
implementation of Data Operators for Forces and Sources
auto getVectorAdaptor(T1 ptr, const size_t n)
Get Vector adaptor.
auto type_from_handle(const EntityHandle h)
get type from entity handle
static auto getFTensor4FromMat(M &data)
Get tensor rank 4 (non symmetric) form data matrix.
decltype(GetFTensor2SymmetricFromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2SymmetricFromMatType
auto sortEigenVals(VectorShallowArrayAdaptor< T > eig, MatrixShallowArrayAdaptor< T > eigen_vec, FTensor::Number< DIM >)
auto getVoigtVecAxisymm(T &t_mat, const double hoop_term)
auto getFTensor2FromMat(M &data)
Get tensor rank 2 (matrix) form data matrix.
bool isEq(const T a, const T b)
auto to_non_symm(const FTensor::Tensor2_symmetric< T, DIM > &symm)
static auto getFTensor3FromMat(M &data, int rr=0, int cc=0)
Get tensor rank 3 (non symmetries) form data matrix.
auto getFTensor2SymmetricLowerFromPtr< 3 >(double *ptr)
auto getFTensor2SymmetricFromPtr(double *ptr)
auto getFTensor2SymmetricLowerFromPtr< 2 >(double *ptr)
FTensor::Tensor3< FTensor::PackPtr< double *, 12 >, 3, 2, 2 > getFTensor3FromPtr< 3, 2, 2 >(double *ptr)
auto getVoigtVec(T &t_mat)
MoFEMErrorCode reconstructMultiIndex(const MI &mi, MO &&mo=Modify_change_nothing())
Template used to reconstruct multi-index.
auto getUniqNb(VectorShallowArrayAdaptor< T > vec, FTensor::Number< DIM >)
Get the Uniq Nb objects.
auto getFTensor2FromVec(VectorDouble &data)
moab::Range::iterator insertOrdered(Range &r, Extractor, Iterator begin_iter, Iterator end_iter)
Insert ordered mofem multi-index into range.
decltype(GetFTensor4FromMatImpl< Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor4FromMatType
MoFEMErrorCode invertTensor2by2(T1 &t, T2 &det, T3 &inv_t)
Calculate matrix inverse 2 by 2.
static auto getFTensor2SymmetricFromMat(M &data)
Get symmetric tensor rank 2 (matrix) form data matrix.
MoFEMErrorCode computeMatrixInverse(MatrixDouble &mat)
compute matrix inverse with lapack dgetri
auto getFTensor1FromArrayDiag(MatrixDouble &data, const size_t rr)
Get FTensor1 from array.
auto getFTensor2HVecFromPtr< 3, 2 >(double *ptr)
auto id_from_handle(const EntityHandle h)
static auto getFTensor3DgFromPtr(T *ptr)
auto getFTensor1FromArray(T &data)
auto convertToShallow(FTensor::Tensor1< T, DIM > &vec)
auto dimension_from_handle(const EntityHandle h)
get entity dimension form handle
auto getFTensor1FromArrayDiag< 2, 2 >(MatrixDouble &data, const size_t rr)
MoFEMErrorCode solveLinearSystem(MatrixDouble &mat, VectorDouble &f)
solve linear system with lapack dgesv
static auto determinantTensor2by2(T &t)
Calculate the determinant of a 2x2 matrix or a tensor of rank 2.
auto getFTensor2HVecFromPtr(double *ptr)
Make Tensor2 for HVec base from pointer.
auto type_name_from_handle(const EntityHandle h)
get entity type name from handle
static auto getFTensor3DgFromMat(M &data)
Get symmetric tensor rank 3 on the first two indices from form data matrix.
auto getFTensor2HVecFromPtr< 3, 3 >(double *ptr)
MoFEMErrorCode invertTensor3by3(ublas::matrix< T, L, A > &jac_data, ublas::vector< T, A > &det_data, ublas::matrix< T, L, A > &inv_jac_data)
Calculate inverse of tensor rank 2 at integration points.
decltype(GetFTensor4DdgFromMatImpl< Tensor_Dim01, Tensor_Dim23, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor4DdgFromMatType
MoFEMErrorCode invertTensor3by3< 3, double, ublas::row_major, DoubleAllocator >(MatrixDouble &jac_data, VectorDouble &det_data, MatrixDouble &inv_jac_data)
auto getFTensor1FromPtr(T *ptr)
static MoFEMErrorCode invertTensor(FTensor::Tensor2< T1, DIM, DIM > &t, T2 &det, FTensor::Tensor2< T3, DIM, DIM > &inv_t)
static auto getFTensor4DdgFromPtr(T *ptr)
constexpr auto make_array(Arg &&...arg)
Create Array.
auto getMatrixAdaptor(T1 ptr, const size_t n, const size_t m)
Get Matrix adaptor.
auto getFTensor1FromMat(M &data, int rr=0, int cc=0)
Get tensor rank 1 (vector) form data matrix.
auto getFTensor4FromPtr(T *ptr)
auto getFTensor2FromArray(MatrixDouble &data, const size_t rr, const size_t cc=0)
static auto determinantTensor(FTensor::Tensor2< T, DIM, DIM > &t)
Calculate the determinant of a tensor of rank DIM.
auto field_bit_from_bit_number(const int bit_number)
get field bit id from bit number
static auto getFTensor0FromPtr(T *ptr)
Get tensor rank 0 (scalar) from pointer.
std::string toString(X x)
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
auto getFTensor2SymmetricLowerFromPtr(double *ptr)
Make symmetric Tensor2 from pointer, taking lower triangle of matrix.
static auto getFTensor4DdgFromMat(M &data)
Get symmetric tensor rank 4 on first two and last indices from form data matrix.
auto getFTensor2FromPtr(double *ptr)
auto getVoigtVecSymm(T &t_mat)
static auto makeFTensor4FromPtrArray(const std::array< T *, Tensor_Dim0 *Tensor_Dim1 *Tensor_Dim2 *Tensor_Dim3 > &ptrs, std::index_sequence< Is... >)
auto getFTensor0FromMat(M &data)
Get tensor rank 0 (scalar) form data vector.
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
decltype(GetFTensor3DgFromMatImpl< Tensor_Dim01, Tensor_Dim2, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor3DgFromMatType
MoFEMErrorCode computeEigenValuesSymmetric(const MatrixDouble &mat, VectorDouble &eig, MatrixDouble &eigen_vec)
compute eigenvalues of a symmetric matrix using lapack dsyev
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
FTensor::Tensor3< FTensor::PackPtr< double *, 27 >, 3, 3, 3 > getFTensor3FromPtr< 3, 3, 3 >(double *ptr)
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
decltype(GetFTensor3FromMatImpl< Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor3FromMatType
auto getVoigtVecSymmAxisymm(T &t_mat, const double hoop_term)
FTensor::Tensor3< FTensor::PackPtr< double *, DIM1 *DIM2 *DIM3 >, DIM1, DIM2, DIM3 > getFTensor3FromPtr(double *ptr)
decltype(GetFTensor2FromMatImpl< Tensor_Dim0, Tensor_Dim1, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2FromMatType
auto rangeInserter(const I f, const I s, boost::function< bool(I it)> tester, boost::function< MoFEMErrorCode(I f, I s)> inserter)
Insert ranges.
auto getFTensor1FromArrayDiag< 3, 3 >(MatrixDouble &data, const size_t rr)
auto ent_form_type_and_id(const EntityType type, const EntityID id)
get entity handle from type and id
constexpr IntegrationType I
constexpr double t
plate stiffness
FTensor::Index< 'm', 3 > m
bool operator()(const id_type &valueA, const id_type &valueB) const
static auto get(M &data, int rr, int cc)
static auto get(M &data, int rr, int cc)
static auto get(M &data, int rr, int cc)
static auto get(M &data, int rr, int cc)
static auto get(M &data, int rr, int cc)
static auto get(M &data, int rr, int cc)
static auto get(M &data, int rr, int cc)
static auto get(M &data, const size_t rr, const size_t cc=0)
static auto make(M &data, const size_t rr, const size_t cc, std::index_sequence< Is... >)
GetFTensor2FromArrayImpl()=delete
static auto get(M &data, const size_t rr, const size_t cc, const int ss=0)
GetFTensor2FromArrayRawPtrImpl()=delete
static auto get(M &data, const size_t rr, const size_t cc, const int ss=0)
GetFTensor2FromArrayRawPtrImpl()=delete
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
static auto get(M &data, int rr=0, int cc=0)
unsigned int operator()(const id_type &value) const
static MoFEMErrorCode invert(T1 &t, T2 &det, T3 &inv_t)
static MoFEMErrorCode invert(T1 &t, T2 &det, T3 &inv_t)
result_type operator()(Arg &arg) const
KeyFromKey(const KeyExtractor1 &key1_=KeyExtractor1(), const KeyExtractor2 &key2_=KeyExtractor2())
KeyExtractor1::result_type result_type
bool operator()(const id_type &valueA, const id_type &valueB) const
static auto get(M &m, const size_t nb_integration_pts)
static auto size(M &m, const size_t nb_integration_pts)
static auto size(M &m, const size_t nb_integration_pts)
static auto get(M &m, const size_t nb_integration_pts)
static auto size(M &m, const size_t nb_integration_pts)
static auto get(M &m, const size_t nb_integration_pts)
static auto get(M &m, const size_t nb_integration_pts)
static auto size(M &m, const size_t nb_integration_pts)
static auto get(M &m, const size_t nb_integration_pts)
static auto size(M &m, const size_t nb_integration_pts)
static auto get(M &m, const size_t nb_integration_pts)
static auto size(M &m, const size_t nb_integration_pts)
static auto size(M &m, const size_t nb_integration_pts)
static auto get(M &m, const size_t nb_integration_pts)
Do nothing, used to rebuild database.
Modify_change_nothing()=default
TempMeshset(moab::Interface &moab)