42 #ifndef _TEUCHOS_SERIALDENSESOLVER_HPP_
43 #define _TEUCHOS_SERIALDENSESOLVER_HPP_
56 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
57 #include "Eigen/Dense"
136 template<
typename OrdinalType,
typename ScalarType>
138 public LAPACK<OrdinalType, ScalarType>
144 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
145 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenMatrix;
146 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,1> EigenVector;
147 typedef typename Eigen::InnerStride<Eigen::Dynamic> EigenInnerStride;
148 typedef typename Eigen::OuterStride<Eigen::Dynamic> EigenOuterStride;
149 typedef typename Eigen::Map<EigenVector,0,EigenInnerStride > EigenVectorMap;
150 typedef typename Eigen::Map<const EigenVector,0,EigenInnerStride > EigenConstVectorMap;
151 typedef typename Eigen::Map<EigenMatrix,0,EigenOuterStride > EigenMatrixMap;
152 typedef typename Eigen::Map<const EigenMatrix,0,EigenOuterStride > EigenConstMatrixMap;
153 typedef typename Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,OrdinalType> EigenPermutationMatrix;
154 typedef typename Eigen::Array<OrdinalType,Eigen::Dynamic,1> EigenOrdinalArray;
155 typedef typename Eigen::Map<EigenOrdinalArray> EigenOrdinalArrayMap;
156 typedef typename Eigen::Array<ScalarType,Eigen::Dynamic,1> EigenScalarArray;
157 typedef typename Eigen::Map<EigenScalarArray> EigenScalarArrayMap;
335 std::vector<OrdinalType>
IPIV()
const {
return(IPIV_);}
338 MagnitudeType
ANORM()
const {
return(ANORM_);}
341 MagnitudeType
RCOND()
const {
return(RCOND_);}
346 MagnitudeType
ROWCND()
const {
return(ROWCND_);}
351 MagnitudeType
COLCND()
const {
return(COLCND_);}
354 MagnitudeType
AMAX()
const {
return(AMAX_);}
357 std::vector<MagnitudeType>
FERR()
const {
return(FERR_);}
360 std::vector<MagnitudeType>
BERR()
const {
return(BERR_);}
363 std::vector<MagnitudeType>
R()
const {
return(R_);}
366 std::vector<MagnitudeType>
C()
const {
return(C_);}
371 void Print(std::ostream& os)
const;
376 void allocateWORK() { LWORK_ = 4*N_; WORK_.resize( LWORK_ );
return;}
382 bool shouldEquilibrate_;
387 bool estimateSolutionErrors_;
388 bool solutionErrorsEstimated_;
391 bool reciprocalConditionEstimated_;
392 bool refineSolution_;
393 bool solutionRefined_;
405 std::vector<OrdinalType> IPIV_;
407 MagnitudeType ANORM_;
408 MagnitudeType RCOND_;
409 MagnitudeType ROWCND_;
410 MagnitudeType COLCND_;
413 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > Matrix_;
414 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > LHS_;
415 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > RHS_;
416 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > Factor_;
420 std::vector<MagnitudeType> FERR_;
421 std::vector<MagnitudeType> BERR_;
422 std::vector<ScalarType> WORK_;
423 std::vector<MagnitudeType> R_;
424 std::vector<MagnitudeType> C_;
425 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
426 Eigen::PartialPivLU<EigenMatrix> lu_;
433 SerialDenseSolver & operator=(
const SerialDenseSolver<OrdinalType, ScalarType>& Source);
441 struct lapack_traits {
442 typedef int iwork_type;
447 struct lapack_traits<std::complex<T> > {
455 template<
typename OrdinalType,
typename ScalarType>
459 shouldEquilibrate_(false),
460 equilibratedA_(false),
461 equilibratedB_(false),
464 estimateSolutionErrors_(false),
465 solutionErrorsEstimated_(false),
468 reciprocalConditionEstimated_(false),
469 refineSolution_(false),
470 solutionRefined_(false),
491 template<
typename OrdinalType,
typename ScalarType>
497 template<
typename OrdinalType,
typename ScalarType>
500 LHS_ = Teuchos::null;
501 RHS_ = Teuchos::null;
502 reciprocalConditionEstimated_ =
false;
503 solutionRefined_ =
false;
505 solutionErrorsEstimated_ =
false;
506 equilibratedB_ =
false;
510 template<
typename OrdinalType,
typename ScalarType>
511 void SerialDenseSolver<OrdinalType,ScalarType>::resetMatrix()
514 equilibratedA_ =
false;
536 template<
typename OrdinalType,
typename ScalarType>
544 Min_MN_ = TEUCHOS_MIN(M_,N_);
553 template<
typename OrdinalType,
typename ScalarType>
559 "SerialDenseSolver<T>::setVectors: X and B are not the same size!");
561 "SerialDenseSolver<T>::setVectors: B is an empty SerialDenseMatrix<T>!");
563 "SerialDenseSolver<T>::setVectors: X is an empty SerialDenseMatrix<T>!");
565 "SerialDenseSolver<T>::setVectors: B has an invalid stride!");
567 "SerialDenseSolver<T>::setVectors: X has an invalid stride!");
576 template<
typename OrdinalType,
typename ScalarType>
579 estimateSolutionErrors_ = flag;
582 refineSolution_ = refineSolution_ || flag;
586 template<
typename OrdinalType,
typename ScalarType>
589 if (factored())
return(0);
592 "SerialDenseSolver<T>::factor: Cannot factor an inverted matrix!");
594 ANORM_ = Matrix_->normOne();
601 if (refineSolution_ ) {
603 AF_ = Factor_->values();
604 LDAF_ = Factor_->stride();
608 if (equilibrate_) ierr = equilibrateMatrix();
610 if (ierr!=0)
return(ierr);
612 if ((
int)IPIV_.size()!=Min_MN_) IPIV_.resize( Min_MN_ );
616 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
617 EigenMatrixMap aMap( AF_, M_, N_, EigenOuterStride(LDAF_) );
618 EigenPermutationMatrix p;
619 EigenOrdinalArray ind;
620 EigenOrdinalArrayMap ipivMap( &IPIV_[0], Min_MN_ );
623 p = lu_.permutationP();
626 EigenMatrix luMat = lu_.matrixLU();
627 for (OrdinalType j=0; j<aMap.outerSize(); j++) {
628 for (OrdinalType i=0; i<aMap.innerSize(); i++) {
629 aMap(i,j) = luMat(i,j);
632 for (OrdinalType i=0; i<ipivMap.innerSize(); i++) {
636 this->GETRF(M_, N_, AF_, LDAF_, &IPIV_[0], &INFO_);
646 template<
typename OrdinalType,
typename ScalarType>
660 ierr = equilibrateRHS();
662 if (ierr != 0)
return(ierr);
665 "SerialDenseSolver<T>::solve: No right-hand side vector (RHS) has been set for the linear system!");
667 "SerialDenseSolver<T>::solve: No solution vector (LHS) has been set for the linear system!");
672 "SerialDenseSolver<T>::solve: X and B must be different vectors if matrix is inverted.");
674 std::logic_error,
"SerialDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
678 RHS_->values(), RHS_->stride(), 0.0, LHS_->values(), LHS_->stride());
679 if (INFO_!=0)
return(INFO_);
684 if (!factored()) factor();
687 std::logic_error,
"SerialDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
689 if (RHS_->values()!=LHS_->values()) {
694 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
695 EigenMatrixMap rhsMap( RHS_->values(), RHS_->numRows(), RHS_->numCols(), EigenOuterStride(RHS_->stride()) );
696 EigenMatrixMap lhsMap( LHS_->values(), LHS_->numRows(), LHS_->numCols(), EigenOuterStride(LHS_->stride()) );
698 lhsMap = lu_.solve(rhsMap);
700 lu_.matrixLU().template triangularView<Eigen::Upper>().transpose().solveInPlace(lhsMap);
701 lu_.matrixLU().template triangularView<Eigen::UnitLower>().transpose().solveInPlace(lhsMap);
702 EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
705 lu_.matrixLU().template triangularView<Eigen::Upper>().adjoint().solveInPlace(lhsMap);
706 lu_.matrixLU().template triangularView<Eigen::UnitLower>().adjoint().solveInPlace(lhsMap);
707 EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
711 this->GETRS(ETranspChar[TRANS_], N_, RHS_->numCols(), AF_, LDAF_, &IPIV_[0], LHS_->values(), LHS_->stride(), &INFO_);
714 if (INFO_!=0)
return(INFO_);
720 if (shouldEquilibrate() && !equilibratedA_)
721 std::cout <<
"WARNING! SerialDenseSolver<T>::solve: System should be equilibrated!" << std::endl;
724 if (refineSolution_ && !inverted()) ierr1 = applyRefinement();
728 if (equilibrate_) ierr1 = unequilibrateLHS();
733 template<
typename OrdinalType,
typename ScalarType>
737 "SerialDenseSolver<T>::applyRefinement: Must have an existing solution!");
739 "SerialDenseSolver<T>::applyRefinement: Cannot apply refinement if no original copy of A!");
741 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
746 OrdinalType NRHS = RHS_->numCols();
747 FERR_.resize( NRHS );
748 BERR_.resize( NRHS );
752 std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GERFS_WORK( N_ );
753 this->GERFS(ETranspChar[TRANS_], N_, NRHS, A_, LDA_, AF_, LDAF_, &IPIV_[0],
754 RHS_->values(), RHS_->stride(), LHS_->values(), LHS_->stride(),
755 &FERR_[0], &BERR_[0], &WORK_[0], &GERFS_WORK[0], &INFO_);
757 solutionErrorsEstimated_ =
true;
758 reciprocalConditionEstimated_ =
true;
759 solutionRefined_ =
true;
767 template<
typename OrdinalType,
typename ScalarType>
770 if (R_.size()!=0)
return(0);
776 this->GEEQU (M_, N_, AF_, LDAF_, &R_[0], &C_[0], &ROWCND_, &COLCND_, &AMAX_, &INFO_);
781 shouldEquilibrate_ =
true;
788 template<
typename OrdinalType,
typename ScalarType>
794 if (equilibratedA_)
return(0);
795 if (R_.size()==0) ierr = computeEquilibrateScaling();
796 if (ierr!=0)
return(ierr);
799 for (j=0; j<N_; j++) {
801 ScalarType s1 = C_[j];
802 for (i=0; i<M_; i++) {
803 *ptr = *ptr*s1*R_[i];
811 for (j=0; j<N_; j++) {
813 ptr1 = AF_ + j*LDAF_;
814 ScalarType s1 = C_[j];
815 for (i=0; i<M_; i++) {
816 *ptr = *ptr*s1*R_[i];
818 *ptr1 = *ptr1*s1*R_[i];
824 equilibratedA_ =
true;
831 template<
typename OrdinalType,
typename ScalarType>
837 if (equilibratedB_)
return(0);
838 if (R_.size()==0) ierr = computeEquilibrateScaling();
839 if (ierr!=0)
return(ierr);
841 MagnitudeType * R_tmp = &R_[0];
842 if (transpose_) R_tmp = &C_[0];
844 OrdinalType LDB = RHS_->stride(), NRHS = RHS_->numCols();
845 ScalarType * B = RHS_->values();
847 for (j=0; j<NRHS; j++) {
849 for (i=0; i<M_; i++) {
850 *ptr = *ptr*R_tmp[i];
855 equilibratedB_ =
true;
862 template<
typename OrdinalType,
typename ScalarType>
867 if (!equilibratedB_)
return(0);
869 MagnitudeType * C_tmp = &C_[0];
870 if (transpose_) C_tmp = &R_[0];
872 OrdinalType LDX = LHS_->stride(), NLHS = LHS_->numCols();
873 ScalarType * X = LHS_->values();
875 for (j=0; j<NLHS; j++) {
877 for (i=0; i<N_; i++) {
878 *ptr = *ptr*C_tmp[i];
888 template<
typename OrdinalType,
typename ScalarType>
892 if (!factored()) factor();
894 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
895 EigenMatrixMap invMap( AF_, M_, N_, EigenOuterStride(LDAF_) );
896 EigenMatrix invMat = lu_.inverse();
897 for (OrdinalType j=0; j<invMap.outerSize(); j++) {
898 for (OrdinalType i=0; i<invMap.innerSize(); i++) {
899 invMap(i,j) = invMat(i,j);
919 this->GETRI( N_, AF_, LDAF_, &IPIV_[0], &WORK_[0], LWORK_, &INFO_);
931 template<
typename OrdinalType,
typename ScalarType>
934 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
938 if (reciprocalConditionEstimated()) {
946 if (!factored()) ierr = factor();
947 if (ierr!=0)
return(ierr);
953 std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GECON_WORK( 2*N_ );
954 this->GECON(
'1', N_, AF_, LDAF_, ANORM_, &RCOND_, &WORK_[0], &GECON_WORK[0], &INFO_);
956 reciprocalConditionEstimated_ =
true;
964 template<
typename OrdinalType,
typename ScalarType>
967 if (Matrix_!=Teuchos::null) os <<
"Solver Matrix" << std::endl << *Matrix_ << std::endl;
968 if (Factor_!=Teuchos::null) os <<
"Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
969 if (LHS_ !=Teuchos::null) os <<
"Solver LHS" << std::endl << *LHS_ << std::endl;
970 if (RHS_ !=Teuchos::null) os <<
"Solver RHS" << std::endl << *RHS_ << std::endl;