15#ifndef dealii_tensor_product_matrix_h
16#define dealii_tensor_product_matrix_h
111template <
int dim,
typename Number,
int n_rows_1d = -1>
136 template <
typename T>
157 template <
typename T>
260 template <
typename Number>
269 std::pair<std::bitset<width>,
279 const auto &M_0 = left.second.first;
280 const auto &K_0 = left.second.second;
281 const auto &M_1 = right.second.first;
282 const auto &K_1 = right.second.second;
284 std::bitset<width>
mask;
286 for (
unsigned int v = 0; v <
width; ++v)
287 mask[v] = left.first[v] && right.first[v];
292 if (comparator(M_0, M_1))
294 else if (comparator(M_1, M_0))
296 else if (comparator(K_0, K_1))
333template <
int dim,
typename Number,
int n_rows_1d = -1>
339 std::bitset<::internal::VectorizedArrayTrait<Number>::width()>,
383 template <
typename T>
385 insert(
const unsigned int index,
const T &Ms,
const T &Ks);
513 template <
typename Number>
515 spectral_assembly(
const Number *mass_matrix,
516 const Number *derivative_matrix,
517 const unsigned int n_rows,
518 const unsigned int n_cols,
524 std::vector<bool> constrained_dofs(n_rows,
false);
526 for (
unsigned int i = 0; i < n_rows; ++i)
528 if (mass_matrix[i + i * n_rows] == 0.0)
530 Assert(derivative_matrix[i + i * n_rows] == 0.0,
533 for (
unsigned int j = 0; j < n_rows; ++j)
535 Assert(derivative_matrix[i + j * n_rows] == 0,
537 Assert(derivative_matrix[j + i * n_rows] == 0,
541 constrained_dofs[i] =
true;
545 const auto transpose_fill_nm = [&constrained_dofs](Number *out,
547 const unsigned int n,
548 const unsigned int m) {
549 for (
unsigned int mm = 0, c = 0; mm < m; ++mm)
550 for (
unsigned int nn = 0; nn < n; ++nn, ++c)
552 (mm == nn && constrained_dofs[mm]) ? Number(1.0) : in[c];
555 std::vector<::Vector<Number>> eigenvecs(n_rows);
559 transpose_fill_nm(&(mass_copy(0, 0)), mass_matrix, n_rows, n_cols);
560 transpose_fill_nm(&(deriv_copy(0, 0)), derivative_matrix, n_rows, n_cols);
565 for (
unsigned int i = 0, c = 0; i < n_rows; ++i)
566 for (
unsigned int j = 0; j < n_cols; ++j, ++c)
567 if (constrained_dofs[i] ==
false)
570 for (
unsigned int i = 0; i < n_rows; ++i, ++
eigenvalues)
576 template <std::
size_t dim,
typename Number>
583 const unsigned int n_rows_1d = mass_matrix[0].n_cols();
586 for (
unsigned int dir = 0; dir < dim; ++dir)
591 derivative_matrix[dir].n_rows());
593 derivative_matrix[dir].n_cols());
596 mass_matrix[dir].n_rows());
597 eigenvalues[dir].resize(mass_matrix[dir].n_cols());
598 internal::TensorProductMatrixSymmetricSum::spectral_assembly<Number>(
599 &(mass_matrix[dir](0, 0)),
600 &(derivative_matrix[dir](0, 0)),
601 mass_matrix[dir].n_rows(),
602 mass_matrix[dir].n_cols(),
610 template <std::
size_t dim,
typename Number, std::
size_t n_lanes>
621 const unsigned int n_rows_1d = mass_matrix[0].n_cols();
622 constexpr unsigned int macro_size =
624 const std::size_t nm_flat_size_max = n_rows_1d * n_rows_1d * macro_size;
625 const std::size_t n_flat_size_max = n_rows_1d * macro_size;
627 std::vector<Number> mass_matrix_flat;
628 std::vector<Number> deriv_matrix_flat;
629 std::vector<Number> eigenvalues_flat;
630 std::vector<Number> eigenvectors_flat;
631 mass_matrix_flat.resize(nm_flat_size_max);
632 deriv_matrix_flat.resize(nm_flat_size_max);
633 eigenvalues_flat.resize(n_flat_size_max);
634 eigenvectors_flat.resize(nm_flat_size_max);
635 std::array<unsigned int, macro_size> offsets_nm;
636 std::array<unsigned int, macro_size> offsets_n;
637 for (
unsigned int dir = 0; dir < dim; ++dir)
642 derivative_matrix[dir].n_rows());
644 derivative_matrix[dir].n_cols());
646 const unsigned int n_rows = mass_matrix[dir].n_rows();
647 const unsigned int n_cols = mass_matrix[dir].n_cols();
648 const unsigned int nm = n_rows * n_cols;
649 for (
unsigned int vv = 0; vv < macro_size; ++vv)
650 offsets_nm[vv] = nm * vv;
652 vectorized_transpose_and_store<Number, n_lanes>(
655 &(mass_matrix[dir](0, 0)),
657 mass_matrix_flat.data());
658 vectorized_transpose_and_store<Number, n_lanes>(
661 &(derivative_matrix[dir](0, 0)),
663 deriv_matrix_flat.data());
665 const Number *mass_cbegin = mass_matrix_flat.data();
666 const Number *deriv_cbegin = deriv_matrix_flat.data();
667 Number *eigenvec_begin = eigenvectors_flat.data();
668 Number *eigenval_begin = eigenvalues_flat.data();
669 for (
unsigned int lane = 0; lane < macro_size; ++lane)
670 internal::TensorProductMatrixSymmetricSum::spectral_assembly<
671 Number>(mass_cbegin + nm * lane,
672 deriv_cbegin + nm * lane,
675 eigenval_begin + n_rows * lane,
676 eigenvec_begin + nm * lane);
680 for (
unsigned int vv = 0; vv < macro_size; ++vv)
681 offsets_n[vv] = n_rows * vv;
682 vectorized_load_and_transpose<Number, n_lanes>(
684 eigenvalues_flat.data(),
687 vectorized_load_and_transpose<Number, n_lanes>(
689 eigenvectors_flat.data(),
697 template <std::
size_t dim,
typename Number>
698 inline std::array<Table<2, Number>, dim>
706 template <std::
size_t dim,
typename Number>
707 inline std::array<Table<2, Number>, dim>
710 std::array<Table<2, Number>, dim> mass_copy;
712 std::transform(mass_matrix.cbegin(),
724 template <std::
size_t dim,
typename Number>
725 inline std::array<Table<2, Number>, dim>
728 std::array<Table<2, Number>, dim> matrices;
730 std::fill(matrices.begin(), matrices.end(), matrix);
737 template <
int n_rows_1d_templated, std::
size_t dim,
typename Number>
742 const unsigned int n_rows_1d_non_templated,
743 const std::array<const Number *, dim> &mass_matrix,
744 const std::array<const Number *, dim> &derivative_matrix)
746 const unsigned int n_rows_1d = n_rows_1d_templated == 0 ?
747 n_rows_1d_non_templated :
749 const unsigned int n = Utilities::fixed_power<dim>(n_rows_1d);
752 Number *t = tmp.
begin();
759 eval({}, {}, {}, n_rows_1d, n_rows_1d);
763 const Number *A = derivative_matrix[0];
764 eval.template apply<0, false, false>(A, src, dst);
769 const Number *A0 = derivative_matrix[0];
770 const Number *M0 = mass_matrix[0];
771 const Number *A1 = derivative_matrix[1];
772 const Number *M1 = mass_matrix[1];
773 eval.template apply<0, false, false>(M0, src, t);
774 eval.template apply<1, false, false>(A1, t, dst);
775 eval.template apply<0, false, false>(A0, src, t);
776 eval.template apply<1, false, true>(M1, t, dst);
781 const Number *A0 = derivative_matrix[0];
782 const Number *M0 = mass_matrix[0];
783 const Number *A1 = derivative_matrix[1];
784 const Number *M1 = mass_matrix[1];
785 const Number *A2 = derivative_matrix[2];
786 const Number *M2 = mass_matrix[2];
787 eval.template apply<0, false, false>(M0, src, t + n);
788 eval.template apply<1, false, false>(M1, t + n, t);
789 eval.template apply<2, false, false>(A2, t, dst);
790 eval.template apply<1, false, false>(A1, t + n, t);
791 eval.template apply<0, false, false>(A0, src, t + n);
792 eval.template apply<1, false, true>(M1, t + n, t);
793 eval.template apply<2, false, true>(M2, t, dst);
802 template <
int n_rows_1d_templated, std::
size_t dim,
typename Number>
804 apply_inverse(Number *dst,
806 const unsigned int n_rows_1d_non_templated,
808 const std::array<const Number *, dim> &
eigenvalues,
809 const Number *inverted_eigenvalues =
nullptr)
811 const unsigned int n_rows_1d = n_rows_1d_templated == 0 ?
812 n_rows_1d_non_templated :
820 eval({}, {}, {}, n_rows_1d, n_rows_1d);
830 eval.template apply<0, true, false>(S, src, dst);
832 for (
unsigned int i = 0; i < n_rows_1d; ++i)
833 if (inverted_eigenvalues)
834 dst[i] *= inverted_eigenvalues[i];
838 eval.template apply<0, false, false>(S, dst, dst);
845 eval.template apply<0, true, false>(S0, src, dst);
846 eval.template apply<1, true, false>(S1, dst, dst);
848 for (
unsigned int i1 = 0, c = 0; i1 < n_rows_1d; ++i1)
849 for (
unsigned int i0 = 0; i0 < n_rows_1d; ++i0, ++c)
850 if (inverted_eigenvalues)
851 dst[c] *= inverted_eigenvalues[c];
855 eval.template apply<1, false, false>(S1, dst, dst);
856 eval.template apply<0, false, false>(S0, dst, dst);
864 eval.template apply<0, true, false>(S0, src, dst);
865 eval.template apply<1, true, false>(S1, dst, dst);
866 eval.template apply<2, true, false>(S2, dst, dst);
868 for (
unsigned int i2 = 0, c = 0; i2 < n_rows_1d; ++i2)
869 for (
unsigned int i1 = 0; i1 < n_rows_1d; ++i1)
870 for (
unsigned int i0 = 0; i0 < n_rows_1d; ++i0, ++c)
871 if (inverted_eigenvalues)
872 dst[c] *= inverted_eigenvalues[c];
877 eval.template apply<2, false, false>(S2, dst, dst);
878 eval.template apply<1, false, false>(S1, dst, dst);
879 eval.template apply<0, false, false>(S0, dst, dst);
888 template <
int n_rows_1d_templated, std::
size_t dim,
typename Number>
890 select_vmult(Number *dst,
893 const unsigned int n_rows_1d,
894 const std::array<const Number *, dim> &mass_matrix,
895 const std::array<const Number *, dim> &derivative_matrix);
899 template <
int n_rows_1d_templated, std::
size_t dim,
typename Number>
901 select_apply_inverse(Number *dst,
903 const unsigned int n_rows_1d,
905 const std::array<const Number *, dim> &
eigenvalues,
906 const Number *inverted_eigenvalues =
nullptr);
911template <
int dim,
typename Number,
int n_rows_1d>
916 for (
unsigned int d = 1;
d < dim; ++
d)
917 m *= mass_matrix[d].n_rows();
923template <
int dim,
typename Number,
int n_rows_1d>
928 for (
unsigned int d = 1;
d < dim; ++
d)
929 n *= mass_matrix[d].n_cols();
935template <
int dim,
typename Number,
int n_rows_1d>
941 std::lock_guard<std::mutex> lock(this->mutex);
942 this->vmult(dst_view, src_view, this->tmp_array);
947template <
int dim,
typename Number,
int n_rows_1d>
957 Number *dst = dst_view.
begin();
958 const Number *src = src_view.
begin();
960 std::array<const Number *, dim>
mass_matrix, derivative_matrix;
962 for (
unsigned int d = 0;
d < dim; ++
d)
965 derivative_matrix[
d] = &this->derivative_matrix[
d](0, 0);
968 const unsigned int n_rows_1d_non_templated = this->mass_matrix[0].n_rows();
971 internal::TensorProductMatrixSymmetricSum::vmult<
972 n_rows_1d == -1 ? 0 : n_rows_1d>(dst,
975 n_rows_1d_non_templated,
979 internal::TensorProductMatrixSymmetricSum::select_vmult<1>(
983 n_rows_1d_non_templated,
990template <
int dim,
typename Number,
int n_rows_1d>
999 Number *dst = dst_view.
begin();
1000 const Number *src = src_view.
begin();
1004 for (
unsigned int d = 0;
d < dim; ++
d)
1010 const unsigned int n_rows_1d_non_templated = this->mass_matrix[0].n_rows();
1012 if (n_rows_1d != -1)
1013 internal::TensorProductMatrixSymmetricSum::apply_inverse<
1014 n_rows_1d == -1 ? 0 : n_rows_1d>(
1017 internal::TensorProductMatrixSymmetricSum::select_apply_inverse<1>(
1023template <
int dim,
typename Number,
int n_rows_1d>
1037template <
int dim,
typename Number,
int n_rows_1d>
1038template <
typename T>
1041 const T &derivative_matrix)
1043 reinit(mass_matrix, derivative_matrix);
1048template <
int dim,
typename Number,
int n_rows_1d>
1049template <
typename T>
1052 const T &mass_matrix,
1053 const T &derivative_matrix)
1056 internal::TensorProductMatrixSymmetricSum::convert<dim>(mass_matrix);
1057 this->derivative_matrix =
1058 internal::TensorProductMatrixSymmetricSum::convert<dim>(derivative_matrix);
1060 internal::TensorProductMatrixSymmetricSum::setup(this->mass_matrix,
1061 this->derivative_matrix,
1068template <
int dim,
typename Number,
int n_rows_1d>
1071 const bool precompute_inverse_diagonal)
1072 : compress_matrices(compress_matrices)
1073 , precompute_inverse_diagonal(precompute_inverse_diagonal)
1078template <
int dim,
typename Number,
int n_rows_1d>
1081 const AdditionalData &additional_data)
1082 : compress_matrices(additional_data.compress_matrices)
1083 , precompute_inverse_diagonal(additional_data.precompute_inverse_diagonal)
1088template <
int dim,
typename Number,
int n_rows_1d>
1091 const unsigned int size)
1093 if (compress_matrices ==
false)
1094 mass_and_derivative_matrices.resize(
size * dim);
1101template <
int dim,
typename Number,
int n_rows_1d>
1102template <
typename T>
1105 const unsigned int index,
1110 internal::TensorProductMatrixSymmetricSum::convert<dim>(Ms_in);
1112 internal::TensorProductMatrixSymmetricSum::convert<dim>(Ks_in);
1114 for (
unsigned int d = 0;
d < dim; ++
d)
1116 if (compress_matrices ==
false)
1118 const MatrixPairType
matrix(Ms[d], Ks[d]);
1119 mass_and_derivative_matrices[
index * dim +
d] =
matrix;
1123 using VectorizedArrayTrait =
1126 std::bitset<VectorizedArrayTrait::width()>
mask;
1128 for (
unsigned int v = 0; v < VectorizedArrayTrait::width(); ++v)
1130 typename VectorizedArrayTrait::value_type a = 0.0;
1132 for (
unsigned int i = 0; i < Ms[
d].size(0); ++i)
1133 for (
unsigned int j = 0; j < Ms[
d].size(1); ++j)
1135 a +=
std::abs(VectorizedArrayTrait::get(Ms[d][i][j], v));
1136 a +=
std::abs(VectorizedArrayTrait::get(Ks[d][i][j], v));
1139 mask[v] = (a != 0.0);
1142 const MatrixPairTypeWithMask
matrix{
mask, {Ms[
d], Ks[
d]}};
1144 const auto ptr = cache.find(matrix);
1146 if (ptr != cache.end())
1148 const auto ptr_index = ptr->second;
1149 indices[
index * dim +
d] = ptr_index;
1152 for (
unsigned int v = 0; v < VectorizedArrayTrait::width();
1154 if ((mask[v] ==
true) && (ptr->first.first[v] ==
false))
1164 auto mask_new = ptr->first.first;
1165 auto Ms_new = ptr->first.second.first;
1166 auto Ks_new = ptr->first.second.second;
1168 for (
unsigned int v = 0; v < VectorizedArrayTrait::width();
1170 if (mask_new[v] ==
false && mask[v] ==
true)
1174 for (
unsigned int i = 0; i < Ms_new.size(0); ++i)
1175 for (
unsigned int j = 0; j < Ms_new.size(1); ++j)
1177 VectorizedArrayTrait::get(Ms_new[i][j], v) =
1178 VectorizedArrayTrait::get(Ms[d][i][j], v);
1179 VectorizedArrayTrait::get(Ks_new[i][j], v) =
1180 VectorizedArrayTrait::get(Ks[d][i][j], v);
1186 const MatrixPairTypeWithMask entry_new{mask_new,
1189 const auto ptr_ = cache.find(entry_new);
1192 cache[entry_new] = ptr_index;
1197 const auto size = cache.size();
1207template <
int dim,
typename Number,
int n_rows_1d>
1211 const auto store = [&](
const unsigned int index,
1212 const MatrixPairType &M_and_K) {
1216 std::array<Table<2, Number>, 1> derivative_matrix;
1217 derivative_matrix[0] = M_and_K.second;
1222 internal::TensorProductMatrixSymmetricSum::setup(mass_matrix,
1227 for (
unsigned int i = 0, m = matrix_ptr[index], v = vector_ptr[index];
1231 for (
unsigned int j = 0; j <
mass_matrix[0].n_cols(); ++j, ++m)
1234 this->derivative_matrices[m] = derivative_matrix[0][i][j];
1242 if (compress_matrices ==
false)
1249 this->vector_ptr.resize(mass_and_derivative_matrices.size() + 1);
1250 this->matrix_ptr.resize(mass_and_derivative_matrices.size() + 1);
1252 for (
unsigned int i = 0; i < mass_and_derivative_matrices.size(); ++i)
1254 const auto &M = mass_and_derivative_matrices[i].first;
1256 this->vector_ptr[i + 1] = M.n_rows();
1257 this->matrix_ptr[i + 1] = M.n_rows() * M.n_cols();
1260 for (
unsigned int i = 0; i < mass_and_derivative_matrices.size(); ++i)
1262 this->vector_ptr[i + 1] += this->vector_ptr[i];
1263 this->matrix_ptr[i + 1] += this->matrix_ptr[i];
1266 this->mass_matrices.resize_fast(matrix_ptr.back());
1267 this->derivative_matrices.resize_fast(matrix_ptr.back());
1268 this->eigenvectors.resize_fast(matrix_ptr.back());
1269 this->eigenvalues.resize_fast(vector_ptr.back());
1271 for (
unsigned int i = 0; i < mass_and_derivative_matrices.size(); ++i)
1272 store(i, mass_and_derivative_matrices[i]);
1274 mass_and_derivative_matrices.clear();
1276 else if (cache.size() == indices.size())
1280 this->vector_ptr.resize(cache.size() + 1);
1281 this->matrix_ptr.resize(cache.size() + 1);
1283 std::map<unsigned int, MatrixPairType> inverted_cache;
1285 for (
const auto &i : cache)
1288 for (
unsigned int i = 0; i < indices.size(); ++i)
1290 const auto &M = inverted_cache[indices[i]].first;
1292 this->vector_ptr[i + 1] = M.n_rows();
1293 this->matrix_ptr[i + 1] = M.n_rows() * M.n_cols();
1296 for (
unsigned int i = 0; i < cache.size(); ++i)
1298 this->vector_ptr[i + 1] += this->vector_ptr[i];
1299 this->matrix_ptr[i + 1] += this->matrix_ptr[i];
1302 this->mass_matrices.resize_fast(matrix_ptr.back());
1303 this->derivative_matrices.resize_fast(matrix_ptr.back());
1304 this->eigenvectors.resize_fast(matrix_ptr.back());
1305 this->eigenvalues.resize_fast(vector_ptr.back());
1307 for (
unsigned int i = 0; i < indices.size(); ++i)
1308 store(i, inverted_cache[indices[i]]);
1317 this->vector_ptr.resize(cache.size() + 1);
1318 this->matrix_ptr.resize(cache.size() + 1);
1320 for (
const auto &i : cache)
1322 const auto &M = i.first.second.first;
1324 this->vector_ptr[i.second + 1] = M.n_rows();
1325 this->matrix_ptr[i.second + 1] = M.n_rows() * M.n_cols();
1328 for (
unsigned int i = 0; i < cache.size(); ++i)
1330 this->vector_ptr[i + 1] += this->vector_ptr[i];
1331 this->matrix_ptr[i + 1] += this->matrix_ptr[i];
1334 this->mass_matrices.resize_fast(matrix_ptr.back());
1335 this->derivative_matrices.resize_fast(matrix_ptr.back());
1336 this->eigenvectors.resize_fast(matrix_ptr.back());
1337 this->eigenvalues.resize_fast(vector_ptr.back());
1339 for (
const auto &i : cache)
1345 if (precompute_inverse_diagonal)
1350 for (
unsigned int i = 0; i < this->eigenvalues.size(); ++i)
1351 this->eigenvalues[i] = Number(1.0) / this->eigenvalues[i];
1352 std::swap(this->inverted_eigenvalues,
eigenvalues);
1362 std::vector<unsigned int> indices_ev;
1364 if (indices.size() > 0)
1367 const unsigned int n_cells = indices.size() / dim;
1368 std::map<std::array<unsigned int, dim>,
unsigned int> cache_ev;
1369 std::vector<unsigned int> cache_ev_idx(n_cells);
1371 for (
unsigned int i = 0, c = 0; i <
n_cells; ++i)
1373 std::array<unsigned int, dim> id;
1375 for (
unsigned int d = 0;
d < dim; ++
d, ++c)
1378 const auto id_ptr = cache_ev.find(
id);
1380 if (id_ptr == cache_ev.end())
1382 const auto size = cache_ev.size();
1383 cache_ev_idx[i] =
size;
1384 cache_ev[id] =
size;
1388 cache_ev_idx[i] = id_ptr->second;
1393 std::vector<unsigned int> new_indices;
1394 new_indices.reserve(indices.size() / dim * (dim + 1));
1396 for (
unsigned int i = 0, c = 0; i <
n_cells; ++i)
1398 for (
unsigned int d = 0;
d < dim; ++
d, ++c)
1399 new_indices.push_back(indices[c]);
1400 new_indices.push_back(cache_ev_idx[i]);
1404 indices_ev.resize(cache_ev.size() * dim);
1405 for (
const auto &entry : cache_ev)
1406 for (unsigned
int d = 0;
d < dim; ++
d)
1407 indices_ev[entry.second * dim + d] = entry.first[d];
1409 std::swap(this->indices, new_indices);
1413 const unsigned int n_diag =
1414 ((indices_ev.size() > 0) ? indices_ev.size() :
1415 (matrix_ptr.size() - 1)) /
1418 std::vector<unsigned int> new_vector_ptr(n_diag + 1, 0);
1419 std::vector<unsigned int> new_vector_n_rows_1d(n_diag, 0);
1421 for (
unsigned int i = 0; i < n_diag; ++i)
1423 const unsigned int c = (indices_ev.size() > 0) ?
1424 indices_ev[dim * i + 0] :
1427 const unsigned int n_rows = vector_ptr[c + 1] - vector_ptr[c];
1429 new_vector_n_rows_1d[i] = n_rows;
1433 for (
unsigned int i = 0; i < n_diag; ++i)
1434 new_vector_ptr[i + 1] += new_vector_ptr[i];
1436 this->inverted_eigenvalues.resize(new_vector_ptr.back());
1439 for (
unsigned int i = 0; i < n_diag; ++i)
1441 std::array<Number *, dim> evs;
1443 for (
unsigned int d = 0;
d < dim; ++
d)
1446 ->
eigenvalues[this->vector_ptr[(indices_ev.size() > 0) ?
1447 indices_ev[dim * i +
d] :
1450 const unsigned int mm = new_vector_n_rows_1d[i];
1453 for (
unsigned int i1 = 0, c = 0; i1 < mm; ++i1)
1454 for (
unsigned int i0 = 0; i0 < mm; ++i0, ++c)
1455 this->inverted_eigenvalues[new_vector_ptr[i] + c] =
1456 Number(1.0) / (evs[1][i1] + evs[0][i0]);
1460 for (
unsigned int i2 = 0, c = 0; i2 < mm; ++i2)
1461 for (
unsigned int i1 = 0; i1 < mm; ++i1)
1462 for (
unsigned int i0 = 0; i0 < mm; ++i0, ++c)
1463 this->inverted_eigenvalues[new_vector_ptr[i] + c] =
1464 Number(1.0) / (evs[2][i2] + evs[1][i1] + evs[0][i0]);
1469 std::swap(this->vector_ptr, new_vector_ptr);
1470 std::swap(this->vector_n_rows_1d, new_vector_n_rows_1d);
1473 this->eigenvalues.clear();
1479template <
int dim,
typename Number,
int n_rows_1d>
1486 Number *dst = dst_in.
begin();
1487 const Number *src = src_in.
begin();
1489 if (this->eigenvalues.empty() ==
false)
1493 unsigned int n_rows_1d_non_templated = 0;
1495 for (
unsigned int d = 0;
d < dim; ++
d)
1497 const unsigned int translated_index =
1498 (indices.size() > 0) ? indices[dim * index + d] : (dim *
index +
d);
1501 this->eigenvectors.data() + matrix_ptr[translated_index];
1503 this->eigenvalues.data() + vector_ptr[translated_index];
1504 n_rows_1d_non_templated =
1505 vector_ptr[translated_index + 1] - vector_ptr[translated_index];
1508 if (n_rows_1d != -1)
1509 internal::TensorProductMatrixSymmetricSum::apply_inverse<
1510 n_rows_1d == -1 ? 0 : n_rows_1d>(
1513 internal::TensorProductMatrixSymmetricSum::select_apply_inverse<1>(
1519 const Number *inverted_eigenvalues =
nullptr;
1520 unsigned int n_rows_1d_non_templated = 0;
1522 for (
unsigned int d = 0;
d < dim; ++
d)
1524 const unsigned int translated_index =
1525 (indices.size() > 0) ?
1526 indices[((dim == 1) ? 1 : (dim + 1)) *
index +
d] :
1530 this->eigenvectors.data() + matrix_ptr[translated_index];
1534 const unsigned int translated_index =
1535 ((indices.size() > 0) && (dim != 1)) ?
1536 indices[(dim + 1) *
index + dim] :
1539 inverted_eigenvalues =
1540 this->inverted_eigenvalues.data() + vector_ptr[translated_index];
1541 n_rows_1d_non_templated =
1543 (vector_ptr[translated_index + 1] - vector_ptr[translated_index]) :
1544 vector_n_rows_1d[translated_index];
1547 if (n_rows_1d != -1)
1548 internal::TensorProductMatrixSymmetricSum::apply_inverse<
1549 n_rows_1d == -1 ? 0 : n_rows_1d>(dst,
1551 n_rows_1d_non_templated,
1554 inverted_eigenvalues);
1556 internal::TensorProductMatrixSymmetricSum::select_apply_inverse<1>(
1559 n_rows_1d_non_templated,
1562 inverted_eigenvalues);
1568template <
int dim,
typename Number,
int n_rows_1d>
1584template <
int dim,
typename Number,
int n_rows_1d>
1589 if (matrix_ptr.empty())
1592 return matrix_ptr.size() - 1;
void resize_fast(const size_type new_size)
std::complex< typename numbers::NumberTraits< number >::real_type > eigenvalue(const size_type i) const
void compute_generalized_eigenvalues_symmetric(LAPACKFullMatrix< number > &B, const number lower_bound, const number upper_bound, const number abs_accuracy, Vector< number > &eigenvalues, std::vector< Vector< number > > &eigenvectors, const types::blas_int itype=1)
std::size_t storage_size() const
AlignedVector< Number > mass_matrices
const bool precompute_inverse_diagonal
std::size_t memory_consumption() const
std::vector< unsigned int > matrix_ptr
void apply_inverse(const unsigned int index, const ArrayView< Number > &dst_in, const ArrayView< const Number > &src_in) const
AlignedVector< Number > eigenvectors
std::vector< unsigned int > vector_ptr
const bool compress_matrices
std::vector< MatrixPairType > mass_and_derivative_matrices
std::pair< std::bitset<::internal::VectorizedArrayTrait< Number >::width()>, MatrixPairType > MatrixPairTypeWithMask
std::pair< Table< 2, Number >, Table< 2, Number > > MatrixPairType
void reserve(const unsigned int size)
void insert(const unsigned int index, const T &Ms, const T &Ks)
AlignedVector< Number > inverted_eigenvalues
std::vector< unsigned int > indices
std::vector< unsigned int > vector_n_rows_1d
std::map< MatrixPairTypeWithMask, unsigned int, internal::TensorProductMatrixSymmetricSum::MatrixPairComparator< Number > > cache
AlignedVector< Number > eigenvalues
AlignedVector< Number > derivative_matrices
TensorProductMatrixSymmetricSumCollection(const AdditionalData &additional_data=AdditionalData())
void vmult(const ArrayView< Number > &dst, const ArrayView< const Number > &src, AlignedVector< Number > &tmp) const
std::array< Table< 2, Number >, dim > eigenvectors
std::array< Table< 2, Number >, dim > derivative_matrix
void reinit(const T &mass_matrix, const T &derivative_matrix)
void apply_inverse(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const
void vmult(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const
AlignedVector< Number > tmp_array
static constexpr int n_rows_1d_static
std::size_t memory_consumption() const
TensorProductMatrixSymmetricSum()=default
std::array< Table< 2, Number >, dim > mass_matrix
std::array< AlignedVector< Number >, dim > eigenvalues
TensorProductMatrixSymmetricSum(const T &mass_matrix, const T &derivative_matrix)
static constexpr std::size_t size()
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcInternalError()
#define AssertThrow(cond, exc)
#define DEAL_II_NOT_IMPLEMENTED()
@ matrix
Contents is actually a matrix.
void mass_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const double factor=1.)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
constexpr T pow(const T base, const int iexp)
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
static const unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
bool precompute_inverse_diagonal
AdditionalData(const bool compress_matrices=true, const bool precompute_inverse_diagonal=true)
typename VectorizedArrayTrait::value_type ScalarNumber
bool operator()(const MatrixPairType &left, const MatrixPairType &right) const
std::pair< std::bitset< width >, std::pair< Table< 2, Number >, Table< 2, Number > > > MatrixPairType
static constexpr std::size_t width
static constexpr std::size_t width()
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)