16#ifndef dealii_tensor_product_matrix_h
17#define dealii_tensor_product_matrix_h
73template <
int dim,
typename Number,
int n_rows_1d = -1>
237template <
int dim,
typename Number,
int n_rows_1d = -1>
316 template <
typename MatrixArray>
329template <
int dim,
typename Number,
int n_rows_1d>
332 VectorizedArray<Number>,
396 template <
typename MatrixArray>
408 namespace TensorProductMatrix
418 template <
typename Number>
420 spectral_assembly(
const Number * mass_matrix,
421 const Number * derivative_matrix,
422 const unsigned int n_rows,
423 const unsigned int n_cols,
429 auto &&transpose_fill_nm = [](Number * out,
431 const unsigned int n,
432 const unsigned int m) {
433 for (
unsigned int mm = 0; mm < m; ++mm)
434 for (
unsigned int nn = 0; nn < n; ++nn)
435 out[mm + nn * m] = *(in++);
438 std::vector<::Vector<Number>> eigenvecs(n_rows);
442 transpose_fill_nm(&(mass_copy(0, 0)), mass_matrix, n_rows, n_cols);
443 transpose_fill_nm(&(deriv_copy(0, 0)), derivative_matrix, n_rows, n_cols);
445 deriv_copy.compute_generalized_eigenvalues_symmetric(mass_copy,
448 for (
unsigned int i = 0; i < n_rows; ++i)
449 for (
unsigned int j = 0; j < n_cols; ++j, ++
eigenvectors)
452 for (
unsigned int i = 0; i < n_rows; ++i, ++
eigenvalues)
459template <
int dim,
typename Number,
int n_rows_1d>
464 for (
unsigned int d = 1;
d < dim; ++
d)
465 m *= mass_matrix[d].n_rows();
471template <
int dim,
typename Number,
int n_rows_1d>
476 for (
unsigned int d = 1;
d < dim; ++
d)
477 n *= mass_matrix[d].n_cols();
483template <
int dim,
typename Number,
int n_rows_1d>
491 std::lock_guard<std::mutex> lock(this->mutex);
492 const unsigned int n = Utilities::fixed_power<dim>(
493 n_rows_1d > 0 ? n_rows_1d :
eigenvalues[0].size());
494 tmp_array.resize_fast(n * 2);
495 constexpr int kernel_size = n_rows_1d > 0 ? n_rows_1d : 0;
505 mass_matrix[0].n_rows());
506 Number * t = tmp_array.begin();
507 const Number *src = src_view.
begin();
508 Number * dst = dst_view.
data();
512 const Number *A = &derivative_matrix[0](0, 0);
513 eval.template apply<0, false, false>(A, src, dst);
518 const Number *A0 = &derivative_matrix[0](0, 0);
520 const Number *A1 = &derivative_matrix[1](0, 0);
522 eval.template apply<0, false, false>(M0, src, t);
523 eval.template apply<1, false, false>(A1, t, dst);
524 eval.template apply<0, false, false>(A0, src, t);
525 eval.template apply<1, false, true>(M1, t, dst);
530 const Number *A0 = &derivative_matrix[0](0, 0);
532 const Number *A1 = &derivative_matrix[1](0, 0);
534 const Number *A2 = &derivative_matrix[2](0, 0);
536 eval.template apply<0, false, false>(M0, src, t + n);
537 eval.template apply<1, false, false>(M1, t + n, t);
538 eval.template apply<2, false, false>(A2, t, dst);
539 eval.template apply<1, false, false>(A1, t + n, t);
540 eval.template apply<0, false, false>(A0, src, t + n);
541 eval.template apply<1, false, true>(M1, t + n, t);
542 eval.template apply<2, false, true>(M2, t, dst);
551template <
int dim,
typename Number,
int n_rows_1d>
559 std::lock_guard<std::mutex> lock(this->mutex);
560 const unsigned int n = n_rows_1d > 0 ? n_rows_1d :
eigenvalues[0].size();
561 tmp_array.resize_fast(Utilities::fixed_power<dim>(n));
562 constexpr int kernel_size = n_rows_1d > 0 ? n_rows_1d : 0;
571 mass_matrix[0].n_rows(),
572 mass_matrix[0].n_rows());
573 Number * t = tmp_array.begin();
574 const Number *src = src_view.
data();
575 Number * dst = dst_view.
data();
585 eval.template apply<0, true, false>(S, src, t);
586 for (
unsigned int i = 0; i < n; ++i)
588 eval.template apply<0, false, false>(S, t, dst);
595 eval.template apply<0, true, false>(S0, src, t);
596 eval.template apply<1, true, false>(S1, t, dst);
597 for (
unsigned int i1 = 0, c = 0; i1 < n; ++i1)
598 for (
unsigned int i0 = 0; i0 < n; ++i0, ++c)
600 eval.template apply<0, false, false>(S0, dst, t);
601 eval.template apply<1, false, false>(S1, t, dst);
609 eval.template apply<0, true, false>(S0, src, t);
610 eval.template apply<1, true, false>(S1, t, dst);
611 eval.template apply<2, true, false>(S2, dst, t);
612 for (
unsigned int i2 = 0, c = 0; i2 < n; ++i2)
613 for (
unsigned int i1 = 0; i1 < n; ++i1)
614 for (
unsigned int i0 = 0; i0 < n; ++i0, ++c)
617 eval.template apply<0, false, false>(S0, t, dst);
618 eval.template apply<1, false, false>(S1, dst, t);
619 eval.template apply<2, false, false>(S2, t, dst);
629template <
int dim,
typename Number,
int n_rows_1d>
635 reinit(mass_matrix, derivative_matrix);
640template <
int dim,
typename Number,
int n_rows_1d>
646 reinit(mass_matrix, derivative_matrix);
651template <
int dim,
typename Number,
int n_rows_1d>
656 reinit(mass_matrix, derivative_matrix);
661template <
int dim,
typename Number,
int n_rows_1d>
662template <
typename MatrixArray>
665 MatrixArray &&mass_matrices_,
666 MatrixArray &&derivative_matrices_)
668 auto &&mass_matrices = std::forward<MatrixArray>(mass_matrices_);
669 auto &&derivative_matrices = std::forward<MatrixArray>(derivative_matrices_);
670 this->mass_matrix = mass_matrices;
671 this->derivative_matrix = derivative_matrices;
673 for (
unsigned int dir = 0; dir < dim; ++dir)
676 (n_rows_1d > 0 &&
static_cast<unsigned int>(n_rows_1d) ==
677 mass_matrices[dir].n_rows()),
679 AssertDimension(mass_matrices[dir].n_rows(), mass_matrices[dir].n_cols());
681 derivative_matrices[dir].n_rows());
683 derivative_matrices[dir].n_cols());
685 this->eigenvectors[dir].reinit(mass_matrices[dir].n_cols(),
686 mass_matrices[dir].n_rows());
687 this->eigenvalues[dir].resize(mass_matrices[dir].n_cols());
688 internal::TensorProductMatrix::spectral_assembly<Number>(
689 &(mass_matrices[dir](0, 0)),
690 &(derivative_matrices[dir](0, 0)),
691 mass_matrices[dir].n_rows(),
692 mass_matrices[dir].n_cols(),
693 this->eigenvalues[dir].
begin(),
694 &(this->eigenvectors[dir](0, 0)));
700template <
int dim,
typename Number,
int n_rows_1d>
706 reinit_impl(mass_matrix, derivative_matrix);
711template <
int dim,
typename Number,
int n_rows_1d>
717 std::array<Table<2, Number>, dim> mass_copy;
718 std::array<Table<2, Number>, dim> deriv_copy;
726 std::transform(derivative_matrix.cbegin(),
727 derivative_matrix.cend(),
733 reinit_impl(std::move(mass_copy), std::move(deriv_copy));
738template <
int dim,
typename Number,
int n_rows_1d>
744 std::array<Table<2, Number>, dim> mass_matrices;
745 std::array<Table<2, Number>, dim> derivative_matrices;
747 std::fill(mass_matrices.begin(), mass_matrices.end(), mass_matrix);
748 std::fill(derivative_matrices.begin(),
749 derivative_matrices.end(),
752 reinit_impl(std::move(mass_matrices), std::move(derivative_matrices));
759template <
int dim,
typename Number,
int n_rows_1d>
763 TensorProductMatrixSymmetricSum(
767 reinit(mass_matrix, derivative_matrix);
772template <
int dim,
typename Number,
int n_rows_1d>
776 TensorProductMatrixSymmetricSum(
780 reinit(mass_matrix, derivative_matrix);
785template <
int dim,
typename Number,
int n_rows_1d>
786template <
typename MatrixArray>
789 reinit_impl(MatrixArray &&mass_matrices_, MatrixArray &&derivative_matrices_)
791 auto &&
mass_matrix = std::forward<MatrixArray>(mass_matrices_);
792 auto &&derivative_matrix = std::forward<MatrixArray>(derivative_matrices_);
794 this->derivative_matrix = derivative_matrix;
797 std::size_t n_rows_max = (n_rows_1d > 0) ? n_rows_1d : 0;
799 for (
unsigned int d = 0;
d < dim; ++
d)
800 n_rows_max =
std::max(n_rows_max, mass_matrix[d].n_rows());
801 const std::size_t nm_flat_size_max = n_rows_max * n_rows_max * macro_size;
802 const std::size_t n_flat_size_max = n_rows_max * macro_size;
804 std::vector<Number> mass_matrix_flat;
805 std::vector<Number> deriv_matrix_flat;
806 std::vector<Number> eigenvalues_flat;
807 std::vector<Number> eigenvectors_flat;
808 mass_matrix_flat.resize(nm_flat_size_max);
809 deriv_matrix_flat.resize(nm_flat_size_max);
810 eigenvalues_flat.resize(n_flat_size_max);
811 eigenvectors_flat.resize(nm_flat_size_max);
812 std::array<unsigned int, macro_size> offsets_nm;
813 std::array<unsigned int, macro_size> offsets_n;
814 for (
unsigned int dir = 0; dir < dim; ++dir)
817 (n_rows_1d > 0 &&
static_cast<unsigned int>(n_rows_1d) ==
818 mass_matrix[dir].n_rows()),
822 derivative_matrix[dir].n_rows());
824 derivative_matrix[dir].n_cols());
826 const unsigned int n_rows =
mass_matrix[dir].n_rows();
827 const unsigned int n_cols =
mass_matrix[dir].n_cols();
828 const unsigned int nm = n_rows * n_cols;
829 for (
unsigned int vv = 0; vv < macro_size; ++vv)
830 offsets_nm[vv] = nm * vv;
834 &(mass_matrix[dir](0, 0)),
836 mass_matrix_flat.data());
839 &(derivative_matrix[dir](0, 0)),
841 deriv_matrix_flat.data());
843 const Number *mass_cbegin = mass_matrix_flat.data();
844 const Number *deriv_cbegin = deriv_matrix_flat.data();
845 Number * eigenvec_begin = eigenvectors_flat.data();
846 Number * eigenval_begin = eigenvalues_flat.data();
847 for (
unsigned int lane = 0; lane < macro_size; ++lane)
848 internal::TensorProductMatrix::spectral_assembly<Number>(
849 mass_cbegin + nm * lane,
850 deriv_cbegin + nm * lane,
853 eigenval_begin + n_rows * lane,
854 eigenvec_begin + nm * lane);
856 this->eigenvalues[dir].resize(n_rows);
857 this->eigenvectors[dir].reinit(n_rows, n_cols);
858 for (
unsigned int vv = 0; vv < macro_size; ++vv)
859 offsets_n[vv] = n_rows * vv;
861 eigenvalues_flat.data(),
863 this->eigenvalues[dir].begin());
865 eigenvectors_flat.data(),
867 &(this->eigenvectors[dir](0, 0)));
873template <
int dim,
typename Number,
int n_rows_1d>
880 reinit_impl(mass_matrix, derivative_matrix);
885template <
int dim,
typename Number,
int n_rows_1d>
891 std::array<Table<2, VectorizedArray<Number>>, dim> mass_matrices;
892 std::array<Table<2, VectorizedArray<Number>>, dim> derivative_matrices;
894 std::fill(mass_matrices.begin(), mass_matrices.end(), mass_matrix);
895 std::fill(derivative_matrices.begin(),
896 derivative_matrices.end(),
899 reinit_impl(std::move(mass_matrices), std::move(derivative_matrices));
value_type * data() const noexcept
std::array< Table< 2, Number >, dim > derivative_matrix
void apply_inverse(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const
std::array< AlignedVector< Number >, dim > eigenvalues
AlignedVector< Number > tmp_array
std::array< Table< 2, Number >, dim > eigenvectors
void vmult(const ArrayView< Number > &dst, const ArrayView< const Number > &src) const
TensorProductMatrixSymmetricSumBase()=default
static constexpr int n_rows_1d_static
std::array< Table< 2, Number >, dim > mass_matrix
TensorProductMatrixSymmetricSum(const Table< 2, VectorizedArray< Number > > &mass_matrix, const Table< 2, VectorizedArray< Number > > &derivative_matrix)
TensorProductMatrixSymmetricSum()=default
void reinit(const Table< 2, VectorizedArray< Number > > &mass_matrix, const Table< 2, VectorizedArray< Number > > &derivative_matrix)
TensorProductMatrixSymmetricSum(const std::array< Table< 2, VectorizedArray< Number > >, dim > &mass_matrix, const std::array< Table< 2, VectorizedArray< Number > >, dim > &derivative_matrix)
void reinit(const std::array< Table< 2, VectorizedArray< Number > >, dim > &mass_matrix, const std::array< Table< 2, VectorizedArray< Number > >, dim > &derivative_matrix)
void reinit_impl(MatrixArray &&mass_matrix, MatrixArray &&derivative_matrix)
void reinit(const std::array< Table< 2, Number >, dim > &mass_matrix, const std::array< Table< 2, Number >, dim > &derivative_matrix)
TensorProductMatrixSymmetricSum(const std::array< FullMatrix< Number >, dim > &mass_matrix, const std::array< FullMatrix< Number >, dim > &derivative_matrix)
void reinit(const std::array< FullMatrix< Number >, dim > &mass_matrix, const std::array< FullMatrix< Number >, dim > &derivative_matrix)
TensorProductMatrixSymmetricSum(const std::array< Table< 2, Number >, dim > &mass_matrix, const std::array< Table< 2, Number >, dim > &derivative_matrix)
void reinit_impl(MatrixArray &&mass_matrix, MatrixArray &&derivative_matrix)
TensorProductMatrixSymmetricSum()=default
void reinit(const Table< 2, Number > &mass_matrix, const Table< 2, Number > &derivative_matrix)
TensorProductMatrixSymmetricSum(const Table< 2, Number > &mass_matrix, const Table< 2, Number > &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 & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define AssertThrow(cond, exc)
void mass_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const double factor=1.)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
VectorType::value_type * begin(VectorType &V)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
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)
void vectorized_load_and_transpose(const unsigned int n_entries, const Number *in, const unsigned int *offsets, VectorizedArray< Number, width > *out)
void vectorized_transpose_and_store(const bool add_into, const unsigned int n_entries, const VectorizedArray< Number, width > *in, const unsigned int *offsets, Number *out)