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) {
238 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
239 constexpr int stride = S == -1 ? Tensor_Dim : S;
241 stride % Tensor_Dim == 0,
242 "getFTensor1FromMat: stride should be a multiple of Tensor_Dim");
245 if (data.size2() != Tensor_Dim)
247 "getFTensor1FromMat<" + boost::lexical_cast<std::string>(Tensor_Dim) +
248 ">: wrong size of data matrix, number of columns should be " +
249 boost::lexical_cast<std::string>(Tensor_Dim) +
" but is " +
250 boost::lexical_cast<std::string>(data.size2()));
251 auto *first = &data(rr + 0, cc + 0);
252 auto *last = &data(rr + 0, cc + 0 + Tensor_Dim - 1);
253 if (last - first != Tensor_Dim - 1)
255 boost::lexical_cast<std::string>(Tensor_Dim) +
256 ">: row slice is not contiguous");
260 &data(rr + 0, cc + 0));
264template <
int S,
class M>
267 static inline auto get(
M &data,
int rr,
int cc) {
268 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
269 constexpr int stride = S == -1 ? 1 : S;
272 if (data.size1() % 3 != 0)
274 "getFTensor1FromMat<3>: wrong size of data matrix, number of "
275 "rows modulo of 3 but is " +
276 boost::lexical_cast<std::string>(data.size1()));
279 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0));
283template <
int S,
class M>
286 static inline auto get(
M &data,
int rr,
int cc) {
287 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
288 constexpr int stride = S == -1 ? 1 : S;
290 if (data.size1() % 4 != 0)
292 "getFTensor1FromMat<4>: wrong size of data matrix, number of "
293 "rows should be 4 but is " +
294 boost::lexical_cast<std::string>(data.size1()));
297 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
298 &data(rr + 3, cc + 0));
302template <
int S,
class M>
305 static inline auto get(
M &data,
int rr,
int cc) {
306 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
307 constexpr int stride = S == -1 ? 1 : S;
309 if (data.size1() % 6 != 0)
311 "getFTensor1FromMat<6>: wrong size of data matrix, number of "
312 "rows should be 6 but is " +
313 boost::lexical_cast<std::string>(data.size1()));
316 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
317 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0));
321template <
int S,
class M>
324 static inline auto get(
M &data,
int rr,
int cc) {
325 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
326 constexpr int stride = S == -1 ? 1 : S;
328 if (data.size1() % 9 != 0)
330 "getFTensor1FromMat<9>: wrong size of data matrix, number of "
331 "rows should be 9 but is " +
332 boost::lexical_cast<std::string>(data.size1()));
335 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
336 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
337 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0));
341template <
int S,
class M>
344 static inline auto get(
M &data,
int rr,
int cc) {
345 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
346 constexpr int stride = S == -1 ? 1 : S;
348 if (data.size1() % 2 != 0)
350 "getFTensor1FromMat<2>: wrong size of data matrix, number of "
351 "row should be 2 but is " +
352 boost::lexical_cast<std::string>(data.size1()));
355 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0));
359template <
int S,
class M>
362 static inline auto get(
M &data,
int rr,
int cc) {
363 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
364 constexpr int stride = S == -1 ? 1 : S;
366 &data(rr + 0, cc + 0));
373template <
int Tensor_Dim,
int S = -1,
374 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
380template <
int Tensor_Dim,
int S = -1,
381 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
385 std::declval<M &>(), 0, 0));
387template <
int Tensor_Dim,
int S = -1,
394 "Data matrix is not available");
398 *data.lock(), rr, cc);
401template <
int Tensor_Dim,
int S = -1,
402 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
408 "Data matrix is not available");
415template <
int Tensor_Dim,
int S = Tensor_Dim,
typename T =
double>
420template <
int Tensor_Dim,
int S = Tensor_Dim>
422 return getFTensor1FromPtr<Tensor_Dim, S, std::complex<double>>(ptr);
426template <
int Tensor_Dim,
int S = Tensor_Dim>
428 return getFTensor1FromPtr<Tensor_Dim, S, adouble>(ptr);
432template <
int Tensor_Dim,
int S = Tensor_Dim,
typename T = VectorDouble>
434 static_assert(S % Tensor_Dim == 0,
435 "getFTensor1FromArray(VectorDouble&) requires S to be a "
436 "multiple of Tensor_Dim");
439 if (data.size() % S != 0) {
441 "getFTensor1FromArray: data size should be divisible by "
442 "pack stride dimension");
445 return getFTensor1FromPtr<Tensor_Dim, S>(data.data().data());
458template <
int DIM,
int S>
472 &data(rr + 0, 0), &data(rr + 1, 1), &data(rr + 2, 2)};
480template <
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class DL,
class M>
482 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
483 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
484 constexpr int stride =
485 S == -1 ? (DL::isGaussByCoeffs ? Tensor_Dim1 * Tensor_Dim2 : 1) : S;
486 if constexpr (DL::isGaussByCoeffs) {
487 static_assert(stride % (Tensor_Dim1 * Tensor_Dim2) == 0,
488 "getFTensor2FromMat: stride should be a multiple of "
489 "Tensor_Dim1 * Tensor_Dim2");
492 if (data.size2() != Tensor_Dim1 * Tensor_Dim2) {
494 "getFTensor2FromMat<" +
495 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
496 boost::lexical_cast<std::string>(Tensor_Dim2) +
497 ">: wrong size of columns in data matrix, should be " +
498 boost::lexical_cast<std::string>(Tensor_Dim1 * Tensor_Dim2) +
499 " but is " + boost::lexical_cast<std::string>(data.size2()));
501 auto *first = &data(rr + 0, cc + 0);
502 auto *last = &data(rr + 0, cc + 0 + Tensor_Dim1 * Tensor_Dim2 - 1);
503 if (last - first != Tensor_Dim1 * Tensor_Dim2 - 1) {
505 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
506 boost::lexical_cast<std::string>(Tensor_Dim2) +
507 ">: row slice is not contiguous");
511 Tensor_Dim2>(&data(rr + 0, cc + 0));
512 }
else if constexpr (DL::isCoeffsByGauss) {
513 std::array<T *, Tensor_Dim1 * Tensor_Dim2> ptrs;
515 if (data.size1() != Tensor_Dim1 * Tensor_Dim2) {
517 "getFTensor2FromMat<" +
518 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
519 boost::lexical_cast<std::string>(Tensor_Dim2) +
520 ">: wrong size of rows in data matrix, should be " +
521 boost::lexical_cast<std::string>(Tensor_Dim1 * Tensor_Dim2) +
522 " but is " + boost::lexical_cast<std::string>(data.size1()));
525 for (
auto i = 0;
i != Tensor_Dim1 * Tensor_Dim2; ++
i)
526 ptrs[
i] = &data(rr +
i, cc + 0);
530 static_assert(!std::is_same<M, M>::value,
531 "Unsupported data layout for getFTensor2FromMatImpl");
539template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
540 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
546template <
int Tensor_Dim0,
int Tensor_Dim1,
int S = -1,
547 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
551 std::declval<M &>(), 0, 0));
556template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
560 if (!data_ptr.lock()) {
562 "Data matrix is not available");
572template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
573 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
578 "Data matrix is not available");
585template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1>
589 Tensor_Dim1 * Tensor_Dim2);
592 decltype(matrix_data)>::get(matrix_data);
595template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
596 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
598 if constexpr (DL::isGaussByCoeffs) {
601 decltype(matrix_data)>::get(matrix_data);
602 }
else if constexpr (DL::isCoeffsByGauss) {
605 decltype(matrix_data)>::get(matrix_data);
609template <
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
610 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
612 if constexpr (DL::isGaussByCoeffs) {
615 decltype(matrix_data)>::get(matrix_data);
616 }
else if constexpr (DL::isCoeffsByGauss) {
619 decltype(matrix_data)>::get(matrix_data);
677 inline static auto get(
M &data,
const size_t rr,
const size_t cc) {
678 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
680 &data(rr + 0, cc + 0), &data(rr + 0, cc + 1),
682 &data(rr + 1, cc + 0), &data(rr + 1, cc + 1)};
688 inline static auto get(
M &data,
const size_t rr,
const size_t cc) {
689 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
691 &data(rr + 0, cc + 0), &data(rr + 0, cc + 1), &data(rr + 0, cc + 2),
692 &data(rr + 1, cc + 0), &data(rr + 1, cc + 1), &data(rr + 1, cc + 2),
693 &data(rr + 2, cc + 0), &data(rr + 2, cc + 1), &data(rr + 2, cc + 2)};
699 inline static auto get(
M &data,
const size_t rr,
const size_t cc,
701 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
703 &data(rr + 0, cc + 0), &data(rr + 0, cc + 1),
705 &data(rr + 1, cc + 0), &data(rr + 1, cc + 1), ss);
711 inline static auto get(
M &data,
const size_t rr,
const size_t cc,
713 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
715 &data(rr + 0, cc + 0), &data(rr + 0, cc + 1), &data(rr + 0, cc + 2),
716 &data(rr + 1, cc + 0), &data(rr + 1, cc + 1), &data(rr + 1, cc + 2),
717 &data(rr + 2, cc + 0), &data(rr + 2, cc + 1), &data(rr + 2, cc + 2),
722template <
int DIM1,
int DIM2,
int S>
724 const size_t cc = 0) {
729template <
int DIM1,
int DIM2>
731 const size_t cc,
const int ss) {
737template <
int DIM1,
int DIM2,
int S>
748template <
int Tensor_Dim,
int S,
class DL,
class M>
751template <
int Tensor_Dim,
int S,
class M>
754 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
755 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
756 constexpr int symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
757 constexpr int stride = S == -1 ? symm_size : S;
758 static_assert(stride % symm_size == 0,
759 "getFTensor2SymmetricFromMat: stride should be a multiple of "
763 if (data.size2() != symm_size)
765 "getFTensor2SymmetricFromMat<" +
766 boost::lexical_cast<std::string>(Tensor_Dim) +
767 ">: wrong size of data matrix, number of columns should be " +
768 boost::lexical_cast<std::string>(symm_size) +
" but is " +
769 boost::lexical_cast<std::string>(data.size2()));
770 auto *first = &data(rr + 0, cc + 0);
771 auto *last = &data(rr + 0, cc + 0 + symm_size - 1);
772 if (last - first != symm_size - 1)
774 boost::lexical_cast<std::string>(Tensor_Dim) +
775 ">: row slice is not contiguous");
778 Tensor_Dim>(&data(rr + 0, cc + 0));
782template <
int S,
class M>
785 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
786 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
787 constexpr int stride = S == -1 ? 1 : S;
789 constexpr int symm_size = 6;
790 if (data.size1() != symm_size)
792 "getFTensor2SymmetricFromMat<3>: wrong size of data matrix, "
793 "number of rows should be 6 but is " +
794 boost::lexical_cast<std::string>(data.size1()));
797 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
798 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0));
802template <
int S,
class M>
805 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
806 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
807 constexpr int stride = S == -1 ? 1 : S;
809 constexpr int symm_size = 3;
810 if (data.size1() != symm_size)
812 "getFTensor2SymmetricFromMat<2>: wrong size of data matrix, "
813 "number of rows should be 3 but is " +
814 boost::lexical_cast<std::string>(data.size1()));
817 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0));
824template <
int Tensor_Dim,
int S = -1,
825 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
831template <
int Tensor_Dim,
int S = -1,
832 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
836 std::declval<M &>(), 0, 0));
838template <
int Tensor_Dim,
int S = -1,
843 if (data_ptr.expired()) {
845 "Data matrix is not available");
852template <
int Tensor_Dim,
int S = -1,
853 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
859 "Data matrix is not available");
871 decltype(matrix_data)>::get(matrix_data, 0, 0);
875template <
int Tensor_Dim>
881 decltype(matrix_data)>::get(matrix_data, 0, 0);
904 ptr + 0, ptr + 1, ptr + 3);
908template <
int DIM,
class T>
913 full(
i,
j) = symm(
i,
j);
922template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class DL,
926template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class M>
929 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
930 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
931 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
932 constexpr int stride = S == -1 ? tensor_size : S;
934 stride % tensor_size == 0,
935 "getFTensor3FromMat: stride should be a multiple of tensor_size");
938 if (data.size2() != tensor_size) {
940 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
941 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
942 boost::lexical_cast<std::string>(Tensor_Dim2) +
943 ">: wrong size of columns in data matrix, should be " +
944 boost::lexical_cast<std::string>(tensor_size) +
" but is " +
945 boost::lexical_cast<std::string>(data.size2()));
947 auto *first = &data(rr + 0, cc + 0);
948 auto *last = &data(rr + 0, cc + 0 + tensor_size - 1);
949 if (last - first != tensor_size - 1)
951 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
952 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
953 boost::lexical_cast<std::string>(Tensor_Dim2) +
954 ">: row slice is not contiguous");
957 Tensor_Dim1, Tensor_Dim2>{&data(rr + 0, cc + 0)};
961template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S,
class M>
964 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
965 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
966 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
967 constexpr int stride = S == -1 ? 1 : S;
968 std::array<T *, tensor_size> ptrs;
970 if (data.size1() != tensor_size) {
972 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
973 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
974 boost::lexical_cast<std::string>(Tensor_Dim2) +
975 ">: wrong size of rows in data matrix, should be " +
976 boost::lexical_cast<std::string>(tensor_size) +
" but is " +
977 boost::lexical_cast<std::string>(data.size1()));
980 for (
auto i = 0;
i != tensor_size; ++
i)
981 ptrs[
i] = &data(rr +
i, cc + 0);
983 Tensor_Dim1, Tensor_Dim2>(ptrs);
1000template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
1001 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1005 M>::get(data, rr, cc);
1008template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
1009 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1013 DL,
M>::get(std::declval<M &>(), 0, 0));
1015template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
1018 int rr = 0,
int cc = 0) {
1020 if (!data_ptr.lock()) {
1022 "Data matrix is not available");
1029template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int S = -1,
1030 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1032 int rr = 0,
int cc = 0) {
1036 "Data matrix is not available");
1050template <
int DIM1,
int DIM2,
int DIM3>
1055 "Such getFTensor3FromPtr is not implemented");
1062 ptr + 0, ptr + 1, ptr + 2, ptr + 3, ptr + 4, ptr + 5, ptr + 6, ptr + 7,
1063 ptr + 8, ptr + 9, ptr + 10, ptr + 11);
1070 ptr + 0, ptr + 1, ptr + 2, ptr + 3, ptr + 4, ptr + 5, ptr + 6, ptr + 7,
1071 ptr + 8, ptr + 9, ptr + 10, ptr + 11, ptr + 12, ptr + 13, ptr + 14,
1072 ptr + 15, ptr + 16, ptr + 17, ptr + 18, ptr + 19, ptr + 20, ptr + 21,
1073 ptr + 22, ptr + 23, ptr + 24, ptr + 25, ptr + 26);
1081template <
int Tensor_Dim01,
int Tensor_Dim2,
int S,
class DL,
class M>
1084template <
int Tensor_Dim01,
int Tensor_Dim2,
int S,
class M>
1088 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1089 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1090 constexpr int symm_size_01 = (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2;
1091 constexpr int dg_size = symm_size_01 * Tensor_Dim2;
1092 constexpr int stride = S == -1 ? dg_size : S;
1094 stride % dg_size == 0,
1095 "getFTensor3DgFromMat: stride should be a multiple of dg_size");
1098 if (data.size2() != dg_size) {
1100 "getFTensor3DgFromMat<" +
1101 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1102 boost::lexical_cast<std::string>(Tensor_Dim2) +
1103 ">: wrong size of data matrix, number of columns should be " +
1104 boost::lexical_cast<std::string>(dg_size) +
" but is " +
1105 boost::lexical_cast<std::string>(data.size2()));
1107 auto *first = &data(rr + 0, cc + 0);
1108 auto *last = &data(rr + 0, cc + 0 + dg_size - 1);
1109 if (last - first != dg_size - 1)
1111 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1112 boost::lexical_cast<std::string>(Tensor_Dim2) +
1113 ">: row slice is not contiguous");
1116 Tensor_Dim2>{&data(rr + 0, cc + 0)};
1120template <
int S,
class M>
1123 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1124 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1125 constexpr int stride = S == -1 ? 1 : S;
1128 constexpr int dg_size = 1;
1129 if (data.size1() != dg_size)
1131 "getFTensor3DgFromMat<1, 1>: wrong size of data matrix, number "
1132 "of rows should be 1 but is " +
1133 boost::lexical_cast<std::string>(data.size1()));
1136 &data(rr + 0, cc + 0)};
1140template <
int S,
class M>
1143 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1144 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1145 constexpr int stride = S == -1 ? 1 : S;
1147 constexpr int dg_size = 6;
1148 if (data.size1() != dg_size) {
1150 "getFTensor3DgFromMat<2, 2>: wrong size of data matrix, number "
1151 "of rows should be 6 but is " +
1152 boost::lexical_cast<std::string>(data.size1()));
1156 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1157 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0)};
1161template <
int S,
class M>
1164 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1165 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1166 constexpr int stride = S == -1 ? 1 : S;
1168 constexpr int dg_size = 18;
1169 if (data.size1() != dg_size) {
1171 "getFTensor3DgFromMat<3, 3>: wrong size of data matrix, number "
1172 "of rows should be 18 but is " +
1173 boost::lexical_cast<std::string>(data.size1()));
1177 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1178 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
1179 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0),
1180 &data(rr + 9, cc + 0), &data(rr + 10, cc + 0), &data(rr + 11, cc + 0),
1181 &data(rr + 12, cc + 0), &data(rr + 13, cc + 0), &data(rr + 14, cc + 0),
1182 &data(rr + 15, cc + 0), &data(rr + 16, cc + 0), &data(rr + 17, cc + 0)};
1198template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1199 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1206template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1207 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1211 std::declval<M &>(), 0, 0));
1213template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1218 if (!data_ptr.lock()) {
1220 "Data matrix is not available");
1227template <
int Tensor_Dim01,
int Tensor_Dim2,
int S = -1,
1228 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1234 "Data matrix is not available");
1241template <
int Tensor_Dim01,
int Tensor_Dim2,
int S,
class T =
double>
1243 constexpr auto dg_size =
1244 ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) * Tensor_Dim2;
1248 decltype(matrix_data)>::get(matrix_data);
1256template <
class T,
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
1257 int Tensor_Dim3,
int S, std::size_t... Is>
1259 const std::array<T *, Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3>
1261 std::index_sequence<Is...>) {
1263 Tensor_Dim2, Tensor_Dim3>(ptrs[Is]...);
1266template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1267 int S,
class DL,
class M>
1269 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1270 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1271 constexpr int tensor_size =
1272 Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3;
1273 constexpr int stride =
1274 S == -1 ? (DL::isGaussByCoeffs ? tensor_size : 1) : S;
1275 if constexpr (DL::isGaussByCoeffs) {
1277 stride % tensor_size == 0,
1278 "getFTensor4FromMat: stride should be a multiple of tensor_size");
1281 if (data.size2() != tensor_size) {
1283 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
1284 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
1285 boost::lexical_cast<std::string>(Tensor_Dim2) +
"," +
1286 boost::lexical_cast<std::string>(Tensor_Dim3) +
1287 ">: wrong size of columns in data matrix, should be " +
1288 boost::lexical_cast<std::string>(tensor_size) +
1290 boost::lexical_cast<std::string>(data.size2()));
1292 auto *first = &data(rr + 0, cc + 0);
1293 auto *last = &data(rr + 0, cc + 0 + tensor_size - 1);
1294 if (last - first != tensor_size - 1) {
1296 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
1297 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
1298 boost::lexical_cast<std::string>(Tensor_Dim2) +
"," +
1299 boost::lexical_cast<std::string>(Tensor_Dim3) +
1300 ">: row slice is not contiguous");
1304 Tensor_Dim1, Tensor_Dim2, Tensor_Dim3>{
1305 &data(rr + 0, cc + 0)};
1306 }
else if constexpr (DL::isCoeffsByGauss) {
1307 std::array<T *, tensor_size> ptrs;
1309 if (data.size1() != tensor_size) {
1311 boost::lexical_cast<std::string>(Tensor_Dim0) +
"," +
1312 boost::lexical_cast<std::string>(Tensor_Dim1) +
"," +
1313 boost::lexical_cast<std::string>(Tensor_Dim2) +
"," +
1314 boost::lexical_cast<std::string>(Tensor_Dim3) +
1315 ">: wrong size of rows in data matrix, should be " +
1316 boost::lexical_cast<std::string>(tensor_size) +
1318 boost::lexical_cast<std::string>(data.size1()));
1321 for (
auto i = 0;
i != tensor_size; ++
i)
1322 ptrs[
i] = &data(rr +
i, cc + 0);
1324 Tensor_Dim3, stride>(
1325 ptrs, std::make_index_sequence<tensor_size>{});
1327 static_assert(!std::is_same<M, M>::value,
1328 "Unsupported data layout for getFTensor4FromMatImpl");
1346template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1347 int S = -1,
class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1351 Tensor_Dim3, S, DL,
M>::get(data);
1354template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1355 int S = -1,
class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1360 M>::get(std::declval<M &>(), 0, 0));
1362template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1366 if (!data_ptr.lock()) {
1368 "Data matrix is not available");
1376template <
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
int Tensor_Dim3,
1377 int S = -1,
class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1383 "Data matrix is not available");
1391template <
int DIM1,
int DIM2,
int DIM3,
int DIM4,
int S = -1,
class T =
double>
1396 decltype(matrix_data)>::get(matrix_data);
1404template <
int Tensor_Dim01,
int Tensor_Dim23,
int S,
class DL,
class M>
1407template <
int Tensor_Dim01,
int Tensor_Dim23,
int S,
class M>
1411 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1412 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1413 constexpr int symm_size_01 = (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2;
1414 constexpr int symm_size_23 = (Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2;
1415 constexpr int ddg_size = symm_size_01 * symm_size_23;
1416 constexpr int stride = S == -1 ? ddg_size : S;
1418 stride % ddg_size == 0,
1419 "Stride should be a multiple of the size of the symmetric tensor");
1422 if (data.size2() != ddg_size) {
1424 "getFTensor4DdgFromMat<" +
1425 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1426 boost::lexical_cast<std::string>(Tensor_Dim23) +
1427 ">: wrong size of data matrix, number of columns should be " +
1428 boost::lexical_cast<std::string>(ddg_size) +
" but is " +
1429 boost::lexical_cast<std::string>(data.size2()));
1431 auto *first = &data(rr + 0, cc + 0);
1432 auto *last = &data(rr + 0, cc + 0 + ddg_size - 1);
1433 if (last - first != ddg_size - 1)
1435 boost::lexical_cast<std::string>(Tensor_Dim01) +
", " +
1436 boost::lexical_cast<std::string>(Tensor_Dim23) +
1437 ">: row slice is not contiguous");
1440 Tensor_Dim23>{&data(rr + 0, cc + 0)};
1444template <
int S,
class M>
1447 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1448 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1449 constexpr int stride = S == -1 ? 1 : S;
1451 constexpr int ddg_size = 1;
1452 if (data.size1() != ddg_size)
1454 "getFTensor4DdgFromMat<1, 1>: wrong size of data matrix, number "
1455 "of rows should be 1 but is " +
1456 boost::lexical_cast<std::string>(data.size1()));
1459 &data(rr + 0, cc + 0)};
1463template <
int S,
class M>
1466 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1467 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1468 constexpr int stride = S == -1 ? 1 : S;
1470 constexpr int ddg_size = 9;
1471 if (data.size1() != ddg_size) {
1473 "getFTensor4DdgFromMat<2, 2>: wrong size of data matrix, number "
1474 "of rows should be 9 but is " +
1475 boost::lexical_cast<std::string>(data.size1()));
1479 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1480 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
1481 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0)};
1485template <
int S,
class M>
1488 static inline auto get(
M &data,
int rr = 0,
int cc = 0) {
1489 using T = std::remove_cv_t<std::remove_reference_t<
decltype(data(0, 0))>>;
1490 constexpr int stride = S == -1 ? 1 : S;
1492 constexpr int ddg_size = 36;
1493 if (data.size1() != ddg_size) {
1495 "getFTensor4DdgFromMat<3, 3>: wrong size of data matrix, number "
1496 "of rows should be 36 but is " +
1497 boost::lexical_cast<std::string>(data.size1()));
1501 &data(rr + 0, cc + 0), &data(rr + 1, cc + 0), &data(rr + 2, cc + 0),
1502 &data(rr + 3, cc + 0), &data(rr + 4, cc + 0), &data(rr + 5, cc + 0),
1503 &data(rr + 6, cc + 0), &data(rr + 7, cc + 0), &data(rr + 8, cc + 0),
1504 &data(rr + 9, cc + 0), &data(rr + 10, cc + 0), &data(rr + 11, cc + 0),
1505 &data(rr + 12, cc + 0), &data(rr + 13, cc + 0), &data(rr + 14, cc + 0),
1506 &data(rr + 15, cc + 0), &data(rr + 16, cc + 0), &data(rr + 17, cc + 0),
1507 &data(rr + 18, cc + 0), &data(rr + 19, cc + 0), &data(rr + 20, cc + 0),
1508 &data(rr + 21, cc + 0), &data(rr + 22, cc + 0), &data(rr + 23, cc + 0),
1509 &data(rr + 24, cc + 0), &data(rr + 25, cc + 0), &data(rr + 26, cc + 0),
1510 &data(rr + 27, cc + 0), &data(rr + 28, cc + 0), &data(rr + 29, cc + 0),
1511 &data(rr + 30, cc + 0), &data(rr + 31, cc + 0), &data(rr + 32, cc + 0),
1512 &data(rr + 33, cc + 0), &data(rr + 34, cc + 0), &data(rr + 35, cc + 0)};
1527template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1528 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1535template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1536 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>,
1540 M>::get(std::declval<M &>(), 0, 0));
1542template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1548 "Data matrix is not available");
1555template <
int Tensor_Dim01,
int Tensor_Dim23,
int S = -1,
1556 class DL = DataLayoutTraits<DataLayout::GaussByCoeffs>>
1562 "Data matrix is not available");
1569template <
int Tensor_Dim01,
int Tensor_Dim23,
int S,
class T =
double>
1571 constexpr auto symm_size01 = (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2;
1572 constexpr auto symm_size23 = (Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2;
1573 constexpr auto symm_size = symm_size01 * symm_size23;
1577 decltype(matrix_data)>::get(matrix_data);
1588template <
class T,
int S,
int Tensor_Dim>
1593 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1594 if (
m.size1() != nb_integration_pts ||
m.size2() != Tensor_Dim) {
1595 m.resize(nb_integration_pts, Tensor_Dim,
false);
1605 [[maybe_unused]]
const size_t nb_integration_pts) {
1607 if (S == -1 || S == Tensor_Dim) {
1608 if (
m.size1() != nb_integration_pts) {
1611 "Matrix size is not compatible with the number of "
1612 "integration points: expected " +
1613 boost::lexical_cast<std::string>(nb_integration_pts) +
1614 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1626template <
class T,
int S,
int Tensor_Dim0,
int Tensor_Dim1>
1628 FTensor::Tensor2<FTensor::CursorPtr<T *, S>, Tensor_Dim0, Tensor_Dim1>,
1631 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1632 if (
m.size1() != nb_integration_pts ||
1633 m.size2() != Tensor_Dim0 * Tensor_Dim1) {
1634 m.resize(nb_integration_pts, Tensor_Dim0 * Tensor_Dim1,
false);
1644 [[maybe_unused]]
const size_t nb_integration_pts) {
1646 if (S == -1 || S == Tensor_Dim0 * Tensor_Dim1) {
1647 if (
m.size1() != nb_integration_pts) {
1650 "Matrix size is not compatible with the number of "
1651 "integration points: expected " +
1652 boost::lexical_cast<std::string>(nb_integration_pts) +
1653 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1665template <
class T,
int S,
int Tensor_Dim>
1667 FTensor::Tensor2_symmetric<FTensor::CursorPtr<T *, S>, Tensor_Dim>,
1670 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1671 constexpr int symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
1672 if (
m.size1() != nb_integration_pts ||
m.size2() != symm_size) {
1673 m.resize(nb_integration_pts, symm_size,
false);
1683 [[maybe_unused]]
const size_t nb_integration_pts) {
1685 constexpr int symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
1686 if (S == -1 || S == symm_size) {
1687 if (
m.size1() != nb_integration_pts) {
1690 "Matrix size is not compatible with the number of "
1691 "integration points: expected " +
1692 boost::lexical_cast<std::string>(nb_integration_pts) +
1693 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1705template <
class T,
int S,
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2>
1707 Tensor_Dim0, Tensor_Dim1, Tensor_Dim2>,
1710 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1711 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
1712 if (
m.size1() != nb_integration_pts ||
m.size2() != tensor_size) {
1713 m.resize(nb_integration_pts, tensor_size,
false);
1723 [[maybe_unused]]
const size_t nb_integration_pts) {
1725 constexpr int tensor_size = Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2;
1726 if (S == -1 || S == tensor_size) {
1727 if (
m.size1() != nb_integration_pts) {
1730 "Matrix size is not compatible with the number of "
1731 "integration points: expected " +
1732 boost::lexical_cast<std::string>(nb_integration_pts) +
1733 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1745template <
class T,
int S,
int Tensor_Dim01,
int Tensor_Dim2>
1747 FTensor::Dg<FTensor::CursorPtr<T *, S>, Tensor_Dim01, Tensor_Dim2>,
1750 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1751 constexpr int dg_size =
1752 ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) * Tensor_Dim2;
1753 if (
m.size1() != nb_integration_pts ||
m.size2() != dg_size) {
1754 m.resize(nb_integration_pts, dg_size,
false);
1758 Tensor_Dim01, Tensor_Dim2, S,
1764 [[maybe_unused]]
const size_t nb_integration_pts) {
1766 constexpr int dg_size =
1767 ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) * Tensor_Dim2;
1768 if (S == -1 || S == dg_size) {
1769 if (
m.size1() != nb_integration_pts) {
1772 "Matrix size is not compatible with the number of "
1773 "integration points: expected " +
1774 boost::lexical_cast<std::string>(nb_integration_pts) +
1775 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1781 Tensor_Dim01, Tensor_Dim2, S,
1787template <
class T,
int S,
int Tensor_Dim0,
int Tensor_Dim1,
int Tensor_Dim2,
1790 FTensor::Tensor4<FTensor::CursorPtr<T *, S>, Tensor_Dim0, Tensor_Dim1,
1791 Tensor_Dim2, Tensor_Dim3>,
1794 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1795 constexpr int tensor_size =
1796 Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3;
1797 if (
m.size1() != nb_integration_pts ||
m.size2() != tensor_size) {
1798 m.resize(nb_integration_pts, tensor_size,
false);
1802 Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3, S,
1808 [[maybe_unused]]
const size_t nb_integration_pts) {
1810 if (S == -1 || S == Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim2 * Tensor_Dim3) {
1811 if (
m.size1() != nb_integration_pts) {
1814 "Matrix size is not compatible with the number of "
1815 "integration points: expected " +
1816 boost::lexical_cast<std::string>(nb_integration_pts) +
1817 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1823 Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3, S,
1829template <
class T,
int S,
int Tensor_Dim01,
int Tensor_Dim23>
1831 FTensor::Ddg<FTensor::CursorPtr<T *, S>, Tensor_Dim01, Tensor_Dim23>,
1834 static inline auto size(
M &
m,
const size_t nb_integration_pts) {
1835 constexpr int ddg_size = ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) *
1836 ((Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2);
1837 if (
m.size1() != nb_integration_pts ||
m.size2() != ddg_size) {
1838 m.resize(nb_integration_pts, ddg_size,
false);
1842 Tensor_Dim01, Tensor_Dim23, S,
1848 [[maybe_unused]]
const size_t nb_integration_pts) {
1850 constexpr int ddg_size = ((Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2) *
1851 ((Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2);
1852 if (S == -1 || S == ddg_size) {
1854 if (
m.size1() != nb_integration_pts) {
1857 "Matrix size is not compatible with the number of "
1858 "integration points: expected " +
1859 boost::lexical_cast<std::string>(nb_integration_pts) +
1860 " but got " + boost::lexical_cast<std::string>(
m.size1()));
1866 Tensor_Dim01, Tensor_Dim23, S,
1881 if constexpr (DIM == 3) {
1882 return std::array<double, 9>{t_mat(0, 0), t_mat(1, 1), t_mat(2, 2),
1883 t_mat(0, 1), t_mat(1, 0), t_mat(0, 2),
1884 t_mat(2, 0), t_mat(1, 2), t_mat(2, 1)};
1886 return std::array<double, 5>{t_mat(0, 0), t_mat(1, 1), 1.0, t_mat(0, 1),
1892 constexpr double sqr2 = boost::math::constants::root_two<double>();
1894 if constexpr (DIM == 3) {
1895 return std::array<double, 9>{t_mat(0, 0),
1905 return std::array<double, 4>{t_mat(0, 0), t_mat(1, 1), 0.0,
1906 sqr2 * t_mat(0, 1)};
1910template <
typename T>
1912 array<double, 5> vec{t_mat(0, 0), t_mat(1, 1), 1. + hoop_term, t_mat(0, 1),
1918template <
typename T>
1920 constexpr double sqr2 = boost::math::constants::root_two<double>();
1922 array<double, 4> vec_sym{t_mat(0, 0), t_mat(1, 1), hoop_term,
1923 sqr2 * t_mat(0, 1)};
1942 const size_t M = mat.size1();
1943 const size_t N = mat.size2();
1947 "The input matrix for inverse computation is not square %zu != %zu",
1950 int *ipv =
new int[
N];
1952 double *work =
new double[lwork];
1961 "lapack error info = %d", info);
1978 const size_t M = mat.size1();
1979 const size_t N = mat.size2();
1981 if (
M == 0 ||
M !=
N)
1983 "The input matrix for inverse computation is not square %zu != %zu",
1990 int *ipiv =
new int[
M];
1992 &*f.data().begin(),
M);
1995 "error lapack solve dgesv info = %d", info);
2013 auto mat_copy = mat;
2019template <
typename T =
double>
inline bool isEq(
const T
a,
const T b) {
2020 const double eps = 100 * std::numeric_limits<T>::epsilon();
2021 const auto abs_max =
2022 std::max(
static_cast<T
>(1), std::max(std::abs(
a), std::abs(b)));
2023 return std::abs(
a - b) <=
eps * abs_max;
2026template <
int DIM,
typename T =
double>
2031template <
int DIM1,
int DIM2,
typename T =
double>
2043template <
int DIM,
typename T =
double>
2045 std::array<double, DIM> tmp;
2046 std::copy(vec.data().begin(), vec.data().begin() + DIM, tmp.begin());
2047 std::sort(tmp.begin(), tmp.end());
2048 std::size_t n_unique = 1;
2049 for (
int i = 1;
i < DIM; ++
i) {
2050 if (!
isEq(tmp[
i], tmp[
i - 1])) {
2057template <
int DIM,
typename T =
double>
2061 if constexpr (DIM == 2) {
2064 static_assert(DIM == 2 || DIM == 3,
"That works only for DIM = 3");
2066 int i = 0,
j = 1,
k = 2;
2067 if (isEq<T>(eig(0), eig(1))) {
2071 }
else if (isEq<T>(eig(0), eig(2))) {
2075 }
else if (isEq<T>(eig(1), eig(2))) {
2080 const std::array<T, 9> eigen_vec_c{
2081 eigen_vec(
i, 0), eigen_vec(
i, 1), eigen_vec(
i, 2),
2082 eigen_vec(
j, 0), eigen_vec(
j, 1), eigen_vec(
j, 2),
2083 eigen_vec(
k, 0), eigen_vec(
k, 1), eigen_vec(
k, 2)};
2084 const std::array<T, 3> eig_c{eig(
i), eig(
j), eig(
k)};
2085 std::copy(eigen_vec_c.begin(), eigen_vec_c.end(), eigen_vec.data().begin());
2086 std::copy(eig_c.begin(), eig_c.end(), eig.data().begin());
2090template <
int DIM,
typename T =
double>
2095template <
int DIM,
typename T =
double>
2123 const size_t M = mat.size1();
2124 const size_t N = mat.size2();
2126 if (
M == 0 ||
M !=
N)
2128 "The input matrix for eigen value computation is not square %zu "
2131 if (eig.size() !=
M)
2132 eig.resize(
M,
false);
2137 const int size = (
M + 2) *
M;
2139 double *work =
new double[size];
2141 if (
lapack_dsyev(
'V',
'U',
n, &*eigen_vec.data().begin(), lda,
2142 &*eig.data().begin(), work, lwork) > 0)
2144 "The algorithm failed to compute eigenvalues.");
2166template <
int DIM,
typename T1,
typename T2>
2173 const int lda = DIM;
2174 const int lwork = (DIM + 2) * DIM;
2175 std::array<
double, (DIM + 2) * DIM> work;
2180 "The algorithm failed to compute eigenvalues.");
2200template <
int DIM,
typename T1,
typename T2,
typename T3>
2206 for (
int ii = 0; ii != DIM; ii++)
2207 for (
int jj = 0; jj != DIM; jj++)
2208 eigen_vec(ii, jj) = mat(ii, jj);
2229 return t(0, 0) *
t(1, 1) *
t(2, 2) +
t(1, 0) *
t(2, 1) *
t(0, 2) +
2230 t(2, 0) *
t(0, 1) *
t(1, 2) -
t(0, 0) *
t(2, 1) *
t(1, 2) -
2231 t(2, 0) *
t(1, 1) *
t(0, 2) -
t(1, 0) *
t(0, 1) *
t(2, 2);
2242 return t(0, 0) *
t(1, 1) -
t(0, 1) *
t(1, 0);
2258template <
typename T,
int DIM>
2266template <
typename T,
int DIM>
2275template <
int Tensor_Dim,
class T,
class L,
class A>
2277 ublas::vector<T, A> &det_data,
2278 ublas::matrix<T, L, A> &inv_jac_data) {
2281 "Specialization for this template not yet implemented");
2294template <
class T1,
class T2>
2305template <
class T1,
class T2>
2316template <
class T1,
class T2,
class T3>
2319 const auto a =
t(0, 0), b =
t(0, 1),
c =
t(0, 2);
2320 const auto d =
t(1, 0), e =
t(1, 1), f =
t(1, 2);
2321 const auto g =
t(2, 0),
h =
t(2, 1),
i =
t(2, 2);
2322 const auto inv_det = 1.0 / det;
2323 inv_t(0, 0) = (e *
i - f *
h) * inv_det;
2324 inv_t(0, 1) = (
c *
h - b *
i) * inv_det;
2325 inv_t(0, 2) = (b * f -
c * e) * inv_det;
2326 inv_t(1, 0) = (f *
g - d *
i) * inv_det;
2327 inv_t(1, 1) = (
a *
i -
c *
g) * inv_det;
2328 inv_t(1, 2) = (
c * d -
a * f) * inv_det;
2329 inv_t(2, 0) = (d *
h - e *
g) * inv_det;
2330 inv_t(2, 1) = (b *
g -
a *
h) * inv_det;
2331 inv_t(2, 2) = (
a * e - b * d) * inv_det;
2339template <
class T1,
class T2,
class T3>
2342 const auto a =
t(0, 0);
2343 const auto b =
t(0, 1);
2344 const auto c =
t(1, 0);
2345 const auto d =
t(1, 1);
2346 inv_t(0, 0) = d / det;
2347 inv_t(0, 1) = -b / det;
2348 inv_t(1, 0) = -
c / det;
2349 inv_t(1, 1) =
a / det;
2357template <
typename T1,
typename T2,
typename T3>
2362 const auto a =
t(0, 0);
2363 const auto b =
t(0, 1);
2364 const auto c =
t(0, 2);
2365 const auto d =
t(1, 1);
2366 const auto e =
t(1, 2);
2367 const auto f =
t(2, 2);
2368 const auto inv_det = 1.0 / det;
2369 inv_t(0, 0) = (d * f - e * e) * inv_det;
2370 inv_t(0, 1) = (
c * e - b * f) * inv_det;
2371 inv_t(0, 2) = (b * e -
c * d) * inv_det;
2372 inv_t(1, 1) = (
a * f -
c *
c) * inv_det;
2373 inv_t(1, 2) = (b *
c -
a * e) * inv_det;
2374 inv_t(2, 2) = (
a * d - b * b) * inv_det;
2382template <
typename T1,
typename T2,
typename T3>
2387 const auto a =
t(0, 0);
2388 const auto b =
t(0, 1);
2389 const auto d =
t(1, 1);
2390 const auto inv_det = 1.0 / det;
2391 inv_t(0, 0) = d * inv_det;
2392 inv_t(0, 1) = -b * inv_det;
2393 inv_t(1, 1) =
a * inv_det;
2397template <
typename T1,
typename T2,
typename T3,
int DIM>
2400template <
typename T1,
typename T2,
typename T3>
2407template <
typename T1,
typename T2,
typename T3>
2414template <
typename T1,
typename T2,
typename T3,
int DIM>
2423template <
typename T1,
typename T2,
typename T3,
int DIM>
2429 DIM>::invert(
t, det, inv_t);
2442 template <
typename Iterator>
2443 static inline EntityHandle
extract(
const Iterator &it) {
2444 return (*it)->getEnt();
2466template <
typename Extractor,
typename Iterator>
2468 Iterator end_iter) {
2469 moab::Range::iterator hint = r.begin();
2470 while (begin_iter != end_iter) {
2472 auto bi = Extractor::extract(begin_iter);
2473 Iterator pj = begin_iter;
2474 while (pj != end_iter && (bi +
j) == Extractor::extract(pj)) {
2478 hint = r.insert(hint, bi, bi + (
j - 1));
2502template <
typename MI,
typename MO = Modify_change_nothing>
2506 for (
auto it = mi.begin(); it != mi.end(); ++it) {
2507 if (!
const_cast<MI &
>(mi).modify(it, mo))
2509 "Houston we have a problem");
2537 return boost::make_shared<TempMeshset>(moab);
2594template <
typename I>
2601 if (tester(first)) {
2603 auto second = first;
2606 while (second != s) {
2613 CHKERR inserter(first, second);
2639template <
typename Dest = void,
typename... Arg>
2641 if constexpr (std::is_same<void, Dest>::value)
2642 return std::array<std::common_type_t<std::decay_t<Arg>...>,
sizeof...(Arg)>{
2643 {std::forward<Arg>(arg)...}};
2645 return std::array<Dest,
sizeof...(Arg)>{{std::forward<Arg>(arg)...}};
2673#define FTENSOR_INDEX(DIM, I) I##_FTIndex<DIM> I;
2675#define FTENSOR_INDEX_DECL(r, DIM, I) FTENSOR_INDEX(DIM, I)
2677#define FTENSOR_INDEXES(DIM, ...) \
2678 BOOST_PP_SEQ_FOR_EACH(FTENSOR_INDEX_DECL, DIM, \
2679 BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
#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)
GetFTensor2FromArrayImpl()=delete
static auto get(M &data, const size_t rr, const size_t cc)
static auto get(M &data, const size_t rr, const size_t cc)
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)