19 #ifndef LIBMESH_DENSE_MATRIX_IMPL_H 20 #define LIBMESH_DENSE_MATRIX_IMPL_H 27 #include "libmesh/dense_matrix.h" 28 #include "libmesh/dense_vector.h" 29 #include "libmesh/int_range.h" 30 #include "libmesh/libmesh.h" 32 #ifdef LIBMESH_HAVE_METAPHYSICL 33 #include "metaphysicl/dualnumber_decl.h" 47 if (this->use_blas_lapack)
48 this->_multiply_blas(M2, LEFT_MULTIPLY);
61 this->resize (M2.
m(), M3.
n());
64 this->multiply(*
this, M2, M3);
84 this->resize (M2.
m(), M3.
n());
87 this->multiply(*
this, M2, M3);
95 if (this->use_blas_lapack)
96 this->_multiply_blas(A, LEFT_MULTIPLY_TRANSPOSE);
98 this->_left_multiply_transpose(A);
103 template<
typename T2>
106 this->_left_multiply_transpose(A);
111 template<
typename T2>
125 const unsigned int n_rows = A.
m();
126 const unsigned int n_cols = A.
n();
129 this->resize(n_cols,n_cols);
132 for (
unsigned int i=0; i<n_cols; ++i)
133 for (
unsigned int j=0; j<=i; ++j)
134 for (
unsigned int k=0; k<n_rows; ++k)
135 (*
this)(i,j) +=
B(k,i)*
B(k,j);
138 for (
unsigned int i=0; i<n_cols; ++i)
139 for (
unsigned int j=i+1; j<n_cols; ++j)
140 (*
this)(i,j) = (*
this)(j,i);
147 this->resize (A.
n(),
B.n());
149 libmesh_assert_equal_to (A.
m(),
B.m());
150 libmesh_assert_equal_to (this->m(), A.
n());
151 libmesh_assert_equal_to (this->n(),
B.n());
153 const unsigned int m_s = A.
n();
154 const unsigned int p_s = A.
m();
155 const unsigned int n_s = this->n();
160 for (
unsigned int i=0; i<m_s; i++)
161 for (
unsigned int k=0; k<p_s; k++)
163 for (
unsigned int j=0; j<n_s; j++)
173 if (this->use_blas_lapack)
174 this->_multiply_blas(M3, RIGHT_MULTIPLY);
187 this->resize (M2.
m(), M3.
n());
189 this->multiply(*
this, M2, M3);
196 template<
typename T2>
209 this->resize (M2.
m(), M3.
n());
211 this->multiply(*
this, M2, M3);
220 if (this->use_blas_lapack)
221 this->_multiply_blas(
B, RIGHT_MULTIPLY_TRANSPOSE);
223 this->_right_multiply_transpose(
B);
229 template<
typename T2>
232 this->_right_multiply_transpose(
B);
238 template<
typename T2>
252 const unsigned int n_rows =
B.m();
253 const unsigned int n_cols =
B.n();
256 this->resize(n_rows,n_rows);
259 for (
unsigned int i=0; i<n_rows; ++i)
260 for (
unsigned int j=0; j<=i; ++j)
261 for (
unsigned int k=0; k<n_cols; ++k)
262 (*
this)(i,j) += A(i,k)*A(j,k);
265 for (
unsigned int i=0; i<n_rows; ++i)
266 for (
unsigned int j=i+1; j<n_rows; ++j)
267 (*
this)(i,j) = (*
this)(j,i);
274 this->resize (A.
m(),
B.m());
276 libmesh_assert_equal_to (A.
n(),
B.n());
277 libmesh_assert_equal_to (this->m(), A.
m());
278 libmesh_assert_equal_to (this->n(),
B.m());
280 const unsigned int m_s = A.
m();
281 const unsigned int p_s = A.
n();
282 const unsigned int n_s = this->n();
287 for (
unsigned int j=0; j<n_s; j++)
288 for (
unsigned int k=0; k<p_s; k++)
289 if (
B.transpose(k,j) != 0.)
290 for (
unsigned int i=0; i<m_s; i++)
291 (*
this)(i,j) += A(i,k)*
B.transpose(k,j);
303 libmesh_assert_equal_to (this->n(), arg.
size());
310 if(this->m() == 0 || this->n() == 0)
313 if (this->use_blas_lapack)
314 this->_matvec_blas(1., 0., dest, arg);
317 const unsigned int n_rows = this->m();
318 const unsigned int n_cols = this->n();
320 for (
unsigned int i=0; i<n_rows; i++)
321 for (
unsigned int j=0; j<n_cols; j++)
322 dest(i) += (*this)(i,j)*arg(j);
329 template<
typename T2>
334 libmesh_assert_equal_to (this->n(), arg.
size());
338 dest.resize(this->m());
341 if (this->m() == 0 || this->n() == 0)
344 const unsigned int n_rows = this->m();
345 const unsigned int n_cols = this->n();
347 for (
unsigned int i=0; i<n_rows; i++)
348 for (
unsigned int j=0; j<n_cols; j++)
349 dest(i) += (*this)(i,j)*arg(j);
359 libmesh_assert_equal_to (this->m(), arg.
size());
369 if (this->use_blas_lapack)
371 this->_matvec_blas(1., 0., dest, arg,
true);
375 const unsigned int n_rows = this->m();
376 const unsigned int n_cols = this->n();
384 for (
unsigned int i=0; i<n_cols; i++)
385 for (
unsigned int j=0; j<n_rows; j++)
386 dest(i) += (*this)(j,i)*arg(j);
393 template<
typename T2>
398 libmesh_assert_equal_to (this->m(), arg.
size());
402 dest.resize(this->n());
408 const unsigned int n_rows = this->m();
409 const unsigned int n_cols = this->n();
417 for (
unsigned int i=0; i<n_cols; i++)
418 for (
unsigned int j=0; j<n_rows; j++)
419 dest(i) += (*this)(j,i)*arg(j);
436 if (this->use_blas_lapack)
437 this->_matvec_blas(factor, 1., dest, arg);
441 this->vector_mult(temp, arg);
442 dest.
add(factor, temp);
449 template<
typename T2,
typename T3>
463 this->vector_mult(temp, arg);
464 dest.add(factor, temp);
476 dest.
resize(sub_m, sub_n);
477 for (
unsigned int i=0; i<sub_m; i++)
478 for (
unsigned int j=0; j<sub_n; j++)
479 dest(i,j) = (*this)(i,j);
488 const unsigned int m = a.
size();
489 const unsigned int n = b.
size();
492 for (
unsigned int i = 0; i < m; ++i)
493 for (
unsigned int j = 0; j < n; ++j)
502 get_principal_submatrix(sub_m, sub_m, dest);
510 dest.
resize(this->n(), this->m());
514 dest(i,j) = (*this)(j,i);
535 libmesh_assert_equal_to (this->m(), this->n());
537 switch(this->_decomposition_type)
541 if (this->use_blas_lapack)
542 this->_lu_decompose_lapack();
544 this->_lu_decompose ();
551 if (this->use_blas_lapack)
554 libmesh_fallthrough();
559 if (!(this->use_blas_lapack))
562 libmesh_fallthrough();
565 libmesh_error_msg(
"Error! This matrix already has a different decomposition...");
568 if (this->use_blas_lapack)
569 this->_lu_back_substitute_lapack (b, x);
571 this->_lu_back_substitute (b, x);
586 libmesh_assert_equal_to (this->m(), n_cols);
587 libmesh_assert_equal_to (this->m(), b.
size());
599 for (
unsigned int i=0; i<n_cols; ++i)
602 if (_pivots[i] != static_cast<pivot_index_t>(i))
603 std::swap( z(i), z(_pivots[i]) );
607 for (
unsigned int j=0; j<i; ++j)
614 const unsigned int last_row = n_cols-1;
616 for (
int i=last_row; i>=0; --i)
618 for (
int j=i+1; j<static_cast<int>(n_cols); ++j)
635 libmesh_assert_equal_to (this->_decomposition_type, NONE);
646 for (
unsigned int i=0; i<n_rows; ++i)
652 auto the_max = std::abs( A(i,i) );
653 for (
unsigned int j=i+1; j<n_rows; ++j)
655 auto candidate_max = std::abs( A(j,i) );
656 if (the_max < candidate_max)
658 the_max = candidate_max;
668 if (_pivots[i] != static_cast<pivot_index_t>(i))
670 for (
unsigned int j=0; j<n_rows; ++j)
671 std::swap( A(i,j), A(_pivots[i], j) );
675 libmesh_error_msg_if(A(i,i) ==
libMesh::zero,
"Matrix A is singular!");
679 const T diag_inv = 1. / A(i,i);
680 for (
unsigned int j=i+1; j<n_rows; ++j)
694 for (
unsigned int row=i+1; row<n_rows; ++row)
695 for (
unsigned int col=i+1; col<n_rows; ++col)
696 A(row,col) -= A(row,i) * A(i,col);
701 this->_decomposition_type = LU;
720 _svd_lapack(sigma, U, VT);
730 _svd_solve_lapack(rhs, x, rcond);
740 _evd_lapack(lambda_real, lambda_imag);
751 _evd_lapack(lambda_real, lambda_imag, &VL,
nullptr);
762 _evd_lapack(lambda_real, lambda_imag,
nullptr, &VR);
774 _evd_lapack(lambda_real, lambda_imag, &VL, &VR);
782 switch(this->_decomposition_type)
789 if (this->use_blas_lapack)
790 this->_lu_decompose_lapack();
792 this->_lu_decompose ();
801 libmesh_error_msg(
"Error! Can't compute the determinant under the current decomposition.");
812 unsigned int n_interchanges = 0;
815 if (this->_decomposition_type==LU)
816 if (_pivots[i] != static_cast<pivot_index_t>(i))
820 if (this->_decomposition_type==LU_BLAS_LAPACK)
821 if (_pivots[i] != static_cast<pivot_index_t>(i+1))
824 determinant *= (*this)(i,i);
829 Real sign = n_interchanges % 2 == 0 ? 1. : -1.;
831 return sign*determinant;
839 template <
typename T>
840 template <
typename T2>
845 switch(this->_decomposition_type)
849 this->_cholesky_decompose ();
860 libmesh_error_msg(
"Error! This matrix already has a different decomposition...");
864 this->_cholesky_back_substitute (b, x);
877 libmesh_assert_equal_to (this->_decomposition_type, NONE);
885 libmesh_assert_equal_to (n_rows, n_cols);
890 for (
unsigned int i=0; i<n_rows; ++i)
892 for (
unsigned int j=i; j<n_cols; ++j)
894 for (
unsigned int k=0; k<i; ++k)
895 A(i,j) -= A(i,k) * A(j,k);
899 #ifndef LIBMESH_USE_COMPLEX_NUMBERS 900 libmesh_error_msg_if(A(i,j) <= 0.0,
901 "Error! Can only use Cholesky decomposition with symmetric positive definite matrices.");
904 A(i,i) = std::sqrt(A(i,j));
907 A(j,i) = A(i,j) / A(i,i);
912 this->_decomposition_type = CHOLESKY;
917 template <
typename T>
918 template <
typename T2>
928 libmesh_assert_equal_to (n_rows, n_cols);
937 for (
unsigned int i=0; i<n_cols; ++i)
941 for (
unsigned int k=0; k<i; ++k)
944 x(i) = temp / A(i,i);
948 for (
unsigned int i=0; i<n_cols; ++i)
950 const unsigned int ib = (n_cols-1)-i;
952 for (
unsigned int k=(ib+1); k<n_cols; ++k)
953 x(ib) -= A(k,ib) * x(k);
1012 #endif // LIBMESH_DENSE_MATRIX_IMPL_H
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 _lu_back_substitute(const DenseVector< T > &b, DenseVector< T > &x) const
Solves the system Ax=b through back substitution.
T transpose(const unsigned int i, const unsigned int j) const
boostcopy::enable_if_c< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseVector< T3 > &vec)
Adds factor times vec to this vector.
void resize(const unsigned int n)
Resize the vector.
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 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...
The libMesh namespace provides an interface to certain functionality in the library.
void outer_product(const DenseVector< T > &a, const DenseVector< T > &b)
Computes the outer (dyadic) product of two vectors and stores in (*this).
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this)^T * arg.
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. ...
void svd(DenseVector< Real > &sigma)
Compute the singular value decomposition of the matrix.
void _lu_decompose()
Form the LU decomposition of the matrix.
void get_transpose(DenseMatrix< T > &dest) const
Put the tranposed matrix into dest.
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 _cholesky_decompose()
Decomposes a symmetric positive definite matrix into a product of two lower triangular matrices accor...
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.
void right_multiply_transpose(const DenseMatrix< T > &A)
Right multiplies by the transpose of the matrix A.
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void evd(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag)
Compute the eigenvalues (both real and imaginary parts) of a general matrix.
void left_multiply_transpose(const DenseMatrix< T > &A)
Left multiplies by the transpose of the matrix A.
virtual void right_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- (*this) * M3.
void _left_multiply_transpose(const DenseMatrix< T2 > &A)
Left multiplies by the transpose of the matrix A which may contain a different numerical type...
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
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...
virtual unsigned int size() const override final
Defines a dense vector for use in Finite Element-type computations.
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
For symmetric positive definite (SPD) matrices.
void _right_multiply_transpose(const DenseMatrix< T2 > &A)
Right multiplies by the transpose of the matrix A which may contain a different numerical type...
Defines an abstract dense matrix base class for use in Finite Element-type computations.
Defines a dense matrix for use in Finite Element-type computations.
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.
virtual void left_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- M2 * (*this)
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this) * arg.