20 #include "libmesh/dense_matrix.h" 21 #include "libmesh/dense_vector.h" 22 #include "libmesh/int_range.h" 24 #if (LIBMESH_HAVE_PETSC) 25 # include "libmesh/petsc_macro.h" 26 # include "libmesh/ignore_warnings.h" 27 # include <petscblaslapack.h> 28 # include "libmesh/restore_warnings.h" 34 #if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS) 48 result_size = other.
m() * this->n();
49 if (other.
n() == this->m())
52 libmesh_fallthrough();
55 result_size = other.
n() * this->m();
56 if (other.
m() == this->n())
59 libmesh_fallthrough();
60 case LEFT_MULTIPLY_TRANSPOSE:
62 result_size = other.
n() * this->n();
63 if (other.
m() == this->m())
66 libmesh_fallthrough();
67 case RIGHT_MULTIPLY_TRANSPOSE:
69 result_size = other.
m() * this->m();
70 if (other.
n() == this->n())
73 libmesh_fallthrough();
75 libmesh_error_msg(
"Unknown flag selected or matrices are incompatible for multiplication.");
79 const DenseMatrix<T> * const_that = cast_ptr<const DenseMatrix<T> *>(&other);
96 if (flag==RIGHT_MULTIPLY || flag==RIGHT_MULTIPLY_TRANSPOSE)
113 PetscBLASInt M =
static_cast<PetscBLASInt
>( A->
n() );
122 PetscBLASInt N =
static_cast<PetscBLASInt
>(
B->m() );
132 PetscBLASInt K =
static_cast<PetscBLASInt
>( A->
m() );
136 PetscBLASInt LDA =
static_cast<PetscBLASInt
>( A->
n() );
140 PetscBLASInt LDB =
static_cast<PetscBLASInt
>(
B->n() );
142 if (flag == LEFT_MULTIPLY_TRANSPOSE)
145 N =
static_cast<PetscBLASInt
>(
B->n() );
148 else if (flag == RIGHT_MULTIPLY_TRANSPOSE)
156 PetscBLASInt LDC = M;
167 std::vector<T> result (result_size);
170 BLASgemm_(transa, transb, &M, &N, &K,
pPS(&alpha),
172 pPS(
B->get_values().data()), &LDB,
pPS(&beta),
173 pPS(result.data()), &LDC);
178 case LEFT_MULTIPLY: { this->_m = other.
m();
break; }
179 case RIGHT_MULTIPLY: { this->_n = other.
n();
break; }
180 case LEFT_MULTIPLY_TRANSPOSE: { this->_m = other.
n();
break; }
181 case RIGHT_MULTIPLY_TRANSPOSE: { this->_n = other.
m();
break; }
183 libmesh_error_msg(
"Unknown flag selected.");
187 this->_val.swap(result);
196 libmesh_error_msg(
"No PETSc-provided BLAS/LAPACK available!");
207 #if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS) 214 libmesh_assert_equal_to (this->_decomposition_type, NONE);
222 PetscBLASInt M = this->n();
227 PetscBLASInt N = this->m();
236 PetscBLASInt LDA = M;
242 this->_pivots.resize( std::min(M,N) );
251 PetscBLASInt INFO = 0;
254 LAPACKgetrf_(&M, &N,
pPS(this->_val.data()), &LDA, _pivots.data(),
258 libmesh_error_msg_if(INFO != 0,
"INFO=" << INFO <<
", Error during Lapack LU factorization!");
261 this->_decomposition_type = LU_BLAS_LAPACK;
269 libmesh_error_msg(
"No PETSc-provided BLAS/LAPACK available!");
305 std::vector<Real> sigma_val;
306 std::vector<Number> U_val;
307 std::vector<Number> VT_val;
309 _svd_helper(JOBU, JOBVT, sigma_val, U_val, VT_val);
312 sigma.
resize(cast_int<unsigned int>(sigma_val.size()));
314 sigma(i) = sigma_val[i];
354 std::vector<Real> sigma_val;
357 int min_MN = (M < N) ? M : N;
376 sigma.
resize(cast_int<unsigned int>(sigma_val.size()));
378 sigma(i) = sigma_val[i];
381 #if (LIBMESH_HAVE_PETSC) 386 std::vector<Real> & sigma_val,
387 std::vector<Number> & U_val,
388 std::vector<Number> & VT_val)
394 PetscBLASInt M = this->n();
399 PetscBLASInt N = this->m();
401 PetscBLASInt min_MN = (M < N) ? M : N;
402 PetscBLASInt max_MN = (M > N) ? M : N;
417 PetscBLASInt LDA = M;
421 sigma_val.resize( min_MN );
426 PetscBLASInt LDU = M;
435 U_val.resize( LDU*min_MN );
437 U_val.resize( LDU*M );
442 PetscBLASInt LDVT = N;
452 VT_val.resize( LDVT*N );
463 PetscBLASInt larger = (3*min_MN+max_MN > 5*min_MN) ? 3*min_MN+max_MN : 5*min_MN;
464 PetscBLASInt LWORK = (larger > 1) ? larger : 1;
474 std::vector<Number> WORK( LWORK );
483 PetscBLASInt INFO = 0;
486 #ifdef LIBMESH_USE_REAL_NUMBERS 488 LAPACKgesvd_(&JOBU, &JOBVT, &M, &N,
pPS(_val.data()), &LDA,
489 pPS(sigma_val.data()),
pPS(U_val.data()), &LDU,
490 pPS(VT_val.data()), &LDVT,
pPS(WORK.data()), &LWORK,
496 std::vector<Number> val_copy(_val.size());
498 val_copy[i] = _val[i];
500 std::vector<Real> RWORK(5 * min_MN);
501 LAPACKgesvd_(&JOBU, &JOBVT, &M, &N, val_copy.data(), &LDA, sigma_val.data(), U_val.data(),
502 &LDU, VT_val.data(), &LDVT, WORK.data(), &LWORK, RWORK.data(), &INFO);
506 libmesh_error_msg_if(INFO != 0,
"INFO=" << INFO <<
", Error during Lapack SVD calculation!");
516 std::vector<Number> &,
517 std::vector<Number> &)
519 libmesh_error_msg(
"No PETSc-provided BLAS/LAPACK available!");
526 #if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS) 542 this->get_transpose(A_trans);
547 PetscBLASInt M = A_trans.
n();
552 PetscBLASInt N = A_trans.
m();
555 PetscBLASInt max_MN = std::max(M,N);
556 PetscBLASInt min_MN = std::min(M,N);
563 PetscBLASInt NRHS = 1;
571 std::vector<T> & A_trans_vals = A_trans.
get_values();
575 PetscBLASInt LDA = M;
597 PetscBLASInt LDB = x.
size();
602 std::vector<T> S(min_MN);
608 PetscScalar RCOND =
PS(rcond);
613 PetscBLASInt RANK = 0;
627 PetscBLASInt LWORK = (3*min_MN + std::max(2*min_MN, std::max(max_MN, NRHS))) * 3/2;
631 std::vector<T> WORK(LWORK);
639 PetscBLASInt INFO = 0;
654 LAPACKgelss_(&M, &N, &NRHS,
pPS(A_trans_vals.data()), &LDA,
655 pPS(
B.data()), &LDB,
pPS(S.data()), &RCOND, &RANK,
656 pPS(WORK.data()), &LWORK, &INFO);
659 libmesh_error_msg_if(INFO < 0,
"Error, argument " << -INFO <<
" to LAPACKgelss_ had an illegal value.");
660 libmesh_error_msg_if(INFO > 0,
"The algorithm for computing the SVD failed to converge!");
686 libmesh_not_implemented();
688 #endif // (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS) 692 #if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS) 701 libmesh_error_msg_if(this->m() != this->n(),
"Can only compute eigen-decompositions for square matrices.");
714 std::swap((*
this)(i,j), (*
this)(j,i));
736 char JOBVL = VL ?
'V' :
'N';
741 char JOBVR = VR ?
'V' :
'N';
745 PetscBLASInt N = this->m();
753 PetscBLASInt LDA = N;
780 PetscBLASInt LDVL = VL ? N : 1;
797 PetscBLASInt LDVR = VR ? N : 1;
811 PetscBLASInt LWORK = (VR || VL) ? 4*N : 3*N;
812 std::vector<T> WORK(LWORK);
821 PetscBLASInt INFO = 0;
824 std::vector<T> & lambda_real_val = lambda_real.
get_values();
825 std::vector<T> & lambda_imag_val = lambda_imag.
get_values();
828 T * VR_ptr =
nullptr;
835 T * VL_ptr =
nullptr;
848 pPS(lambda_real_val.data()),
849 pPS(lambda_imag_val.data()),
859 libmesh_error_msg_if(INFO != 0,
"INFO=" << INFO <<
", Error during Lapack eigenvalue calculation!");
870 std::swap((*VR)(i,j), (*VR)(j,i));
877 std::swap((*VL)(i,j), (*VL)(j,i));
889 libmesh_error_msg(
"_evd_lapack is currently only available when LIBMESH_USE_REAL_NUMBERS is defined!");
898 #if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS) 913 PetscBLASInt N = this->m();
919 PetscBLASInt NRHS = 1;
927 PetscBLASInt LDA = N;
949 PetscBLASInt LDB = N;
954 PetscBLASInt INFO = 0;
957 LAPACKgetrs_(TRANS, &N, &NRHS,
pPS(_val.data()), &LDA,
958 _pivots.data(),
pPS(x_vec.data()), &LDB, &INFO);
961 libmesh_error_msg_if(INFO != 0,
"INFO=" << INFO <<
", Error during Lapack LU solve!");
978 libmesh_error_msg(
"No PETSc-provided BLAS/LAPACK available!");
987 #if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS) 1001 libmesh_error_msg_if((dest.
size() != this->m()) || (arg.
size() != this->n()),
1002 "Improper input argument sizes!");
1010 libmesh_error_msg_if((dest.
size() != this->n()) || (arg.
size() != this->m()),
1011 "Improper input argument sizes!");
1029 PetscBLASInt M = this->n();
1034 PetscBLASInt N = this->m();
1053 PetscBLASInt LDA = M;
1069 PetscBLASInt INCX = 1;
1089 PetscBLASInt INCY = 1;
1092 BLASgemv_(TRANS, &M, &N,
pPS(&alpha),
pPS(a.data()), &LDA,
1093 pPS(x.data()), &INCX,
pPS(&beta),
pPS(y.data()), &INCY);
1100 template<
typename T>
1107 libmesh_error_msg(
"No PETSc-provided BLAS/LAPACK available!");
1127 DenseMatrix<Number> &,
1128 DenseMatrix<Number> &);
1131 std::vector<Real> &,
1132 std::vector<Number> &,
1133 std::vector<Number> &);
1140 #if !(LIBMESH_USE_REAL_NUMBERS) 1144 DenseVector<Number> &);
1147 DenseVector<Number> &,
1148 const DenseVector<Number> &,
1152 DenseMatrix<Number> &,
1153 DenseMatrix<Number> &);
1156 std::vector<Real> &,
1157 std::vector<Number> &,
1158 std::vector<Number> &);
1161 DenseVector<Number> &,
1162 DenseMatrix<Number> *,
1163 DenseMatrix<Number> *);
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 _lu_decompose_lapack()
Computes an LU factorization of the matrix using the Lapack routine "getrf".
_BLAS_Multiply_Flag
Enumeration used to determine the behavior of the _multiply_blas function.
template class LIBMESH_EXPORT DenseVector< Real >
void _svd_solve_lapack(const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond) const
Called by svd_solve(rhs).
void resize(const unsigned int n)
Resize the vector.
std::vector< T > & get_values()
PetscScalar * pPS(T *ptr)
The libMesh namespace provides an interface to certain functionality in the library.
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 _lu_back_substitute_lapack(const DenseVector< T > &b, DenseVector< T > &x)
Companion function to _lu_decompose_lapack().
template class LIBMESH_EXPORT DenseMatrix< Real >
void _svd_lapack(DenseVector< Real > &sigma)
Computes an SVD of the matrix using the Lapack routine "getsvd".
std::vector< T > & get_values()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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".
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.
Defines an abstract dense matrix base class for use in Finite Element-type computations.
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.
Defines a dense matrix for use in Finite Element-type computations.
template class LIBMESH_EXPORT DenseMatrixBase< Real >