10 #ifndef _TEUCHOS_SERIALDENSESOLVER_HPP_
11 #define _TEUCHOS_SERIALDENSESOLVER_HPP_
24 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
25 #include "Eigen/Dense"
104 template<
typename OrdinalType,
typename ScalarType>
106 public LAPACK<OrdinalType, ScalarType>
112 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
113 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenMatrix;
114 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,1> EigenVector;
115 typedef typename Eigen::InnerStride<Eigen::Dynamic> EigenInnerStride;
116 typedef typename Eigen::OuterStride<Eigen::Dynamic> EigenOuterStride;
117 typedef typename Eigen::Map<EigenVector,0,EigenInnerStride > EigenVectorMap;
118 typedef typename Eigen::Map<const EigenVector,0,EigenInnerStride > EigenConstVectorMap;
119 typedef typename Eigen::Map<EigenMatrix,0,EigenOuterStride > EigenMatrixMap;
120 typedef typename Eigen::Map<const EigenMatrix,0,EigenOuterStride > EigenConstMatrixMap;
121 typedef typename Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,OrdinalType> EigenPermutationMatrix;
122 typedef typename Eigen::Array<OrdinalType,Eigen::Dynamic,1> EigenOrdinalArray;
123 typedef typename Eigen::Map<EigenOrdinalArray> EigenOrdinalArrayMap;
124 typedef typename Eigen::Array<ScalarType,Eigen::Dynamic,1> EigenScalarArray;
125 typedef typename Eigen::Map<EigenScalarArray> EigenScalarArrayMap;
325 std::vector<MagnitudeType>
FERR()
const {
return(
FERR_);}
328 std::vector<MagnitudeType>
BERR()
const {
return(
BERR_);}
331 std::vector<MagnitudeType>
R()
const {
return(
R_);}
334 std::vector<MagnitudeType>
C()
const {
return(
C_);}
339 void Print(std::ostream& os)
const;
391 std::vector<MagnitudeType>
R_;
392 std::vector<MagnitudeType>
C_;
393 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
394 Eigen::PartialPivLU<EigenMatrix> lu_;
423 template<
typename OrdinalType,
typename ScalarType>
427 shouldEquilibrate_(false),
428 equilibratedA_(false),
429 equilibratedB_(false),
432 estimateSolutionErrors_(false),
433 solutionErrorsEstimated_(false),
436 reciprocalConditionEstimated_(false),
437 refineSolution_(false),
438 solutionRefined_(false),
459 template<
typename OrdinalType,
typename ScalarType>
465 template<
typename OrdinalType,
typename ScalarType>
470 reciprocalConditionEstimated_ =
false;
471 solutionRefined_ =
false;
473 solutionErrorsEstimated_ =
false;
474 equilibratedB_ =
false;
478 template<
typename OrdinalType,
typename ScalarType>
482 equilibratedA_ =
false;
504 template<
typename OrdinalType,
typename ScalarType>
521 template<
typename OrdinalType,
typename ScalarType>
527 "SerialDenseSolver<T>::setVectors: X and B are not the same size!");
529 "SerialDenseSolver<T>::setVectors: B is an empty SerialDenseMatrix<T>!");
531 "SerialDenseSolver<T>::setVectors: X is an empty SerialDenseMatrix<T>!");
533 "SerialDenseSolver<T>::setVectors: B has an invalid stride!");
535 "SerialDenseSolver<T>::setVectors: X has an invalid stride!");
544 template<
typename OrdinalType,
typename ScalarType>
547 estimateSolutionErrors_ = flag;
550 refineSolution_ = refineSolution_ || flag;
554 template<
typename OrdinalType,
typename ScalarType>
557 if (factored())
return(0);
560 "SerialDenseSolver<T>::factor: Cannot factor an inverted matrix!");
562 ANORM_ = Matrix_->normOne();
569 if (refineSolution_ ) {
571 AF_ = Factor_->values();
572 LDAF_ = Factor_->stride();
576 if (equilibrate_) ierr = equilibrateMatrix();
578 if (ierr!=0)
return(ierr);
580 if ((
int)IPIV_.size()!=Min_MN_) IPIV_.resize( Min_MN_ );
584 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
585 EigenMatrixMap aMap( AF_, M_, N_, EigenOuterStride(LDAF_) );
586 EigenPermutationMatrix p;
587 EigenOrdinalArray ind;
588 EigenOrdinalArrayMap ipivMap( &IPIV_[0], Min_MN_ );
591 p = lu_.permutationP();
594 EigenMatrix luMat = lu_.matrixLU();
595 for (OrdinalType j=0; j<aMap.outerSize(); j++) {
596 for (OrdinalType i=0; i<aMap.innerSize(); i++) {
597 aMap(i,j) = luMat(i,j);
600 for (OrdinalType i=0; i<ipivMap.innerSize(); i++) {
604 this->GETRF(M_, N_, AF_, LDAF_, &IPIV_[0], &INFO_);
614 template<
typename OrdinalType,
typename ScalarType>
628 ierr = equilibrateRHS();
630 if (ierr != 0)
return(ierr);
633 "SerialDenseSolver<T>::solve: No right-hand side vector (RHS) has been set for the linear system!");
635 "SerialDenseSolver<T>::solve: No solution vector (LHS) has been set for the linear system!");
640 "SerialDenseSolver<T>::solve: X and B must be different vectors if matrix is inverted.");
642 std::logic_error,
"SerialDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
646 RHS_->values(), RHS_->stride(), 0.0, LHS_->values(), LHS_->stride());
647 if (INFO_!=0)
return(INFO_);
652 if (!factored()) factor();
655 std::logic_error,
"SerialDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
657 if (RHS_->values()!=LHS_->values()) {
662 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
663 EigenMatrixMap rhsMap( RHS_->values(), RHS_->numRows(), RHS_->numCols(), EigenOuterStride(RHS_->stride()) );
664 EigenMatrixMap lhsMap( LHS_->values(), LHS_->numRows(), LHS_->numCols(), EigenOuterStride(LHS_->stride()) );
666 lhsMap = lu_.solve(rhsMap);
668 lu_.matrixLU().template triangularView<Eigen::Upper>().transpose().solveInPlace(lhsMap);
669 lu_.matrixLU().template triangularView<Eigen::UnitLower>().transpose().solveInPlace(lhsMap);
670 EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
673 lu_.matrixLU().template triangularView<Eigen::Upper>().adjoint().solveInPlace(lhsMap);
674 lu_.matrixLU().template triangularView<Eigen::UnitLower>().adjoint().solveInPlace(lhsMap);
675 EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
679 this->GETRS(
ETranspChar[TRANS_], N_, RHS_->numCols(), AF_, LDAF_, &IPIV_[0], LHS_->values(), LHS_->stride(), &INFO_);
682 if (INFO_!=0)
return(INFO_);
688 if (shouldEquilibrate() && !equilibratedA_)
689 std::cout <<
"WARNING! SerialDenseSolver<T>::solve: System should be equilibrated!" << std::endl;
692 if (refineSolution_ && !inverted()) ierr1 = applyRefinement();
696 if (equilibrate_) ierr1 = unequilibrateLHS();
701 template<
typename OrdinalType,
typename ScalarType>
705 "SerialDenseSolver<T>::applyRefinement: Must have an existing solution!");
707 "SerialDenseSolver<T>::applyRefinement: Cannot apply refinement if no original copy of A!");
709 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
714 OrdinalType NRHS = RHS_->numCols();
715 FERR_.resize( NRHS );
716 BERR_.resize( NRHS );
720 std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GERFS_WORK( N_ );
721 this->GERFS(
ETranspChar[TRANS_], N_, NRHS, A_, LDA_, AF_, LDAF_, &IPIV_[0],
722 RHS_->values(), RHS_->stride(), LHS_->values(), LHS_->stride(),
723 &FERR_[0], &BERR_[0], &WORK_[0], &GERFS_WORK[0], &INFO_);
725 solutionErrorsEstimated_ =
true;
726 reciprocalConditionEstimated_ =
true;
727 solutionRefined_ =
true;
735 template<
typename OrdinalType,
typename ScalarType>
738 if (R_.size()!=0)
return(0);
744 this->GEEQU (M_, N_, AF_, LDAF_, &R_[0], &C_[0], &ROWCND_, &COLCND_, &AMAX_, &INFO_);
749 shouldEquilibrate_ =
true;
756 template<
typename OrdinalType,
typename ScalarType>
762 if (equilibratedA_)
return(0);
763 if (R_.size()==0) ierr = computeEquilibrateScaling();
764 if (ierr!=0)
return(ierr);
767 for (j=0; j<N_; j++) {
769 ScalarType s1 = C_[j];
770 for (i=0; i<M_; i++) {
771 *ptr = *ptr*s1*R_[i];
779 for (j=0; j<N_; j++) {
781 ptr1 = AF_ + j*LDAF_;
782 ScalarType s1 = C_[j];
783 for (i=0; i<M_; i++) {
784 *ptr = *ptr*s1*R_[i];
786 *ptr1 = *ptr1*s1*R_[i];
792 equilibratedA_ =
true;
799 template<
typename OrdinalType,
typename ScalarType>
805 if (equilibratedB_)
return(0);
806 if (R_.size()==0) ierr = computeEquilibrateScaling();
807 if (ierr!=0)
return(ierr);
810 if (transpose_) R_tmp = &C_[0];
812 OrdinalType LDB = RHS_->stride(), NRHS = RHS_->numCols();
813 ScalarType *
B = RHS_->values();
815 for (j=0; j<NRHS; j++) {
817 for (i=0; i<M_; i++) {
818 *ptr = *ptr*R_tmp[i];
823 equilibratedB_ =
true;
830 template<
typename OrdinalType,
typename ScalarType>
835 if (!equilibratedB_)
return(0);
838 if (transpose_) C_tmp = &R_[0];
840 OrdinalType LDX = LHS_->stride(), NLHS = LHS_->numCols();
841 ScalarType * X = LHS_->values();
843 for (j=0; j<NLHS; j++) {
845 for (i=0; i<N_; i++) {
846 *ptr = *ptr*C_tmp[i];
856 template<
typename OrdinalType,
typename ScalarType>
860 if (!factored()) factor();
862 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
863 EigenMatrixMap invMap( AF_, M_, N_, EigenOuterStride(LDAF_) );
864 EigenMatrix invMat = lu_.inverse();
865 for (OrdinalType j=0; j<invMap.outerSize(); j++) {
866 for (OrdinalType i=0; i<invMap.innerSize(); i++) {
867 invMap(i,j) = invMat(i,j);
887 this->GETRI( N_, AF_, LDAF_, &IPIV_[0], &WORK_[0], LWORK_, &INFO_);
899 template<
typename OrdinalType,
typename ScalarType>
902 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
906 if (reciprocalConditionEstimated()) {
914 if (!factored()) ierr = factor();
915 if (ierr!=0)
return(ierr);
921 std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GECON_WORK( 2*N_ );
922 this->GECON(
'1', N_, AF_, LDAF_, ANORM_, &RCOND_, &WORK_[0], &GECON_WORK[0], &INFO_);
924 reciprocalConditionEstimated_ =
true;
932 template<
typename OrdinalType,
typename ScalarType>
935 if (Matrix_!=
Teuchos::null) os <<
"Solver Matrix" << std::endl << *Matrix_ << std::endl;
936 if (Factor_!=
Teuchos::null) os <<
"Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
937 if (LHS_ !=
Teuchos::null) os <<
"Solver LHS" << std::endl << *LHS_ << std::endl;
938 if (RHS_ !=
Teuchos::null) os <<
"Solver RHS" << std::endl << *RHS_ << std::endl;
int equilibrateMatrix()
Equilibrates the this matrix.
void Print(std::ostream &os) const
Print service methods; defines behavior of ostream << operator.
T magnitudeType
Mandatory typedef for result of magnitude.
Templated serial dense matrix class.
void solveWithTranspose(bool flag)
If flag is true, causes all subsequent function calls to work with the transpose of this matrix...
SerialDenseSolver & operator=(const SerialDenseSolver< OrdinalType, ScalarType > &Source)
std::vector< MagnitudeType > R() const
Returns a pointer to the row scaling vector used for equilibration.
Templated interface class to BLAS routines.
std::vector< MagnitudeType > C_
bool solutionErrorsEstimated_
int solve()
Computes the solution X to AX = B for the this matrix and the B provided to SetVectors()..
ScalarTraits< T >::magnitudeType iwork_type
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
bool solved()
Returns true if the current set of vectors has been solved.
bool solutionRefined()
Returns true if the current set of vectors has been refined.
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
bool reciprocalConditionEstimated_
std::vector< MagnitudeType > FERR_
bool reciprocalConditionEstimated()
Returns true if the condition number of the this matrix has been computed (value available via Recipr...
std::vector< ScalarType > WORK_
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getFactoredMatrix() const
Returns pointer to factored matrix (assuming factorization has been performed).
Object for storing data and providing functionality that is common to all computational classes...
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > Matrix_
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getRHS() const
Returns pointer to current RHS.
std::vector< MagnitudeType > FERR() const
Returns a pointer to the forward error estimates computed by LAPACK.
This structure defines some basic traits for a scalar field type.
int unequilibrateLHS()
Unscales the solution vectors if equilibration was used to solve the system.
void solveToRefinedSolution(bool flag)
Causes all solves to compute solution to best ability using iterative refinement. ...
bool factored()
Returns true if matrix is factored (factor available via getFactoredMatrix()).
Functionality and data that is common to all computational classes.
Templated interface class to LAPACK routines.
bool estimateSolutionErrors_
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getLHS() const
Returns pointer to current LHS.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
bool shouldEquilibrate()
Returns true if the LAPACK general rules for equilibration suggest you should equilibrate the system...
bool inverted()
Returns true if matrix inverse has been computed (inverse available via getFactoredMatrix()).
int reciprocalConditionEstimate(MagnitudeType &Value)
Returns the reciprocal of the 1-norm condition number of the this matrix.
void factorWithEquilibration(bool flag)
Causes equilibration to be called just before the matrix factorization as part of the call to factor...
std::vector< OrdinalType > IPIV_
void solveWithTransposeFlag(Teuchos::ETransp trans)
All subsequent function calls will work with the transpose-type set by this method (Teuchos::NO_TRANS...
int invert()
Inverts the this matrix.
bool transpose()
Returns true if transpose of this matrix has and will be used.
int applyRefinement()
Apply Iterative Refinement.
int computeEquilibrateScaling()
Computes the scaling vector S(i) = 1/sqrt(A(i,i)) of the this matrix.
void estimateSolutionErrors(bool flag)
Causes all solves to estimate the forward and backward solution error.
MagnitudeType ANORM() const
Returns the 1-Norm of the this matrix (returns -1 if not yet computed).
bool equilibratedB()
Returns true if RHS is equilibrated (RHS available via getRHS()).
SerialDenseSolver()
Default constructor; matrix should be set using setMatrix(), LHS and RHS set with setVectors()...
bool solutionErrorsEstimated()
Returns true if forward and backward error estimated have been computed (available via FERR() and BER...
The Templated LAPACK Wrapper Class.
std::vector< MagnitudeType > R_
virtual ~SerialDenseSolver()
SerialDenseSolver destructor.
std::vector< OrdinalType > IPIV() const
Returns pointer to pivot vector (if factorization has been computed), zero otherwise.
OrdinalType numRows() const
Returns row dimension of system.
std::vector< MagnitudeType > C() const
Returns a pointer to the column scale vector used for equilibration.
int equilibrateRHS()
Equilibrates the current RHS.
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).
MagnitudeType COLCND() const
Ratio of smallest to largest column scale factors for the this matrix (returns -1 if not yet computed...
MagnitudeType ROWCND() const
Ratio of smallest to largest row scale factors for the this matrix (returns -1 if not yet computed)...
std::vector< MagnitudeType > BERR() const
Returns a pointer to the backward error estimates computed by LAPACK.
MagnitudeType AMAX() const
Returns the absolute value of the largest entry of the this matrix (returns -1 if not yet computed)...
Defines basic traits for the scalar field type.
TEUCHOSNUMERICS_LIB_DLL_EXPORT const char ETranspChar[]
Teuchos::ScalarTraits< ScalarType >::magnitudeType MagnitudeType
OrdinalType numCols() const
Returns column dimension of system.
Smart reference counting pointer class for automatic garbage collection.
int factor()
Computes the in-place LU factorization of the matrix using the LAPACK routine _GETRF.
std::vector< MagnitudeType > BERR_
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > Factor_
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > RHS_
bool equilibratedA()
Returns true if factor is equilibrated (factor available via getFactoredMatrix()).
#define TEUCHOS_MIN(x, y)
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getMatrix() const
Returns pointer to current matrix.
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 > > LHS_
A class for solving dense linear problems.
MagnitudeType RCOND() const
Returns the reciprocal of the condition number of the this matrix (returns -1 if not yet computed)...
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)
Sets the pointers for coefficient matrix.
This class creates and provides basic support for dense rectangular matrix of templated type...