Amesos Package Browser (Single Doxygen Collection) Development
Amesos_Umfpack.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                Amesos: Direct Sparse Solver 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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #include "Amesos_Umfpack.h"
00030 extern "C" {
00031 #include "umfpack.h"
00032 }
00033 #include "Epetra_Map.h"
00034 #include "Epetra_Import.h"
00035 #include "Epetra_Export.h"
00036 #include "Epetra_RowMatrix.h"
00037 #include "Epetra_CrsMatrix.h"
00038 #include "Epetra_Vector.h"
00039 #include "Epetra_Util.h"
00040 
00041 //
00042 //  Hack to deal with Bug #1418  - circular dependencies in amesos, umfpack and amd libraries 
00043 //
00044 #include "Amesos_Klu.h"
00045 extern "C" {
00046 #include "amd.h"  
00047 }
00048 
00049 //=============================================================================
00050 Amesos_Umfpack::Amesos_Umfpack(const Epetra_LinearProblem &prob ) :
00051   Symbolic(0),
00052   Numeric(0),
00053   SerialMatrix_(0), 
00054   UseTranspose_(false),
00055   Problem_(&prob), 
00056   Rcond_(0.0), 
00057   RcondValidOnAllProcs_(true),
00058   MtxConvTime_(-1),
00059   MtxRedistTime_(-1),
00060   VecRedistTime_(-1),
00061   SymFactTime_(-1),
00062   NumFactTime_(-1),
00063   SolveTime_(-1),
00064   OverheadTime_(-1)
00065 {
00066   
00067   // MS // move declaration of Problem_ above because I need it
00068   // MS // set up before calling Comm()
00069   Teuchos::ParameterList ParamList ;
00070   SetParameters( ParamList ) ; 
00071 
00072   //
00073   //  Hack to deal with Bug #1418  - circular dependencies in amesos, umfpack and amd libraries 
00074   //  This causes the amd files to be pulled in from libamesos.a
00075   //
00076   if ( UseTranspose_ ) {
00077     double control[3];
00078     //  This should never be called
00079     Amesos_Klu Nothing(*Problem_); 
00080     amd_defaults(control);
00081   }
00082 
00083 }
00084 
00085 //=============================================================================
00086 Amesos_Umfpack::~Amesos_Umfpack(void) 
00087 {
00088   if (Symbolic) umfpack_di_free_symbolic (&Symbolic);
00089   if (Numeric) umfpack_di_free_numeric (&Numeric);
00090 
00091   // print out some information if required by the user
00092   if ((verbose_ && PrintTiming_) || verbose_ == 2) PrintTiming();
00093   if ((verbose_ && PrintStatus_) || verbose_ == 2) PrintStatus();
00094 
00095 }
00096 
00097 //=============================================================================
00098 // If FirstTime is true, then build SerialMap and ImportToSerial,
00099 // otherwise simply re-ship the matrix, so that the numerical values
00100 // are updated.
00101 int Amesos_Umfpack::ConvertToSerial(const bool FirstTime) 
00102 { 
00103   ResetTimer(0);
00104   ResetTimer(1);
00105   
00106   const Epetra_Map &OriginalMap = Matrix()->RowMatrixRowMap() ; 
00107 
00108   NumGlobalElements_ = Matrix()->NumGlobalRows();
00109   numentries_ = Matrix()->NumGlobalNonzeros();
00110   assert (NumGlobalElements_ == Matrix()->NumGlobalCols());
00111 
00112   int NumMyElements_ = 0 ;
00113   if (MyPID_ == 0) NumMyElements_ = NumGlobalElements_;
00114 
00115   IsLocal_ = ( OriginalMap.NumMyElements() == 
00116          OriginalMap.NumGlobalElements() )?1:0;
00117 
00118   //  if ( AddZeroToDiag_ ) IsLocal_ = 0 ;   // bug #  Umfpack does not support AddZeroToDiag_
00119 
00120   Comm().Broadcast( &IsLocal_, 1, 0 ) ; 
00121 
00122   //  Convert Original Matrix to Serial (if it is not already) 
00123   //
00124   if (IsLocal_== 1) {
00125      SerialMatrix_ = Matrix();
00126   } 
00127   else 
00128   {
00129     if (FirstTime)
00130     {
00131       SerialMap_ = rcp(new Epetra_Map(NumGlobalElements_,NumMyElements_,
00132                                       0,Comm()));
00133 
00134       if (SerialMap_.get() == 0)
00135         AMESOS_CHK_ERR(-1);
00136 
00137       ImportToSerial_ = rcp(new Epetra_Import (SerialMap(),OriginalMap));
00138 
00139       if (ImportToSerial_.get() == 0)
00140         AMESOS_CHK_ERR(-1);
00141     }
00142 
00143     SerialCrsMatrixA_ = rcp(new Epetra_CrsMatrix(Copy,SerialMap(),0));
00144 
00145     if (SerialCrsMatrixA_.get() == 0)
00146       AMESOS_CHK_ERR(-1);
00147 
00148     SerialCrsMatrix().Import(*Matrix(), Importer(),Insert); 
00149     
00150 #if 0 
00151 
00152     I was not able to make this work - 11 Feb 2006
00153 
00154     if (AddZeroToDiag_ ) { 
00155       int OriginalTracebackMode = SerialCrsMatrix().GetTracebackMode() ; 
00156       SerialCrsMatrix().SetTracebackMode( EPETRA_MIN( OriginalTracebackMode, 0) ) ; // ExportToSerial is called both by PerformSymbolicFactorization() and PerformNumericFactorization().  When called by the latter, the call to insertglobalvalues is both unnecessary and illegal.  Fortunately, Epetra allows us to ignore the error message by setting the traceback mode to 0.
00157 
00158       //
00159       //  Add 0.0 to each diagonal entry to avoid empty diagonal entries;
00160       //
00161       double zero = 0.0;
00162       for ( int i = 0 ; i < SerialMap_->NumGlobalElements(); i++ ) 
00163   if ( SerialCrsMatrix().LRID(i) >= 0 ) 
00164     SerialCrsMatrix().InsertGlobalValues( i, 1, &zero, &i ) ;
00165       SerialCrsMatrix().SetTracebackMode( OriginalTracebackMode ) ; 
00166     }
00167 #endif
00168     SerialCrsMatrix().FillComplete(); 
00169     SerialMatrix_ = &SerialCrsMatrix();
00170     assert( numentries_ == SerialMatrix_->NumGlobalNonzeros());  // This should be set to an assignment if AddToZeroDiag is non -zero
00171   }
00172 
00173 
00174   MtxRedistTime_ = AddTime("Total matrix redistribution time", MtxRedistTime_, 0);
00175   OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1);
00176   
00177   return(0);
00178 } 
00179 
00180 //=============================================================================
00181 int Amesos_Umfpack::ConvertToUmfpackCRS()
00182 {
00183   ResetTimer(0);
00184   ResetTimer(1);
00185   
00186   // Convert matrix to the form that Umfpack expects (Ap, Ai, Aval),
00187   // only on processor 0. The matrix has already been assembled in
00188   // SerialMatrix_; if only one processor is used, then SerialMatrix_
00189   // points to the problem's matrix.
00190 
00191   if (MyPID_ == 0) 
00192   {
00193     Ap.resize( NumGlobalElements_+1 );
00194     Ai.resize( EPETRA_MAX( NumGlobalElements_, numentries_) ) ; 
00195     Aval.resize( EPETRA_MAX( NumGlobalElements_, numentries_) ) ; 
00196 
00197     int NumEntries = SerialMatrix_->MaxNumEntries();
00198 
00199     int NumEntriesThisRow;
00200     int Ai_index = 0 ; 
00201     int MyRow;
00202     for (MyRow = 0 ; MyRow < NumGlobalElements_; MyRow++) 
00203     {
00204       int ierr;
00205       Ap[MyRow] = Ai_index ; 
00206       ierr = SerialMatrix_->ExtractMyRowCopy(MyRow, NumEntries, 
00207                NumEntriesThisRow, 
00208                &Aval[Ai_index], &Ai[Ai_index]);
00209       if (ierr)
00210   AMESOS_CHK_ERR(-1);
00211 
00212 #if 1
00213       // MS // added on 15-Mar-05 and KSS restored 8-Feb-06
00214       if (AddToDiag_ != 0.0) {
00215         for (int i = 0 ; i < NumEntriesThisRow ; ++i) {
00216           if (Ai[Ai_index+i] == MyRow) {
00217             Aval[Ai_index+i] += AddToDiag_;
00218             break;
00219           }
00220         }
00221       }
00222 #endif
00223       Ai_index += NumEntriesThisRow;
00224     }
00225 
00226     Ap[MyRow] = Ai_index ; 
00227   }
00228 
00229   MtxConvTime_ = AddTime("Total matrix conversion time", MtxConvTime_, 0);
00230   OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1);
00231   
00232   return 0;
00233 }   
00234 
00235 //=============================================================================
00236 int Amesos_Umfpack::SetParameters( Teuchos::ParameterList &ParameterList ) 
00237 {
00238   // ========================================= //
00239   // retrive UMFPACK's parameters from list.   //
00240   // default values defined in the constructor //
00241   // ========================================= //
00242 
00243   // retrive general parameters
00244   SetStatusParameters( ParameterList ) ;
00245   SetControlParameters( ParameterList ) ;
00246 
00247   return 0;
00248 }
00249 
00250 //=============================================================================
00251 int Amesos_Umfpack::PerformSymbolicFactorization() 
00252 {
00253   // MS // no overhead time in this method
00254   ResetTimer(0);  
00255   
00256   double *Control = (double *) NULL, *Info = (double *) NULL;
00257   
00258   if (Symbolic) 
00259     umfpack_di_free_symbolic (&Symbolic) ;
00260   if (MyPID_== 0) {
00261     (void) umfpack_di_symbolic (NumGlobalElements_, NumGlobalElements_, &Ap[0], 
00262         &Ai[0], &Aval[0], 
00263         &Symbolic, Control, Info) ;
00264   }
00265 
00266   SymFactTime_ = AddTime("Total symbolic factorization time", SymFactTime_, 0);
00267 
00268   return 0;
00269 }
00270 
00271 //=============================================================================
00272 int Amesos_Umfpack::PerformNumericFactorization( ) 
00273 {
00274   // MS // no overhead time in this method
00275   ResetTimer(0);
00276 
00277   RcondValidOnAllProcs_ = false ; 
00278   if (MyPID_ == 0) {
00279     std::vector<double> Control(UMFPACK_CONTROL);
00280     std::vector<double> Info(UMFPACK_INFO);
00281     umfpack_di_defaults( &Control[0] ) ; 
00282     if (Numeric) umfpack_di_free_numeric (&Numeric) ;
00283     int status = umfpack_di_numeric (&Ap[0], 
00284              &Ai[0], 
00285              &Aval[0], 
00286              Symbolic, 
00287              &Numeric, 
00288              &Control[0], 
00289              &Info[0]) ;
00290     Rcond_ = Info[UMFPACK_RCOND]; 
00291 
00292 #if NOT_DEF
00293     std::cout << " Rcond_ = " << Rcond_ << std::endl ; 
00294 
00295     int lnz1 = 1000 ;
00296     int unz1 = 1000 ;
00297     int n = 4;
00298     int * Lp = (int *) malloc ((n+1) * sizeof (int)) ;
00299     int * Lj = (int *) malloc (lnz1 * sizeof (int)) ;
00300     double * Lx = (double *) malloc (lnz1 * sizeof (double)) ;
00301     int * Up = (int *) malloc ((n+1) * sizeof (int)) ;
00302     int * Ui = (int *) malloc (unz1 * sizeof (int)) ;
00303     double * Ux = (double *) malloc (unz1 * sizeof (double)) ;
00304     int * P = (int *) malloc (n * sizeof (int)) ;
00305     int * Q = (int *) malloc (n * sizeof (int)) ;
00306     double * Dx = (double *) NULL ; /* D vector not requested */
00307     double * Rs  = (double *) malloc (n * sizeof (double)) ;
00308     if (!Lp || !Lj || !Lx || !Up || !Ui || !Ux || !P || !Q || !Rs)
00309     {
00310       assert( false ) ; 
00311     }
00312     int do_recip;
00313     status = umfpack_di_get_numeric (Lp, Lj, Lx, Up, Ui, Ux,
00314   P, Q, Dx, &do_recip, Rs, Numeric) ;
00315     if (status < 0)
00316     {
00317       assert( false ) ; 
00318     }
00319 
00320     printf ("\nL (lower triangular factor of C): ") ;
00321     (void) umfpack_di_report_matrix (n, n, Lp, Lj, Lx, 0, &Control[0]) ;
00322     printf ("\nU (upper triangular factor of C): ") ;
00323     (void) umfpack_di_report_matrix (n, n, Up, Ui, Ux, 1, &Control[0]) ;
00324     printf ("\nP: ") ;
00325     (void) umfpack_di_report_perm (n, P, &Control[0]) ;
00326     printf ("\nQ: ") ;
00327     (void) umfpack_di_report_perm (n, Q, &Control[0]) ;
00328     printf ("\nScale factors: row i of A is to be ") ;
00329 
00330 #endif
00331 
00332     assert( status == 0 ) ; 
00333   }
00334   
00335   NumFactTime_ = AddTime("Total numeric factorization time", NumFactTime_, 0);
00336 
00337   return 0;
00338 }
00339 
00340 //=============================================================================
00341 double Amesos_Umfpack::GetRcond() const 
00342 {
00343   if ( !RcondValidOnAllProcs_ ) {
00344     Comm().Broadcast( &Rcond_, 1, 0 ) ; 
00345     RcondValidOnAllProcs_ = true; 
00346   }
00347   return(Rcond_);
00348 }
00349 
00350 //=============================================================================
00351 bool Amesos_Umfpack::MatrixShapeOK() const 
00352 { 
00353   bool OK = true;
00354 
00355   if ( GetProblem()->GetOperator()->OperatorRangeMap().NumGlobalPoints() != 
00356        GetProblem()->GetOperator()->OperatorDomainMap().NumGlobalPoints() ) OK = false;
00357   return OK; 
00358 }
00359 
00360 
00361 //=============================================================================
00362 int Amesos_Umfpack::SymbolicFactorization() 
00363 {
00364   // MS // NOTE: If you change this method, also change
00365   // MS // NumericFactorization(), because it performs part of the actions
00366   // MS // of this method. This is to avoid to ship the matrix twice
00367   // MS // (once for the symbolic factorization, and once for the numeric
00368   // MS // factorization) when it is not necessary.
00369   
00370   IsSymbolicFactorizationOK_ = false;
00371   IsNumericFactorizationOK_ = false;
00372 
00373   CreateTimer(Comm(), 2);
00374   // MS // Initialize two timers:
00375   // MS // timer 1: this will track all time spent in Amesos most
00376   // MS //          important functions, *including* UMFPACK functions
00377   // MS // timer 2: this will track all time spent in this function
00378   // MS //          that is not due to UMFPACK calls, and therefore it
00379   // MS //          tracks down how much Amesos costs. The timer starts
00380   // MS //          and ends in *each* method, unless the method does not
00381   // MS //          perform any real operation. If a method calls another
00382   // MS //          method, the timer will be stopped before the called
00383   // MS //          method, then restared.
00384   // MS //          All the time of this timer goes into "overhead"
00385 
00386   MyPID_    = Comm().MyPID();
00387   NumProcs_ = Comm().NumProc();
00388 
00389   AMESOS_CHK_ERR(ConvertToSerial(true)); 
00390   AMESOS_CHK_ERR(ConvertToUmfpackCRS());
00391   
00392   AMESOS_CHK_ERR(PerformSymbolicFactorization());
00393 
00394   IsSymbolicFactorizationOK_ = true; 
00395 
00396   NumSymbolicFact_++;  
00397 
00398   return 0;
00399 }
00400 
00401 //=============================================================================
00402 int Amesos_Umfpack::NumericFactorization() 
00403 {
00404   IsNumericFactorizationOK_ = false;
00405 
00406   if (IsSymbolicFactorizationOK_ == false)
00407   {
00408     // Call here what is needed, to avoid double shipping of the matrix
00409     CreateTimer(Comm(), 2);
00410 
00411     MyPID_    = Comm().MyPID();
00412     NumProcs_ = Comm().NumProc();
00413 
00414     AMESOS_CHK_ERR(ConvertToSerial(true)); 
00415     AMESOS_CHK_ERR(ConvertToUmfpackCRS());
00416   
00417     AMESOS_CHK_ERR(PerformSymbolicFactorization());
00418 
00419     IsSymbolicFactorizationOK_ = true; 
00420 
00421     NumSymbolicFact_++;  
00422 
00423     AMESOS_CHK_ERR(PerformNumericFactorization());
00424   }
00425   else
00426   {
00427     // need to reshuffle and reconvert because entry values may have changed
00428     AMESOS_CHK_ERR(ConvertToSerial(false));
00429     AMESOS_CHK_ERR(ConvertToUmfpackCRS());
00430 
00431     AMESOS_CHK_ERR(PerformNumericFactorization());
00432   }
00433 
00434   NumNumericFact_++;  
00435 
00436   IsNumericFactorizationOK_ = true;
00437 
00438   return 0;
00439 }
00440 
00441 //=============================================================================
00442 int Amesos_Umfpack::Solve() 
00443 { 
00444   // if necessary, perform numeric factorization. 
00445   // This may call SymbolicFactorization() as well.
00446   if (!IsNumericFactorizationOK_)
00447     AMESOS_CHK_ERR(NumericFactorization()); 
00448 
00449   ResetTimer(1);
00450 
00451   Epetra_MultiVector* vecX = Problem_->GetLHS(); 
00452   Epetra_MultiVector* vecB = Problem_->GetRHS(); 
00453 
00454   if ((vecX == 0) || (vecB == 0))
00455     AMESOS_CHK_ERR(-1);
00456 
00457   int NumVectors = vecX->NumVectors(); 
00458   if (NumVectors != vecB->NumVectors())
00459     AMESOS_CHK_ERR(-1);
00460 
00461   Epetra_MultiVector *SerialB, *SerialX; 
00462 
00463   //  Extract Serial versions of X and B 
00464   //
00465   double *SerialXvalues ;
00466   double *SerialBvalues ;
00467 
00468   Epetra_MultiVector* SerialXextract = 0;
00469   Epetra_MultiVector* SerialBextract = 0;
00470     
00471   //  Copy B to the serial version of B
00472   //
00473   ResetTimer(0);
00474   
00475   if (IsLocal_ == 1) { 
00476     SerialB = vecB ; 
00477     SerialX = vecX ; 
00478   } else { 
00479     assert (IsLocal_ == 0);
00480     SerialXextract = new Epetra_MultiVector(SerialMap(),NumVectors); 
00481     SerialBextract = new Epetra_MultiVector(SerialMap(),NumVectors); 
00482 
00483     SerialBextract->Import(*vecB,Importer(),Insert);
00484     SerialB = SerialBextract; 
00485     SerialX = SerialXextract; 
00486   } 
00487 
00488   VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_, 0);
00489   
00490   //  Call UMFPACK to perform the solve
00491   //  Note:  UMFPACK uses a Compressed Column Storage instead of compressed row storage, 
00492   //  Hence to compute A X = B, we ask UMFPACK to perform A^T X = B and vice versa
00493 
00494   OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1);
00495 
00496   ResetTimer(0);
00497 
00498   int SerialBlda, SerialXlda ; 
00499   int UmfpackRequest = UseTranspose()?UMFPACK_A:UMFPACK_At ;
00500   int status = 0;
00501 
00502   if ( MyPID_ == 0 ) {
00503     int ierr;
00504     ierr = SerialB->ExtractView(&SerialBvalues, &SerialBlda);
00505     assert (ierr == 0);
00506     ierr = SerialX->ExtractView(&SerialXvalues, &SerialXlda);
00507     assert (ierr == 0);
00508     assert( SerialBlda == NumGlobalElements_ ) ; 
00509     assert( SerialXlda == NumGlobalElements_ ) ; 
00510     
00511     for ( int j =0 ; j < NumVectors; j++ ) { 
00512       double *Control = (double *) NULL, *Info = (double *) NULL ;
00513 
00514       status = umfpack_di_solve (UmfpackRequest, &Ap[0], 
00515              &Ai[0], &Aval[0], 
00516              &SerialXvalues[j*SerialXlda], 
00517              &SerialBvalues[j*SerialBlda], 
00518              Numeric, Control, Info) ;
00519     }
00520   }
00521     
00522   if (status) AMESOS_CHK_ERR(status);
00523 
00524   SolveTime_ = AddTime("Total solve time", SolveTime_, 0);
00525   
00526   //  Copy X back to the original vector
00527   
00528   ResetTimer(0);
00529   ResetTimer(1);
00530 
00531   if ( IsLocal_ == 0 ) {
00532     vecX->Export(*SerialX, Importer(), Insert ) ;
00533     if (SerialBextract) delete SerialBextract ;
00534     if (SerialXextract) delete SerialXextract ;
00535   }
00536 
00537   VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_, 0);
00538 
00539   if (ComputeTrueResidual_)
00540   {
00541     Epetra_RowMatrix* Matrix = 
00542       dynamic_cast<Epetra_RowMatrix*>(Problem_->GetOperator());
00543     ComputeTrueResidual(*Matrix, *vecX, *vecB, UseTranspose(), "Amesos_Umfpack");
00544   }
00545 
00546   if (ComputeVectorNorms_) {
00547     ComputeVectorNorms(*vecX, *vecB, "Amesos_Umfpack");
00548   }
00549 
00550   NumSolve_++;
00551 
00552   OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1); // Amesos overhead
00553 
00554   return(0);
00555 }
00556 
00557 // ====================================================================== 
00558 void Amesos_Umfpack::PrintStatus() const
00559 {
00560   if (MyPID_ != 0) return;
00561 
00562   PrintLine();
00563 
00564   std::cout << "Amesos_Umfpack : Matrix has " << NumGlobalElements_ << " rows"
00565       << " and " << numentries_ << " nonzeros" << std::endl;
00566   std::cout << "Amesos_Umfpack : Nonzero elements per row = "
00567        << 1.0*numentries_/NumGlobalElements_ << std::endl;
00568   std::cout << "Amesos_Umfpack : Percentage of nonzero elements = "
00569        << 100.0*numentries_/(pow(double(NumGlobalElements_),double(2.0))) << std::endl;
00570   std::cout << "Amesos_Umfpack : Use transpose = " << UseTranspose_ << std::endl;
00571 
00572   PrintLine();
00573 
00574   return;
00575 }
00576 
00577 // ====================================================================== 
00578 void Amesos_Umfpack::PrintTiming() const
00579 {
00580   if (Problem_->GetOperator() == 0 || MyPID_ != 0)
00581     return;
00582 
00583   double ConTime = GetTime(MtxConvTime_);
00584   double MatTime = GetTime(MtxRedistTime_);
00585   double VecTime = GetTime(VecRedistTime_);
00586   double SymTime = GetTime(SymFactTime_);
00587   double NumTime = GetTime(NumFactTime_);
00588   double SolTime = GetTime(SolveTime_);
00589   double OveTime = GetTime(OverheadTime_);
00590 
00591   if (NumSymbolicFact_)
00592     SymTime /= NumSymbolicFact_;
00593 
00594   if (NumNumericFact_)
00595     NumTime /= NumNumericFact_;
00596 
00597   if (NumSolve_)
00598     SolTime /= NumSolve_;
00599 
00600   std::string p = "Amesos_Umfpack : ";
00601   PrintLine();
00602 
00603   std::cout << p << "Time to convert matrix to Umfpack format = "
00604        << ConTime << " (s)" << std::endl;
00605   std::cout << p << "Time to redistribute matrix = "
00606        << MatTime << " (s)" << std::endl;
00607   std::cout << p << "Time to redistribute vectors = "
00608        << VecTime << " (s)" << std::endl;
00609   std::cout << p << "Number of symbolic factorizations = "
00610        << NumSymbolicFact_ << std::endl;
00611   std::cout << p << "Time for sym fact = "
00612        << SymTime * NumSymbolicFact_ << " (s), avg = " 
00613        << SymTime << " (s)" << std::endl;
00614   std::cout << p << "Number of numeric factorizations = "
00615        << NumNumericFact_ << std::endl;
00616   std::cout << p << "Time for num fact = "
00617        << NumTime * NumNumericFact_ << " (s), avg = " 
00618        << NumTime << " (s)" << std::endl;
00619   std::cout << p << "Number of solve phases = "
00620        << NumSolve_ << std::endl;
00621   std::cout << p << "Time for solve = "
00622        << SolTime * NumSolve_ << " (s), avg = " << SolTime << " (s)" << std::endl;
00623   double tt = SymTime * NumSymbolicFact_ + NumTime * NumNumericFact_ + SolTime * NumSolve_;
00624   if (tt != 0)
00625   {
00626     std::cout << p << "Total time spent in Amesos = " << tt << " (s) " << std::endl;
00627     std::cout << p << "Total time spent in the Amesos interface = " << OveTime << " (s)" << std::endl;
00628     std::cout << p << "(the above time does not include UMFPACK time)" << std::endl;
00629     std::cout << p << "Amesos interface time / total time = " << OveTime / tt << std::endl;
00630   }
00631 
00632   PrintLine();
00633 
00634   return;
00635 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines