IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
Ifpack_SerialTriDiSolver.cpp
00001 //@HEADER
00002 // ************************************************************************
00003 //
00004 //               Epetra: Linear Algebra Services Package
00005 //                 Copyright 2011 Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
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 #include "Ifpack_SerialTriDiSolver.h"
00043 #include "Ifpack_SerialTriDiMatrix.h"
00044 #include "Epetra_SerialDenseVector.h"
00045 #include <iostream>
00046 
00047 //=============================================================================
00048 Ifpack_SerialTriDiSolver::Ifpack_SerialTriDiSolver()
00049   : Epetra_CompObject(),
00050     Epetra_BLAS(),
00051     Transpose_(false),
00052     Factored_(false),
00053     EstimateSolutionErrors_(false),
00054     SolutionErrorsEstimated_(false),
00055     Solved_(false),
00056     Inverted_(false),
00057     ReciprocalConditionEstimated_(false),
00058     RefineSolution_(false),
00059     SolutionRefined_(false),
00060     TRANS_('N'),
00061     N_(0),
00062     NRHS_(0),
00063     LDA_(0),
00064     LDAF_(0),
00065     LDB_(0),
00066     LDX_(0),
00067     INFO_(0),
00068     LWORK_(0),
00069     IPIV_(0),
00070     IWORK_(0),
00071     ANORM_(0.0),
00072     RCOND_(0.0),
00073     ROWCND_(0.0),
00074     COLCND_(0.0),
00075     AMAX_(0.0),
00076     Matrix_(0),
00077     LHS_(0),
00078     RHS_(0),
00079     Factor_(0),
00080     A_(0),
00081     FERR_(0),
00082     BERR_(0),
00083     AF_(0),
00084     WORK_(0),
00085     B_(0),
00086     X_(0)
00087 {
00088   InitPointers();
00089   ResetMatrix();
00090   ResetVectors();
00091 }
00092 //=============================================================================
00093 Ifpack_SerialTriDiSolver::~Ifpack_SerialTriDiSolver()
00094 {
00095   DeleteArrays();
00096 }
00097 //=============================================================================
00098 void Ifpack_SerialTriDiSolver::InitPointers()
00099 {
00100   IWORK_ = 0;
00101   FERR_ = 0;
00102   BERR_ = 0;
00103   Factor_ =0;
00104   Matrix_ =0;
00105   AF_ = 0;
00106   IPIV_ = 0;
00107   WORK_ = 0;
00108   INFO_ = 0;
00109   LWORK_ = 0;
00110 }
00111 //=============================================================================
00112 void Ifpack_SerialTriDiSolver::DeleteArrays()
00113 { 
00114   if (IWORK_ != 0) {delete [] IWORK_;IWORK_ = 0;}
00115   if (FERR_ != 0)  {delete [] FERR_; FERR_ = 0;}
00116   if (BERR_ != 0)  {delete [] BERR_; BERR_ = 0;}
00117   if (Factor_ != Matrix_ && Factor_ != 0)   {delete Factor_; Factor_ = 0;}
00118   if (Factor_ !=0) Factor_ = 0;
00119 
00120   if (IPIV_ != 0)  {delete [] IPIV_;IPIV_ = 0;}
00121   if (WORK_ != 0)  {delete [] WORK_;WORK_ = 0;}
00122 
00123   if (AF_ !=0) AF_ = 0;
00124 
00125   INFO_ = 0;
00126   LWORK_ = 0;
00127 }
00128 //=============================================================================
00129 void Ifpack_SerialTriDiSolver::ResetMatrix()
00130 {
00131   DeleteArrays();
00132   ResetVectors();
00133   Matrix_ = 0;
00134   Factor_ = 0;
00135   Factored_ = false;
00136   Inverted_ = false;
00137   N_ = 0;
00138   LDA_ = 0;
00139   LDAF_ = 0;
00140   ANORM_ = -1.0;
00141   RCOND_ = -1.0;
00142   ROWCND_ = -1.0;
00143   COLCND_ = -1.0;
00144   AMAX_ = -1.0;
00145   A_ = 0;
00146 
00147 }
00148 //=============================================================================
00149 int Ifpack_SerialTriDiSolver::SetMatrix(Ifpack_SerialTriDiMatrix & A_in) {
00150   ResetMatrix();
00151   Matrix_ = &A_in;
00152   Factor_ = &A_in;
00153   N_ = A_in.N();
00154   A_ = A_in.A();
00155   LDA_ = A_in.LDA();
00156   LDAF_ = LDA_;
00157   AF_ = A_in.A();
00158   return(0);
00159 }
00160 //=============================================================================
00161 void Ifpack_SerialTriDiSolver::ResetVectors()
00162 {
00163   LHS_ = 0;
00164   RHS_ = 0;
00165   B_ = 0;
00166   X_ = 0;
00167   ReciprocalConditionEstimated_ = false;
00168   SolutionRefined_ = false;
00169   Solved_ = false;
00170   SolutionErrorsEstimated_ = false;
00171   NRHS_ = 0;
00172   LDB_ = 0;
00173   LDX_ = 0;
00174 }
00175 //=============================================================================
00176 int Ifpack_SerialTriDiSolver::SetVectors(Epetra_SerialDenseMatrix & X_in, Epetra_SerialDenseMatrix & B_in)
00177 {
00178   if (B_in.N() != X_in.N()) EPETRA_CHK_ERR(-1);
00179   if (B_in.A()==0) EPETRA_CHK_ERR(-2);
00180   if (X_in.A()==0) EPETRA_CHK_ERR(-4);
00181 
00182   ResetVectors();
00183   LHS_ = &X_in;
00184   RHS_ = &B_in;
00185   NRHS_ = B_in.N();
00186 
00187   B_ = B_in.A();
00188   X_ = X_in.A();
00189   return(0);
00190 }
00191 //=============================================================================
00192 void Ifpack_SerialTriDiSolver::EstimateSolutionErrors(bool Flag) {
00193   EstimateSolutionErrors_ = Flag;
00194   // If the errors are estimated, this implies that the solution must be refined
00195   RefineSolution_ = RefineSolution_ || Flag;
00196   return;
00197 }
00198 //=============================================================================
00199 int Ifpack_SerialTriDiSolver::Factor(void) {
00200   if (Factored()) return(0); // Already factored
00201   if (Inverted()) EPETRA_CHK_ERR(-100); // Cannot factor inverted matrix
00202 
00203   ANORM_ = Matrix_->OneNorm(); // Compute 1-Norm of A
00204 
00205   // If we want to refine the solution, then the factor must
00206   // be stored separatedly from the original matrix
00207 
00208   Ifpack_SerialTriDiMatrix * F = Matrix_;
00209 
00210   if (A_ == AF_)
00211     if (RefineSolution_ ) {
00212       Factor_ = new Ifpack_SerialTriDiMatrix(*Matrix_);
00213       F = Factor_;
00214       AF_ = Factor_->A();
00215       LDAF_ = Factor_->LDA();
00216     }
00217 
00218   if (IPIV_==0) IPIV_ = new int[N_]; // Allocated Pivot vector if not already done.
00219   
00220   double * DL_  = F->DL();
00221   double * D_   = F->D();
00222   double * DU_  = F->DU();
00223   double * DU2_ = F->DU2();
00224 
00225   lapack.GTTRF(N_, DL_, D_, DU_, DU2_, IPIV_, &INFO_);
00226 
00227   Factored_ = true;
00228   double DN = N_;
00229   UpdateFlops( (N_ == 1)? 1. : 4*(DN-1) );
00230 
00231   EPETRA_CHK_ERR(INFO_);
00232   return(0);
00233 
00234 }
00235 
00236 //=============================================================================
00237 int Ifpack_SerialTriDiSolver::Solve(void) {
00238   int ierr = 0;
00239 
00240   // We will call one of four routines depending on what services the user wants and
00241   // whether or not the matrix has been inverted or factored already.
00242   //
00243   // If the matrix has been inverted, use DGEMM to compute solution.
00244   // Otherwise, if the user want the matrix to be equilibrated or wants a refined solution, we will
00245   // call the X interface.
00246   // Otherwise, if the matrix is already factored we will call the TRS interface.
00247   // Otherwise, if the matrix is unfactored we will call the SV interface.
00248 
00249   if (B_==0) EPETRA_CHK_ERR(-3); // No B
00250   if (X_==0) EPETRA_CHK_ERR(-4); // No X
00251 
00252   double DN = N_;
00253   double DNRHS = NRHS_;
00254   if (Inverted()) {
00255 
00256     EPETRA_CHK_ERR(-101);  // don't allow this \cbl
00257 
00258   }
00259   else {
00260 
00261     if (!Factored()) Factor(); // Matrix must be factored
00262 
00263     if (B_!=X_) {
00264        *LHS_ = *RHS_; // Copy B to X if needed
00265        X_ = LHS_->A(); 
00266     }
00267 
00268     Ifpack_SerialTriDiMatrix * F;
00269     if(A_ == AF_)
00270       F = Matrix_;
00271     else
00272       F = Factor_;
00273 
00274     double * DL_  = F->DL();
00275     double * D_   = F->D();
00276     double * DU_  = F->DU();
00277     double * DU2_ = F->DU2();
00278 
00279     lapack.GTTRS(TRANS_,N_,NRHS_,DL_,D_,DU_,DU2_,IPIV_,X_,N_,&INFO_);
00280     
00281     if (INFO_!=0) EPETRA_CHK_ERR(INFO_);
00282     UpdateFlops(2.0*4*DN*DNRHS);
00283     Solved_ = true;
00284 
00285   }
00286   int ierr1=0;
00287   if (RefineSolution_ && !Inverted()) ierr1 = ApplyRefinement();
00288   if (ierr1!=0) EPETRA_CHK_ERR(ierr1)
00289   else
00290     EPETRA_CHK_ERR(ierr);
00291 
00292   return(0);
00293 }
00294 //=============================================================================
00295  int Ifpack_SerialTriDiSolver::ApplyRefinement(void)
00296  {
00297    std::cout<<" SerialTriDiSolver::ApplyRefinement this function is not supported"<<std::endl;
00298    EPETRA_CHK_ERR(-102);
00299    return(0);
00300  }
00301 
00302 //=============================================================================
00303 int Ifpack_SerialTriDiSolver::Invert(void)
00304 {
00305   if (!Factored()) Factor(); // Need matrix factored.
00306 
00307   // Setting LWORK = -1 and calling GETRI will return optimal work space size in
00308   AllocateWORK();
00309 
00310   lapack.GETRI ( N_, AF_, LDAF_, IPIV_, WORK_, LWORK_, &INFO_);
00311 
00312   double DN = N_;
00313   UpdateFlops((DN*DN*DN));
00314   Inverted_ = true;
00315   Factored_ = false;
00316 
00317   EPETRA_CHK_ERR(INFO_);
00318   return(0);
00319 }
00320 
00321 //=============================================================================
00322 int Ifpack_SerialTriDiSolver::ReciprocalConditionEstimate(double & Value)
00323 {
00324   int ierr = 0;
00325   if (ReciprocalConditionEstimated()) {
00326     Value = RCOND_;
00327     return(0); // Already computed, just return it.
00328   }
00329 
00330   if (ANORM_<0.0) ANORM_ = Matrix_->OneNorm();
00331   if (!Factored()) ierr = Factor(); // Need matrix factored.
00332   if (ierr!=0) EPETRA_CHK_ERR(ierr-2);
00333 
00334   AllocateWORK();
00335   AllocateIWORK();
00336   // We will assume a one-norm condition number \\ works for TriDi
00337   lapack.GECON( '1', N_, AF_, LDAF_, ANORM_, &RCOND_, WORK_, IWORK_, &INFO_);
00338   ReciprocalConditionEstimated_ = true;
00339   Value = RCOND_;
00340   UpdateFlops(2*N_*N_); // Not sure of count
00341   EPETRA_CHK_ERR(INFO_);
00342   return(0);
00343 }
00344 //=============================================================================
00345 void Ifpack_SerialTriDiSolver::Print(std::ostream& os) const {
00346 
00347   if (Matrix_!=0) os << "Solver Matrix"          << std::endl << *Matrix_ << std::endl;
00348   if (Factor_!=0) os << "Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
00349   if (LHS_   !=0) os << "Solver LHS"             << std::endl << *LHS_    << std::endl;
00350   if (RHS_   !=0) os << "Solver RHS"             << std::endl << *RHS_    << std::endl;
00351 
00352 }
 All Classes Files Functions Variables Enumerations Friends