19 #ifndef LIBMESH_DENSE_MATRIX_IMPL_H 20 #define LIBMESH_DENSE_MATRIX_IMPL_H 42 if (this->use_blas_lapack)
43 this->_multiply_blas(M2, LEFT_MULTIPLY);
56 this->resize (M2.
m(), M3.
n());
59 this->multiply(*
this, M2, M3);
79 this->resize (M2.
m(), M3.
n());
82 this->multiply(*
this, M2, M3);
90 if (this->use_blas_lapack)
91 this->_multiply_blas(
A, LEFT_MULTIPLY_TRANSPOSE);
105 const unsigned int n_rows =
A.m();
106 const unsigned int n_cols =
A.n();
109 this->resize(n_cols,n_cols);
112 for (
unsigned int i=0; i<n_cols; ++i)
113 for (
unsigned int j=0; j<=i; ++j)
114 for (
unsigned int k=0; k<n_rows; ++k)
115 (*
this)(i,j) += B(k,i)*B(k,j);
118 for (
unsigned int i=0; i<n_cols; ++i)
119 for (
unsigned int j=i+1; j<n_cols; ++j)
120 (*
this)(i,j) = (*
this)(j,i);
127 this->resize (
A.n(), B.
n());
129 libmesh_assert_equal_to (
A.m(), B.
m());
130 libmesh_assert_equal_to (this->m(),
A.n());
131 libmesh_assert_equal_to (this->n(), B.
n());
133 const unsigned int m_s =
A.n();
134 const unsigned int p_s =
A.m();
135 const unsigned int n_s = this->n();
140 for (
unsigned int i=0; i<m_s; i++)
141 for (
unsigned int k=0; k<p_s; k++)
142 if (
A.transpose(i,k) != 0.)
143 for (
unsigned int j=0; j<n_s; j++)
144 (*
this)(i,j) +=
A.transpose(i,k)*B(k,j);
153 template<
typename T2>
167 const unsigned int n_rows =
A.m();
168 const unsigned int n_cols =
A.n();
171 this->resize(n_cols,n_cols);
174 for (
unsigned int i=0; i<n_cols; ++i)
175 for (
unsigned int j=0; j<=i; ++j)
176 for (
unsigned int k=0; k<n_rows; ++k)
177 (*
this)(i,j) += B(k,i)*B(k,j);
180 for (
unsigned int i=0; i<n_cols; ++i)
181 for (
unsigned int j=i+1; j<n_cols; ++j)
182 (*
this)(i,j) = (*
this)(j,i);
189 this->resize (
A.n(), B.
n());
191 libmesh_assert_equal_to (
A.m(), B.
m());
192 libmesh_assert_equal_to (this->m(),
A.n());
193 libmesh_assert_equal_to (this->n(), B.
n());
195 const unsigned int m_s =
A.n();
196 const unsigned int p_s =
A.m();
197 const unsigned int n_s = this->n();
202 for (
unsigned int i=0; i<m_s; i++)
203 for (
unsigned int k=0; k<p_s; k++)
204 if (
A.transpose(i,k) != 0.)
205 for (
unsigned int j=0; j<n_s; j++)
206 (*
this)(i,j) +=
A.transpose(i,k)*B(k,j);
215 if (this->use_blas_lapack)
216 this->_multiply_blas(M3, RIGHT_MULTIPLY);
229 this->resize (M2.
m(), M3.
n());
231 this->multiply(*
this, M2, M3);
238 template<
typename T2>
251 this->resize (M2.
m(), M3.
n());
253 this->multiply(*
this, M2, M3);
262 if (this->use_blas_lapack)
263 this->_multiply_blas(B, RIGHT_MULTIPLY_TRANSPOSE);
277 const unsigned int n_rows = B.
m();
278 const unsigned int n_cols = B.
n();
281 this->resize(n_rows,n_rows);
284 for (
unsigned int i=0; i<n_rows; ++i)
285 for (
unsigned int j=0; j<=i; ++j)
286 for (
unsigned int k=0; k<n_cols; ++k)
287 (*
this)(i,j) +=
A(i,k)*
A(j,k);
290 for (
unsigned int i=0; i<n_rows; ++i)
291 for (
unsigned int j=i+1; j<n_rows; ++j)
292 (*
this)(i,j) = (*
this)(j,i);
299 this->resize (
A.m(), B.
m());
301 libmesh_assert_equal_to (
A.n(), B.
n());
302 libmesh_assert_equal_to (this->m(),
A.m());
303 libmesh_assert_equal_to (this->n(), B.
m());
305 const unsigned int m_s =
A.m();
306 const unsigned int p_s =
A.n();
307 const unsigned int n_s = this->n();
312 for (
unsigned int j=0; j<n_s; j++)
313 for (
unsigned int k=0; k<p_s; k++)
315 for (
unsigned int i=0; i<m_s; i++)
324 template<
typename T2>
338 const unsigned int n_rows = B.
m();
339 const unsigned int n_cols = B.
n();
342 this->resize(n_rows,n_rows);
345 for (
unsigned int i=0; i<n_rows; ++i)
346 for (
unsigned int j=0; j<=i; ++j)
347 for (
unsigned int k=0; k<n_cols; ++k)
348 (*
this)(i,j) +=
A(i,k)*
A(j,k);
351 for (
unsigned int i=0; i<n_rows; ++i)
352 for (
unsigned int j=i+1; j<n_rows; ++j)
353 (*
this)(i,j) = (*
this)(j,i);
360 this->resize (
A.m(), B.
m());
362 libmesh_assert_equal_to (
A.n(), B.
n());
363 libmesh_assert_equal_to (this->m(),
A.m());
364 libmesh_assert_equal_to (this->n(), B.
m());
366 const unsigned int m_s =
A.m();
367 const unsigned int p_s =
A.n();
368 const unsigned int n_s = this->n();
373 for (
unsigned int j=0; j<n_s; j++)
374 for (
unsigned int k=0; k<p_s; k++)
376 for (
unsigned int i=0; i<m_s; i++)
389 libmesh_assert_equal_to (this->n(), arg.
size());
396 if(this->m() == 0 || this->n() == 0)
399 if (this->use_blas_lapack)
400 this->_matvec_blas(1., 0., dest, arg);
403 const unsigned int n_rows = this->m();
404 const unsigned int n_cols = this->n();
406 for (
unsigned int i=0; i<n_rows; i++)
407 for (
unsigned int j=0; j<n_cols; j++)
408 dest(i) += (*this)(i,j)*arg(j);
415 template<
typename T2>
420 libmesh_assert_equal_to (this->n(), arg.
size());
424 dest.resize(this->m());
427 if (this->m() == 0 || this->n() == 0)
430 const unsigned int n_rows = this->m();
431 const unsigned int n_cols = this->n();
433 for (
unsigned int i=0; i<n_rows; i++)
434 for (
unsigned int j=0; j<n_cols; j++)
435 dest(i) += (*this)(i,j)*arg(j);
445 libmesh_assert_equal_to (this->m(), arg.
size());
455 if (this->use_blas_lapack)
457 this->_matvec_blas(1., 0., dest, arg,
true);
461 const unsigned int n_rows = this->m();
462 const unsigned int n_cols = this->n();
470 for (
unsigned int i=0; i<n_cols; i++)
471 for (
unsigned int j=0; j<n_rows; j++)
472 dest(i) += (*this)(j,i)*arg(j);
479 template<
typename T2>
484 libmesh_assert_equal_to (this->m(), arg.
size());
488 dest.resize(this->n());
494 const unsigned int n_rows = this->m();
495 const unsigned int n_cols = this->n();
503 for (
unsigned int i=0; i<n_cols; i++)
504 for (
unsigned int j=0; j<n_rows; j++)
505 dest(i) += (*this)(j,i)*arg(j);
522 if (this->use_blas_lapack)
523 this->_matvec_blas(factor, 1., dest, arg);
527 this->vector_mult(temp, arg);
528 dest.
add(factor, temp);
535 template<
typename T2,
typename T3>
549 this->vector_mult(temp, arg);
550 dest.add(factor, temp);
560 libmesh_assert( (sub_m <= this->m()) && (sub_n <= this->n()) );
562 dest.
resize(sub_m, sub_n);
563 for (
unsigned int i=0; i<sub_m; i++)
564 for (
unsigned int j=0; j<sub_n; j++)
565 dest(i,j) = (*this)(i,j);
574 const unsigned int m = a.
size();
575 const unsigned int n = b.
size();
578 for (
unsigned int i = 0; i < m; ++i)
579 for (
unsigned int j = 0; j < n; ++j)
588 get_principal_submatrix(sub_m, sub_m, dest);
596 dest.
resize(this->n(), this->m());
598 for (
unsigned int i=0; i<dest.
m(); i++)
599 for (
unsigned int j=0; j<dest.
n(); j++)
600 dest(i,j) = (*this)(j,i);
621 libmesh_assert_equal_to (this->m(), this->n());
623 switch(this->_decomposition_type)
627 if (this->use_blas_lapack)
628 this->_lu_decompose_lapack();
630 this->_lu_decompose ();
637 if (this->use_blas_lapack)
640 libmesh_fallthrough();
645 if (!(this->use_blas_lapack))
648 libmesh_fallthrough();
651 libmesh_error_msg(
"Error! This matrix already has a different decomposition...");
654 if (this->use_blas_lapack)
655 this->_lu_back_substitute_lapack (b, x);
657 this->_lu_back_substitute (b, x);
672 libmesh_assert_equal_to (this->m(), n_cols);
673 libmesh_assert_equal_to (this->m(), b.
size());
685 for (
unsigned int i=0; i<n_cols; ++i)
688 if (_pivots[i] != static_cast<pivot_index_t>(i))
693 for (
unsigned int j=0; j<i; ++j)
700 const unsigned int last_row = n_cols-1;
702 for (
int i=last_row; i>=0; --i)
704 for (
int j=i+1; j<static_cast<int>(n_cols); ++j)
721 libmesh_assert_equal_to (this->_decomposition_type, NONE);
730 _pivots.resize(n_rows);
732 for (
unsigned int i=0; i<n_rows; ++i)
739 for (
unsigned int j=i+1; j<n_rows; ++j)
742 if (the_max < candidate_max)
744 the_max = candidate_max;
754 if (_pivots[i] != static_cast<pivot_index_t>(i))
756 for (
unsigned int j=0; j<n_rows; ++j)
763 libmesh_error_msg(
"Matrix A is singular!");
767 const T diag_inv = 1. /
A(i,i);
768 for (
unsigned int j=i+1; j<n_rows; ++j)
782 for (
unsigned int row=i+1; row<n_rows; ++row)
783 for (
unsigned int col=i+1; col<n_rows; ++col)
784 A(row,col) -=
A(row,i) *
A(i,col);
789 this->_decomposition_type = LU;
808 _svd_lapack(sigma, U, VT);
818 _svd_solve_lapack(rhs, x, rcond);
828 _evd_lapack(lambda_real, lambda_imag);
839 _evd_lapack(lambda_real, lambda_imag, &VL,
nullptr);
850 _evd_lapack(lambda_real, lambda_imag,
nullptr, &VR);
862 _evd_lapack(lambda_real, lambda_imag, &VL, &VR);
870 switch(this->_decomposition_type)
877 if (this->use_blas_lapack)
878 this->_lu_decompose_lapack();
880 this->_lu_decompose ();
889 libmesh_error_msg(
"Error! Can't compute the determinant under the current decomposition.");
900 unsigned int n_interchanges = 0;
901 for (
unsigned int i=0; i<this->m(); i++)
903 if (this->_decomposition_type==LU)
904 if (_pivots[i] != static_cast<pivot_index_t>(i))
908 if (this->_decomposition_type==LU_BLAS_LAPACK)
909 if (_pivots[i] != static_cast<pivot_index_t>(i+1))
912 determinant *= (*this)(i,i);
917 Real sign = n_interchanges % 2 == 0 ? 1. : -1.;
919 return sign*determinant;
927 template <
typename T>
928 template <
typename T2>
933 switch(this->_decomposition_type)
937 this->_cholesky_decompose ();
948 libmesh_error_msg(
"Error! This matrix already has a different decomposition...");
952 this->_cholesky_back_substitute (b, x);
965 libmesh_assert_equal_to (this->_decomposition_type, NONE);
973 libmesh_assert_equal_to (n_rows, n_cols);
978 for (
unsigned int i=0; i<n_rows; ++i)
980 for (
unsigned int j=i; j<n_cols; ++j)
982 for (
unsigned int k=0; k<i; ++k)
983 A(i,j) -=
A(i,k) *
A(j,k);
987 #ifndef LIBMESH_USE_COMPLEX_NUMBERS 989 libmesh_error_msg(
"Error! Can only use Cholesky decomposition with symmetric positive definite matrices.");
992 A(i,i) = std::sqrt(
A(i,j));
995 A(j,i) =
A(i,j) /
A(i,i);
1000 this->_decomposition_type = CHOLESKY;
1005 template <
typename T>
1006 template <
typename T2>
1016 libmesh_assert_equal_to (n_rows, n_cols);
1025 for (
unsigned int i=0; i<n_cols; ++i)
1029 for (
unsigned int k=0; k<i; ++k)
1030 temp -=
A(i,k)*x(k);
1032 x(i) = temp /
A(i,i);
1036 for (
unsigned int i=0; i<n_cols; ++i)
1038 const unsigned int ib = (n_cols-1)-i;
1040 for (
unsigned int k=(ib+1); k<n_cols; ++k)
1041 x(ib) -=
A(k,ib) * x(k);
1100 #endif // LIBMESH_DENSE_MATRIX_IMPL_H virtual unsigned int size() const override
void _lu_back_substitute(const DenseVector< T > &b, DenseVector< T > &x) const
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)
void resize(const unsigned int n)
void evd_left(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL)
void evd_left_and_right(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL, DenseMatrix< T > &VR)
void outer_product(const DenseVector< T > &a, const DenseVector< T > &b)
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
void svd(DenseVector< Real > &sigma)
void get_transpose(DenseMatrix< T > &dest) const
virtual void right_multiply(const DenseMatrixBase< T > &M2) override
void evd_right(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VR)
void _cholesky_back_substitute(const DenseVector< T2 > &b, DenseVector< T2 > &x) const
void _cholesky_decompose()
void get_principal_submatrix(unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
void right_multiply_transpose(const DenseMatrix< T > &A)
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void evd(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag)
void left_multiply_transpose(const DenseMatrix< T > &A)
static PetscErrorCode Mat * A
void swap(Iterator &lhs, Iterator &rhs)
void resize(const unsigned int new_m, const unsigned int new_n)
virtual void left_multiply(const DenseMatrixBase< T > &M2) override
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
A matrix object used for finite element assembly and numerics.
void svd_solve(const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond=std::numeric_limits< Real >::epsilon()) const
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const