42 #ifndef _TEUCHOS_SERIALBANDDENSESOLVER_HPP_
43 #define _TEUCHOS_SERIALBANDDENSESOLVER_HPP_
59 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
60 #include "Eigen/Dense"
165 template<
typename OrdinalType,
typename ScalarType>
167 public LAPACK<OrdinalType, ScalarType>
173 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
174 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenMatrix;
175 typedef typename Eigen::internal::BandMatrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenBandMatrix;
176 typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,1> EigenVector;
177 typedef typename Eigen::InnerStride<Eigen::Dynamic> EigenInnerStride;
178 typedef typename Eigen::OuterStride<Eigen::Dynamic> EigenOuterStride;
179 typedef typename Eigen::Map<EigenVector,0,EigenInnerStride > EigenVectorMap;
180 typedef typename Eigen::Map<const EigenVector,0,EigenInnerStride > EigenConstVectorMap;
181 typedef typename Eigen::Map<EigenMatrix,0,EigenOuterStride > EigenMatrixMap;
182 typedef typename Eigen::Map<const EigenMatrix,0,EigenOuterStride > EigenConstMatrixMap;
183 typedef typename Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,OrdinalType> EigenPermutationMatrix;
184 typedef typename Eigen::Array<OrdinalType,Eigen::Dynamic,1> EigenOrdinalArray;
185 typedef typename Eigen::Map<EigenOrdinalArray> EigenOrdinalArrayMap;
186 typedef typename Eigen::Array<ScalarType,Eigen::Dynamic,1> EigenScalarArray;
187 typedef typename Eigen::Map<EigenScalarArray> EigenScalarArrayMap;
354 std::vector<OrdinalType>
IPIV()
const {
return(IPIV_);}
357 MagnitudeType
ANORM()
const {
return(ANORM_);}
360 MagnitudeType
RCOND()
const {
return(RCOND_);}
365 MagnitudeType
ROWCND()
const {
return(ROWCND_);}
370 MagnitudeType
COLCND()
const {
return(COLCND_);}
373 MagnitudeType
AMAX()
const {
return(AMAX_);}
376 std::vector<MagnitudeType>
FERR()
const {
return(FERR_);}
379 std::vector<MagnitudeType>
BERR()
const {
return(BERR_);}
382 std::vector<MagnitudeType>
R()
const {
return(R_);}
385 std::vector<MagnitudeType>
C()
const {
return(C_);}
390 void Print(std::ostream& os)
const;
395 void allocateWORK() { LWORK_ = 3*N_; WORK_.resize( LWORK_ );
return;}
401 bool shouldEquilibrate_;
406 bool estimateSolutionErrors_;
407 bool solutionErrorsEstimated_;
409 bool reciprocalConditionEstimated_;
410 bool refineSolution_;
411 bool solutionRefined_;
425 std::vector<OrdinalType> IPIV_;
426 std::vector<int> IWORK_;
428 MagnitudeType ANORM_;
429 MagnitudeType RCOND_;
430 MagnitudeType ROWCND_;
431 MagnitudeType COLCND_;
434 RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> > Matrix_;
435 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > LHS_;
436 RCP<SerialDenseMatrix<OrdinalType, ScalarType> > RHS_;
437 RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> > Factor_;
441 std::vector<MagnitudeType> FERR_;
442 std::vector<MagnitudeType> BERR_;
443 std::vector<ScalarType> WORK_;
444 std::vector<MagnitudeType> R_;
445 std::vector<MagnitudeType> C_;
446 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
447 Eigen::PartialPivLU<EigenMatrix> lu_;
463 template<
typename OrdinalType,
typename ScalarType>
467 shouldEquilibrate_(false),
468 equilibratedA_(false),
469 equilibratedB_(false),
472 estimateSolutionErrors_(false),
473 solutionErrorsEstimated_(false),
475 reciprocalConditionEstimated_(false),
476 refineSolution_(false),
477 solutionRefined_(false),
500 template<
typename OrdinalType,
typename ScalarType>
506 template<
typename OrdinalType,
typename ScalarType>
509 LHS_ = Teuchos::null;
510 RHS_ = Teuchos::null;
511 reciprocalConditionEstimated_ =
false;
512 solutionRefined_ =
false;
514 solutionErrorsEstimated_ =
false;
515 equilibratedB_ =
false;
519 template<
typename OrdinalType,
typename ScalarType>
520 void SerialBandDenseSolver<OrdinalType,ScalarType>::resetMatrix()
523 equilibratedA_ =
false;
545 template<
typename OrdinalType,
typename ScalarType>
549 OrdinalType m = AB->numRows();
550 OrdinalType n = AB->numCols();
551 OrdinalType kl = AB->lowerBandwidth();
552 OrdinalType ku = AB->upperBandwidth();
556 "SerialBandDenseSolver<T>::setMatrix: A is an empty SerialBandDenseMatrix<T>!");
565 Min_MN_ = TEUCHOS_MIN(M_,N_);
575 template<
typename OrdinalType,
typename ScalarType>
581 "SerialBandDenseSolver<T>::setVectors: X and B are not the same size!");
583 "SerialBandDenseSolver<T>::setVectors: B is an empty SerialDenseMatrix<T>!");
585 "SerialBandDenseSolver<T>::setVectors: X is an empty SerialDenseMatrix<T>!");
587 "SerialBandDenseSolver<T>::setVectors: B has an invalid stride!");
589 "SerialBandDenseSolver<T>::setVectors: X has an invalid stride!");
598 template<
typename OrdinalType,
typename ScalarType>
601 estimateSolutionErrors_ = flag;
604 refineSolution_ = refineSolution_ || flag;
608 template<
typename OrdinalType,
typename ScalarType>
611 if (factored())
return(0);
613 ANORM_ = Matrix_->normOne();
619 if (refineSolution_ ) {
621 AF_ = Factor_->values();
622 LDAF_ = Factor_->stride();
626 if (equilibrate_) ierr = equilibrateMatrix();
628 if (ierr!=0)
return(ierr);
630 if (IPIV_.size()==0) IPIV_.resize( N_ );
634 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
635 EigenMatrixMap aMap( AF_+KL_, KL_+KU_+1, N_, EigenOuterStride(LDAF_) );
636 EigenMatrix fullMatrix(M_, N_);
637 for (OrdinalType j=0; j<N_; j++) {
638 for (OrdinalType i=TEUCHOS_MAX(0,j-KU_); i<=TEUCHOS_MIN(M_-1, j+KL_); i++) {
639 fullMatrix(i,j) = aMap(KU_+i-j, j);
643 EigenPermutationMatrix p;
644 EigenOrdinalArray ind;
645 EigenOrdinalArrayMap ipivMap( &IPIV_[0], Min_MN_ );
647 lu_.compute(fullMatrix);
648 p = lu_.permutationP();
651 for (OrdinalType i=0; i<ipivMap.innerSize(); i++) {
656 this->GBTRF(M_, N_, KL_, KU_, AF_, LDAF_, &IPIV_[0], &INFO_);
666 template<
typename OrdinalType,
typename ScalarType>
676 ierr = equilibrateRHS();
678 if (ierr != 0)
return(ierr);
681 "SerialBandDenseSolver<T>::solve: No right-hand side vector (RHS) has been set for the linear system!");
683 "SerialBandDenseSolver<T>::solve: No solution vector (LHS) has been set for the linear system!");
685 if (!factored()) factor();
688 std::logic_error,
"SerialBandDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
690 if (shouldEquilibrate() && !equilibratedA_)
691 std::cout <<
"WARNING! SerialBandDenseSolver<T>::solve: System should be equilibrated!" << std::endl;
693 if (RHS_->values()!=LHS_->values()) {
698 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
699 EigenMatrixMap rhsMap( RHS_->values(), RHS_->numRows(), RHS_->numCols(), EigenOuterStride(RHS_->stride()) );
700 EigenMatrixMap lhsMap( LHS_->values(), LHS_->numRows(), LHS_->numCols(), EigenOuterStride(LHS_->stride()) );
702 lhsMap = lu_.solve(rhsMap);
704 lu_.matrixLU().template triangularView<Eigen::Upper>().transpose().solveInPlace(lhsMap);
705 lu_.matrixLU().template triangularView<Eigen::UnitLower>().transpose().solveInPlace(lhsMap);
706 EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
709 lu_.matrixLU().template triangularView<Eigen::Upper>().adjoint().solveInPlace(lhsMap);
710 lu_.matrixLU().template triangularView<Eigen::UnitLower>().adjoint().solveInPlace(lhsMap);
711 EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
715 this->GBTRS(ETranspChar[TRANS_], N_, KL_, KU_, RHS_->numCols(), AF_, LDAF_, &IPIV_[0], LHS_->values(), LHS_->stride(), &INFO_);
718 if (INFO_!=0)
return(INFO_);
722 if (refineSolution_) ierr1 = applyRefinement();
726 if (equilibrate_) ierr1 = unequilibrateLHS();
732 template<
typename OrdinalType,
typename ScalarType>
736 "SerialBandDenseSolver<T>::applyRefinement: Must have an existing solution!");
738 "SerialBandDenseSolver<T>::applyRefinement: Cannot apply refinement if no original copy of A!");
740 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
745 OrdinalType NRHS = RHS_->numCols();
746 FERR_.resize( NRHS );
747 BERR_.resize( NRHS );
751 std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GBRFS_WORK( N_ );
752 this->GBRFS(ETranspChar[TRANS_], N_, KL_, KU_, NRHS, A_+KL_, LDA_, AF_, LDAF_, &IPIV_[0],
753 RHS_->values(), RHS_->stride(), LHS_->values(), LHS_->stride(),
754 &FERR_[0], &BERR_[0], &WORK_[0], &GBRFS_WORK[0], &INFO_);
756 solutionErrorsEstimated_ =
true;
757 reciprocalConditionEstimated_ =
true;
758 solutionRefined_ =
true;
766 template<
typename OrdinalType,
typename ScalarType>
769 if (R_.size()!=0)
return(0);
775 this->GBEQU (M_, N_, KL_, KU_, AF_+KL_, LDAF_, &R_[0], &C_[0], &ROWCND_, &COLCND_, &AMAX_, &INFO_);
780 shouldEquilibrate_ =
true;
787 template<
typename OrdinalType,
typename ScalarType>
793 if (equilibratedA_)
return(0);
794 if (R_.size()==0) ierr = computeEquilibrateScaling();
795 if (ierr!=0)
return(ierr);
800 for (j=0; j<N_; j++) {
801 ptr = A_ + KL_ + j*LDA_ + TEUCHOS_MAX(KU_-j, 0);
802 ScalarType s1 = C_[j];
803 for (i=TEUCHOS_MAX(0,j-KU_); i<=TEUCHOS_MIN(M_-1,j+KL_); i++) {
804 *ptr = *ptr*s1*R_[i];
813 for (j=0; j<N_; j++) {
814 ptr = A_ + KL_ + j*LDA_ + TEUCHOS_MAX(KU_-j, 0);
815 ScalarType s1 = C_[j];
816 for (i=TEUCHOS_MAX(0,j-KU_); i<=TEUCHOS_MIN(M_-1,j+KL_); i++) {
817 *ptr = *ptr*s1*R_[i];
821 for (j=0; j<N_; j++) {
822 ptrU = AF_ + j*LDAF_ + TEUCHOS_MAX(KL_+KU_-j, 0);
823 ptrL = AF_ + KL_ + KU_ + 1 + j*LDAF_;
824 ScalarType s1 = C_[j];
825 for (i=TEUCHOS_MAX(0,j-(KL_+KU_)); i<=TEUCHOS_MIN(M_-1,j); i++) {
826 *ptrU = *ptrU*s1*R_[i];
829 for (i=TEUCHOS_MAX(0,j); i<=TEUCHOS_MIN(M_-1,j+KL_); i++) {
830 *ptrL = *ptrL*s1*R_[i];
836 equilibratedA_ =
true;
843 template<
typename OrdinalType,
typename ScalarType>
849 if (equilibratedB_)
return(0);
850 if (R_.size()==0) ierr = computeEquilibrateScaling();
851 if (ierr!=0)
return(ierr);
853 MagnitudeType * R_tmp = &R_[0];
854 if (transpose_) R_tmp = &C_[0];
856 OrdinalType LDB = RHS_->stride(), NRHS = RHS_->numCols();
857 ScalarType * B = RHS_->values();
859 for (j=0; j<NRHS; j++) {
861 for (i=0; i<M_; i++) {
862 *ptr = *ptr*R_tmp[i];
867 equilibratedB_ =
true;
875 template<
typename OrdinalType,
typename ScalarType>
880 if (!equilibratedB_)
return(0);
882 MagnitudeType * C_tmp = &C_[0];
883 if (transpose_) C_tmp = &R_[0];
885 OrdinalType LDX = LHS_->stride(), NLHS = LHS_->numCols();
886 ScalarType * X = LHS_->values();
888 for (j=0; j<NLHS; j++) {
890 for (i=0; i<N_; i++) {
891 *ptr = *ptr*C_tmp[i];
901 template<
typename OrdinalType,
typename ScalarType>
904 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
909 if (reciprocalConditionEstimated()) {
917 if (!factored()) ierr = factor();
918 if (ierr!=0)
return(ierr);
924 std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GBCON_WORK( N_ );
925 this->GBCON(
'1', N_, KL_, KU_, AF_, LDAF_, &IPIV_[0], ANORM_, &RCOND_, &WORK_[0], &GBCON_WORK[0], &INFO_);
926 reciprocalConditionEstimated_ =
true;
934 template<
typename OrdinalType,
typename ScalarType>
937 if (Matrix_!=Teuchos::null) os <<
"Solver Matrix" << std::endl << *Matrix_ << std::endl;
938 if (Factor_!=Teuchos::null) os <<
"Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
939 if (LHS_ !=Teuchos::null) os <<
"Solver LHS" << std::endl << *LHS_ << std::endl;
940 if (RHS_ !=Teuchos::null) os <<
"Solver RHS" << std::endl << *RHS_ << std::endl;