IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
Ifpack_AdditiveSchwarz.h
00001 /*
00002 //@HEADER
00003 // ***********************************************************************
00004 //
00005 //       Ifpack: Object-Oriented Algebraic Preconditioner Package
00006 //                 Copyright (2002) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 //@HEADER
00042 */
00043 
00044 #ifndef IFPACK_ADDITIVESCHWARZ_H
00045 #define IFPACK_ADDITIVESCHWARZ_H
00046 
00047 #include "Ifpack_ConfigDefs.h"
00048 #include "Ifpack_Preconditioner.h"
00049 #include "Ifpack_ConfigDefs.h"
00050 #include "Ifpack_Preconditioner.h"
00051 #include "Ifpack_Reordering.h"
00052 #include "Ifpack_RCMReordering.h"
00053 #include "Ifpack_METISReordering.h"
00054 #include "Ifpack_LocalFilter.h"
00055 #include "Ifpack_NodeFilter.h"
00056 #include "Ifpack_SingletonFilter.h"
00057 #include "Ifpack_ReorderFilter.h"
00058 #include "Ifpack_Utils.h"
00059 #include "Ifpack_OverlappingRowMatrix.h"
00060 #include "Epetra_CombineMode.h"
00061 #include "Epetra_MultiVector.h"
00062 #include "Epetra_Map.h"
00063 #include "Epetra_Comm.h"
00064 #include "Epetra_Time.h"
00065 #include "Epetra_LinearProblem.h"
00066 #include "Epetra_RowMatrix.h"
00067 #include "Epetra_CrsMatrix.h"
00068 #include "Teuchos_ParameterList.hpp"
00069 #include "Teuchos_RefCountPtr.hpp"
00070 
00071 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00072 #include "Ifpack_SubdomainFilter.h"
00073 #include "EpetraExt_Reindex_CrsMatrix.h"
00074 #include "EpetraExt_Reindex_MultiVector.h"
00075 #endif
00076 #ifdef IFPACK_NODE_AWARE_CODE
00077 #include "EpetraExt_OperatorOut.h"
00078 #include "EpetraExt_RowMatrixOut.h"
00079 #include "EpetraExt_BlockMapOut.h"
00080 #endif
00081 
00082 #ifdef HAVE_IFPACK_AMESOS
00083   #include "Ifpack_AMDReordering.h"
00084 #endif
00085 
00086 
00088 
00141 template<typename T>
00142 class Ifpack_AdditiveSchwarz : public virtual Ifpack_Preconditioner {
00143       
00144 public:
00145 
00147 
00148 
00159   Ifpack_AdditiveSchwarz(Epetra_RowMatrix* Matrix_in,
00160              int OverlapLevel_in = 0);
00161   
00163   virtual ~Ifpack_AdditiveSchwarz() {};
00165 
00167 
00169 
00178     virtual int SetUseTranspose(bool UseTranspose_in);
00180   
00182 
00184 
00194     virtual int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
00195 
00197 
00208     virtual int ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
00209 
00211     virtual double NormInf() const;
00213   
00215 
00217     virtual const char * Label() const;
00218 
00220     virtual bool UseTranspose() const;
00221 
00223     virtual bool HasNormInf() const;
00224 
00226     virtual const Epetra_Comm & Comm() const;
00227 
00229     virtual const Epetra_Map & OperatorDomainMap() const;
00230 
00232     virtual const Epetra_Map & OperatorRangeMap() const;
00234 
00236   virtual bool IsInitialized() const
00237   {
00238     return(IsInitialized_);
00239   }
00240 
00242   virtual bool IsComputed() const
00243   {
00244     return(IsComputed_);
00245   }
00246 
00248 
00267   virtual int SetParameters(Teuchos::ParameterList& List);
00268 
00269   // @}
00270 
00271   // @{ Query methods
00272   
00274   virtual int Initialize();
00275 
00277   virtual int Compute();
00278 
00280   virtual double Condest(const Ifpack_CondestType CT = Ifpack_Cheap,
00281                          const int MaxIters = 1550,
00282                          const double Tol = 1e-9,
00283              Epetra_RowMatrix* Matrix_in = 0);
00284 
00286   virtual double Condest() const
00287   {
00288     return(Condest_);
00289   }
00290 
00292   virtual const Epetra_RowMatrix& Matrix() const
00293   {
00294     return(*Matrix_);
00295   }
00296 
00298   virtual bool IsOverlapping() const
00299   {
00300     return(IsOverlapping_);
00301   }
00302 
00304   virtual std::ostream& Print(std::ostream&) const;
00305   
00306   virtual const T* Inverse() const
00307   {
00308     return(&*Inverse_);
00309   }
00310 
00312   virtual int NumInitialize() const
00313   {
00314     return(NumInitialize_);
00315   }
00316 
00318   virtual int NumCompute() const
00319   {
00320     return(NumCompute_);
00321   }
00322 
00324   virtual int NumApplyInverse() const
00325   {
00326     return(NumApplyInverse_);
00327   }
00328 
00330   virtual double InitializeTime() const
00331   {
00332     return(InitializeTime_);
00333   }
00334 
00336   virtual double ComputeTime() const
00337   {
00338     return(ComputeTime_);
00339   }
00340 
00342   virtual double ApplyInverseTime() const
00343   {
00344     return(ApplyInverseTime_);
00345   }
00346 
00348   virtual double InitializeFlops() const
00349   {
00350     return(InitializeFlops_);
00351   }
00352 
00353   virtual double ComputeFlops() const
00354   {
00355     return(ComputeFlops_);
00356   }
00357 
00358   virtual double ApplyInverseFlops() const
00359   {
00360     return(ApplyInverseFlops_);
00361   }
00362 
00364   virtual int OverlapLevel() const
00365   {
00366     return(OverlapLevel_);
00367   }
00368 
00370   virtual const Teuchos::ParameterList& List() const
00371   {
00372     return(List_);
00373   }
00374 
00375 protected:
00376 
00377   // @}
00378 
00379   // @{ Internal merhods.
00380   
00382   Ifpack_AdditiveSchwarz(const Ifpack_AdditiveSchwarz& RHS)
00383   { }
00384 
00386   int Setup();
00387   
00388   // @}
00389 
00390   // @{ Internal data.
00391   
00393   Teuchos::RefCountPtr<const Epetra_RowMatrix> Matrix_;
00395   Teuchos::RefCountPtr<Ifpack_OverlappingRowMatrix> OverlappingMatrix_;
00397 /*
00398   //TODO if we choose to expose the node aware code, i.e., no ifdefs,
00399   //TODO then we should switch to this definition.
00400   Teuchos::RefCountPtr<Epetra_RowMatrix> LocalizedMatrix_;
00401 */
00402 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00403 
00404   Teuchos::RCP<Epetra_RowMatrix> LocalizedMatrix_;
00406   Teuchos::RCP<Epetra_CrsMatrix> SubdomainCrsMatrix_;
00408   Teuchos::RCP<Epetra_CrsMatrix> ReindexedCrsMatrix_;
00409 
00410   // The following data members are needed when doing ApplyInverse
00411   // with an Ifpack_SubdomainFilter local matrix
00412   Teuchos::RCP<Epetra_Map> tempMap_;
00413   Teuchos::RCP<Epetra_Map> tempDomainMap_;
00414   Teuchos::RCP<Epetra_Map> tempRangeMap_;
00415   Teuchos::RCP<EpetraExt::CrsMatrix_Reindex> SubdomainMatrixReindexer_;
00416   Teuchos::RCP<EpetraExt::MultiVector_Reindex> DomainVectorReindexer_;
00417   Teuchos::RCP<EpetraExt::MultiVector_Reindex> RangeVectorReindexer_;
00418   mutable Teuchos::RCP<Epetra_MultiVector> tempX_;
00419   mutable Teuchos::RCP<Epetra_MultiVector> tempY_;
00420 #else
00421 # ifdef IFPACK_NODE_AWARE_CODE
00422   Teuchos::RefCountPtr<Ifpack_NodeFilter> LocalizedMatrix_;
00423 # else
00424   Teuchos::RefCountPtr<Ifpack_LocalFilter> LocalizedMatrix_;
00425 # endif
00426 #endif
00427 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00428   // Some data members used for determining the subdomain id (color)
00430   int MpiRank_;
00432   int NumMpiProcs_;
00434   int NumMpiProcsPerSubdomain_;
00436   int NumSubdomains_;
00438   int SubdomainId_;
00439 #endif
00440 
00441   string Label_;
00443   bool IsInitialized_;
00445   bool IsComputed_;
00447   bool UseTranspose_;
00449   bool IsOverlapping_;
00451   int OverlapLevel_;
00453   Teuchos::ParameterList List_;
00455   Epetra_CombineMode CombineMode_;
00457   double Condest_;
00459   bool ComputeCondest_;
00461   bool UseReordering_;
00463   string ReorderingType_;
00465   Teuchos::RefCountPtr<Ifpack_Reordering> Reordering_;
00467   Teuchos::RefCountPtr<Ifpack_ReorderFilter> ReorderedLocalizedMatrix_;
00469   bool FilterSingletons_;
00471   Teuchos::RefCountPtr<Ifpack_SingletonFilter> SingletonFilter_;
00473   int NumInitialize_;
00475   int NumCompute_;
00477   mutable int NumApplyInverse_;
00479   double InitializeTime_;
00481   double ComputeTime_;
00483   mutable double ApplyInverseTime_;
00485   double InitializeFlops_;
00487   double ComputeFlops_;
00489   mutable double ApplyInverseFlops_;
00491   Teuchos::RefCountPtr<Epetra_Time> Time_;
00493   Teuchos::RefCountPtr<T> Inverse_;
00495 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00496   mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingX;
00497   mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingY;
00498 #endif
00499 # ifdef IFPACK_NODE_AWARE_CODE
00500   mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingX;
00501   mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingY;
00502 #endif
00503 
00504 }; // class Ifpack_AdditiveSchwarz<T>
00505 
00506 //==============================================================================
00507 template<typename T>
00508 Ifpack_AdditiveSchwarz<T>::
00509 Ifpack_AdditiveSchwarz(Epetra_RowMatrix* Matrix_in,
00510                        int OverlapLevel_in) :
00511 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00512   MpiRank_(0),
00513   NumMpiProcs_(1),
00514   NumMpiProcsPerSubdomain_(1),
00515   NumSubdomains_(1),
00516   SubdomainId_(0),
00517 #endif
00518   IsInitialized_(false),
00519   IsComputed_(false),
00520   UseTranspose_(false),
00521   IsOverlapping_(false),
00522   OverlapLevel_(OverlapLevel_in),
00523   CombineMode_(Zero),
00524   Condest_(-1.0),
00525   ComputeCondest_(true),
00526   UseReordering_(false),
00527   ReorderingType_("none"),
00528   FilterSingletons_(false),
00529   NumInitialize_(0),
00530   NumCompute_(0),
00531   NumApplyInverse_(0),
00532   InitializeTime_(0.0),
00533   ComputeTime_(0.0),
00534   ApplyInverseTime_(0.0),
00535   InitializeFlops_(0.0),
00536   ComputeFlops_(0.0),
00537   ApplyInverseFlops_(0.0)
00538 {
00539   // Construct a reference-counted pointer with the input matrix, don't manage the memory.
00540   Matrix_ = Teuchos::rcp( Matrix_in, false );
00541 
00542   if (Matrix_->Comm().NumProc() == 1)
00543     OverlapLevel_ = 0;
00544 
00545   if ((OverlapLevel_ != 0) && (Matrix_->Comm().NumProc() > 1))
00546     IsOverlapping_ = true;
00547   // Sets parameters to default values
00548   Teuchos::ParameterList List_in;
00549   SetParameters(List_in);
00550 }
00551 
00552 #ifdef IFPACK_NODE_AWARE_CODE
00553 extern int ML_NODE_ID;
00554 #endif
00555 
00556 //==============================================================================
00557 template<typename T>
00558 int Ifpack_AdditiveSchwarz<T>::Setup()
00559 {
00560 
00561   Epetra_RowMatrix* MatrixPtr;
00562 
00563 #ifndef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00564 # ifdef IFPACK_NODE_AWARE_CODE
00565 /*
00566   sleep(3);
00567   if (Comm().MyPID() == 0) cout << "Printing out ovArowmap" << endl;
00568   Comm().Barrier();
00569 
00570   EpetraExt::BlockMapToMatrixMarketFile("ovArowmap",OverlappingMatrix_->RowMatrixRowMap());
00571   if (Comm().MyPID() == 0) cout << "Printing out ovAcolmap" << endl;
00572   Comm().Barrier();
00573   EpetraExt::BlockMapToMatrixMarketFile("ovAcolmap",OverlappingMatrix_->RowMatrixColMap());
00574   Comm().Barrier();
00575 */
00576 /*
00577   EpetraExt::RowMatrixToMatlabFile("ovA",*OverlappingMatrix_);
00578   fprintf(stderr,"p %d n %d matrix file done\n",Comm().MyPID(),ML_NODE_ID);
00579   Comm().Barrier();
00580 */
00581   int nodeID;
00582   try{ nodeID = List_.get("ML node id",0);}
00583   catch(...){fprintf(stderr,"%s","Ifpack_AdditiveSchwarz<T>::Setup(): no parameter \"ML node id\"\n\n");
00584              cout << List_ << endl;}
00585 # endif
00586 #endif
00587 
00588   try{
00589   if (OverlappingMatrix_ != Teuchos::null)
00590   {
00591 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00592     if (NumMpiProcsPerSubdomain_ > 1) {
00593       LocalizedMatrix_ = Teuchos::rcp(new Ifpack_SubdomainFilter(OverlappingMatrix_, SubdomainId_));
00594     } else {
00595       LocalizedMatrix_ = Teuchos::rcp(new Ifpack_LocalFilter(OverlappingMatrix_));
00596     }
00597 #else
00598 #   ifdef IFPACK_NODE_AWARE_CODE
00599     Ifpack_NodeFilter *tt = new Ifpack_NodeFilter(OverlappingMatrix_,nodeID); //FIXME
00600     LocalizedMatrix_ = Teuchos::rcp(tt);
00601     //LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(OverlappingMatrix_) );
00602 #   else
00603     LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(OverlappingMatrix_) );
00604 #   endif
00605 #endif
00606   }
00607   else
00608   {
00609 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00610 
00611     if (NumMpiProcsPerSubdomain_ > 1) {
00612       LocalizedMatrix_ = Teuchos::rcp(new Ifpack_SubdomainFilter(Matrix_, SubdomainId_));
00613     } else {
00614       LocalizedMatrix_ = Teuchos::rcp(new Ifpack_LocalFilter(Matrix_));
00615     }
00616 #else
00617 #   ifdef IFPACK_NODE_AWARE_CODE
00618     Ifpack_NodeFilter *tt = new Ifpack_NodeFilter(Matrix_,nodeID); //FIXME
00619     LocalizedMatrix_ = Teuchos::rcp(tt);
00620     //LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(Matrix_) );
00621 #   else
00622     LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(Matrix_) );
00623 #   endif
00624 #endif
00625   }
00626   }
00627   catch(...) {
00628      fprintf(stderr,"%s","AdditiveSchwarz Setup: problem creating local filter matrix.\n");
00629   }
00630 
00631   if (LocalizedMatrix_ == Teuchos::null)
00632     IFPACK_CHK_ERR(-5);
00633 
00634   // users may want to skip singleton check
00635   if (FilterSingletons_) {
00636     SingletonFilter_ = Teuchos::rcp( new Ifpack_SingletonFilter(LocalizedMatrix_) );
00637     MatrixPtr = &*SingletonFilter_;
00638   }
00639   else
00640     MatrixPtr = &*LocalizedMatrix_;
00641 
00642   if (UseReordering_) {
00643 
00644     // create reordering and compute it
00645     if (ReorderingType_ == "rcm")
00646       Reordering_ = Teuchos::rcp( new Ifpack_RCMReordering() );
00647     else if (ReorderingType_ == "metis")
00648       Reordering_ = Teuchos::rcp( new Ifpack_METISReordering() );
00649 #ifdef HAVE_IFPACK_AMESOS   
00650     else if (ReorderingType_ == "amd" )
00651       Reordering_ = Teuchos::rcp( new Ifpack_AMDReordering() );
00652 #endif
00653     else {
00654       cerr << "reordering type not correct (" << ReorderingType_ << ")" << endl;
00655       exit(EXIT_FAILURE);
00656     }
00657     if (Reordering_ == Teuchos::null) IFPACK_CHK_ERR(-5);
00658 
00659     IFPACK_CHK_ERR(Reordering_->SetParameters(List_));
00660     IFPACK_CHK_ERR(Reordering_->Compute(*MatrixPtr));
00661 
00662     // now create reordered localized matrix
00663     ReorderedLocalizedMatrix_ = 
00664       Teuchos::rcp( new Ifpack_ReorderFilter(Teuchos::rcp( MatrixPtr, false ), Reordering_) );
00665 
00666     if (ReorderedLocalizedMatrix_ == Teuchos::null) IFPACK_CHK_ERR(-5);
00667 
00668     MatrixPtr = &*ReorderedLocalizedMatrix_;
00669   }
00670 
00671 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00672   // The subdomain matrix needs to be reindexed by Amesos so we need to make a CrsMatrix
00673   // and then reindex it with EpetraExt.
00674   // The reindexing is done here because this feature is only implemented in Amesos_Klu,
00675   // and it is desired to have reindexing with other direct solvers in the Amesos package
00676 
00677   SubdomainCrsMatrix_.reset(new Epetra_CrsMatrix(Copy, MatrixPtr->RowMatrixRowMap(), -1));
00678   Teuchos::RCP<Epetra_Import> tempImporter = Teuchos::rcp(new Epetra_Import(SubdomainCrsMatrix_->Map(), MatrixPtr->Map()));
00679   SubdomainCrsMatrix_->Import(*MatrixPtr, *tempImporter, Insert);
00680   SubdomainCrsMatrix_->FillComplete();
00681 
00682   if (NumMpiProcsPerSubdomain_ > 1) {
00683     tempMap_.reset(new Epetra_Map(SubdomainCrsMatrix_->RowMap().NumGlobalElements(),
00684                                   SubdomainCrsMatrix_->RowMap().NumMyElements(),
00685                                   0, SubdomainCrsMatrix_->Comm()));
00686     tempRangeMap_.reset(new Epetra_Map(SubdomainCrsMatrix_->OperatorRangeMap().NumGlobalElements(),
00687                                        SubdomainCrsMatrix_->OperatorRangeMap().NumMyElements(),
00688                                        0, SubdomainCrsMatrix_->Comm()));
00689     tempDomainMap_.reset(new Epetra_Map(SubdomainCrsMatrix_->OperatorDomainMap().NumGlobalElements(),
00690                                         SubdomainCrsMatrix_->OperatorDomainMap().NumMyElements(),
00691                                         0, SubdomainCrsMatrix_->Comm()));
00692 
00693     SubdomainMatrixReindexer_.reset(new EpetraExt::CrsMatrix_Reindex(*tempMap_));
00694     DomainVectorReindexer_.reset(new EpetraExt::MultiVector_Reindex(*tempDomainMap_));
00695     RangeVectorReindexer_.reset(new EpetraExt::MultiVector_Reindex(*tempRangeMap_));
00696 
00697     ReindexedCrsMatrix_.reset(&((*SubdomainMatrixReindexer_)(*SubdomainCrsMatrix_)), false);
00698 
00699     MatrixPtr = &*ReindexedCrsMatrix_;
00700 
00701     Inverse_ = Teuchos::rcp( new T(&*ReindexedCrsMatrix_) );
00702   } else {
00703     Inverse_ = Teuchos::rcp( new T(&*SubdomainCrsMatrix_) );
00704   }
00705 #else
00706   Inverse_ = Teuchos::rcp( new T(MatrixPtr) );
00707 #endif
00708 
00709   if (Inverse_ == Teuchos::null)
00710     IFPACK_CHK_ERR(-5);
00711 
00712   return(0);
00713 }
00714 
00715 //==============================================================================
00716 template<typename T>
00717 int Ifpack_AdditiveSchwarz<T>::SetParameters(Teuchos::ParameterList& List_in)
00718 {
00719 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00720   MpiRank_ = Matrix_->Comm().MyPID();
00721   NumMpiProcs_ = Matrix_->Comm().NumProc();
00722   NumMpiProcsPerSubdomain_ = List_in.get("subdomain: number-of-processors", 1);
00723   NumSubdomains_ = NumMpiProcs_ / NumMpiProcsPerSubdomain_;
00724   SubdomainId_ = MpiRank_ / NumMpiProcsPerSubdomain_;
00725 
00726   if (NumSubdomains_ == 1) {
00727       IsOverlapping_ = false;
00728   }
00729 
00730 #endif
00731   // compute the condition number each time Compute() is invoked.
00732   ComputeCondest_ = List_in.get("schwarz: compute condest", ComputeCondest_);
00733   // combine mode
00734   if( Teuchos::ParameterEntry *combineModeEntry = List_in.getEntryPtr("schwarz: combine mode") )
00735   {
00736     if( typeid(std::string) == combineModeEntry->getAny().type() )
00737     {
00738       std::string mode = List_in.get("schwarz: combine mode", "Add");
00739       if (mode == "Add")
00740         CombineMode_ = Add;
00741       else if (mode == "Zero")
00742         CombineMode_ = Zero;
00743       else if (mode == "Insert")
00744         CombineMode_ = Insert;
00745       else if (mode == "InsertAdd")
00746         CombineMode_ = InsertAdd;
00747       else if (mode == "Average")
00748         CombineMode_ = Average;
00749       else if (mode == "AbsMax")
00750         CombineMode_ = AbsMax;
00751       else
00752       {
00753         TEUCHOS_TEST_FOR_EXCEPTION(
00754           true,std::logic_error
00755           ,"Error, The (Epetra) combine mode of \""<<mode<<"\" is not valid!  Only the values"
00756           " \"Add\", \"Zero\", \"Insert\", \"InsertAdd\", \"Average\", and \"AbsMax\" are accepted!"
00757           );
00758       }
00759     }
00760     else if ( typeid(Epetra_CombineMode) == combineModeEntry->getAny().type() )
00761     {
00762       CombineMode_ = Teuchos::any_cast<Epetra_CombineMode>(combineModeEntry->getAny());
00763     }
00764     else
00765     {
00766       // Throw exception with good error message!
00767       Teuchos::getParameter<std::string>(List_in,"schwarz: combine mode");
00768     }
00769   }
00770   else
00771   {
00772     // Make the default be a string to be consistent with the valid parameters!
00773     List_in.get("schwarz: combine mode","Zero");
00774   }
00775   // type of reordering
00776   ReorderingType_ = List_in.get("schwarz: reordering type", ReorderingType_);
00777   if (ReorderingType_ == "none")
00778     UseReordering_ = false;
00779   else 
00780     UseReordering_ = true;
00781   // if true, filter singletons. NOTE: the filtered matrix can still have
00782   // singletons! A simple example: upper triangular matrix, if I remove
00783   // the lower node, I still get a matrix with a singleton! However, filter
00784   // singletons should help for PDE problems with Dirichlet BCs.
00785   FilterSingletons_ = List_in.get("schwarz: filter singletons", FilterSingletons_);
00786 
00787   // This copy may be needed by Amesos or other preconditioners.
00788   List_ = List_in;
00789 
00790   return(0);
00791 }
00792 
00793 //==============================================================================
00794 template<typename T>
00795 int Ifpack_AdditiveSchwarz<T>::Initialize()
00796 {
00797   IsInitialized_ = false;
00798   IsComputed_ = false; // values required
00799   Condest_ = -1.0; // zero-out condest
00800 
00801   if (Time_ == Teuchos::null)
00802     Time_ = Teuchos::rcp( new Epetra_Time(Comm()) );
00803 
00804   Time_->ResetStartTime();
00805 
00806   // compute the overlapping matrix if necessary
00807   if (IsOverlapping_) {
00808 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00809     if (NumMpiProcsPerSubdomain_ > 1) {
00810       OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_, SubdomainId_) );
00811     } else {
00812       OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_));
00813     }
00814 #else
00815 #     ifdef IFPACK_NODE_AWARE_CODE
00816     int myNodeID;
00817     try{ myNodeID = List_.get("ML node id",-1);}
00818     catch(...){fprintf(stderr,"pid %d: no such entry (returned %d)\n",Comm().MyPID(),myNodeID);}
00819 /*
00820       cout << "pid " << Comm().MyPID()
00821            << ": calling Ifpack_OverlappingRowMatrix with myNodeID = "
00822            << myNodeID << ", OverlapLevel_ = " << OverlapLevel_ << endl;
00823 */
00824     OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_, myNodeID) );
00825 #   else
00826     OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_) );
00827 #   endif
00828 #endif
00829 
00830     if (OverlappingMatrix_ == Teuchos::null) {
00831       IFPACK_CHK_ERR(-5);
00832     } 
00833   }
00834 
00835 # ifdef IFPACK_NODE_AWARE_CODE
00836 /*
00837   sleep(1);
00838   Comm().Barrier();
00839 */
00840 # endif
00841 
00842   IFPACK_CHK_ERR(Setup());
00843 
00844 # ifdef IFPACK_NODE_AWARE_CODE
00845 /*
00846   sleep(1);
00847   Comm().Barrier();
00848 */
00849 #endif
00850 
00851   if (Inverse_ == Teuchos::null)
00852     IFPACK_CHK_ERR(-5);
00853 
00854   if (LocalizedMatrix_ == Teuchos::null)
00855     IFPACK_CHK_ERR(-5);
00856 
00857   IFPACK_CHK_ERR(Inverse_->SetUseTranspose(UseTranspose()));
00858   IFPACK_CHK_ERR(Inverse_->SetParameters(List_));
00859   IFPACK_CHK_ERR(Inverse_->Initialize());
00860 
00861   // Label is for Aztec-like solvers
00862   Label_ = "Ifpack_AdditiveSchwarz, ";
00863   if (UseTranspose())
00864     Label_ += ", transp";
00865   Label_ += ", ov = " + Ifpack_toString(OverlapLevel_)
00866     + ", local solver = \n\t\t***** `" + string(Inverse_->Label()) + "'";
00867 
00868   IsInitialized_ = true;
00869   ++NumInitialize_;
00870   InitializeTime_ += Time_->ElapsedTime();
00871 
00872 #ifdef IFPACK_FLOPCOUNTERS
00873   // count flops by summing up all the InitializeFlops() in each
00874   // Inverse. Each Inverse() can only give its flops -- it acts on one
00875   // process only
00876   double partial = Inverse_->InitializeFlops();
00877   double total;
00878   Comm().SumAll(&partial, &total, 1);
00879   InitializeFlops_ += total;
00880 #endif
00881 
00882   return(0);
00883 }
00884 
00885 //==============================================================================
00886 template<typename T>
00887 int Ifpack_AdditiveSchwarz<T>::Compute()
00888 {
00889   if (IsInitialized() == false)
00890     IFPACK_CHK_ERR(Initialize());
00891 
00892   Time_->ResetStartTime();
00893   IsComputed_ = false;
00894   Condest_ = -1.0;
00895   
00896   IFPACK_CHK_ERR(Inverse_->Compute());
00897 
00898   IsComputed_ = true; // need this here for Condest(Ifpack_Cheap)
00899   ++NumCompute_;
00900   ComputeTime_ += Time_->ElapsedTime();
00901 
00902 #ifdef IFPACK_FLOPCOUNTERS
00903   // sum up flops
00904   double partial = Inverse_->ComputeFlops();
00905    double total;
00906   Comm().SumAll(&partial, &total, 1);
00907   ComputeFlops_ += total;
00908 #endif
00909 
00910   // reset the Label
00911   string R = "";
00912   if (UseReordering_)
00913     R = ReorderingType_ + " reord, ";
00914 
00915   if (ComputeCondest_)
00916     Condest(Ifpack_Cheap);
00917   
00918   // add Condest() to label
00919   Label_ = "Ifpack_AdditiveSchwarz, ov = " + Ifpack_toString(OverlapLevel_)
00920     + ", local solver = \n\t\t***** `" + string(Inverse_->Label()) + "'"
00921     + "\n\t\t***** " + R + "Condition number estimate = "
00922     + Ifpack_toString(Condest_);
00923 
00924   return(0);
00925 }
00926 
00927 //==============================================================================
00928 template<typename T>
00929 int Ifpack_AdditiveSchwarz<T>::SetUseTranspose(bool UseTranspose_in)
00930 {
00931   // store the flag -- it will be set in Initialize() if Inverse_ does not
00932   // exist.
00933   UseTranspose_ = UseTranspose_in;
00934 
00935   // If Inverse_ exists, pass it right now.
00936   if (Inverse_!=Teuchos::null)
00937     IFPACK_CHK_ERR(Inverse_->SetUseTranspose(UseTranspose_in));
00938   return(0);
00939 }
00940 
00941 //==============================================================================
00942 template<typename T>
00943 int Ifpack_AdditiveSchwarz<T>::
00944 Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00945 {
00946   IFPACK_CHK_ERR(Matrix_->Apply(X,Y));
00947   return(0);
00948 }
00949 
00950 //==============================================================================
00951 template<typename T>
00952 double Ifpack_AdditiveSchwarz<T>::NormInf() const
00953 {
00954   return(-1.0);
00955 }
00956 
00957 //==============================================================================
00958 template<typename T>
00959 const char * Ifpack_AdditiveSchwarz<T>::Label() const
00960 {
00961   return(Label_.c_str());
00962 }
00963 
00964 //==============================================================================
00965 template<typename T>
00966 bool Ifpack_AdditiveSchwarz<T>::UseTranspose() const
00967 {
00968   return(UseTranspose_);
00969 }
00970 
00971 //==============================================================================
00972 template<typename T>
00973 bool Ifpack_AdditiveSchwarz<T>::HasNormInf() const
00974 {
00975   return(false);
00976 }
00977 
00978 //==============================================================================
00979 template<typename T>
00980 const Epetra_Comm & Ifpack_AdditiveSchwarz<T>::Comm() const
00981 {
00982   return(Matrix_->Comm());
00983 }
00984 
00985 //==============================================================================
00986 template<typename T>
00987 const Epetra_Map & Ifpack_AdditiveSchwarz<T>::OperatorDomainMap() const
00988 {
00989   return(Matrix_->OperatorDomainMap());
00990 }
00991 
00992 //==============================================================================
00993 template<typename T>
00994 const Epetra_Map & Ifpack_AdditiveSchwarz<T>::OperatorRangeMap() const
00995 {
00996   return(Matrix_->OperatorRangeMap());
00997 }
00998 
00999 //==============================================================================
01000 template<typename T>
01001 int Ifpack_AdditiveSchwarz<T>::
01002 ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
01003 {
01004   // compute the preconditioner is not done by the user
01005   if (!IsComputed())
01006     IFPACK_CHK_ERR(-3);
01007 
01008   int NumVectors = X.NumVectors();
01009 
01010   if (NumVectors != Y.NumVectors())
01011     IFPACK_CHK_ERR(-2); // wrong input
01012 
01013   Time_->ResetStartTime();
01014 
01015   Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingX;
01016   Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingY;
01017   Teuchos::RefCountPtr<Epetra_MultiVector> Xtmp;
01018 
01019   // for flop count, see bottom of this function
01020 #ifdef IFPACK_FLOPCOUNTERS
01021   double pre_partial = Inverse_->ApplyInverseFlops();
01022   double pre_total;
01023   Comm().SumAll(&pre_partial, &pre_total, 1);
01024 #endif
01025 
01026   // process overlap, may need to create vectors and import data
01027   if (IsOverlapping()) {
01028 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
01029     if (OverlappingX == Teuchos::null) {
01030       OverlappingX = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(), X.NumVectors()) );
01031       if (OverlappingX == Teuchos::null) IFPACK_CHK_ERR(-5);
01032     } else assert(OverlappingX->NumVectors() == X.NumVectors());
01033     if (OverlappingY == Teuchos::null) {
01034       OverlappingY = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(), Y.NumVectors()) );
01035       if (OverlappingY == Teuchos::null) IFPACK_CHK_ERR(-5);
01036     } else assert(OverlappingY->NumVectors() == Y.NumVectors());
01037 #else
01038 #   ifdef IFPACK_NODE_AWARE_CODE
01039     if (OverlappingX == Teuchos::null) {
01040       OverlappingX = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
01041                                    X.NumVectors()) );
01042       if (OverlappingX == Teuchos::null) IFPACK_CHK_ERR(-5);
01043     } else assert(OverlappingX->NumVectors() == X.NumVectors());
01044     if (OverlappingY == Teuchos::null) {
01045       OverlappingY = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
01046                                      Y.NumVectors()) );
01047       if (OverlappingY == Teuchos::null) IFPACK_CHK_ERR(-5);
01048     } else assert(OverlappingY->NumVectors() == Y.NumVectors());
01049 #else
01050     OverlappingX = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
01051                             X.NumVectors()) );
01052     OverlappingY = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
01053                             Y.NumVectors()) );
01054     if (OverlappingY == Teuchos::null) IFPACK_CHK_ERR(-5);
01055 #   endif
01056 #endif
01057     OverlappingY->PutScalar(0.0);
01058     OverlappingX->PutScalar(0.0);
01059     IFPACK_CHK_ERR(OverlappingMatrix_->ImportMultiVector(X,*OverlappingX,Insert));
01060     // FIXME: this will not work with overlapping and non-zero starting
01061     // solutions. The same for other cases below.
01062     // IFPACK_CHK_ERR(OverlappingMatrix_->ImportMultiVector(Y,*OverlappingY,Insert));
01063   }
01064   else {
01065     Xtmp = Teuchos::rcp( new Epetra_MultiVector(X) );
01066     OverlappingX = Xtmp;
01067     OverlappingY = Teuchos::rcp( &Y, false );
01068   }
01069 
01070   if (FilterSingletons_) {
01071     // process singleton filter
01072     Epetra_MultiVector ReducedX(SingletonFilter_->Map(),NumVectors);
01073     Epetra_MultiVector ReducedY(SingletonFilter_->Map(),NumVectors);
01074     IFPACK_CHK_ERR(SingletonFilter_->SolveSingletons(*OverlappingX,*OverlappingY));
01075     IFPACK_CHK_ERR(SingletonFilter_->CreateReducedRHS(*OverlappingY,*OverlappingX,ReducedX));
01076 
01077     // process reordering
01078     if (!UseReordering_) {
01079       IFPACK_CHK_ERR(Inverse_->ApplyInverse(ReducedX,ReducedY));
01080     }
01081     else {
01082       Epetra_MultiVector ReorderedX(ReducedX);
01083       Epetra_MultiVector ReorderedY(ReducedY);
01084       IFPACK_CHK_ERR(Reordering_->P(ReducedX,ReorderedX));
01085       IFPACK_CHK_ERR(Inverse_->ApplyInverse(ReorderedX,ReorderedY));
01086       IFPACK_CHK_ERR(Reordering_->Pinv(ReorderedY,ReducedY));
01087     }
01088 
01089     // finish up with singletons
01090     IFPACK_CHK_ERR(SingletonFilter_->UpdateLHS(ReducedY,*OverlappingY));
01091   }
01092   else {
01093     // process reordering
01094     if (!UseReordering_) {
01095 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
01096         if (NumMpiProcsPerSubdomain_ > 1) {
01097           tempX_.reset(&((*RangeVectorReindexer_)(*OverlappingX)), false);
01098           tempY_.reset(&((*DomainVectorReindexer_)(*OverlappingY)), false);
01099           IFPACK_CHK_ERR(Inverse_->ApplyInverse(*tempX_,*tempY_));
01100         } else {
01101           IFPACK_CHK_ERR(Inverse_->ApplyInverse(*OverlappingX, *OverlappingY));
01102         }
01103 #else
01104       IFPACK_CHK_ERR(Inverse_->ApplyInverse(*OverlappingX,*OverlappingY));
01105 #endif
01106     }
01107     else {
01108       Epetra_MultiVector ReorderedX(*OverlappingX);
01109       Epetra_MultiVector ReorderedY(*OverlappingY);
01110       IFPACK_CHK_ERR(Reordering_->P(*OverlappingX,ReorderedX));
01111       IFPACK_CHK_ERR(Inverse_->ApplyInverse(ReorderedX,ReorderedY));
01112       IFPACK_CHK_ERR(Reordering_->Pinv(ReorderedY,*OverlappingY));
01113     }
01114   }
01115 
01116   if (IsOverlapping()) {
01117     IFPACK_CHK_ERR(OverlappingMatrix_->ExportMultiVector(*OverlappingY,Y,
01118                              CombineMode_));
01119   }
01120 
01121 #ifdef IFPACK_FLOPCOUNTERS
01122   // add flops. Note the we only have to add the newly counted
01123   // flops -- and each Inverse returns the cumulative sum
01124   double partial = Inverse_->ApplyInverseFlops();
01125   double total;
01126   Comm().SumAll(&partial, &total, 1);
01127   ApplyInverseFlops_ += total - pre_total;
01128 #endif
01129 
01130   // FIXME: right now I am skipping the overlap and singletons
01131   ++NumApplyInverse_;
01132   ApplyInverseTime_ += Time_->ElapsedTime();
01133 
01134   return(0);
01135  
01136 }
01137 
01138 //==============================================================================
01139 template<typename T>
01140 std::ostream& Ifpack_AdditiveSchwarz<T>::
01141 Print(std::ostream& os) const
01142 {
01143 #ifdef IFPACK_FLOPCOUNTERS
01144   double IF = InitializeFlops();
01145   double CF = ComputeFlops();
01146   double AF = ApplyInverseFlops();
01147 
01148   double IFT = 0.0, CFT = 0.0, AFT = 0.0;
01149   if (InitializeTime() != 0.0)
01150     IFT = IF / InitializeTime();
01151   if (ComputeTime() != 0.0)
01152     CFT = CF / ComputeTime();
01153   if (ApplyInverseTime() != 0.0)
01154     AFT = AF / ApplyInverseTime();
01155 #endif
01156 
01157   if (Matrix().Comm().MyPID())
01158     return(os);
01159 
01160   os << endl;
01161   os << "================================================================================" << endl;
01162   os << "Ifpack_AdditiveSchwarz, overlap level = " << OverlapLevel_ << endl;
01163   if (CombineMode_ == Insert)
01164     os << "Combine mode                          = Insert" << endl;
01165   else if (CombineMode_ == Add)
01166     os << "Combine mode                          = Add" << endl;
01167   else if (CombineMode_ == Zero)
01168     os << "Combine mode                          = Zero" << endl;
01169   else if (CombineMode_ == Average)
01170     os << "Combine mode                          = Average" << endl;
01171   else if (CombineMode_ == AbsMax)
01172     os << "Combine mode                          = AbsMax" << endl;
01173 
01174   os << "Condition number estimate             = " << Condest_ << endl;
01175   os << "Global number of rows                 = " << Matrix_->NumGlobalRows64() << endl;
01176 
01177 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
01178   os << endl;
01179   os << "================================================================================" << endl;
01180   os << "Subcommunicator stats" << endl;
01181   os << "Number of MPI processes in simulation: " << NumMpiProcs_ << endl;
01182   os << "Number of subdomains: " << NumSubdomains_ << endl;
01183   os << "Number of MPI processes per subdomain: " << NumMpiProcsPerSubdomain_ << endl;
01184 #endif
01185 
01186   os << endl;
01187   os << "Phase           # calls   Total Time (s)       Total MFlops     MFlops/s" << endl;
01188   os << "-----           -------   --------------       ------------     --------" << endl;
01189   os << "Initialize()    "   << std::setw(5) << NumInitialize()
01190      << "  " << std::setw(15) << InitializeTime() 
01191 #ifdef IFPACK_FLOPCOUNTERS
01192      << "  " << std::setw(15) << 1.0e-6 * IF 
01193      << "  " << std::setw(15) << 1.0e-6 * IFT
01194 #endif
01195      << endl;
01196   os << "Compute()       "   << std::setw(5) << NumCompute() 
01197      << "  " << std::setw(15) << ComputeTime()
01198 #ifdef IFPACK_FLOPCOUNTERS
01199      << "  " << std::setw(15) << 1.0e-6 * CF
01200      << "  " << std::setw(15) << 1.0e-6 * CFT
01201 #endif
01202      << endl;
01203   os << "ApplyInverse()  "   << std::setw(5) << NumApplyInverse() 
01204      << "  " << std::setw(15) << ApplyInverseTime()
01205 #ifdef IFPACK_FLOPCOUNTERS
01206      << "  " << std::setw(15) << 1.0e-6 * AF
01207      << "  " << std::setw(15) << 1.0e-6 * AFT
01208 #endif
01209      << endl;
01210   os << "================================================================================" << endl;
01211   os << endl;
01212 
01213   return(os);
01214 }
01215 
01216 #include "Ifpack_Condest.h"
01217 //==============================================================================
01218 template<typename T>
01219 double Ifpack_AdditiveSchwarz<T>::
01220 Condest(const Ifpack_CondestType CT, const int MaxIters, 
01221         const double Tol, Epetra_RowMatrix* Matrix_in)
01222 {
01223   if (!IsComputed()) // cannot compute right now
01224     return(-1.0);
01225 
01226   Condest_ = Ifpack_Condest(*this, CT, MaxIters, Tol, Matrix_in);
01227 
01228   return(Condest_);
01229 }
01230 
01231 #endif // IFPACK_ADDITIVESCHWARZ_H
 All Classes Files Functions Variables Enumerations Friends