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>
318 template <
int dim,
typename Number,
int size>
321 VectorizedArray<Number>,
385 template <
typename MatrixArray>
397 namespace TensorProductMatrix
407 template <
typename Number>
409 spectral_assembly(
const Number * mass_matrix,
410 const Number * derivative_matrix,
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);
434 deriv_copy.compute_generalized_eigenvalues_symmetric(mass_copy,
437 for (
unsigned int i = 0; i < n_rows; ++i)
438 for (
unsigned int j = 0; j < n_cols; ++j, ++
eigenvectors)
441 for (
unsigned int i = 0; i < n_rows; ++i, ++
eigenvalues)
448 template <
int dim,
typename Number,
int size>
453 for (
unsigned int d = 1;
d < dim; ++
d)
454 m *= mass_matrix[d].n_rows();
460 template <
int dim,
typename Number,
int size>
465 for (
unsigned int d = 1;
d < dim; ++
d)
466 n *= mass_matrix[d].n_cols();
472 template <
int dim,
typename Number,
int size>
480 std::lock_guard<std::mutex> lock(this->mutex);
481 const unsigned int n =
482 Utilities::fixed_power<dim>(size > 0 ? size :
eigenvalues[0].size());
483 tmp_array.resize_fast(n * 2);
484 constexpr
int kernel_size = size > 0 ? size : 0;
495 Number * t = tmp_array.begin();
496 const Number *src = src_view.
begin();
497 Number * dst = dst_view.
data();
501 const Number *A = &derivative_matrix[0](0, 0);
502 eval.template apply<0, false, false>(A, src, dst);
507 const Number *A0 = &derivative_matrix[0](0, 0);
509 const Number *A1 = &derivative_matrix[1](0, 0);
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);
519 const Number *A0 = &derivative_matrix[0](0, 0);
521 const Number *A1 = &derivative_matrix[1](0, 0);
523 const Number *A2 = &derivative_matrix[2](0, 0);
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>
548 std::lock_guard<std::mutex> lock(this->mutex);
549 const unsigned int n = size > 0 ? size :
eigenvalues[0].size();
550 tmp_array.resize_fast(Utilities::fixed_power<dim>(n));
551 constexpr
int kernel_size = size > 0 ? size : 0;
560 mass_matrix[0].n_rows(),
561 mass_matrix[0].n_rows());
562 Number * t = tmp_array.begin();
563 const Number *src = src_view.
data();
564 Number * dst = dst_view.
data();
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>
624 reinit(mass_matrix, derivative_matrix);
629 template <
int dim,
typename Number,
int size>
635 reinit(mass_matrix, derivative_matrix);
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(),
681 this->eigenvalues[dir].begin(),
682 &(this->eigenvectors[dir](0, 0)));
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;
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>
749 TensorProductMatrixSymmetricSum(
753 reinit(mass_matrix, derivative_matrix);
758 template <
int dim,
typename Number,
int size>
760 TensorProductMatrixSymmetricSum(
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_);
778 this->derivative_matrix = derivative_matrix;
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;
817 &(mass_matrix[dir](0, 0)),
819 mass_matrix_flat.data());
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);
839 this->eigenvalues[dir].resize(n_rows);
840 this->eigenvectors[dir].reinit(n_rows, n_cols);
841 for (
unsigned int vv = 0; vv < macro_size; ++vv)
842 offsets_n[vv] = n_rows * vv;
844 eigenvalues_flat.data(),
846 this->eigenvalues[dir].begin());
848 eigenvectors_flat.data(),
850 &(this->eigenvectors[dir](0, 0)));
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
std::array< std::pair< Number, Tensor< 1, dim, Number > >, std::integral_constant< int, dim >::value > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)
AlignedVector< Number > tmp_array
void reinit(const std::array< Table< 2, Number >, dim > &mass_matrix, const std::array< Table< 2, Number >, dim > &derivative_matrix)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, std::integral_constant< int, dim >::value > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)
TensorProductMatrixSymmetricSum()=default
#define AssertThrow(cond, exc)
std::array< Table< 2, Number >, dim > mass_matrix
LinearAlgebra::distributed::Vector< Number > Vector
void reinit_impl(MatrixArray &&mass_matrix, MatrixArray &&derivative_matrix)
void vectorized_transpose_and_store(const bool add_into, const unsigned int n_entries, const VectorizedArray< Number > *in, const unsigned int *offsets, Number *out)
void mass_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const double factor=1.)
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
value_type * data() const noexcept
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
void vectorized_load_and_transpose(const unsigned int n_entries, const Number *in, const unsigned int *offsets, VectorizedArray< Number > *out)
TensorProductMatrixSymmetricSumBase()=default
std::array< Table< 2, Number >, dim > eigenvectors
void vmult(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const
static ::ExceptionBase & ExcNotImplemented()
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
void apply_inverse(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const