16 #ifndef dealii_tensor_product_matrix_h
17 #define dealii_tensor_product_matrix_h
75 template <
int dim,
typename Number,
int n_rows_1d = -1>
241 template <
int dim,
typename Number,
int n_rows_1d = -1>
320 template <
typename MatrixArray>
335 template <
int dim,
typename Number,
int n_rows_1d>
338 VectorizedArray<Number>,
402 template <
typename MatrixArray>
414 namespace TensorProductMatrix
424 template <
typename Number>
427 const Number * derivative_matrix,
428 const unsigned int n_rows,
429 const unsigned int n_cols,
435 auto &&transpose_fill_nm = [](Number * out,
437 const unsigned int n,
438 const unsigned int m) {
439 for (
unsigned int mm = 0; mm < m; ++mm)
440 for (
unsigned int nn = 0; nn < n; ++nn)
441 out[mm + nn * m] = *(in++);
444 std::vector<::Vector<Number>> eigenvecs(n_rows);
448 transpose_fill_nm(&(mass_copy(0, 0)),
mass_matrix, n_rows, n_cols);
449 transpose_fill_nm(&(deriv_copy(0, 0)), derivative_matrix, n_rows, n_cols);
451 deriv_copy.compute_generalized_eigenvalues_symmetric(mass_copy,
454 for (
unsigned int i = 0; i < n_rows; ++i)
455 for (
unsigned int j = 0; j < n_cols; ++j, ++
eigenvectors)
458 for (
unsigned int i = 0; i < n_rows; ++i, ++
eigenvalues)
465 template <
int dim,
typename Number,
int n_rows_1d>
470 for (
unsigned int d = 1;
d < dim; ++
d)
477 template <
int dim,
typename Number,
int n_rows_1d>
482 for (
unsigned int d = 1;
d < dim; ++
d)
489 template <
int dim,
typename Number,
int n_rows_1d>
497 std::lock_guard<std::mutex> lock(this->mutex);
498 const unsigned int n = Utilities::fixed_power<dim>(
499 n_rows_1d > 0 ? n_rows_1d :
eigenvalues[0].size());
500 tmp_array.resize_fast(n * 2);
501 constexpr
int kernel_size = n_rows_1d > 0 ? n_rows_1d : 0;
512 Number * t = tmp_array.begin();
513 const Number *src = src_view.
begin();
514 Number * dst = dst_view.
data();
518 const Number *
A = &derivative_matrix[0](0, 0);
519 eval.template apply<0, false, false>(
A, src, dst);
524 const Number *A0 = &derivative_matrix[0](0, 0);
526 const Number *A1 = &derivative_matrix[1](0, 0);
528 eval.template apply<0, false, false>(M0, src, t);
529 eval.template apply<1, false, false>(A1, t, dst);
530 eval.template apply<0, false, false>(A0, src, t);
531 eval.template apply<1, false, true>(M1, t, dst);
536 const Number *A0 = &derivative_matrix[0](0, 0);
538 const Number *A1 = &derivative_matrix[1](0, 0);
540 const Number *A2 = &derivative_matrix[2](0, 0);
542 eval.template apply<0, false, false>(M0, src, t + n);
543 eval.template apply<1, false, false>(M1, t + n, t);
544 eval.template apply<2, false, false>(A2, t, dst);
545 eval.template apply<1, false, false>(A1, t + n, t);
546 eval.template apply<0, false, false>(A0, src, t + n);
547 eval.template apply<1, false, true>(M1, t + n, t);
548 eval.template apply<2, false, true>(M2, t, dst);
557 template <
int dim,
typename Number,
int n_rows_1d>
565 std::lock_guard<std::mutex> lock(this->mutex);
566 const unsigned int n = n_rows_1d > 0 ? n_rows_1d :
eigenvalues[0].size();
567 tmp_array.resize_fast(Utilities::fixed_power<dim>(n));
568 constexpr
int kernel_size = n_rows_1d > 0 ? n_rows_1d : 0;
579 Number * t = tmp_array.begin();
580 const Number *src = src_view.
data();
581 Number * dst = dst_view.
data();
591 eval.template apply<0, true, false>(S, src, t);
592 for (
unsigned int i = 0; i < n; ++i)
594 eval.template apply<0, false, false>(S, t, dst);
601 eval.template apply<0, true, false>(S0, src, t);
602 eval.template apply<1, true, false>(S1, t, dst);
603 for (
unsigned int i1 = 0, c = 0; i1 < n; ++i1)
604 for (
unsigned int i0 = 0; i0 < n; ++i0, ++c)
606 eval.template apply<0, false, false>(S0, dst, t);
607 eval.template apply<1, false, false>(S1, t, dst);
615 eval.template apply<0, true, false>(S0, src, t);
616 eval.template apply<1, true, false>(S1, t, dst);
617 eval.template apply<2, true, false>(S2, dst, t);
618 for (
unsigned int i2 = 0, c = 0; i2 < n; ++i2)
619 for (
unsigned int i1 = 0; i1 < n; ++i1)
620 for (
unsigned int i0 = 0; i0 < n; ++i0, ++c)
623 eval.template apply<0, false, false>(S0, t, dst);
624 eval.template apply<1, false, false>(S1, dst, t);
625 eval.template apply<2, false, false>(S2, t, dst);
635 template <
int dim,
typename Number,
int n_rows_1d>
646 template <
int dim,
typename Number,
int n_rows_1d>
657 template <
int dim,
typename Number,
int n_rows_1d>
667 template <
int dim,
typename Number,
int n_rows_1d>
668 template <
typename MatrixArray>
671 MatrixArray &&mass_matrices_,
672 MatrixArray &&derivative_matrices_)
674 auto &&mass_matrices = std::forward<MatrixArray>(mass_matrices_);
675 auto &&derivative_matrices = std::forward<MatrixArray>(derivative_matrices_);
676 this->mass_matrix = mass_matrices;
677 this->derivative_matrix = derivative_matrices;
679 for (
int dir = 0; dir < dim; ++dir)
682 (n_rows_1d > 0 &&
static_cast<unsigned int>(n_rows_1d) ==
683 mass_matrices[dir].n_rows()),
685 AssertDimension(mass_matrices[dir].n_rows(), mass_matrices[dir].n_cols());
687 derivative_matrices[dir].n_rows());
689 derivative_matrices[dir].n_cols());
691 this->eigenvectors[dir].reinit(mass_matrices[dir].n_cols(),
692 mass_matrices[dir].n_rows());
693 this->eigenvalues[dir].resize(mass_matrices[dir].n_cols());
694 internal::TensorProductMatrix::spectral_assembly<Number>(
695 &(mass_matrices[dir](0, 0)),
696 &(derivative_matrices[dir](0, 0)),
697 mass_matrices[dir].n_rows(),
698 mass_matrices[dir].n_cols(),
699 this->eigenvalues[dir].
begin(),
700 &(this->eigenvectors[dir](0, 0)));
706 template <
int dim,
typename Number,
int n_rows_1d>
717 template <
int dim,
typename Number,
int n_rows_1d>
723 std::array<Table<2, Number>, dim> mass_copy;
724 std::array<Table<2, Number>, dim> deriv_copy;
733 derivative_matrix.cend(),
739 reinit_impl(std::move(mass_copy), std::move(deriv_copy));
744 template <
int dim,
typename Number,
int n_rows_1d>
750 std::array<Table<2, Number>, dim> mass_matrices;
751 std::array<Table<2, Number>, dim> derivative_matrices;
753 std::fill(mass_matrices.begin(), mass_matrices.end(),
mass_matrix);
754 std::fill(derivative_matrices.begin(),
755 derivative_matrices.end(),
758 reinit_impl(std::move(mass_matrices), std::move(derivative_matrices));
765 template <
int dim,
typename Number,
int n_rows_1d>
769 TensorProductMatrixSymmetricSum(
778 template <
int dim,
typename Number,
int n_rows_1d>
782 TensorProductMatrixSymmetricSum(
791 template <
int dim,
typename Number,
int n_rows_1d>
792 template <
typename MatrixArray>
795 reinit_impl(MatrixArray &&mass_matrices_, MatrixArray &&derivative_matrices_)
797 auto &&
mass_matrix = std::forward<MatrixArray>(mass_matrices_);
798 auto &&derivative_matrix = std::forward<MatrixArray>(derivative_matrices_);
800 this->derivative_matrix = derivative_matrix;
803 std::size_t n_rows_max = (n_rows_1d > 0) ? n_rows_1d : 0;
805 for (
unsigned int d = 0;
d < dim; ++
d)
807 const std::size_t nm_flat_size_max = n_rows_max * n_rows_max * macro_size;
808 const std::size_t n_flat_size_max = n_rows_max * macro_size;
810 std::vector<Number> mass_matrix_flat;
811 std::vector<Number> deriv_matrix_flat;
812 std::vector<Number> eigenvalues_flat;
813 std::vector<Number> eigenvectors_flat;
814 mass_matrix_flat.resize(nm_flat_size_max);
815 deriv_matrix_flat.resize(nm_flat_size_max);
816 eigenvalues_flat.resize(n_flat_size_max);
817 eigenvectors_flat.resize(nm_flat_size_max);
818 std::array<unsigned int, macro_size> offsets_nm;
819 std::array<unsigned int, macro_size> offsets_n;
820 for (
int dir = 0; dir < dim; ++dir)
823 (n_rows_1d > 0 &&
static_cast<unsigned int>(n_rows_1d) ==
828 derivative_matrix[dir].n_rows());
830 derivative_matrix[dir].n_cols());
832 const unsigned int n_rows =
mass_matrix[dir].n_rows();
833 const unsigned int n_cols =
mass_matrix[dir].n_cols();
834 const unsigned int nm = n_rows * n_cols;
835 for (
unsigned int vv = 0; vv < macro_size; ++vv)
836 offsets_nm[vv] = nm * vv;
842 mass_matrix_flat.data());
845 &(derivative_matrix[dir](0, 0)),
847 deriv_matrix_flat.data());
849 const Number *mass_cbegin = mass_matrix_flat.data();
850 const Number *deriv_cbegin = deriv_matrix_flat.data();
851 Number * eigenvec_begin = eigenvectors_flat.data();
852 Number * eigenval_begin = eigenvalues_flat.data();
853 for (
unsigned int lane = 0; lane < macro_size; ++lane)
854 internal::TensorProductMatrix::spectral_assembly<Number>(
855 mass_cbegin + nm * lane,
856 deriv_cbegin + nm * lane,
859 eigenval_begin + n_rows * lane,
860 eigenvec_begin + nm * lane);
862 this->eigenvalues[dir].resize(n_rows);
863 this->eigenvectors[dir].reinit(n_rows, n_cols);
864 for (
unsigned int vv = 0; vv < macro_size; ++vv)
865 offsets_n[vv] = n_rows * vv;
867 eigenvalues_flat.data(),
869 this->eigenvalues[dir].begin());
871 eigenvectors_flat.data(),
873 &(this->eigenvectors[dir](0, 0)));
879 template <
int dim,
typename Number,
int n_rows_1d>
891 template <
int dim,
typename Number,
int n_rows_1d>
897 std::array<Table<2, VectorizedArray<Number>>, dim> mass_matrices;
898 std::array<Table<2, VectorizedArray<Number>>, dim> derivative_matrices;
900 std::fill(mass_matrices.begin(), mass_matrices.end(),
mass_matrix);
901 std::fill(derivative_matrices.begin(),
902 derivative_matrices.end(),
905 reinit_impl(std::move(mass_matrices), std::move(derivative_matrices));