16 #ifndef dealii_tensor_product_matrix_h 17 #define dealii_tensor_product_matrix_h 20 #include <deal.II/base/config.h> 22 #include <deal.II/base/array_view.h> 23 #include <deal.II/base/thread_management.h> 25 #include <deal.II/lac/lapack_full_matrix.h> 27 #include <deal.II/matrix_free/tensor_product_kernels.h> 29 DEAL_II_NAMESPACE_OPEN
72 template <
int dim,
typename Number,
int size = -1>
224 template <
int dim,
typename Number,
int size = -1>
303 template <
typename MatrixArray>
305 reinit_impl(MatrixArray &&mass_matrix, MatrixArray &&derivative_matrix);
318 template <
int dim,
typename Number,
int size>
321 VectorizedArray<Number>,
385 template <
typename MatrixArray>
397 namespace TensorProductMatrix
407 template <
typename Number>
411 const unsigned int n_rows,
412 const unsigned int n_cols,
418 auto &&transpose_fill_nm = [](Number * out,
420 const unsigned int n,
421 const unsigned int m) {
422 for (
unsigned int mm = 0; mm <
m; ++mm)
423 for (
unsigned int nn = 0; nn <
n; ++nn)
424 out[mm + nn * m] = *(in++);
427 std::vector<::Vector<Number>> eigenvecs(n_rows);
431 transpose_fill_nm(&(mass_copy(0, 0)), mass_matrix, n_rows, n_cols);
432 transpose_fill_nm(&(deriv_copy(0, 0)), derivative_matrix, n_rows, n_cols);
437 for (
unsigned int i = 0; i < n_rows; ++i)
438 for (
unsigned int j = 0; j < n_cols; ++j, ++
eigenvectors)
439 *eigenvectors = eigenvecs[j][i];
441 for (
unsigned int i = 0; i < n_rows; ++i, ++
eigenvalues)
442 *eigenvalues = deriv_copy.
eigenvalue(i).real();
448 template <
int dim,
typename Number,
int size>
453 for (
unsigned int d = 1; d < dim; ++d)
460 template <
int dim,
typename Number,
int size>
465 for (
unsigned int d = 1; d < dim; ++d)
472 template <
int dim,
typename Number,
int size>
481 const unsigned int n =
482 Utilities::fixed_power<dim>(size > 0 ? size :
eigenvalues[0].size());
484 constexpr
int kernel_size = size > 0 ? size : 0;
496 const Number *src = src_view.
begin();
497 Number * dst = &(dst_view[0]);
502 eval.template apply<0, false, false>(A, src, dst);
511 eval.template apply<0, false, false>(M0, src, t);
512 eval.template apply<1, false, false>(A1, t, dst);
513 eval.template apply<0, false, false>(A0, src, t);
514 eval.template apply<1, false, true>(M1, t, dst);
525 eval.template apply<0, false, false>(M0, src, t +
n);
526 eval.template apply<1, false, false>(M1, t +
n, t);
527 eval.template apply<2, false, false>(A2, t, dst);
528 eval.template apply<1, false, false>(A1, t +
n, t);
529 eval.template apply<0, false, false>(A0, src, t +
n);
530 eval.template apply<1, false, true>(M1, t +
n, t);
531 eval.template apply<2, false, true>(M2, t, dst);
540 template <
int dim,
typename Number,
int size>
549 const unsigned int n = size > 0 ? size :
eigenvalues[0].size();
551 constexpr
int kernel_size = size > 0 ? size : 0;
563 const Number *src = src_view.
data();
564 Number * dst = &(dst_view[0]);
574 eval.template apply<0, true, false>(S, src, t);
575 for (
unsigned int i = 0; i <
n; ++i)
577 eval.template apply<0, false, false>(S, t, dst);
584 eval.template apply<0, true, false>(S0, src, t);
585 eval.template apply<1, true, false>(S1, t, dst);
586 for (
unsigned int i1 = 0, c = 0; i1 <
n; ++i1)
587 for (
unsigned int i0 = 0; i0 <
n; ++i0, ++c)
589 eval.template apply<0, false, false>(S0, dst, t);
590 eval.template apply<1, false, false>(S1, t, dst);
598 eval.template apply<0, true, false>(S0, src, t);
599 eval.template apply<1, true, false>(S1, t, dst);
600 eval.template apply<2, true, false>(S2, dst, t);
601 for (
unsigned int i2 = 0, c = 0; i2 <
n; ++i2)
602 for (
unsigned int i1 = 0; i1 <
n; ++i1)
603 for (
unsigned int i0 = 0; i0 <
n; ++i0, ++c)
606 eval.template apply<0, false, false>(S0, t, dst);
607 eval.template apply<1, false, false>(S1, dst, t);
608 eval.template apply<2, false, false>(S2, t, dst);
618 template <
int dim,
typename Number,
int size>
629 template <
int dim,
typename Number,
int size>
640 template <
int dim,
typename Number,
int size>
645 reinit(mass_matrix, derivative_matrix);
650 template <
int dim,
typename Number,
int size>
651 template <
typename MatrixArray>
654 MatrixArray &&mass_matrices_,
655 MatrixArray &&derivative_matrices_)
657 auto &&mass_matrices = std::forward<MatrixArray>(mass_matrices_);
658 auto &&derivative_matrices = std::forward<MatrixArray>(derivative_matrices_);
659 this->mass_matrix = mass_matrices;
660 this->derivative_matrix = derivative_matrices;
662 for (
int dir = 0; dir < dim; ++dir)
664 Assert(size == -1 || (size > 0 && static_cast<unsigned int>(size) ==
665 mass_matrices[dir].n_rows()),
667 AssertDimension(mass_matrices[dir].n_rows(), mass_matrices[dir].n_cols());
669 derivative_matrices[dir].n_rows());
671 derivative_matrices[dir].n_cols());
673 this->
eigenvectors[dir].reinit(mass_matrices[dir].n_cols(),
674 mass_matrices[dir].n_rows());
675 this->
eigenvalues[dir].resize(mass_matrices[dir].n_cols());
676 internal::TensorProductMatrix ::spectral_assembly<Number>(
677 &(mass_matrices[dir](0, 0)),
678 &(derivative_matrices[dir](0, 0)),
679 mass_matrices[dir].n_rows(),
680 mass_matrices[dir].n_cols(),
688 template <
int dim,
typename Number,
int size>
694 reinit_impl(mass_matrix, derivative_matrix);
699 template <
int dim,
typename Number,
int size>
705 std::array<Table<2, Number>, dim> mass_copy;
706 std::array<Table<2, Number>, dim> deriv_copy;
708 std::transform(mass_matrix.cbegin(),
714 std::transform(derivative_matrix.cbegin(),
715 derivative_matrix.cend(),
721 reinit_impl(std::move(mass_copy), std::move(deriv_copy));
726 template <
int dim,
typename Number,
int size>
732 std::array<Table<2, Number>, dim> mass_matrices;
733 std::array<Table<2, Number>, dim> derivative_matrices;
735 std::fill(mass_matrices.begin(), mass_matrices.end(),
mass_matrix);
736 std::fill(derivative_matrices.begin(),
737 derivative_matrices.end(),
740 reinit_impl(std::move(mass_matrices), std::move(derivative_matrices));
747 template <
int dim,
typename Number,
int size>
753 reinit(mass_matrix, derivative_matrix);
758 template <
int dim,
typename Number,
int size>
764 reinit(mass_matrix, derivative_matrix);
769 template <
int dim,
typename Number,
int size>
770 template <
typename MatrixArray>
773 reinit_impl(MatrixArray &&mass_matrices_, MatrixArray &&derivative_matrices_)
775 auto &&mass_matrix = std::forward<MatrixArray>(mass_matrices_);
776 auto &&derivative_matrix = std::forward<MatrixArray>(derivative_matrices_);
781 std::size_t n_rows_max = (size > 0) ? size : 0;
783 for (
unsigned int d = 0; d < dim; ++d)
784 n_rows_max = std::max(n_rows_max, mass_matrix[d].n_rows());
785 const std::size_t nm_flat_size_max = n_rows_max * n_rows_max * macro_size;
786 const std::size_t n_flat_size_max = n_rows_max * macro_size;
788 std::vector<Number> mass_matrix_flat;
789 std::vector<Number> deriv_matrix_flat;
790 std::vector<Number> eigenvalues_flat;
791 std::vector<Number> eigenvectors_flat;
792 mass_matrix_flat.resize(nm_flat_size_max);
793 deriv_matrix_flat.resize(nm_flat_size_max);
794 eigenvalues_flat.resize(n_flat_size_max);
795 eigenvectors_flat.resize(nm_flat_size_max);
796 std::array<unsigned int, macro_size> offsets_nm;
797 std::array<unsigned int, macro_size> offsets_n;
798 for (
int dir = 0; dir < dim; ++dir)
800 Assert(size == -1 || (size > 0 && static_cast<unsigned int>(size) ==
801 mass_matrix[dir].n_rows()),
805 derivative_matrix[dir].n_rows());
807 derivative_matrix[dir].n_cols());
809 const unsigned int n_rows = mass_matrix[dir].n_rows();
810 const unsigned int n_cols = mass_matrix[dir].n_cols();
811 const unsigned int nm = n_rows * n_cols;
812 for (
unsigned int vv = 0; vv < macro_size; ++vv)
813 offsets_nm[vv] = nm * vv;
815 vectorized_transpose_and_store(
false,
817 &(mass_matrix[dir](0, 0)),
819 mass_matrix_flat.data());
820 vectorized_transpose_and_store(
false,
822 &(derivative_matrix[dir](0, 0)),
824 deriv_matrix_flat.data());
826 const Number *mass_cbegin = mass_matrix_flat.data();
827 const Number *deriv_cbegin = deriv_matrix_flat.data();
828 Number * eigenvec_begin = eigenvectors_flat.data();
829 Number * eigenval_begin = eigenvalues_flat.data();
830 for (
unsigned int lane = 0; lane < macro_size; ++lane)
831 internal::TensorProductMatrix ::spectral_assembly<Number>(
832 mass_cbegin + nm * lane,
833 deriv_cbegin + nm * lane,
836 eigenval_begin + n_rows * lane,
837 eigenvec_begin + nm * lane);
841 for (
unsigned int vv = 0; vv < macro_size; ++vv)
842 offsets_n[vv] = n_rows * vv;
843 vectorized_load_and_transpose(n_rows,
844 eigenvalues_flat.data(),
847 vectorized_load_and_transpose(nm,
848 eigenvectors_flat.data(),
856 template <
int dim,
typename Number,
int size>
862 reinit_impl(mass_matrix, derivative_matrix);
867 template <
int dim,
typename Number,
int size>
873 std::array<Table<2, VectorizedArray<Number>>, dim> mass_matrices;
874 std::array<Table<2, VectorizedArray<Number>>, dim> derivative_matrices;
876 std::fill(mass_matrices.begin(), mass_matrices.end(),
mass_matrix);
877 std::fill(derivative_matrices.begin(),
878 derivative_matrices.end(),
881 reinit_impl(std::move(mass_matrices), std::move(derivative_matrices));
888 DEAL_II_NAMESPACE_CLOSE
#define AssertDimension(dim1, dim2)
std::array< Table< 2, Number >, dim > derivative_matrix
std::array< AlignedVector< Number >, dim > eigenvalues
AlignedVector< Number > tmp_array
void reinit(const std::array< Table< 2, Number >, dim > &mass_matrix, const std::array< Table< 2, Number >, dim > &derivative_matrix)
TensorProductMatrixSymmetricSum()=default
#define AssertThrow(cond, exc)
std::array< Table< 2, Number >, dim > mass_matrix
void reinit_impl(MatrixArray &&mass_matrix, MatrixArray &&derivative_matrix)
void apply_inverse(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const
#define Assert(cond, exc)
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void vmult(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const
TensorProductMatrixSymmetricSumBase()=default
void resize_fast(const size_type size)
std::array< Table< 2, Number >, dim > eigenvectors
value_type * data() const noexcept
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)
static::ExceptionBase & ExcNotImplemented()
std::complex< number > eigenvalue(const size_type i) const