16 #ifndef dealii_tensor_product_matrix_h 17 #define dealii_tensor_product_matrix_h 20 #include <deal.II/base/array_view.h> 21 #include <deal.II/base/config.h> 22 #include <deal.II/base/thread_management.h> 23 #include <deal.II/lac/lapack_full_matrix.h> 24 #include <deal.II/matrix_free/tensor_product_kernels.h> 26 DEAL_II_NAMESPACE_OPEN
28 template <
typename>
class Vector;
66 template <
int dim,
typename Number,
int size = -1>
75 unsigned int m ()
const;
82 unsigned int n ()
const;
214 template <
int dim,
typename Number,
int size = -1>
286 template <
typename MatrixArray>
301 template <
int dim,
typename Number,
int size>
358 template <
typename MatrixArray>
370 namespace TensorProductMatrix
380 template <
typename Number>
382 spectral_assembly (
const Number *mass_matrix,
383 const Number *derivative_matrix,
384 const unsigned int n_rows,
385 const unsigned int n_cols,
391 auto &&transpose_fill_nm
392 = [](Number *out,
const Number *in,
const unsigned int n,
const unsigned int m)
394 for (
unsigned int mm = 0; mm < m; ++mm)
395 for (
unsigned int nn = 0; nn < n; ++nn)
396 out[mm+nn*m] = *(in++);
399 std::vector<::Vector<Number> > eigenvecs(n_rows);
403 transpose_fill_nm (&(mass_copy(0,0)), mass_matrix, n_rows, n_cols);
404 transpose_fill_nm (&(deriv_copy(0,0)), derivative_matrix, n_rows, n_cols);
406 deriv_copy.compute_generalized_eigenvalues_symmetric (mass_copy, eigenvecs);
408 for (
unsigned int i=0; i<n_rows; ++i)
412 for (
unsigned int i=0; i<n_rows; ++i, ++
eigenvalues)
419 template <
int dim,
typename Number,
int size>
425 for (
unsigned int d = 1;
d < dim; ++
d)
426 m *= mass_matrix[d].n_rows();
432 template <
int dim,
typename Number,
int size>
438 for (
unsigned int d = 1;
d < dim; ++
d)
439 n *= mass_matrix[d].n_cols();
445 template <
int dim,
typename Number,
int size>
455 const unsigned int n = Utilities::fixed_power<dim>(size > 0 ? size :
eigenvalues[0].size());
456 tmp_array.resize_fast(n*2);
457 constexpr
int kernel_size = size > 0 ? size : 0;
461 Number *t = tmp_array.begin();
462 const Number *src = src_view.
begin();
463 Number *dst = &(dst_view[0]);
467 const Number *A = &derivative_matrix[0](0,0);
468 eval.template apply<0, false, false> (A, src, dst);
473 const Number *A0 = &derivative_matrix[0](0,0);
475 const Number *A1 = &derivative_matrix[1](0,0);
477 eval.template apply<0, false, false> (M0, src, t);
478 eval.template apply<1, false, false> (A1, t, dst);
479 eval.template apply<0, false, false> (A0, src, t);
480 eval.template apply<1, false, true> (M1, t, dst);
485 const Number *A0 = &derivative_matrix[0](0,0);
487 const Number *A1 = &derivative_matrix[1](0,0);
489 const Number *A2 = &derivative_matrix[2](0,0);
491 eval.template apply<0, false, false> (M0, src, t+n);
492 eval.template apply<1, false, false> (M1, t+n, t);
493 eval.template apply<2, false, false> (A2, t, dst);
494 eval.template apply<1, false, false> (A1, t+n, t);
495 eval.template apply<0, false, false> (A0, src, t+n);
496 eval.template apply<1, false, true> (M1, t+n, t);
497 eval.template apply<2, false, true> (M2, t, dst);
506 template <
int dim,
typename Number,
int size>
516 const unsigned int n = size > 0 ? size :
eigenvalues[0].size();
517 tmp_array.resize_fast (Utilities::fixed_power<dim>(n));
518 constexpr
int kernel_size = size > 0 ? size : 0;
522 Number *t = tmp_array.begin();
523 const Number *src = src_view.
data();
524 Number *dst = &(dst_view[0]);
534 eval.template apply<0, true, false> (S, src, t);
535 for (
unsigned int i=0; i<n; ++i)
537 eval.template apply<0, false, false> (S, t, dst);
544 eval.template apply<0, true, false> (S0, src, t);
545 eval.template apply<1, true, false> (S1, t, dst);
546 for (
unsigned int i1=0, c=0; i1<n; ++i1)
547 for (
unsigned int i0=0; i0<n; ++i0, ++c)
549 eval.template apply<0, false, false> (S0, dst, t);
550 eval.template apply<1, false, false> (S1, t, dst);
558 eval.template apply<0, true, false> (S0, src, t);
559 eval.template apply<1, true, false> (S1, t, dst);
560 eval.template apply<2, true, false> (S2, dst, t);
561 for (
unsigned int i2=0, c=0; i2<n; ++i2)
562 for (
unsigned int i1=0; i1<n; ++i1)
563 for (
unsigned int i0=0; i0<n; ++i0, ++c)
565 eval.template apply<0, false, false> (S0, t, dst);
566 eval.template apply<1, false, false> (S1, dst, t);
567 eval.template apply<2, false, false> (S2, t, dst);
577 template <
int dim,
typename Number,
int size>
583 reinit (mass_matrix, derivative_matrix);
588 template <
int dim,
typename Number,
int size>
594 reinit (mass_matrix, derivative_matrix);
599 template <
int dim,
typename Number,
int size>
605 reinit (mass_matrix, derivative_matrix);
610 template <
int dim,
typename Number,
int size>
611 template <
typename MatrixArray>
616 MatrixArray &&derivative_matrices_)
618 auto &&mass_matrices = std::forward<MatrixArray>(mass_matrices_);
619 auto &&derivative_matrices = std::forward<MatrixArray>(derivative_matrices_);
620 this->mass_matrix = mass_matrices;
621 this->derivative_matrix = derivative_matrices;
623 for (
int dir = 0; dir < dim; ++dir)
625 Assert (size == -1 || (size > 0 && static_cast<unsigned int>(size) == mass_matrices[dir].n_rows()),
627 AssertDimension (mass_matrices[dir].n_rows(), mass_matrices[dir].n_cols());
628 AssertDimension (mass_matrices[dir].n_rows(), derivative_matrices[dir].n_rows());
629 AssertDimension (mass_matrices[dir].n_rows(), derivative_matrices[dir].n_cols());
631 this->eigenvectors[dir].reinit (mass_matrices[dir].n_cols(), mass_matrices[dir].n_rows());
632 this->eigenvalues[dir].resize (mass_matrices[dir].n_cols());
633 internal::TensorProductMatrix
634 ::spectral_assembly<Number> (&(mass_matrices[dir](0,0)),
635 &(derivative_matrices[dir](0,0)),
636 mass_matrices[dir].n_rows(),
637 mass_matrices[dir].n_cols(),
638 this->eigenvalues[dir].begin(),
639 &(this->eigenvectors[dir](0,0)));
645 template <
int dim,
typename Number,
int size>
652 reinit_impl (mass_matrix, derivative_matrix);
657 template <
int dim,
typename Number,
int size>
664 std::array<Table<2,Number>,dim> mass_copy;
665 std::array<Table<2,Number>,dim> deriv_copy;
669 std::transform (derivative_matrix.cbegin(), derivative_matrix.cend(), deriv_copy.begin(),
672 reinit_impl (std::move(mass_copy), std::move(deriv_copy));
677 template <
int dim,
typename Number,
int size>
684 std::array<Table<2,Number>,dim> mass_matrices;
685 std::array<Table<2,Number>,dim> derivative_matrices;
687 std::fill (mass_matrices.begin(), mass_matrices.end(),
mass_matrix);
688 std::fill (derivative_matrices.begin(), derivative_matrices.end(), derivative_matrix);
690 reinit_impl (std::move(mass_matrices), std::move(derivative_matrices));
697 template <
int dim,
typename Number,
int size>
703 reinit (mass_matrix, derivative_matrix);
708 template <
int dim,
typename Number,
int size>
714 reinit (mass_matrix, derivative_matrix);
719 template <
int dim,
typename Number,
int size>
720 template <
typename MatrixArray>
724 ::reinit_impl (MatrixArray &&mass_matrices_,
725 MatrixArray &&derivative_matrices_)
727 auto &&
mass_matrix = std::forward<MatrixArray>(mass_matrices_);
728 auto &&derivative_matrix = std::forward<MatrixArray>(derivative_matrices_);
730 this->derivative_matrix = derivative_matrix;
733 std::size_t n_rows_max = (size > 0) ? size : 0 ;
735 for (
unsigned int d = 0;
d < dim; ++
d)
736 n_rows_max = std::max(n_rows_max, mass_matrix[d].n_rows());
737 const std::size_t nm_flat_size_max = n_rows_max * n_rows_max * macro_size;
738 const std::size_t n_flat_size_max = n_rows_max * macro_size;
740 std::vector<Number> mass_matrix_flat;
741 std::vector<Number> deriv_matrix_flat;
742 std::vector<Number> eigenvalues_flat;
743 std::vector<Number> eigenvectors_flat;
744 mass_matrix_flat.resize (nm_flat_size_max);
745 deriv_matrix_flat.resize (nm_flat_size_max);
746 eigenvalues_flat.resize (n_flat_size_max);
747 eigenvectors_flat.resize (nm_flat_size_max);
748 std::array<unsigned int,macro_size> offsets_nm;
749 std::array<unsigned int,macro_size> offsets_n;
750 for (
int dir = 0; dir < dim; ++dir)
753 (size > 0 && static_cast<unsigned int>(size) == mass_matrix[dir].n_rows()),
755 AssertDimension (mass_matrix[dir].n_rows(), mass_matrix[dir].n_cols());
756 AssertDimension (mass_matrix[dir].n_rows(), derivative_matrix[dir].n_rows());
757 AssertDimension (mass_matrix[dir].n_rows(), derivative_matrix[dir].n_cols());
759 const unsigned int n_rows =
mass_matrix[dir].n_rows();
760 const unsigned int n_cols =
mass_matrix[dir].n_cols();
761 const unsigned int nm = n_rows * n_cols;
762 for (
unsigned int vv=0; vv<macro_size; ++vv)
763 offsets_nm[vv] = nm * vv;
766 offsets_nm.cbegin(), mass_matrix_flat.data());
768 offsets_nm.cbegin(), deriv_matrix_flat.data());
770 const Number *mass_cbegin = mass_matrix_flat.data();
771 const Number *deriv_cbegin = deriv_matrix_flat.data();
772 Number *eigenvec_begin = eigenvectors_flat.data();
773 Number *eigenval_begin = eigenvalues_flat.data();
774 for (
unsigned int lane = 0; lane < macro_size; ++lane)
775 internal::TensorProductMatrix
776 ::spectral_assembly<Number> (mass_cbegin+nm*lane, deriv_cbegin+nm*lane, n_rows, n_cols,
777 eigenval_begin+n_rows*lane, eigenvec_begin+nm*lane);
779 this->eigenvalues[dir].resize (n_rows);
780 this->eigenvectors[dir].reinit (n_rows, n_cols);
781 for (
unsigned int vv=0; vv<macro_size; ++vv)
782 offsets_n[vv] = n_rows * vv;
784 offsets_n.cbegin(), this->eigenvalues[dir].begin());
786 offsets_nm.cbegin(), &(this->eigenvectors[dir](0,0)));
792 template <
int dim,
typename Number,
int size>
799 reinit_impl (mass_matrix, derivative_matrix);
804 template <
int dim,
typename Number,
int size>
811 std::array<Table<2,VectorizedArray<Number> >,dim> mass_matrices;
812 std::array<Table<2,VectorizedArray<Number> >,dim> derivative_matrices;
814 std::fill (mass_matrices.begin(), mass_matrices.end(),
mass_matrix);
815 std::fill (derivative_matrices.begin(), derivative_matrices.end(), derivative_matrix);
817 reinit_impl (std::move(mass_matrices), std::move(derivative_matrices));
824 DEAL_II_NAMESPACE_CLOSE
#define AssertDimension(dim1, dim2)
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
std::array< Table< 2, Number >, dim > derivative_matrix
#define AssertThrow(cond, exc)
std::array< Table< 2, Number >, dim > mass_matrix
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)
std::array< Table< 2, Number >, dim > eigenvectors
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
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)
std::array< AlignedVector< Number >, dim > eigenvalues
TensorProductMatrixSymmetricSumBase()=default
value_type * data() const noexcept
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