10#ifndef _TEUCHOS_SERIALQRDENSESOLVER_HPP_
11#define _TEUCHOS_SERIALQRDENSESOLVER_HPP_
25#ifdef HAVE_TEUCHOSNUMERICS_EIGEN
99 template<
typename OrdinalType,
typename ScalarType>
101 public LAPACK<OrdinalType, ScalarType>
107#ifdef HAVE_TEUCHOSNUMERICS_EIGEN
108 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenMatrix;
109 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,1> EigenVector;
110 typedef typename Eigen::InnerStride<Eigen::Dynamic> EigenInnerStride;
111 typedef typename Eigen::OuterStride<Eigen::Dynamic> EigenOuterStride;
112 typedef typename Eigen::Map<EigenVector,0,EigenInnerStride > EigenVectorMap;
113 typedef typename Eigen::Map<const EigenVector,0,EigenInnerStride > EigenConstVectorMap;
114 typedef typename Eigen::Map<EigenMatrix,0,EigenOuterStride > EigenMatrixMap;
115 typedef typename Eigen::Map<const EigenMatrix,0,EigenOuterStride > EigenConstMatrixMap;
116 typedef typename Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,OrdinalType> EigenPermutationMatrix;
117 typedef typename Eigen::Array<OrdinalType,Eigen::Dynamic,1> EigenOrdinalArray;
118 typedef typename Eigen::Map<EigenOrdinalArray> EigenOrdinalArrayMap;
119 typedef typename Eigen::Array<ScalarType,Eigen::Dynamic,1> EigenScalarArray;
120 typedef typename Eigen::Map<EigenScalarArray> EigenScalarArrayMap;
288 std::vector<ScalarType>
tau()
const {
return(TAU_);}
291 MagnitudeType
ANORM()
const {
return(ANORM_);}
298 void Print(std::ostream& os)
const;
302 void allocateWORK() { LWORK_ = 4*N_; WORK_.resize( LWORK_ );
return;}
308 bool shouldEquilibrate_;
311 OrdinalType equilibrationModeA_;
312 OrdinalType equilibrationModeB_;
332 std::vector<ScalarType> TAU_;
334 MagnitudeType ANORM_;
335 MagnitudeType BNORM_;
337 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > Matrix_;
338 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > LHS_;
339 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > TMP_;
340 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > RHS_;
341 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > Factor_;
342 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > FactorQ_;
343 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > FactorR_;
349 std::vector<ScalarType> WORK_;
350#ifdef HAVE_TEUCHOSNUMERICS_EIGEN
351 Eigen::HouseholderQR<EigenMatrix> qr_;
363 using namespace details;
367template<
typename OrdinalType,
typename ScalarType>
371 shouldEquilibrate_(false),
372 equilibratedA_(false),
373 equilibratedB_(false),
374 equilibrationModeA_(0),
375 equilibrationModeB_(0),
379 matrixIsZero_(false),
403template<
typename OrdinalType,
typename ScalarType>
409template<
typename OrdinalType,
typename ScalarType>
410void SerialQRDenseSolver<OrdinalType,ScalarType>::resetVectors()
412 LHS_ = Teuchos::null;
413 TMP_ = Teuchos::null;
414 RHS_ = Teuchos::null;
416 equilibratedB_ =
false;
420template<
typename OrdinalType,
typename ScalarType>
421void SerialQRDenseSolver<OrdinalType,ScalarType>::resetMatrix()
424 equilibratedA_ =
false;
425 equilibrationModeA_ = 0;
426 equilibrationModeB_ = 0;
428 matrixIsZero_ =
false;
449template<
typename OrdinalType,
typename ScalarType>
453 "SerialQRDenseSolver<T>::setMatrix: the matrix A must have A.numRows() >= A.numCols()!");
462 Min_MN_ = TEUCHOS_MIN(M_,N_);
476template<
typename OrdinalType,
typename ScalarType>
482 "SerialQRDenseSolver<T>::setVectors: X and B have different numbers of columns!");
484 "SerialQRDenseSolver<T>::setVectors: B is an empty SerialDenseMatrix<T>!");
486 "SerialQRDenseSolver<T>::setVectors: X is an empty SerialDenseMatrix<T>!");
488 "SerialQRDenseSolver<T>::setVectors: B has an invalid stride!");
490 "SerialQRDenseSolver<T>::setVectors: X has an invalid stride!");
500template<
typename OrdinalType,
typename ScalarType>
508 if (ierr!=0)
return(ierr);
511 if ((
int)TAU_.size()!=Min_MN_) TAU_.resize( Min_MN_ );
516#ifdef HAVE_TEUCHOSNUMERICS_EIGEN
517 EigenMatrixMap aMap( AF_, M_, N_, EigenOuterStride(LDAF_) );
518 EigenScalarArray
tau;
519 EigenScalarArrayMap tauMap(&TAU_[0],TEUCHOS_MIN(M_,N_));
522 for (OrdinalType i=0; i<tauMap.innerSize(); i++) {
525 EigenMatrix qrMat = qr_.matrixQR();
526 for (OrdinalType j=0; j<aMap.outerSize(); j++) {
527 for (OrdinalType i=0; i<aMap.innerSize(); i++) {
528 aMap(i,j) = qrMat(i,j);
532 this->
GEQRF(M_, N_, AF_, LDAF_, &TAU_[0], &WORK_[0], LWORK_, &INFO_);
542template<
typename OrdinalType,
typename ScalarType>
556 if (ierr != 0)
return(ierr);
559 "SerialQRDenseSolver<T>::solve: No right-hand side vector (RHS) has been set for the linear system!");
561 "SerialQRDenseSolver<T>::solve: No solution vector (LHS) has been set for the linear system!");
564 "SerialQRDenseSolver<T>::solve: No transpose: must have LHS_->numRows() = N_");
567 "SerialQRDenseSolver<T>::solve: Transpose: must have LHS_->numRows() = M_");
571 std::cout <<
"WARNING! SerialQRDenseSolver<T>::solve: System should be equilibrated!" << std::endl;
577 std::logic_error,
"SerialQRDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
580 for (OrdinalType j=0; j<RHS_->numCols(); j++) {
581 for (OrdinalType i=0; i<RHS_->numRows(); i++) {
582 (*TMP_)(i,j) = (*RHS_)(i,j);
599 for (OrdinalType j = 0; j < RHS_->numCols(); j++ ) {
600 for (OrdinalType i = N_; i < M_; i++ ) {
607 for (OrdinalType j = 0; j < LHS_->numCols(); j++ ) {
608 for (OrdinalType i = 0; i < LHS_->numRows(); i++ ) {
609 (*LHS_)(i, j) = (*TMP_)(i,j);
628template<
typename OrdinalType,
typename ScalarType>
643 for (j = 0; j < N_; j++) {
644 for (i = 0; i < M_; i++) {
651 if (ANORM_ > mZero && ANORM_ < smlnum) {
653 shouldEquilibrate_ =
true;
654 }
else if (ANORM_ > bignum) {
656 shouldEquilibrate_ =
true;
657 }
else if (ANORM_ == mZero) {
659 matrixIsZero_ =
true;
667template<
typename OrdinalType,
typename ScalarType>
670 if (equilibratedA_)
return(0);
685 for (j = 0; j < N_; j++) {
686 for (i = 0; i < M_; i++) {
693 if (ANORM_ > mZero && ANORM_ < smlnum) {
695 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, smlnum, M_, N_, A_, LDA_, &INFO_);
696 equilibrationModeA_ = 1;
697 }
else if (ANORM_ > bignum) {
699 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, bignum, M_, N_, A_, LDA_, &INFO_);
700 equilibrationModeA_ = 2;
701 }
else if (ANORM_ == mZero) {
703 matrixIsZero_ =
true;
706 equilibratedA_ =
true;
713template<
typename OrdinalType,
typename ScalarType>
716 if (equilibratedB_)
return(0);
731 for (j = 0; j <RHS_->numCols(); j++) {
732 for (i = 0; i < RHS_->numRows(); i++) {
740 if (BNORM_ > mZero && BNORM_ < smlnum) {
742 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, BNORM_, smlnum, RHS_->numRows(), RHS_->numCols(),
743 RHS_->values(), RHS_->stride(), &INFO_);
744 equilibrationModeB_ = 1;
745 }
else if (BNORM_ > bignum) {
747 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, BNORM_, bignum, RHS_->numRows(), RHS_->numCols(),
748 RHS_->values(), RHS_->stride(), &INFO_);
749 equilibrationModeB_ = 2;
752 equilibratedB_ =
true;
759template<
typename OrdinalType,
typename ScalarType>
762 if (!equilibratedB_)
return(0);
776 if (equilibrationModeA_ == 1) {
777 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, smlnum, LHS_->numRows(), LHS_->numCols(),
778 LHS_->values(), LHS_->stride(), &INFO_);
779 }
else if (equilibrationModeA_ == 2) {
780 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, bignum, LHS_->numRows(), LHS_->numCols(),
781 LHS_->values(), LHS_->stride(), &INFO_);
783 if (equilibrationModeB_ == 1) {
784 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, smlnum, BNORM_, LHS_->numRows(), LHS_->numCols(),
785 LHS_->values(), LHS_->stride(), &INFO_);
786 }
else if (equilibrationModeB_ == 2) {
787 this->
LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, bignum, BNORM_, LHS_->numRows(), LHS_->numCols(),
788 LHS_->values(), LHS_->stride(), &INFO_);
796template<
typename OrdinalType,
typename ScalarType>
805 Q_ = FactorQ_->values();
806 LDQ_ = FactorQ_->stride();
812#ifdef HAVE_TEUCHOSNUMERICS_EIGEN
813 EigenMatrixMap qMap( Q_, M_, N_, EigenOuterStride(LDQ_) );
814 EigenMatrix qMat = qr_.householderQ();
815 for (OrdinalType j=0; j<qMap.outerSize(); j++) {
816 for (OrdinalType i=0; i<qMap.innerSize(); i++) {
817 qMap(i,j) = qMat(i,j);
821 this->
UNGQR(M_, N_, N_, Q_, LDQ_, &TAU_[0], &WORK_[0], LWORK_, &INFO_);
824 if (INFO_!=0)
return(INFO_);
833template<
typename OrdinalType,
typename ScalarType>
842 R_ = FactorR_->values();
843 LDR_ = FactorR_->stride();
847 for (OrdinalType j=0; j<N_; j++) {
848 for (OrdinalType i=0; i<=j; i++) {
849 (*FactorR_)(i,j) = (*Factor_)(i,j);
860template<
typename OrdinalType,
typename ScalarType>
866 "SerialQRDenseSolver<T>::multiplyQ: C.numRows() != M_!");
868 "SerialQRDenseSolver<T>::multiplyQ: C is an empty SerialDenseMatrix<T>!");
876#ifdef HAVE_TEUCHOSNUMERICS_EIGEN
880 cMap = qr_.householderQ() * cMap;
883 cMap = qr_.householderQ().adjoint() * cMap;
884 for (OrdinalType j = 0; j < C.
numCols(); j++) {
885 for (OrdinalType i = N_; i < C.
numRows(); i++ ) {
899 &TAU_[0], C.
values(), C.
stride(), &WORK_[0], LWORK_, &INFO_);
904 this->
UNMQR(ESideChar[SIDE], ETranspChar[
TRANS], M_, C.
numCols(), N_, AF_, LDAF_,
905 &TAU_[0], C.
values(), C.
stride(), &WORK_[0], LWORK_, &INFO_);
907 for (OrdinalType j = 0; j < C.
numCols(); j++) {
908 for (OrdinalType i = N_; i < C.
numRows(); i++ ) {
921template<
typename OrdinalType,
typename ScalarType>
927 "SerialQRDenseSolver<T>::solveR: must have N_ < C.numRows() < M_!");
929 "SerialQRDenseSolver<T>::solveR: C is an empty SerialDenseMatrix<T>!");
937#ifdef HAVE_TEUCHOSNUMERICS_EIGEN
940 for (OrdinalType j=0; j<N_; j++) {
948 qr_.matrixQR().topRows(N_).template triangularView<Eigen::Upper>().solveInPlace(cMap);
951 qr_.matrixQR().topRows(N_).template triangularView<Eigen::Upper>().adjoint().solveInPlace(cMap);
959 ScalarType* RMAT = (formedR_) ? R_ : AF_;
960 OrdinalType LDRMAT = (formedR_) ? LDR_ : LDAF_;
971 this->
TRTRS(EUploChar[UPLO], ETranspChar[
TRANS], EDiagChar[DIAG], N_, C.
numCols(),
983template<
typename OrdinalType,
typename ScalarType>
986 if (Matrix_!=Teuchos::null) os <<
"Solver Matrix" << std::endl << *Matrix_ << std::endl;
987 if (Factor_!=Teuchos::null) os <<
"Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
988 if (Q_!=Teuchos::null) os <<
"Solver Factor Q" << std::endl << *Q_ << std::endl;
989 if (LHS_ !=Teuchos::null) os <<
"Solver LHS" << std::endl << *LHS_ << std::endl;
990 if (RHS_ !=Teuchos::null) os <<
"Solver RHS" << std::endl << *RHS_ << std::endl;
Templated interface class to BLAS routines.
Object for storing data and providing functionality that is common to all computational classes.
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
Templated interface class to LAPACK routines.
Reference-counted pointer class and non-member templated function implementations.
Defines basic traits for the scalar field type.
Templated serial dense matrix class.
Templated class for solving dense linear problems.
BLAS(void)
Default constructor.
CompObject()
Default constructor.
void TRTRS(const char &UPLO, const char &TRANS, const char &DIAG, const OrdinalType &n, const OrdinalType &nrhs, const ScalarType *A, const OrdinalType &lda, ScalarType *B, const OrdinalType &ldb, OrdinalType *info) const
Solves a triangular linear system of the form A*X=B or A**T*X=B, where A is a triangular matrix.
void UNGQR(const OrdinalType &m, const OrdinalType &n, const OrdinalType &k, ScalarType *A, const OrdinalType &lda, const ScalarType *TAU, ScalarType *WORK, const OrdinalType &lwork, OrdinalType *info) const
Compute explicit QR factor from QR factorization (GEQRF) (complex case).
void UNMQR(const char &SIDE, const char &TRANS, const OrdinalType &m, const OrdinalType &n, const OrdinalType &k, const ScalarType *A, const OrdinalType &lda, const ScalarType *TAU, ScalarType *C, const OrdinalType &ldc, ScalarType *WORK, const OrdinalType &lwork, OrdinalType *info) const
Apply Householder reflectors (complex case).
void LASCL(const char &TYPE, const OrdinalType &kl, const OrdinalType &ku, const MagnitudeType cfrom, const MagnitudeType cto, const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, OrdinalType *info) const
Multiplies the m by n matrix A by the real scalar cto/cfrom.
LAPACK(void)
Default Constructor.
void GEQRF(const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, ScalarType *TAU, ScalarType *WORK, const OrdinalType &lwork, OrdinalType *info) const
Computes a QR factorization of a general m by n matrix A.
Object(int tracebackModeIn=-1)
Default Constructor.
Smart reference counting pointer class for automatic garbage collection.
This class creates and provides basic support for dense rectangular matrix of templated type.
OrdinalType stride() const
Returns the stride between the columns of this matrix in memory.
OrdinalType numRows() const
Returns the row dimension of this matrix.
ScalarType * values() const
Data array access method.
OrdinalType numCols() const
Returns the column dimension of this matrix.
void factorWithEquilibration(bool flag)
Causes equilibration to be called just before the matrix factorization as part of the call to factor.
int solveR(ETransp transr, SerialDenseMatrix< OrdinalType, ScalarType > &C)
Solve input matrix on the left with the upper triangular matrix R or its adjoint.
bool solved()
Returns true if the current set of vectors has been solved.
bool equilibratedB()
Returns true if RHS is equilibrated (RHS available via getRHS()).
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getLHS() const
Returns pointer to current LHS.
bool formedR()
Returns true if R has been formed explicitly.
int formR()
Explicitly forms the upper triangular matrix R.
bool shouldEquilibrate()
Returns true if the LAPACK general rules for equilibration suggest you should equilibrate the system.
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
Sets the pointers for left and right hand side vector(s).
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getMatrix() const
Returns pointer to current matrix.
void solveWithTranspose(bool flag)
If flag is true, causes all subsequent function calls to work with the adjoint of this matrix,...
bool transpose()
Returns true if adjoint of this matrix has and will be used.
int multiplyQ(ETransp transq, SerialDenseMatrix< OrdinalType, ScalarType > &C)
Left multiply the input matrix by the unitary matrix Q or its adjoint.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getQ() const
Returns pointer to Q (assuming factorization has been performed).
MagnitudeType ANORM() const
Returns the absolute value of the largest element of this matrix (returns -1 if not yet computed).
OrdinalType numCols() const
Returns column dimension of system.
bool formedQ()
Returns true if Q has been formed explicitly.
std::vector< ScalarType > tau() const
Returns pointer to pivot vector (if factorization has been computed), zero otherwise.
OrdinalType numRows() const
Returns row dimension of system.
virtual ~SerialQRDenseSolver()
SerialQRDenseSolver destructor.
int factor()
Computes the in-place QR factorization of the matrix using the LAPACK routine _GETRF or the Eigen cla...
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getFactoredMatrix() const
Returns pointer to factored matrix (assuming factorization has been performed).
int solve()
Computes the solution X to AX = B for the this matrix and the B provided to SetVectors()....
SerialQRDenseSolver()
Default constructor; matrix should be set using setMatrix(), LHS and RHS set with setVectors().
void solveWithTransposeFlag(Teuchos::ETransp trans)
All subsequent function calls will work with the transpose-type set by this method (Teuchos::NO_TRANS...
bool factored()
Returns true if matrix is factored (factor available via getFactoredMatrix()).
void Print(std::ostream &os) const
Print service methods; defines behavior of ostream << operator.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getR() const
Returns pointer to R (assuming factorization has been performed).
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)
Sets the pointers for coefficient matrix.
int formQ()
Explicitly forms the unitary matrix Q.
int equilibrateMatrix()
Equilibrates the this matrix.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getRHS() const
Returns pointer to current RHS.
int equilibrateRHS()
Equilibrates the current RHS.
bool equilibratedA()
Returns true if factor is equilibrated (factor available via getFactoredMatrix()).
int computeEquilibrateScaling()
Determines if this matrix should be scaled.
int unequilibrateLHS()
Unscales the solution vectors if equilibration was used to solve the system.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
This structure defines some basic traits for a scalar field type.
static magnitudeType magnitude(T a)
Returns the magnitudeType of the scalar type a.
static T one()
Returns representation of one for this scalar type.
T magnitudeType
Mandatory typedef for result of magnitude.
static T zero()
Returns representation of zero for this scalar type.
static const bool isComplex
Determines if scalar type is std::complex.
static magnitudeType sfmin()
Returns safe minimum (sfmin), such that 1/sfmin does not overflow.
static magnitudeType prec()
Returns eps*base.