|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
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_ */
1.7.6.1