Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Teuchos_SerialBandDenseSolver.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef _TEUCHOS_SERIALBANDDENSESOLVER_HPP_
00043 #define _TEUCHOS_SERIALBANDDENSESOLVER_HPP_
00044 
00045 
00046 
00047 
00048 
00049 #include "Teuchos_CompObject.hpp"
00050 #include "Teuchos_BLAS.hpp"
00051 #include "Teuchos_LAPACK.hpp"
00052 #include "Teuchos_RCP.hpp"
00053 #include "Teuchos_ConfigDefs.hpp"
00054 #include "Teuchos_SerialDenseMatrix.hpp"
00055 #include "Teuchos_SerialBandDenseMatrix.hpp"
00056 #include "Teuchos_SerialDenseSolver.hpp"
00057 #include "Teuchos_ScalarTraits.hpp"
00058 
00059 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
00060 #include "Eigen/Dense"
00061 #endif
00062 
00063 namespace Teuchos {
00064 
00165   template<typename OrdinalType, typename ScalarType>
00166   class SerialBandDenseSolver : public CompObject, public Object, public BLAS<OrdinalType, ScalarType>,
00167         public LAPACK<OrdinalType, ScalarType>
00168   {
00169 
00170   public:
00171 
00172     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00173 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
00174     typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenMatrix;
00175     typedef typename Eigen::internal::BandMatrix<ScalarType,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> EigenBandMatrix;
00176     typedef typename Eigen::Matrix<ScalarType,Eigen::Dynamic,1> EigenVector;
00177     typedef typename Eigen::InnerStride<Eigen::Dynamic> EigenInnerStride;
00178     typedef typename Eigen::OuterStride<Eigen::Dynamic> EigenOuterStride;
00179     typedef typename Eigen::Map<EigenVector,0,EigenInnerStride > EigenVectorMap;
00180     typedef typename Eigen::Map<const EigenVector,0,EigenInnerStride > EigenConstVectorMap;
00181     typedef typename Eigen::Map<EigenMatrix,0,EigenOuterStride > EigenMatrixMap;
00182     typedef typename Eigen::Map<const EigenMatrix,0,EigenOuterStride > EigenConstMatrixMap;
00183     typedef typename Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,OrdinalType> EigenPermutationMatrix;
00184     typedef typename Eigen::Array<OrdinalType,Eigen::Dynamic,1> EigenOrdinalArray;
00185     typedef typename Eigen::Map<EigenOrdinalArray> EigenOrdinalArrayMap;
00186     typedef typename Eigen::Array<ScalarType,Eigen::Dynamic,1> EigenScalarArray;
00187     typedef typename Eigen::Map<EigenScalarArray> EigenScalarArrayMap;
00188 #endif
00189 
00191 
00192 
00194     SerialBandDenseSolver();
00195 
00197     virtual ~SerialBandDenseSolver();
00198 
00200 
00201 
00202 
00204     int setMatrix(const RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> >& AB);
00205 
00207 
00210     int setVectors(const RCP<SerialDenseMatrix<OrdinalType, ScalarType> >& X,
00211        const RCP<SerialDenseMatrix<OrdinalType, ScalarType> >& B);
00212 
00214 
00215 
00216 
00219     void factorWithEquilibration(bool flag) {equilibrate_ = flag; return;}
00220 
00224     void solveWithTranspose(bool flag) {transpose_ = flag; if (flag) TRANS_ = Teuchos::TRANS; else TRANS_ = Teuchos::NO_TRANS; return;}
00225 
00228     void solveWithTransposeFlag(Teuchos::ETransp trans) {TRANS_ = trans; if (trans != Teuchos::NO_TRANS) {  transpose_ = true; } }
00229 
00231     void solveToRefinedSolution(bool flag) {refineSolution_ = flag; return;}
00232 
00234 
00237     void estimateSolutionErrors(bool flag);
00239 
00241 
00242 
00244 
00247     int factor();
00248 
00250 
00253     int solve();
00254 
00256 
00259     int computeEquilibrateScaling();
00260 
00262 
00265     int equilibrateMatrix();
00266 
00268 
00271     int equilibrateRHS();
00272 
00274 
00277     int applyRefinement();
00278 
00280 
00283     int unequilibrateLHS();
00284 
00286 
00292      int reciprocalConditionEstimate(MagnitudeType & Value);
00294 
00296 
00297 
00299     bool transpose() {return(transpose_);}
00300 
00302     bool factored() {return(factored_);}
00303 
00305     bool equilibratedA() {return(equilibratedA_);}
00306 
00308     bool equilibratedB() {return(equilibratedB_);}
00309 
00311      bool shouldEquilibrate() {computeEquilibrateScaling(); return(shouldEquilibrate_);}
00312 
00314     bool solutionErrorsEstimated() {return(solutionErrorsEstimated_);}
00315 
00317     bool reciprocalConditionEstimated() {return(reciprocalConditionEstimated_);}
00318 
00320     bool solved() {return(solved_);}
00321 
00323     bool solutionRefined() {return(solutionRefined_);}
00325 
00327 
00328 
00330     RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> > getMatrix()  const {return(Matrix_);}
00331 
00333     RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> > getFactoredMatrix()  const {return(Factor_);}
00334 
00336     RCP<SerialDenseMatrix<OrdinalType, ScalarType> > getLHS() const {return(LHS_);}
00337 
00339     RCP<SerialDenseMatrix<OrdinalType, ScalarType> > getRHS() const {return(RHS_);}
00340 
00342     OrdinalType numRows()  const {return(M_);}
00343 
00345     OrdinalType numCols()  const {return(N_);}
00346 
00348     OrdinalType numLower()  const {return(KL_);}
00349 
00351     OrdinalType numUpper()  const {return(KU_);}
00352 
00354     std::vector<OrdinalType> IPIV()  const {return(IPIV_);}
00355 
00357     MagnitudeType ANORM()  const {return(ANORM_);}
00358 
00360     MagnitudeType RCOND()  const {return(RCOND_);}
00361 
00363 
00365     MagnitudeType ROWCND()  const {return(ROWCND_);}
00366 
00368 
00370     MagnitudeType COLCND()  const {return(COLCND_);}
00371 
00373     MagnitudeType AMAX()  const {return(AMAX_);}
00374 
00376     std::vector<MagnitudeType> FERR()  const {return(FERR_);}
00377 
00379     std::vector<MagnitudeType> BERR()  const {return(BERR_);}
00380 
00382     std::vector<MagnitudeType> R()  const {return(R_);}
00383 
00385     std::vector<MagnitudeType> C()  const {return(C_);}
00387 
00389 
00390 
00391     void Print(std::ostream& os) const;
00393   protected:
00394 
00395     void allocateWORK() { LWORK_ = 3*N_; WORK_.resize( LWORK_ ); return;}
00396     void resetMatrix();
00397     void resetVectors();
00398 
00399 
00400     bool equilibrate_;
00401     bool shouldEquilibrate_;
00402     bool equilibratedA_;
00403     bool equilibratedB_;
00404     bool transpose_;
00405     bool factored_;
00406     bool estimateSolutionErrors_;
00407     bool solutionErrorsEstimated_;
00408     bool solved_;
00409     bool reciprocalConditionEstimated_;
00410     bool refineSolution_;
00411     bool solutionRefined_;
00412 
00413     Teuchos::ETransp TRANS_;
00414 
00415     OrdinalType M_;
00416     OrdinalType N_;
00417     OrdinalType KL_;
00418     OrdinalType KU_;
00419     OrdinalType Min_MN_;
00420     OrdinalType LDA_;
00421     OrdinalType LDAF_;
00422     OrdinalType INFO_;
00423     OrdinalType LWORK_;
00424 
00425     std::vector<OrdinalType> IPIV_;
00426     std::vector<int> IWORK_;
00427 
00428     MagnitudeType ANORM_;
00429     MagnitudeType RCOND_;
00430     MagnitudeType ROWCND_;
00431     MagnitudeType COLCND_;
00432     MagnitudeType AMAX_;
00433 
00434     RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> > Matrix_;
00435     RCP<SerialDenseMatrix<OrdinalType, ScalarType> > LHS_;
00436     RCP<SerialDenseMatrix<OrdinalType, ScalarType> > RHS_;
00437     RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> > Factor_;
00438 
00439     ScalarType * A_;
00440     ScalarType * AF_;
00441     std::vector<MagnitudeType> FERR_;
00442     std::vector<MagnitudeType> BERR_;
00443     std::vector<ScalarType> WORK_;
00444     std::vector<MagnitudeType> R_;
00445     std::vector<MagnitudeType> C_;
00446 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
00447     Eigen::PartialPivLU<EigenMatrix> lu_;
00448 #endif
00449 
00450   private:
00451 
00452     // SerialBandDenseSolver copy constructor (put here because we don't want user access)
00453     SerialBandDenseSolver(const SerialBandDenseSolver<OrdinalType, ScalarType>& Source);
00454     SerialBandDenseSolver & operator=(const SerialBandDenseSolver<OrdinalType, ScalarType>& Source);
00455 
00456   };
00457 
00458   // Helper traits to distinguish work arrays for real and complex-valued datatypes.
00459   using namespace details;
00460 
00461 //=============================================================================
00462 
00463 template<typename OrdinalType, typename ScalarType>
00464 SerialBandDenseSolver<OrdinalType,ScalarType>::SerialBandDenseSolver()
00465   : CompObject(),
00466     Object("Teuchos::SerialBandDenseSolver"),
00467     equilibrate_(false),
00468     shouldEquilibrate_(false),
00469     equilibratedA_(false),
00470     equilibratedB_(false),
00471     transpose_(false),
00472     factored_(false),
00473     estimateSolutionErrors_(false),
00474     solutionErrorsEstimated_(false),
00475     solved_(false),
00476     reciprocalConditionEstimated_(false),
00477     refineSolution_(false),
00478     solutionRefined_(false),
00479     TRANS_(Teuchos::NO_TRANS),
00480     M_(0),
00481     N_(0),
00482     KL_(0),
00483     KU_(0),
00484     Min_MN_(0),
00485     LDA_(0),
00486     LDAF_(0),
00487     INFO_(0),
00488     LWORK_(0),
00489     RCOND_(ScalarTraits<MagnitudeType>::zero()),
00490     ROWCND_(ScalarTraits<MagnitudeType>::zero()),
00491     COLCND_(ScalarTraits<MagnitudeType>::zero()),
00492     AMAX_(ScalarTraits<MagnitudeType>::zero()),
00493     A_(0),
00494     AF_(0),
00495     ANORM_(0.0)
00496 {
00497   resetMatrix();
00498 }
00499 //=============================================================================
00500 
00501 template<typename OrdinalType, typename ScalarType>
00502 SerialBandDenseSolver<OrdinalType,ScalarType>::~SerialBandDenseSolver()
00503 {}
00504 
00505 //=============================================================================
00506 
00507 template<typename OrdinalType, typename ScalarType>
00508 void SerialBandDenseSolver<OrdinalType,ScalarType>::resetVectors()
00509 {
00510   LHS_ = Teuchos::null;
00511   RHS_ = Teuchos::null;
00512   reciprocalConditionEstimated_ = false;
00513   solutionRefined_ = false;
00514   solved_ = false;
00515   solutionErrorsEstimated_ = false;
00516   equilibratedB_ = false;
00517 }
00518 //=============================================================================
00519 
00520 template<typename OrdinalType, typename ScalarType>
00521 void SerialBandDenseSolver<OrdinalType,ScalarType>::resetMatrix()
00522 {
00523   resetVectors();
00524   equilibratedA_ = false;
00525   factored_ = false;
00526   M_ = 0;
00527   N_ = 0;
00528   KL_ = 0;
00529   KU_ = 0;
00530   Min_MN_ = 0;
00531   LDA_ = 0;
00532   LDAF_ = 0;
00533   RCOND_ = -ScalarTraits<MagnitudeType>::one();
00534   ROWCND_ = -ScalarTraits<MagnitudeType>::one();
00535   COLCND_ = -ScalarTraits<MagnitudeType>::one();
00536   AMAX_ = -ScalarTraits<MagnitudeType>::one();
00537   A_ = 0;
00538   AF_ = 0;
00539   INFO_ = 0;
00540   LWORK_ = 0;
00541   R_.resize(0);
00542   C_.resize(0);
00543 }
00544 //=============================================================================
00545 
00546 template<typename OrdinalType, typename ScalarType>
00547 int SerialBandDenseSolver<OrdinalType,ScalarType>::setMatrix(const RCP<SerialBandDenseMatrix<OrdinalType,ScalarType> >& AB)
00548 {
00549 
00550   OrdinalType m = AB->numRows();
00551   OrdinalType n = AB->numCols();
00552   OrdinalType kl = AB->lowerBandwidth();
00553   OrdinalType ku = AB->upperBandwidth();
00554 
00555   // Check that the new matrix is consistent.
00556   TEUCHOS_TEST_FOR_EXCEPTION(AB->values()==0, std::invalid_argument,
00557          "SerialBandDenseSolver<T>::setMatrix: A is an empty SerialBandDenseMatrix<T>!");
00558 
00559   resetMatrix();
00560   Matrix_ = AB;
00561   Factor_ = AB;
00562   M_ = m;
00563   N_ = n;
00564   KL_ = kl;
00565   KU_ = ku-kl;
00566   Min_MN_ = TEUCHOS_MIN(M_,N_);
00567   LDA_ = AB->stride();
00568   LDAF_ = LDA_;
00569   A_ = AB->values();
00570   AF_ = AB->values();
00571 
00572   return(0);
00573 }
00574 //=============================================================================
00575 
00576 template<typename OrdinalType, typename ScalarType>
00577 int SerialBandDenseSolver<OrdinalType,ScalarType>::setVectors(const RCP<SerialDenseMatrix<OrdinalType,ScalarType> >& X,
00578                  const RCP<SerialDenseMatrix<OrdinalType,ScalarType> >& B)
00579 {
00580   // Check that these new vectors are consistent.
00581   TEUCHOS_TEST_FOR_EXCEPTION(B->numRows()!=X->numRows() || B->numCols() != X->numCols(), std::invalid_argument,
00582          "SerialBandDenseSolver<T>::setVectors: X and B are not the same size!");
00583   TEUCHOS_TEST_FOR_EXCEPTION(B->values()==0, std::invalid_argument,
00584          "SerialBandDenseSolver<T>::setVectors: B is an empty SerialDenseMatrix<T>!");
00585   TEUCHOS_TEST_FOR_EXCEPTION(X->values()==0, std::invalid_argument,
00586          "SerialBandDenseSolver<T>::setVectors: X is an empty SerialDenseMatrix<T>!");
00587   TEUCHOS_TEST_FOR_EXCEPTION(B->stride()<1, std::invalid_argument,
00588          "SerialBandDenseSolver<T>::setVectors: B has an invalid stride!");
00589   TEUCHOS_TEST_FOR_EXCEPTION(X->stride()<1, std::invalid_argument,
00590          "SerialBandDenseSolver<T>::setVectors: X has an invalid stride!");
00591 
00592   resetVectors();
00593   LHS_ = X;
00594   RHS_ = B;
00595   return(0);
00596 }
00597 //=============================================================================
00598 
00599 template<typename OrdinalType, typename ScalarType>
00600 void SerialBandDenseSolver<OrdinalType,ScalarType>::estimateSolutionErrors(bool flag)
00601 {
00602   estimateSolutionErrors_ = flag;
00603 
00604   // If the errors are estimated, this implies that the solution must be refined
00605   refineSolution_ = refineSolution_ || flag;
00606 }
00607 //=============================================================================
00608 
00609 template<typename OrdinalType, typename ScalarType>
00610 int SerialBandDenseSolver<OrdinalType,ScalarType>::factor() {
00611 
00612   if (factored()) return(0); // Already factored
00613 
00614   ANORM_ = Matrix_->normOne(); // Compute 1-Norm of A
00615 
00616   // If we want to refine the solution, then the factor must
00617   // be stored separatedly from the original matrix
00618 
00619   if (A_ == AF_)
00620     if (refineSolution_ ) {
00621       Factor_ = rcp( new SerialBandDenseMatrix<OrdinalType,ScalarType>(*Matrix_) );
00622       AF_ = Factor_->values();
00623       LDAF_ = Factor_->stride();
00624     }
00625 
00626   int ierr = 0;
00627   if (equilibrate_) ierr = equilibrateMatrix();
00628 
00629   if (ierr!=0) return(ierr);
00630 
00631   if (IPIV_.size()==0) IPIV_.resize( N_ ); // Allocated Pivot vector if not already done.
00632 
00633   INFO_ = 0;
00634 
00635 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
00636   EigenMatrixMap aMap( AF_+KL_, KL_+KU_+1, N_, EigenOuterStride(LDAF_) );
00637   EigenMatrix fullMatrix(M_, N_);
00638   for (OrdinalType j=0; j<N_; j++) {
00639     for (OrdinalType i=TEUCHOS_MAX(0,j-KU_); i<=TEUCHOS_MIN(M_-1, j+KL_); i++) {
00640       fullMatrix(i,j) = aMap(KU_+i-j, j);
00641     }
00642   }
00643 
00644   EigenPermutationMatrix p;
00645   EigenOrdinalArray ind;
00646   EigenOrdinalArrayMap ipivMap( &IPIV_[0], Min_MN_ );
00647 
00648   lu_.compute(fullMatrix);
00649   p = lu_.permutationP();
00650   ind = p.indices();
00651 
00652   for (OrdinalType i=0; i<ipivMap.innerSize(); i++) {
00653     ipivMap(i) = ind(i);
00654   }
00655 
00656 #else
00657   this->GBTRF(M_, N_, KL_, KU_, AF_, LDAF_, &IPIV_[0], &INFO_);
00658 #endif
00659 
00660   factored_ = true;
00661 
00662   return(INFO_);
00663 }
00664 
00665 //=============================================================================
00666 
00667 template<typename OrdinalType, typename ScalarType>
00668 int SerialBandDenseSolver<OrdinalType,ScalarType>::solve() {
00669 
00670   // If the user want the matrix to be equilibrated or wants a refined solution, we will
00671   // call the X interface.
00672   // Otherwise, if the matrix is already factored we will call the TRS interface.
00673   // Otherwise, if the matrix is unfactored we will call the SV interface.
00674 
00675   int ierr = 0;
00676   if (equilibrate_) {
00677     ierr = equilibrateRHS();
00678     equilibratedB_ = true;
00679   }
00680   if (ierr != 0) return(ierr);  // Can't equilibrate B, so return.
00681 
00682   TEUCHOS_TEST_FOR_EXCEPTION( (equilibratedA_ && !equilibratedB_) || (!equilibratedA_ && equilibratedB_) ,
00683          std::logic_error, "SerialBandDenseSolver<T>::solve: Matrix and vectors must be similarly scaled!");
00684   TEUCHOS_TEST_FOR_EXCEPTION( RHS_==Teuchos::null, std::invalid_argument,
00685          "SerialBandDenseSolver<T>::solve: No right-hand side vector (RHS) has been set for the linear system!");
00686   TEUCHOS_TEST_FOR_EXCEPTION( LHS_==Teuchos::null, std::invalid_argument,
00687          "SerialBandDenseSolver<T>::solve: No solution vector (LHS) has been set for the linear system!");
00688 
00689   if (shouldEquilibrate() && !equilibratedA_)
00690     std::cout << "WARNING!  SerialBandDenseSolver<T>::solve: System should be equilibrated!" << std::endl;
00691 
00692   if (!factored()) factor(); // Matrix must be factored
00693 
00694   if (RHS_->values()!=LHS_->values()) {
00695     (*LHS_) = (*RHS_); // Copy B to X if needed
00696   }
00697   INFO_ = 0;
00698 
00699 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
00700     EigenMatrixMap rhsMap( RHS_->values(), RHS_->numRows(), RHS_->numCols(), EigenOuterStride(RHS_->stride()) );
00701     EigenMatrixMap lhsMap( LHS_->values(), LHS_->numRows(), LHS_->numCols(), EigenOuterStride(LHS_->stride()) );
00702     if ( TRANS_ == Teuchos::NO_TRANS ) {
00703       lhsMap = lu_.solve(rhsMap);
00704     } else if ( TRANS_ == Teuchos::TRANS ) {
00705       lu_.matrixLU().template triangularView<Eigen::Upper>().transpose().solveInPlace(lhsMap);
00706       lu_.matrixLU().template triangularView<Eigen::UnitLower>().transpose().solveInPlace(lhsMap);
00707       EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
00708       lhsMap = x;
00709     } else {
00710       lu_.matrixLU().template triangularView<Eigen::Upper>().adjoint().solveInPlace(lhsMap);
00711       lu_.matrixLU().template triangularView<Eigen::UnitLower>().adjoint().solveInPlace(lhsMap);
00712       EigenMatrix x = lu_.permutationP().transpose() * lhsMap;
00713       lhsMap = x;
00714     }
00715 #else
00716   this->GBTRS(ETranspChar[TRANS_], N_, KL_, KU_, RHS_->numCols(), AF_, LDAF_, &IPIV_[0], LHS_->values(), LHS_->stride(), &INFO_);
00717 #endif
00718 
00719   if (INFO_!=0) return(INFO_);
00720   solved_ = true;
00721 
00722   int ierr1=0;
00723   if (refineSolution_) ierr1 = applyRefinement();
00724   if (ierr1!=0)
00725     return(ierr1);
00726 
00727   if (equilibrate_) ierr1 = unequilibrateLHS();
00728 
00729   return(ierr1);
00730 }
00731 //=============================================================================
00732 
00733 template<typename OrdinalType, typename ScalarType>
00734 int SerialBandDenseSolver<OrdinalType,ScalarType>::applyRefinement()
00735 {
00736   TEUCHOS_TEST_FOR_EXCEPTION(!solved(), std::logic_error,
00737          "SerialBandDenseSolver<T>::applyRefinement: Must have an existing solution!");
00738   TEUCHOS_TEST_FOR_EXCEPTION(A_==AF_, std::logic_error,
00739          "SerialBandDenseSolver<T>::applyRefinement: Cannot apply refinement if no original copy of A!");
00740 
00741 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
00742   // Implement templated GERFS or use Eigen.
00743   return (-1);
00744 #else
00745 
00746   OrdinalType NRHS = RHS_->numCols();
00747   FERR_.resize( NRHS );
00748   BERR_.resize( NRHS );
00749   allocateWORK();
00750 
00751   INFO_ = 0;
00752   std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GBRFS_WORK( N_ );
00753   this->GBRFS(ETranspChar[TRANS_], N_, KL_, KU_, NRHS, A_+KL_, LDA_, AF_, LDAF_, &IPIV_[0],
00754         RHS_->values(), RHS_->stride(), LHS_->values(), LHS_->stride(),
00755         &FERR_[0], &BERR_[0], &WORK_[0], &GBRFS_WORK[0], &INFO_);
00756 
00757   solutionErrorsEstimated_ = true;
00758   reciprocalConditionEstimated_ = true;
00759   solutionRefined_ = true;
00760 
00761   return(INFO_);
00762 #endif
00763 }
00764 
00765 //=============================================================================
00766 
00767 template<typename OrdinalType, typename ScalarType>
00768 int SerialBandDenseSolver<OrdinalType,ScalarType>::computeEquilibrateScaling()
00769 {
00770   if (R_.size()!=0) return(0); // Already computed
00771 
00772   R_.resize( M_ );
00773   C_.resize( N_ );
00774 
00775   INFO_ = 0;
00776   this->GBEQU (M_, N_, KL_, KU_, AF_+KL_, LDAF_, &R_[0], &C_[0], &ROWCND_, &COLCND_, &AMAX_, &INFO_);
00777 
00778   if (COLCND_<0.1*ScalarTraits<MagnitudeType>::one() ||
00779       ROWCND_<0.1*ScalarTraits<MagnitudeType>::one() ||
00780       AMAX_ < ScalarTraits<ScalarType>::rmin() || AMAX_ > ScalarTraits<ScalarType>::rmax() )
00781     shouldEquilibrate_ = true;
00782 
00783   return(INFO_);
00784 }
00785 
00786 //=============================================================================
00787 
00788 template<typename OrdinalType, typename ScalarType>
00789 int SerialBandDenseSolver<OrdinalType,ScalarType>::equilibrateMatrix()
00790 {
00791   OrdinalType i, j;
00792   int ierr = 0;
00793 
00794   if (equilibratedA_) return(0); // Already done.
00795   if (R_.size()==0) ierr = computeEquilibrateScaling(); // Compute R and C if needed.
00796   if (ierr!=0) return(ierr);     // If return value is not zero, then can't equilibrate.
00797 
00798   if (A_==AF_) {
00799 
00800     ScalarType * ptr;
00801     for (j=0; j<N_; j++) {
00802       ptr = A_ + KL_ + j*LDA_ + TEUCHOS_MAX(KU_-j, 0);
00803       ScalarType s1 = C_[j];
00804       for (i=TEUCHOS_MAX(0,j-KU_); i<=TEUCHOS_MIN(M_-1,j+KL_); i++) {
00805   *ptr = *ptr*s1*R_[i];
00806   ptr++;
00807       }
00808     }
00809   } else {
00810 
00811     ScalarType * ptr;
00812     ScalarType * ptrL;
00813     ScalarType * ptrU;
00814     for (j=0; j<N_; j++) {
00815       ptr = A_ + KL_ + j*LDA_ + TEUCHOS_MAX(KU_-j, 0);
00816       ScalarType s1 = C_[j];
00817       for (i=TEUCHOS_MAX(0,j-KU_); i<=TEUCHOS_MIN(M_-1,j+KL_); i++) {
00818   *ptr = *ptr*s1*R_[i];
00819   ptr++;
00820       }
00821     }
00822     for (j=0; j<N_; j++) {
00823       ptrU = AF_ + j*LDAF_ + TEUCHOS_MAX(KL_+KU_-j, 0);
00824       ptrL = AF_ + KL_ + KU_ + 1 + j*LDAF_;
00825       ScalarType s1 = C_[j];
00826       for (i=TEUCHOS_MAX(0,j-(KL_+KU_)); i<=TEUCHOS_MIN(M_-1,j); i++) {
00827   *ptrU = *ptrU*s1*R_[i];
00828   ptrU++;
00829       }
00830       for (i=TEUCHOS_MAX(0,j); i<=TEUCHOS_MIN(M_-1,j+KL_); i++) {
00831   *ptrL = *ptrL*s1*R_[i];
00832   ptrL++;
00833       }
00834     }
00835   }
00836 
00837   equilibratedA_ = true;
00838 
00839   return(0);
00840 }
00841 
00842 //=============================================================================
00843 
00844 template<typename OrdinalType, typename ScalarType>
00845 int SerialBandDenseSolver<OrdinalType,ScalarType>::equilibrateRHS()
00846 {
00847   OrdinalType i, j;
00848   int ierr = 0;
00849 
00850   if (equilibratedB_) return(0); // Already done.
00851   if (R_.size()==0) ierr = computeEquilibrateScaling(); // Compute R and C if needed.
00852   if (ierr!=0) return(ierr);     // Can't count on R and C being computed.
00853 
00854   MagnitudeType * R_tmp = &R_[0];
00855   if (transpose_) R_tmp = &C_[0];
00856 
00857   OrdinalType LDB = RHS_->stride(), NRHS = RHS_->numCols();
00858   ScalarType * B = RHS_->values();
00859   ScalarType * ptr;
00860   for (j=0; j<NRHS; j++) {
00861     ptr = B + j*LDB;
00862     for (i=0; i<M_; i++) {
00863       *ptr = *ptr*R_tmp[i];
00864       ptr++;
00865     }
00866   }
00867 
00868   equilibratedB_ = true;
00869 
00870   return(0);
00871 }
00872 
00873 
00874 //=============================================================================
00875 
00876 template<typename OrdinalType, typename ScalarType>
00877 int SerialBandDenseSolver<OrdinalType,ScalarType>::unequilibrateLHS()
00878 {
00879   OrdinalType i, j;
00880 
00881   if (!equilibratedB_) return(0); // Nothing to do
00882 
00883   MagnitudeType * C_tmp = &C_[0];
00884   if (transpose_) C_tmp = &R_[0];
00885 
00886   OrdinalType LDX = LHS_->stride(), NLHS = LHS_->numCols();
00887   ScalarType * X = LHS_->values();
00888   ScalarType * ptr;
00889   for (j=0; j<NLHS; j++) {
00890     ptr = X + j*LDX;
00891     for (i=0; i<N_; i++) {
00892       *ptr = *ptr*C_tmp[i];
00893       ptr++;
00894     }
00895   }
00896 
00897   return(0);
00898 }
00899 
00900 //=============================================================================
00901 
00902 template<typename OrdinalType, typename ScalarType>
00903 int SerialBandDenseSolver<OrdinalType,ScalarType>::reciprocalConditionEstimate(MagnitudeType & Value)
00904 {
00905 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
00906   // Implement templated GECON or use Eigen. Eigen currently doesn't have a condition estimation function.
00907   return (-1);
00908 #else
00909 
00910   if (reciprocalConditionEstimated()) {
00911     Value = RCOND_;
00912     return(0); // Already computed, just return it.
00913   }
00914 
00915   if ( ANORM_<ScalarTraits<MagnitudeType>::zero() ) ANORM_ = Matrix_->normOne();
00916 
00917   int ierr = 0;
00918   if (!factored()) ierr = factor(); // Need matrix factored.
00919   if (ierr!=0) return(ierr);
00920 
00921   allocateWORK();
00922 
00923   // We will assume a one-norm condition number
00924   INFO_ = 0;
00925   std::vector<typename details::lapack_traits<ScalarType>::iwork_type> GBCON_WORK( N_ );
00926   this->GBCON( '1', N_, KL_, KU_, AF_, LDAF_, &IPIV_[0], ANORM_, &RCOND_, &WORK_[0], &GBCON_WORK[0], &INFO_);
00927   reciprocalConditionEstimated_ = true;
00928   Value = RCOND_;
00929 
00930   return(INFO_);
00931 #endif
00932 }
00933 //=============================================================================
00934 
00935 template<typename OrdinalType, typename ScalarType>
00936 void SerialBandDenseSolver<OrdinalType,ScalarType>::Print(std::ostream& os) const {
00937 
00938   if (Matrix_!=Teuchos::null) os << "Solver Matrix"          << std::endl << *Matrix_ << std::endl;
00939   if (Factor_!=Teuchos::null) os << "Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
00940   if (LHS_   !=Teuchos::null) os << "Solver LHS"             << std::endl << *LHS_    << std::endl;
00941   if (RHS_   !=Teuchos::null) os << "Solver RHS"             << std::endl << *RHS_    << std::endl;
00942 
00943 }
00944 
00945 //=============================================================================
00946 
00947 
00948 //=============================================================================
00949 
00950 
00951 } // namespace Teuchos
00952 
00953 #endif /* _TEUCHOS_SERIALBANDDENSESOLVER_HPP_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines