20#ifndef LIBMESH_DENSE_MATRIX_H
21#define LIBMESH_DENSE_MATRIX_H
24#include "libmesh/libmesh_common.h"
25#include "libmesh/dense_matrix_base.h"
26#include "libmesh/int_range.h"
29#if (LIBMESH_HAVE_PETSC)
30# include "libmesh/petsc_macro.h"
35#include "libmesh/ignore_warnings.h"
37#include "libmesh/restore_warnings.h"
47#include <initializer_list>
49#ifdef LIBMESH_HAVE_METAPHYSICL
50#include "metaphysicl/dualnumber_decl.h"
51#include "metaphysicl/raw_type.h"
58template <
typename T>
class DenseVector;
79 const unsigned int new_n=0);
86 template <
typename T2>
89 std::initializer_list<T2> init_list);
106 virtual void zero() override final;
112 unsigned int col_id,
unsigned int col_size) const;
117 T operator() (const
unsigned int i,
118 const
unsigned int j) const;
123 T & operator() (const
unsigned int i,
124 const
unsigned int j);
126 virtual T
el(const
unsigned int i,
127 const
unsigned int j) const override final
128 {
return (*
this)(i,j); }
130 virtual T &
el(
const unsigned int i,
131 const unsigned int j)
override final
132 {
return (*
this)(i,j); }
139 template <
typename T2>
147 template <
typename T2>
162 template <
typename T2>
178 template <
typename T2>
195 template <
typename T2,
typename T3>
238 template <
typename T2>
254 const unsigned int new_n);
278 template<
typename T2,
typename T3>
279 typename std::enable_if<
348 template <typename T2>
361 template <typename T2>
368 const
unsigned int j) const;
396 const unsigned int j,
439 template <
typename T2>
487 Real rcond=std::numeric_limits<Real>::epsilon())
const;
633 template <
typename T2>
713 std::vector<Real> & sigma_val,
714 std::vector<Number> & U_val,
715 std::vector<Number> & VT_val);
735#if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS)
769 bool trans=
false)
const;
775 template <
typename T2>
782 template <
typename T2>
794namespace DenseMatrices
816using namespace DenseMatrices;
821#if defined(LIBMESH_HAVE_PETSC) && \
822 defined(LIBMESH_USE_REAL_NUMBERS) && \
823 defined(LIBMESH_DEFAULT_DOUBLE_PRECISION)
827 static const bool value =
true;
837 const unsigned int new_n) :
841 _decomposition_type(NONE)
843 this->
resize(new_m,new_n);
847template <
typename T2>
850 std::initializer_list<T2> init_list) :
853 _val(init_list.begin(), init_list.end()),
854 _decomposition_type(NONE)
858 libmesh_assert_equal_to(nrow * ncol, init_list.size());
867 std::swap(this->_m, other_matrix.
_m);
868 std::swap(this->_n, other_matrix.
_n);
869 _val.swap(other_matrix.
_val);
877template <
typename T2>
882 unsigned int mat_m = mat.
m(), mat_n = mat.
n();
883 this->resize(mat_m, mat_n);
884 for (
unsigned int i=0; i<mat_m; i++)
885 for (
unsigned int j=0; j<mat_n; j++)
886 (*
this)(i,j) = mat(i,j);
896 const unsigned int new_n)
913 _decomposition_type = NONE;
915 std::fill (_val.begin(), _val.end(),
static_cast<T
>(0));
923 unsigned int col_id,
unsigned int col_size)
const
925 libmesh_assert_less (row_id + row_size - 1, this->_m);
926 libmesh_assert_less (col_id + col_size - 1, this->_n);
931 sub.
_val.resize(row_size * col_size);
933 unsigned int end_col = this->_n - col_size - col_id;
934 unsigned int p = row_id * this->_n;
936 for (
unsigned int i=0; i<row_size; i++)
940 for (
unsigned int j=0; j<col_size; j++)
941 sub.
_val[q++] = _val[p++];
954 const unsigned int j)
const
956 libmesh_assert_less (i*j, _val.size());
957 libmesh_assert_less (i, this->_m);
958 libmesh_assert_less (j, this->_n);
962 return _val[(i)*(this->_n) + (j)];
970 const unsigned int j)
972 libmesh_assert_less (i*j, _val.size());
973 libmesh_assert_less (i, this->_m);
974 libmesh_assert_less (j, this->_n);
977 return _val[(i)*(this->_n) + (j)];
988 for (
auto & v : _val)
998 (*
this)(i, col) *= factor;
1007 this->scale(factor);
1014template<
typename T2,
typename T3>
1016typename std::enable_if<
1021 libmesh_assert_equal_to (this->m(), mat.
m());
1022 libmesh_assert_equal_to (this->n(), mat.
n());
1026 (*
this)(i,j) += factor * mat(i,j);
1036 if (_val[i] != mat.
_val[i])
1049 if (_val[i] != mat.
_val[i])
1062 _val[i] += mat.
_val[i];
1074 _val[i] -= mat.
_val[i];
1089 for (
unsigned int i=0; i!=this->_m; i++)
1091 for (
unsigned int j=0; j!=this->_n; j++)
1094 my_min = (my_min < current? my_min : current);
1110 for (
unsigned int i=0; i!=this->_m; i++)
1112 for (
unsigned int j=0; j!=this->_n; j++)
1115 my_max = (my_max > current? my_max : current);
1131 auto columnsum = abs(T(0));
1132 for (
unsigned int i=0; i!=this->_m; i++)
1134 columnsum += abs((*
this)(i,0));
1136 auto my_max = columnsum;
1137 for (
unsigned int j=1; j!=this->_n; j++)
1140 for (
unsigned int i=0; i!=this->_m; i++)
1142 columnsum += abs((*
this)(i,j));
1144 my_max = (my_max > columnsum? my_max : columnsum);
1159 auto rowsum = abs(T(0));
1160 for (
unsigned int j=0; j!=this->_n; j++)
1162 rowsum += abs((*
this)(0,j));
1164 auto my_max = rowsum;
1165 for (
unsigned int i=1; i!=this->_m; i++)
1168 for (
unsigned int j=0; j!=this->_n; j++)
1170 rowsum += abs((*
this)(i,j));
1172 my_max = (my_max > rowsum? my_max : rowsum);
1182 const unsigned int j)
const
1185 return (*
this)(j,i);
1222template <
typename T>
1225 using std::isfinite;
1227 const auto m = var.
m(), n = var.
n();
1243template <
typename T>
1250 const auto m = var.
m(), n = var.
n();
1251 bool has_inf =
false;
1256 if (
isnan(var(i,j)))
1258 has_inf = has_inf ||
isinf(var(i,j));
1271template <
typename T>
1276 const auto m = var.
m(), n = var.
n();
1279 if (
isnan(var(i,j)))
1287#ifdef LIBMESH_HAVE_METAPHYSICL
1290template <
typename T>
1297 const auto m = in.
m(), n = in.
n();
1299 for (
unsigned int i = 0; i < m; ++i)
1300 for (
unsigned int j = 0; j < n; ++j)
1301 ret(i,j) = raw_value(in(i,j));
Defines an abstract dense matrix base class for use in Finite Element-type computations.
void condense(const unsigned int i, const unsigned int j, const T val, DenseVectorBase< T > &rhs)
Condense-out the (i,j) entry of the matrix, forcing it to take on the value val.
unsigned int _n
The column dimension.
unsigned int _m
The row dimension.
Defines a dense matrix for use in Finite Element-type computations.
void scale_column(const unsigned int col, const T factor)
Multiplies every element in the column col matrix by factor.
auto min() const -> decltype(libmesh_real(T(0)))
void _cholesky_decompose()
Decomposes a symmetric positive definite matrix into a product of two lower triangular matrices accor...
void _lu_decompose()
Form the LU decomposition of the matrix.
DenseMatrix(DenseMatrix &&)=default
The 5 special functions can be defaulted for this class, as it does not manage any memory itself.
void evd_left(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL)
Compute the eigenvalues (both real and imaginary parts) and left eigenvectors of a general matrix,...
void _lu_back_substitute(const DenseVector< T > &b, DenseVector< T > &x) const
Solves the system Ax=b through back substitution.
void right_multiply_transpose(const DenseMatrix< T > &A)
Right multiplies by the transpose of the matrix A.
DenseMatrix(const unsigned int new_m=0, const unsigned int new_n=0)
Constructor.
void _left_multiply_transpose(const DenseMatrix< T2 > &A)
Left multiplies by the transpose of the matrix A which may contain a different numerical type.
std::vector< T > & get_values()
virtual T & el(const unsigned int i, const unsigned int j) override final
void _right_multiply_transpose(const DenseMatrix< T2 > &A)
Right multiplies by the transpose of the matrix A which may contain a different numerical type.
void _evd_lapack(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > *VL=nullptr, DenseMatrix< T > *VR=nullptr)
Computes the eigenvalues of the matrix using the Lapack routine "DGEEV".
DenseMatrix(unsigned int nrow, unsigned int ncol, std::initializer_list< T2 > init_list)
Constructor taking the number of rows, columns, and an initializer_list, which must be of length nrow...
DenseMatrix sub_matrix(unsigned int row_id, unsigned int row_size, unsigned int col_id, unsigned int col_size) const
Get submatrix with the smallest row and column indices and the submatrix size.
void _lu_decompose_lapack()
Computes an LU factorization of the matrix using the Lapack routine "getrf".
void svd_solve(const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond=std::numeric_limits< Real >::epsilon()) const
Solve the system of equations for in the least-squares sense.
DenseMatrix & operator=(const DenseMatrix &)=default
void _svd_lapack(DenseVector< Real > &sigma)
Computes an SVD of the matrix using the Lapack routine "getsvd".
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this) * arg.
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
For symmetric positive definite (SPD) matrices.
bool operator!=(const DenseMatrix< T > &mat) const
DenseMatrix(const DenseMatrix &)=default
void _cholesky_back_substitute(const DenseVector< T2 > &b, DenseVector< T2 > &x) const
Solves the equation Ax=b for the unknown value x and rhs b based on the Cholesky factorization of A.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
void svd(DenseVector< Real > &sigma)
Compute the singular value decomposition of the matrix.
bool use_blas_lapack
Computes the inverse of the dense matrix (assuming it is invertible) by first computing the LU decomp...
std::vector< T > _val
The actual data values, stored as a 1D array.
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b.
void _svd_solve_lapack(const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond) const
Called by svd_solve(rhs).
T operator()(const unsigned int i, const unsigned int j) const
virtual void right_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- (*this) * M3.
void get_principal_submatrix(unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
Put the sub_m x sub_n principal submatrix into dest.
std::vector< pivot_index_t > _pivots
void evd_right(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VR)
Compute the eigenvalues (both real and imaginary parts) and right eigenvectors of a general matrix,...
void get_transpose(DenseMatrix< T > &dest) const
Put the tranposed matrix into dest.
virtual T el(const unsigned int i, const unsigned int j) const override final
void swap(DenseMatrix< T > &other_matrix)
STL-like swap method.
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this)^T * arg.
DenseMatrix< T > & operator-=(const DenseMatrix< T > &mat)
Subtracts mat from this matrix.
T transpose(const unsigned int i, const unsigned int j) const
const std::vector< T > & get_values() const
DecompositionType _decomposition_type
This flag keeps track of which type of decomposition has been performed on the matrix.
void _svd_helper(char JOBU, char JOBVT, std::vector< Real > &sigma_val, std::vector< Number > &U_val, std::vector< Number > &VT_val)
Helper function that actually performs the SVD.
void scale(const T factor)
Multiplies every element in the matrix by factor.
virtual void left_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- M2 * (*this)
void outer_product(const DenseVector< T > &a, const DenseVector< T > &b)
Computes the outer (dyadic) product of two vectors and stores in (*this).
PetscBLASInt pivot_index_t
Array used to store pivot indices.
void _matvec_blas(T alpha, T beta, DenseVector< T > &dest, const DenseVector< T > &arg, bool trans=false) const
Uses the BLAS GEMV function (through PETSc) to compute.
void condense(const unsigned int i, const unsigned int j, const T val, DenseVector< T > &rhs)
Condense-out the (i,j) entry of the matrix, forcing it to take on the value val.
void evd(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag)
Compute the eigenvalues (both real and imaginary parts) of a general matrix.
std::enable_if< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseMatrix< T3 > &mat)
Adds factor times mat to this matrix.
void evd_left_and_right(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL, DenseMatrix< T > &VR)
Compute the eigenvalues (both real and imaginary parts) as well as the left and right eigenvectors of...
virtual ~DenseMatrix()=default
bool operator==(const DenseMatrix< T > &mat) const
void _multiply_blas(const DenseMatrixBase< T > &other, _BLAS_Multiply_Flag flag)
The _multiply_blas function computes A <- op(A) * op(B) using BLAS gemm function.
void left_multiply_transpose(const DenseMatrix< T > &A)
Left multiplies by the transpose of the matrix A.
auto max() const -> decltype(libmesh_real(T(0)))
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
Performs the scaled matrix-vector multiplication, dest += factor * (*this) * arg.
DenseMatrix< T > & operator*=(const T factor)
Multiplies every element in the matrix by factor.
DecompositionType
The decomposition schemes above change the entries of the matrix A.
DenseMatrix< T > & operator+=(const DenseMatrix< T > &mat)
Adds mat to this matrix.
void _lu_back_substitute_lapack(const DenseVector< T > &b, DenseVector< T > &x)
Companion function to _lu_decompose_lapack().
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
_BLAS_Multiply_Flag
Enumeration used to determine the behavior of the _multiply_blas function.
@ LEFT_MULTIPLY_TRANSPOSE
@ RIGHT_MULTIPLY_TRANSPOSE
Defines a dense vector for use in Finite Element-type computations.
DenseMatrix< Complex > ComplexDenseMatrix
This typedef may be either a real-only matrix, or a truly complex matrix, depending on how Number was...
DenseMatrix< Real > RealDenseMatrix
Convenient definition of a real-only dense matrix.
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
bool isfinite(std::complex< T > a)
bool isnan(std::complex< T > a)
bool isinf(std::complex< T > a)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Helper structure for determining whether to use blas_lapack.