42 #ifndef _TEUCHOS_SERIALQRDENSESOLVER_HPP_
43 #define _TEUCHOS_SERIALQRDENSESOLVER_HPP_
57 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
58 #include "Eigen/Dense"
131 template<
typename OrdinalType,
typename ScalarType>
133 public LAPACK<OrdinalType, ScalarType>
139 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
140 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenMatrix;
141 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,1> EigenVector;
142 typedef typename Eigen::InnerStride<Eigen::Dynamic> EigenInnerStride;
143 typedef typename Eigen::OuterStride<Eigen::Dynamic> EigenOuterStride;
144 typedef typename Eigen::Map<EigenVector,0,EigenInnerStride > EigenVectorMap;
145 typedef typename Eigen::Map<const EigenVector,0,EigenInnerStride > EigenConstVectorMap;
146 typedef typename Eigen::Map<EigenMatrix,0,EigenOuterStride > EigenMatrixMap;
147 typedef typename Eigen::Map<const EigenMatrix,0,EigenOuterStride > EigenConstMatrixMap;
148 typedef typename Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,OrdinalType> EigenPermutationMatrix;
149 typedef typename Eigen::Array<OrdinalType,Eigen::Dynamic,1> EigenOrdinalArray;
150 typedef typename Eigen::Map<EigenOrdinalArray> EigenOrdinalArrayMap;
151 typedef typename Eigen::Array<ScalarType,Eigen::Dynamic,1> EigenScalarArray;
152 typedef typename Eigen::Map<EigenScalarArray> EigenScalarArrayMap;
320 std::vector<ScalarType>
tau()
const {
return(TAU_);}
323 MagnitudeType
ANORM()
const {
return(ANORM_);}
329 void Print(std::ostream& os)
const;
334 void allocateWORK() { LWORK_ = 4*N_; WORK_.resize( LWORK_ );
return;}
340 bool shouldEquilibrate_;
343 OrdinalType equilibrationModeA_;
344 OrdinalType equilibrationModeB_;
364 std::vector<ScalarType> TAU_;
366 MagnitudeType ANORM_;
367 MagnitudeType BNORM_;
369 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > Matrix_;
370 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > LHS_;
371 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > TMP_;
372 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > RHS_;
373 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > Factor_;
374 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > FactorQ_;
375 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > FactorR_;
381 std::vector<ScalarType> WORK_;
382 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
383 Eigen::HouseholderQR<EigenMatrix> qr_;
390 SerialQRDenseSolver & operator=(
const SerialQRDenseSolver<OrdinalType, ScalarType>& Source);
395 using namespace details;
399 template<
typename OrdinalType,
typename ScalarType>
403 shouldEquilibrate_(false),
404 equilibratedA_(false),
405 equilibratedB_(false),
406 equilibrationModeA_(0),
407 equilibrationModeB_(0),
411 matrixIsZero_(false),
435 template<
typename OrdinalType,
typename ScalarType>
441 template<
typename OrdinalType,
typename ScalarType>
444 LHS_ = Teuchos::null;
445 TMP_ = Teuchos::null;
446 RHS_ = Teuchos::null;
448 equilibratedB_ =
false;
452 template<
typename OrdinalType,
typename ScalarType>
453 void SerialQRDenseSolver<OrdinalType,ScalarType>::resetMatrix()
456 equilibratedA_ =
false;
457 equilibrationModeA_ = 0;
458 equilibrationModeB_ = 0;
460 matrixIsZero_ =
false;
481 template<
typename OrdinalType,
typename ScalarType>
485 "SerialQRDenseSolver<T>::setMatrix: the matrix A must have A.numRows() >= A.numCols()!");
494 Min_MN_ = TEUCHOS_MIN(M_,N_);
508 template<
typename OrdinalType,
typename ScalarType>
514 "SerialQRDenseSolver<T>::setVectors: X and B have different numbers of columns!");
516 "SerialQRDenseSolver<T>::setVectors: B is an empty SerialDenseMatrix<T>!");
518 "SerialQRDenseSolver<T>::setVectors: X is an empty SerialDenseMatrix<T>!");
520 "SerialQRDenseSolver<T>::setVectors: B has an invalid stride!");
522 "SerialQRDenseSolver<T>::setVectors: X has an invalid stride!");
532 template<
typename OrdinalType,
typename ScalarType>
535 if (factored())
return(0);
539 if (equilibrate_) ierr = equilibrateMatrix();
540 if (ierr!=0)
return(ierr);
543 if ((
int)TAU_.size()!=Min_MN_) TAU_.resize( Min_MN_ );
548 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
549 EigenMatrixMap aMap( AF_, M_, N_, EigenOuterStride(LDAF_) );
550 EigenScalarArray tau;
551 EigenScalarArrayMap tauMap(&TAU_[0],TEUCHOS_MIN(M_,N_));
554 for (OrdinalType i=0; i<tauMap.innerSize(); i++) {
557 EigenMatrix qrMat = qr_.matrixQR();
558 for (OrdinalType j=0; j<aMap.outerSize(); j++) {
559 for (OrdinalType i=0; i<aMap.innerSize(); i++) {
560 aMap(i,j) = qrMat(i,j);
564 this->GEQRF(M_, N_, AF_, LDAF_, &TAU_[0], &WORK_[0], LWORK_, &INFO_);
574 template<
typename OrdinalType,
typename ScalarType>
586 ierr = equilibrateRHS();
588 if (ierr != 0)
return(ierr);
591 "SerialQRDenseSolver<T>::solve: No right-hand side vector (RHS) has been set for the linear system!");
593 "SerialQRDenseSolver<T>::solve: No solution vector (LHS) has been set for the linear system!");
596 "SerialQRDenseSolver<T>::solve: No transpose: must have LHS_->numRows() = N_");
599 "SerialQRDenseSolver<T>::solve: Transpose: must have LHS_->numRows() = M_");
602 if (shouldEquilibrate() && !equilibratedA_)
603 std::cout <<
"WARNING! SerialQRDenseSolver<T>::solve: System should be equilibrated!" << std::endl;
606 if (!factored()) factor();
609 std::logic_error,
"SerialQRDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
612 for (OrdinalType j=0; j<RHS_->numCols(); j++) {
613 for (OrdinalType i=0; i<RHS_->numRows(); i++) {
614 (*TMP_)(i,j) = (*RHS_)(i,j);
631 for (OrdinalType j = 0; j < RHS_->numCols(); j++ ) {
632 for (OrdinalType i = N_; i < M_; i++ ) {
639 for (OrdinalType j = 0; j < LHS_->numCols(); j++ ) {
640 for (OrdinalType i = 0; i < LHS_->numRows(); i++ ) {
641 (*LHS_)(i, j) = (*TMP_)(i,j);
649 ierr = unequilibrateLHS();
660 template<
typename OrdinalType,
typename ScalarType>
675 for (j = 0; j < N_; j++) {
676 for (i = 0; i < M_; i++) {
683 if (ANORM_ > mZero && ANORM_ < smlnum) {
685 shouldEquilibrate_ =
true;
686 }
else if (ANORM_ > bignum) {
688 shouldEquilibrate_ =
true;
689 }
else if (ANORM_ == mZero) {
691 matrixIsZero_ =
true;
699 template<
typename OrdinalType,
typename ScalarType>
702 if (equilibratedA_)
return(0);
717 for (j = 0; j < N_; j++) {
718 for (i = 0; i < M_; i++) {
725 if (ANORM_ > mZero && ANORM_ < smlnum) {
727 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, smlnum, M_, N_, A_, LDA_, &INFO_);
728 equilibrationModeA_ = 1;
729 }
else if (ANORM_ > bignum) {
731 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, bignum, M_, N_, A_, LDA_, &INFO_);
732 equilibrationModeA_ = 2;
733 }
else if (ANORM_ == mZero) {
735 matrixIsZero_ =
true;
738 equilibratedA_ =
true;
745 template<
typename OrdinalType,
typename ScalarType>
748 if (equilibratedB_)
return(0);
763 for (j = 0; j <RHS_->numCols(); j++) {
764 for (i = 0; i < RHS_->numRows(); i++) {
772 if (BNORM_ > mZero && BNORM_ < smlnum) {
774 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, BNORM_, smlnum, RHS_->numRows(), RHS_->numCols(),
775 RHS_->values(), RHS_->stride(), &INFO_);
776 equilibrationModeB_ = 1;
777 }
else if (BNORM_ > bignum) {
779 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, BNORM_, bignum, RHS_->numRows(), RHS_->numCols(),
780 RHS_->values(), RHS_->stride(), &INFO_);
781 equilibrationModeB_ = 2;
784 equilibratedB_ =
true;
791 template<
typename OrdinalType,
typename ScalarType>
794 if (!equilibratedB_)
return(0);
808 if (equilibrationModeA_ == 1) {
809 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, smlnum, LHS_->numRows(), LHS_->numCols(),
810 LHS_->values(), LHS_->stride(), &INFO_);
811 }
else if (equilibrationModeA_ == 2) {
812 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, ANORM_, bignum, LHS_->numRows(), LHS_->numCols(),
813 LHS_->values(), LHS_->stride(), &INFO_);
815 if (equilibrationModeB_ == 1) {
816 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, smlnum, BNORM_, LHS_->numRows(), LHS_->numCols(),
817 LHS_->values(), LHS_->stride(), &INFO_);
818 }
else if (equilibrationModeB_ == 2) {
819 this->LASCL(Teuchos::ETypeChar[
Teuchos::FULL], BW, BW, bignum, BNORM_, LHS_->numRows(), LHS_->numCols(),
820 LHS_->values(), LHS_->stride(), &INFO_);
828 template<
typename OrdinalType,
typename ScalarType>
832 if (!factored()) factor();
837 Q_ = FactorQ_->values();
838 LDQ_ = FactorQ_->stride();
844 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
845 EigenMatrixMap qMap( Q_, M_, N_, EigenOuterStride(LDQ_) );
846 EigenMatrix qMat = qr_.householderQ();
847 for (OrdinalType j=0; j<qMap.outerSize(); j++) {
848 for (OrdinalType i=0; i<qMap.innerSize(); i++) {
849 qMap(i,j) = qMat(i,j);
853 this->UNGQR(M_, N_, N_, Q_, LDQ_, &TAU_[0], &WORK_[0], LWORK_, &INFO_);
856 if (INFO_!=0)
return(INFO_);
865 template<
typename OrdinalType,
typename ScalarType>
869 if (!factored()) factor();
874 R_ = FactorR_->values();
875 LDR_ = FactorR_->stride();
879 for (OrdinalType j=0; j<N_; j++) {
880 for (OrdinalType i=0; i<=j; i++) {
881 (*FactorR_)(i,j) = (*Factor_)(i,j);
892 template<
typename OrdinalType,
typename ScalarType>
898 "SerialQRDenseSolver<T>::multiplyQ: C.numRows() != M_!");
900 "SerialQRDenseSolver<T>::multiplyQ: C is an empty SerialDenseMatrix<T>!");
903 if (!factored()) factor();
908 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
912 cMap = qr_.householderQ() * cMap;
915 cMap = qr_.householderQ().adjoint() * cMap;
916 for (OrdinalType j = 0; j < C.
numCols(); j++) {
917 for (OrdinalType i = N_; i < C.
numRows(); i++ ) {
930 this->UNMQR(ESideChar[SIDE], ETranspChar[NO_TRANS], M_, C.
numCols(), N_, AF_, LDAF_,
931 &TAU_[0], C.
values(), C.
stride(), &WORK_[0], LWORK_, &INFO_);
936 this->UNMQR(ESideChar[SIDE], ETranspChar[TRANS], M_, C.
numCols(), N_, AF_, LDAF_,
937 &TAU_[0], C.
values(), C.
stride(), &WORK_[0], LWORK_, &INFO_);
939 for (OrdinalType j = 0; j < C.
numCols(); j++) {
940 for (OrdinalType i = N_; i < C.
numRows(); i++ ) {
953 template<
typename OrdinalType,
typename ScalarType>
959 "SerialQRDenseSolver<T>::solveR: must have N_ < C.numRows() < M_!");
961 "SerialQRDenseSolver<T>::solveR: C is an empty SerialDenseMatrix<T>!");
964 if (!factored()) factor();
969 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
972 for (OrdinalType j=0; j<N_; j++) {
980 qr_.matrixQR().topRows(N_).template triangularView<Eigen::Upper>().solveInPlace(cMap);
983 qr_.matrixQR().topRows(N_).template triangularView<Eigen::Upper>().adjoint().solveInPlace(cMap);
991 ScalarType* RMAT = (formedR_) ? R_ : AF_;
992 OrdinalType LDRMAT = (formedR_) ? LDR_ : LDAF_;
997 this->TRTRS(EUploChar[UPLO], ETranspChar[NO_TRANS], EDiagChar[DIAG], N_, C.
numCols(),
1003 this->TRTRS(EUploChar[UPLO], ETranspChar[TRANS], EDiagChar[DIAG], N_, C.
numCols(),
1015 template<
typename OrdinalType,
typename ScalarType>
1018 if (Matrix_!=Teuchos::null) os <<
"Solver Matrix" << std::endl << *Matrix_ << std::endl;
1019 if (Factor_!=Teuchos::null) os <<
"Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
1020 if (Q_!=Teuchos::null) os <<
"Solver Factor Q" << std::endl << *Q_ << std::endl;
1021 if (LHS_ !=Teuchos::null) os <<
"Solver LHS" << std::endl << *LHS_ << std::endl;
1022 if (RHS_ !=Teuchos::null) os <<
"Solver RHS" << std::endl << *RHS_ << std::endl;
ScalarType * values() const
Data array access method.
int unequilibrateLHS()
Unscales the solution vectors if equilibration was used to solve the system.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getMatrix() const
Returns pointer to current matrix.
OrdinalType numRows() const
Returns row dimension of system.
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)
Sets the pointers for coefficient matrix.
Templated serial dense matrix class.
int multiplyQ(ETransp transq, SerialDenseMatrix< OrdinalType, ScalarType > &C)
Left multiply the input matrix by the unitary matrix Q or its adjoint.
int solveR(ETransp transr, SerialDenseMatrix< OrdinalType, ScalarType > &C)
Solve input matrix on the left with the upper triangular matrix R or its adjoint. ...
int formQ()
Explicitly forms the unitary matrix Q.
Templated interface class to BLAS routines.
bool formedQ()
Returns true if Q has been formed explicitly.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
bool equilibratedA()
Returns true if factor is equilibrated (factor available via getFactoredMatrix()).
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getRHS() const
Returns pointer to current RHS.
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
Object for storing data and providing functionality that is common to all computational classes...
bool factored()
Returns true if matrix is factored (factor available via getFactoredMatrix()).
int solve()
Computes the solution X to AX = B for the this matrix and the B provided to SetVectors()..
static magnitudeType sfmin()
Returns safe minimum (sfmin), such that 1/sfmin does not overflow.
This structure defines some basic traits for a scalar field type.
A class for solving dense linear problems.
Templated class for solving dense linear problems.
Functionality and data that is common to all computational classes.
Templated interface class to LAPACK routines.
void solveWithTransposeFlag(Teuchos::ETransp trans)
All subsequent function calls will work with the transpose-type set by this method (Teuchos::NO_TRANS...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
static magnitudeType prec()
Returns eps*base.
void Print(std::ostream &os) const
Print service methods; defines behavior of ostream << operator.
int equilibrateRHS()
Equilibrates the current RHS.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getFactoredMatrix() const
Returns pointer to factored matrix (assuming factorization has been performed).
The Templated LAPACK Wrapper Class.
void solveWithTranspose(bool flag)
If flag is true, causes all subsequent function calls to work with the adjoint of this matrix...
bool solved()
Returns true if the current set of vectors has been solved.
SerialQRDenseSolver()
Default constructor; matrix should be set using setMatrix(), LHS and RHS set with setVectors()...
std::vector< ScalarType > tau() const
Returns pointer to pivot vector (if factorization has been computed), zero otherwise.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getLHS() const
Returns pointer to current LHS.
bool equilibratedB()
Returns true if RHS is equilibrated (RHS available via getRHS()).
OrdinalType numCols() const
Returns column dimension of system.
static magnitudeType magnitude(T a)
Returns the magnitudeType of the scalar type a.
OrdinalType numCols() const
Returns the column dimension of this matrix.
bool shouldEquilibrate()
Returns true if the LAPACK general rules for equilibration suggest you should equilibrate the system...
MagnitudeType ANORM() const
Returns the absolute value of the largest element of this matrix (returns -1 if not yet computed)...
void factorWithEquilibration(bool flag)
Causes equilibration to be called just before the matrix factorization as part of the call to factor...
int equilibrateMatrix()
Equilibrates the this matrix.
Defines basic traits for the scalar field type.
static T zero()
Returns representation of zero for this scalar type.
virtual ~SerialQRDenseSolver()
SerialQRDenseSolver destructor.
int computeEquilibrateScaling()
Determines if this matrix should be scaled.
Smart reference counting pointer class for automatic garbage collection.
int formR()
Explicitly forms the upper triangular matrix R.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getQ() const
Returns pointer to Q (assuming factorization has been performed).
int factor()
Computes the in-place QR factorization of the matrix using the LAPACK routine _GETRF or the Eigen cla...
bool transpose()
Returns true if adjoint of this matrix has and will be used.
bool formedR()
Returns true if R has been formed explicitly.
Reference-counted pointer class and non-member templated function implementations.
static T one()
Returns representation of one for this scalar type.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getR() const
Returns pointer to R (assuming factorization has been performed).
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).
OrdinalType stride() const
Returns the stride between the columns of this matrix in memory.
OrdinalType numRows() const
Returns the row dimension of this matrix.
This class creates and provides basic support for dense rectangular matrix of templated type...