IFPACK  Development
 All Classes Namespaces Files Functions Variables Enumerations Friends Pages
Ifpack_AdditiveSchwarz.h
1 /*
2 //@HEADER
3 // ***********************************************************************
4 //
5 // Ifpack: Object-Oriented Algebraic Preconditioner Package
6 // Copyright (2002) Sandia Corporation
7 //
8 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9 // license for use of this work by or on behalf of the U.S. Government.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 //@HEADER
42 */
43 
44 #ifndef IFPACK_ADDITIVESCHWARZ_H
45 #define IFPACK_ADDITIVESCHWARZ_H
46 
47 #if defined(Ifpack_SHOW_DEPRECATED_WARNINGS)
48 #ifdef __GNUC__
49 #warning "The Ifpack package is deprecated"
50 #endif
51 #endif
52 
53 #include "Ifpack_ConfigDefs.h"
54 #include "Ifpack_Preconditioner.h"
55 #include "Ifpack_ConfigDefs.h"
56 #include "Ifpack_Preconditioner.h"
57 #include "Ifpack_Reordering.h"
58 #include "Ifpack_RCMReordering.h"
59 #include "Ifpack_METISReordering.h"
60 #include "Ifpack_LocalFilter.h"
61 #include "Ifpack_NodeFilter.h"
62 #include "Ifpack_SingletonFilter.h"
63 #include "Ifpack_ReorderFilter.h"
64 #include "Ifpack_Utils.h"
65 #include "Ifpack_OverlappingRowMatrix.h"
66 #include "Epetra_CombineMode.h"
67 #include "Epetra_MultiVector.h"
68 #include "Epetra_Map.h"
69 #include "Epetra_Comm.h"
70 #include "Epetra_Time.h"
71 #include "Epetra_LinearProblem.h"
72 #include "Epetra_RowMatrix.h"
73 #include "Epetra_CrsMatrix.h"
74 #include "Teuchos_ParameterList.hpp"
75 #include "Teuchos_RefCountPtr.hpp"
76 
77 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
78 #include "Ifpack_SubdomainFilter.h"
79 #include "EpetraExt_Reindex_CrsMatrix.h"
80 #include "EpetraExt_Reindex_MultiVector.h"
81 #endif
82 #ifdef IFPACK_NODE_AWARE_CODE
83 #include "EpetraExt_OperatorOut.h"
84 #include "EpetraExt_RowMatrixOut.h"
85 #include "EpetraExt_BlockMapOut.h"
86 #endif
87 
88 #ifdef HAVE_IFPACK_AMESOS
89  #include "Ifpack_AMDReordering.h"
90 #endif
91 
92 
94 
147 template<typename T>
149 
150 public:
151 
153 
166  int OverlapLevel_in = 0);
167 
171 
173 
175 
184  virtual int SetUseTranspose(bool UseTranspose_in);
186 
188 
190 
200  virtual int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
201 
203 
214  virtual int ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
215 
217  virtual double NormInf() const;
219 
221 
223  virtual const char * Label() const;
224 
226  virtual bool UseTranspose() const;
227 
229  virtual bool HasNormInf() const;
230 
232  virtual const Epetra_Comm & Comm() const;
233 
235  virtual const Epetra_Map & OperatorDomainMap() const;
236 
238  virtual const Epetra_Map & OperatorRangeMap() const;
240 
242  virtual bool IsInitialized() const
243  {
244  return(IsInitialized_);
245  }
246 
248  virtual bool IsComputed() const
249  {
250  return(IsComputed_);
251  }
252 
254 
273  virtual int SetParameters(Teuchos::ParameterList& List);
274 
275  // @}
276 
277  // @{ Query methods
278 
280  virtual int Initialize();
281 
283  virtual int Compute();
284 
286  virtual double Condest(const Ifpack_CondestType CT = Ifpack_Cheap,
287  const int MaxIters = 1550,
288  const double Tol = 1e-9,
289  Epetra_RowMatrix* Matrix_in = 0);
290 
292  virtual double Condest() const
293  {
294  return(Condest_);
295  }
296 
298  virtual const Epetra_RowMatrix& Matrix() const
299  {
300  return(*Matrix_);
301  }
302 
304  virtual bool IsOverlapping() const
305  {
306  return(IsOverlapping_);
307  }
308 
310  virtual std::ostream& Print(std::ostream&) const;
311 
312  virtual const T* Inverse() const
313  {
314  return(&*Inverse_);
315  }
316 
318  virtual int NumInitialize() const
319  {
320  return(NumInitialize_);
321  }
322 
324  virtual int NumCompute() const
325  {
326  return(NumCompute_);
327  }
328 
330  virtual int NumApplyInverse() const
331  {
332  return(NumApplyInverse_);
333  }
334 
336  virtual double InitializeTime() const
337  {
338  return(InitializeTime_);
339  }
340 
342  virtual double ComputeTime() const
343  {
344  return(ComputeTime_);
345  }
346 
348  virtual double ApplyInverseTime() const
349  {
350  return(ApplyInverseTime_);
351  }
352 
354  virtual double InitializeFlops() const
355  {
356  return(InitializeFlops_);
357  }
358 
359  virtual double ComputeFlops() const
360  {
361  return(ComputeFlops_);
362  }
363 
364  virtual double ApplyInverseFlops() const
365  {
366  return(ApplyInverseFlops_);
367  }
368 
370  virtual int OverlapLevel() const
371  {
372  return(OverlapLevel_);
373  }
374 
376  virtual const Teuchos::ParameterList& List() const
377  {
378  return(List_);
379  }
380 
381 protected:
382 
383  // @}
384 
385  // @{ Internal merhods.
386 
389  { }
390 
392  int Setup();
393 
394  // @}
395 
396  // @{ Internal data.
397 
399  Teuchos::RefCountPtr<const Epetra_RowMatrix> Matrix_;
401  Teuchos::RefCountPtr<Ifpack_OverlappingRowMatrix> OverlappingMatrix_;
403 /*
404  //TODO if we choose to expose the node aware code, i.e., no ifdefs,
405  //TODO then we should switch to this definition.
406  Teuchos::RefCountPtr<Epetra_RowMatrix> LocalizedMatrix_;
407 */
408 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
409  Teuchos::RCP<Epetra_RowMatrix> LocalizedMatrix_;
412  Teuchos::RCP<Epetra_CrsMatrix> SubdomainCrsMatrix_;
414  Teuchos::RCP<Epetra_CrsMatrix> ReindexedCrsMatrix_;
415 
416  // The following data members are needed when doing ApplyInverse
417  // with an Ifpack_SubdomainFilter local matrix
418  Teuchos::RCP<Epetra_Map> tempMap_;
419  Teuchos::RCP<Epetra_Map> tempDomainMap_;
420  Teuchos::RCP<Epetra_Map> tempRangeMap_;
421  Teuchos::RCP<EpetraExt::CrsMatrix_Reindex> SubdomainMatrixReindexer_;
422  Teuchos::RCP<EpetraExt::MultiVector_Reindex> DomainVectorReindexer_;
423  Teuchos::RCP<EpetraExt::MultiVector_Reindex> RangeVectorReindexer_;
424  mutable Teuchos::RCP<Epetra_MultiVector> tempX_;
425  mutable Teuchos::RCP<Epetra_MultiVector> tempY_;
426 #else
427 # ifdef IFPACK_NODE_AWARE_CODE
428  Teuchos::RefCountPtr<Ifpack_NodeFilter> LocalizedMatrix_;
429 # else
430  Teuchos::RefCountPtr<Ifpack_LocalFilter> LocalizedMatrix_;
431 # endif
432 #endif
433 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
434  // Some data members used for determining the subdomain id (color)
436  int MpiRank_;
438  int NumMpiProcs_;
440  int NumMpiProcsPerSubdomain_;
442  int NumSubdomains_;
444  int SubdomainId_;
445 #endif
446  std::string Label_;
459  Teuchos::ParameterList List_;
463  double Condest_;
469  std::string ReorderingType_;
471  Teuchos::RefCountPtr<Ifpack_Reordering> Reordering_;
473  Teuchos::RefCountPtr<Ifpack_ReorderFilter> ReorderedLocalizedMatrix_;
477  Teuchos::RefCountPtr<Ifpack_SingletonFilter> SingletonFilter_;
483  mutable int NumApplyInverse_;
487  double ComputeTime_;
489  mutable double ApplyInverseTime_;
495  mutable double ApplyInverseFlops_;
497  Teuchos::RefCountPtr<Epetra_Time> Time_;
499  Teuchos::RefCountPtr<T> Inverse_;
501 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
502  mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingX;
503  mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingY;
504 #endif
505 # ifdef IFPACK_NODE_AWARE_CODE
506  mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingX;
507  mutable Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingY;
508 #endif
509 
510 }; // class Ifpack_AdditiveSchwarz<T>
511 
512 //==============================================================================
513 template<typename T>
516  int OverlapLevel_in) :
517 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
518  MpiRank_(0),
519  NumMpiProcs_(1),
520  NumMpiProcsPerSubdomain_(1),
521  NumSubdomains_(1),
522  SubdomainId_(0),
523 #endif
524  IsInitialized_(false),
525  IsComputed_(false),
526  UseTranspose_(false),
527  IsOverlapping_(false),
528  OverlapLevel_(OverlapLevel_in),
529  CombineMode_(Zero),
530  Condest_(-1.0),
531  ComputeCondest_(true),
532  UseReordering_(false),
533  ReorderingType_("none"),
534  FilterSingletons_(false),
535  NumInitialize_(0),
536  NumCompute_(0),
537  NumApplyInverse_(0),
538  InitializeTime_(0.0),
539  ComputeTime_(0.0),
540  ApplyInverseTime_(0.0),
541  InitializeFlops_(0.0),
542  ComputeFlops_(0.0),
543  ApplyInverseFlops_(0.0)
544 {
545  // Construct a reference-counted pointer with the input matrix, don't manage the memory.
546  Matrix_ = Teuchos::rcp( Matrix_in, false );
547 
548  if (Matrix_->Comm().NumProc() == 1)
549  OverlapLevel_ = 0;
550 
551  if ((OverlapLevel_ != 0) && (Matrix_->Comm().NumProc() > 1))
552  IsOverlapping_ = true;
553  // Sets parameters to default values
554  Teuchos::ParameterList List_in;
555  SetParameters(List_in);
556 }
557 
558 #ifdef IFPACK_NODE_AWARE_CODE
559 extern int ML_NODE_ID;
560 #endif
561 
562 //==============================================================================
563 template<typename T>
565 {
566  using std::cerr;
567  using std::endl;
568 
569  Epetra_RowMatrix* MatrixPtr;
570 
571 #ifndef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
572 # ifdef IFPACK_NODE_AWARE_CODE
573 /*
574  sleep(3);
575  if (Comm().MyPID() == 0) cout << "Printing out ovArowmap" << endl;
576  Comm().Barrier();
577 
578  EpetraExt::BlockMapToMatrixMarketFile("ovArowmap",OverlappingMatrix_->RowMatrixRowMap());
579  if (Comm().MyPID() == 0) cout << "Printing out ovAcolmap" << endl;
580  Comm().Barrier();
581  EpetraExt::BlockMapToMatrixMarketFile("ovAcolmap",OverlappingMatrix_->RowMatrixColMap());
582  Comm().Barrier();
583 */
584 /*
585  EpetraExt::RowMatrixToMatlabFile("ovA",*OverlappingMatrix_);
586  fprintf(stderr,"p %d n %d matrix file done\n",Comm().MyPID(),ML_NODE_ID);
587  Comm().Barrier();
588 */
589  int nodeID;
590  try{ nodeID = List_.get("ML node id",0);}
591  catch(...){fprintf(stderr,"%s","Ifpack_AdditiveSchwarz<T>::Setup(): no parameter \"ML node id\"\n\n");
592  std::cout << List_ << std::endl;}
593 # endif
594 #endif
595 
596  try{
597  if (OverlappingMatrix_ != Teuchos::null)
598  {
599 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
600  if (NumMpiProcsPerSubdomain_ > 1) {
601  LocalizedMatrix_ = Teuchos::rcp(new Ifpack_SubdomainFilter(OverlappingMatrix_, SubdomainId_));
602  } else {
603  LocalizedMatrix_ = Teuchos::rcp(new Ifpack_LocalFilter(OverlappingMatrix_));
604  }
605 #else
606 # ifdef IFPACK_NODE_AWARE_CODE
607  Ifpack_NodeFilter *tt = new Ifpack_NodeFilter(OverlappingMatrix_,nodeID); //FIXME
608  LocalizedMatrix_ = Teuchos::rcp(tt);
609  //LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(OverlappingMatrix_) );
610 # else
611  LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(OverlappingMatrix_) );
612 # endif
613 #endif
614  }
615  else
616  {
617 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
618 
619  if (NumMpiProcsPerSubdomain_ > 1) {
620  LocalizedMatrix_ = Teuchos::rcp(new Ifpack_SubdomainFilter(Matrix_, SubdomainId_));
621  } else {
622  LocalizedMatrix_ = Teuchos::rcp(new Ifpack_LocalFilter(Matrix_));
623  }
624 #else
625 # ifdef IFPACK_NODE_AWARE_CODE
626  Ifpack_NodeFilter *tt = new Ifpack_NodeFilter(Matrix_,nodeID); //FIXME
627  LocalizedMatrix_ = Teuchos::rcp(tt);
628  //LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(Matrix_) );
629 # else
630  LocalizedMatrix_ = Teuchos::rcp( new Ifpack_LocalFilter(Matrix_) );
631 # endif
632 #endif
633  }
634  }
635  catch(...) {
636  fprintf(stderr,"%s","AdditiveSchwarz Setup: problem creating local filter matrix.\n");
637  }
638 
639  if (LocalizedMatrix_ == Teuchos::null)
640  IFPACK_CHK_ERR(-5);
641 
642  // users may want to skip singleton check
643  if (FilterSingletons_) {
644  SingletonFilter_ = Teuchos::rcp( new Ifpack_SingletonFilter(LocalizedMatrix_) );
645  MatrixPtr = &*SingletonFilter_;
646  }
647  else
648  MatrixPtr = &*LocalizedMatrix_;
649 
650  if (UseReordering_) {
651 
652  // create reordering and compute it
653  if (ReorderingType_ == "rcm")
654  Reordering_ = Teuchos::rcp( new Ifpack_RCMReordering() );
655  else if (ReorderingType_ == "metis")
656  Reordering_ = Teuchos::rcp( new Ifpack_METISReordering() );
657 #ifdef HAVE_IFPACK_AMESOS
658  else if (ReorderingType_ == "amd" )
659  Reordering_ = Teuchos::rcp( new Ifpack_AMDReordering() );
660 #endif
661  else {
662  cerr << "reordering type not correct (" << ReorderingType_ << ")" << endl;
663  exit(EXIT_FAILURE);
664  }
665  if (Reordering_ == Teuchos::null) IFPACK_CHK_ERR(-5);
666 
667  IFPACK_CHK_ERR(Reordering_->SetParameters(List_));
668  IFPACK_CHK_ERR(Reordering_->Compute(*MatrixPtr));
669 
670  // now create reordered localized matrix
671  ReorderedLocalizedMatrix_ =
672  Teuchos::rcp( new Ifpack_ReorderFilter(Teuchos::rcp( MatrixPtr, false ), Reordering_) );
673 
674  if (ReorderedLocalizedMatrix_ == Teuchos::null) IFPACK_CHK_ERR(-5);
675 
676  MatrixPtr = &*ReorderedLocalizedMatrix_;
677  }
678 
679 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
680  // The subdomain matrix needs to be reindexed by Amesos so we need to make a CrsMatrix
681  // and then reindex it with EpetraExt.
682  // The reindexing is done here because this feature is only implemented in Amesos_Klu,
683  // and it is desired to have reindexing with other direct solvers in the Amesos package
684 
685  SubdomainCrsMatrix_.reset(new Epetra_CrsMatrix(Copy, MatrixPtr->RowMatrixRowMap(), -1));
686  Teuchos::RCP<Epetra_Import> tempImporter = Teuchos::rcp(new Epetra_Import(SubdomainCrsMatrix_->Map(), MatrixPtr->Map()));
687  SubdomainCrsMatrix_->Import(*MatrixPtr, *tempImporter, Insert);
688  SubdomainCrsMatrix_->FillComplete();
689 
690  if (NumMpiProcsPerSubdomain_ > 1) {
691  tempMap_.reset(new Epetra_Map(SubdomainCrsMatrix_->RowMap().NumGlobalElements(),
692  SubdomainCrsMatrix_->RowMap().NumMyElements(),
693  0, SubdomainCrsMatrix_->Comm()));
694  tempRangeMap_.reset(new Epetra_Map(SubdomainCrsMatrix_->OperatorRangeMap().NumGlobalElements(),
695  SubdomainCrsMatrix_->OperatorRangeMap().NumMyElements(),
696  0, SubdomainCrsMatrix_->Comm()));
697  tempDomainMap_.reset(new Epetra_Map(SubdomainCrsMatrix_->OperatorDomainMap().NumGlobalElements(),
698  SubdomainCrsMatrix_->OperatorDomainMap().NumMyElements(),
699  0, SubdomainCrsMatrix_->Comm()));
700 
701  SubdomainMatrixReindexer_.reset(new EpetraExt::CrsMatrix_Reindex(*tempMap_));
702  DomainVectorReindexer_.reset(new EpetraExt::MultiVector_Reindex(*tempDomainMap_));
703  RangeVectorReindexer_.reset(new EpetraExt::MultiVector_Reindex(*tempRangeMap_));
704 
705  ReindexedCrsMatrix_.reset(&((*SubdomainMatrixReindexer_)(*SubdomainCrsMatrix_)), false);
706 
707  MatrixPtr = &*ReindexedCrsMatrix_;
708 
709  Inverse_ = Teuchos::rcp( new T(&*ReindexedCrsMatrix_) );
710  } else {
711  Inverse_ = Teuchos::rcp( new T(&*SubdomainCrsMatrix_) );
712  }
713 #else
714  Inverse_ = Teuchos::rcp( new T(MatrixPtr) );
715 #endif
716 
717  if (Inverse_ == Teuchos::null)
718  IFPACK_CHK_ERR(-5);
719 
720  return(0);
721 }
722 
723 //==============================================================================
724 template<typename T>
725 int Ifpack_AdditiveSchwarz<T>::SetParameters(Teuchos::ParameterList& List_in)
726 {
727 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
728  MpiRank_ = Matrix_->Comm().MyPID();
729  NumMpiProcs_ = Matrix_->Comm().NumProc();
730  NumMpiProcsPerSubdomain_ = List_in.get("subdomain: number-of-processors", 1);
731  NumSubdomains_ = NumMpiProcs_ / NumMpiProcsPerSubdomain_;
732  SubdomainId_ = MpiRank_ / NumMpiProcsPerSubdomain_;
733 
734  if (NumSubdomains_ == 1) {
735  IsOverlapping_ = false;
736  }
737 
738 #endif
739  // compute the condition number each time Compute() is invoked.
740  ComputeCondest_ = List_in.get("schwarz: compute condest", ComputeCondest_);
741  // combine mode
742  if( Teuchos::ParameterEntry *combineModeEntry = List_in.getEntryPtr("schwarz: combine mode") )
743  {
744  if( typeid(std::string) == combineModeEntry->getAny().type() )
745  {
746  std::string mode = List_in.get("schwarz: combine mode", "Add");
747  if (mode == "Add")
748  CombineMode_ = Add;
749  else if (mode == "Zero")
750  CombineMode_ = Zero;
751  else if (mode == "Insert")
752  CombineMode_ = Insert;
753  else if (mode == "InsertAdd")
754  CombineMode_ = InsertAdd;
755  else if (mode == "Average")
756  CombineMode_ = Average;
757  else if (mode == "AbsMax")
758  CombineMode_ = AbsMax;
759  else
760  {
761  TEUCHOS_TEST_FOR_EXCEPTION(
762  true,std::logic_error
763  ,"Error, The (Epetra) combine mode of \""<<mode<<"\" is not valid! Only the values"
764  " \"Add\", \"Zero\", \"Insert\", \"InsertAdd\", \"Average\", and \"AbsMax\" are accepted!"
765  );
766  }
767  }
768  else if ( typeid(Epetra_CombineMode) == combineModeEntry->getAny().type() )
769  {
770  CombineMode_ = Teuchos::any_cast<Epetra_CombineMode>(combineModeEntry->getAny());
771  }
772  else
773  {
774  // Throw exception with good error message!
775  Teuchos::getParameter<std::string>(List_in,"schwarz: combine mode");
776  }
777  }
778  else
779  {
780  // Make the default be a std::string to be consistent with the valid parameters!
781  List_in.get("schwarz: combine mode","Zero");
782  }
783  // type of reordering
784  ReorderingType_ = List_in.get("schwarz: reordering type", ReorderingType_);
785  if (ReorderingType_ == "none")
786  UseReordering_ = false;
787  else
788  UseReordering_ = true;
789  // if true, filter singletons. NOTE: the filtered matrix can still have
790  // singletons! A simple example: upper triangular matrix, if I remove
791  // the lower node, I still get a matrix with a singleton! However, filter
792  // singletons should help for PDE problems with Dirichlet BCs.
793  FilterSingletons_ = List_in.get("schwarz: filter singletons", FilterSingletons_);
794 
795  // This copy may be needed by Amesos or other preconditioners.
796  List_ = List_in;
797 
798  return(0);
799 }
800 
801 //==============================================================================
802 template<typename T>
804 {
805  IsInitialized_ = false;
806  IsComputed_ = false; // values required
807  Condest_ = -1.0; // zero-out condest
808 
809  if (Time_ == Teuchos::null)
810  Time_ = Teuchos::rcp( new Epetra_Time(Comm()) );
811 
812  Time_->ResetStartTime();
813 
814  // compute the overlapping matrix if necessary
815  if (IsOverlapping_) {
816 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
817  if (NumMpiProcsPerSubdomain_ > 1) {
818  OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_, SubdomainId_) );
819  } else {
820  OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_));
821  }
822 #else
823 # ifdef IFPACK_NODE_AWARE_CODE
824  int myNodeID;
825  try{ myNodeID = List_.get("ML node id",-1);}
826  catch(...){fprintf(stderr,"pid %d: no such entry (returned %d)\n",Comm().MyPID(),myNodeID);}
827 /*
828  cout << "pid " << Comm().MyPID()
829  << ": calling Ifpack_OverlappingRowMatrix with myNodeID = "
830  << myNodeID << ", OverlapLevel_ = " << OverlapLevel_ << endl;
831 */
832  OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_, myNodeID) );
833 # else
834  OverlappingMatrix_ = Teuchos::rcp( new Ifpack_OverlappingRowMatrix(Matrix_, OverlapLevel_) );
835 # endif
836 #endif
837 
838  if (OverlappingMatrix_ == Teuchos::null) {
839  IFPACK_CHK_ERR(-5);
840  }
841  }
842 
843 # ifdef IFPACK_NODE_AWARE_CODE
844 /*
845  sleep(1);
846  Comm().Barrier();
847 */
848 # endif
849 
850  IFPACK_CHK_ERR(Setup());
851 
852 # ifdef IFPACK_NODE_AWARE_CODE
853 /*
854  sleep(1);
855  Comm().Barrier();
856 */
857 #endif
858 
859  if (Inverse_ == Teuchos::null)
860  IFPACK_CHK_ERR(-5);
861 
862  if (LocalizedMatrix_ == Teuchos::null)
863  IFPACK_CHK_ERR(-5);
864 
865  IFPACK_CHK_ERR(Inverse_->SetUseTranspose(UseTranspose()));
866  IFPACK_CHK_ERR(Inverse_->SetParameters(List_));
867  IFPACK_CHK_GLOBAL_ERR(Inverse_->Initialize());
868 
869  // Label is for Aztec-like solvers
870  Label_ = "Ifpack_AdditiveSchwarz, ";
871  if (UseTranspose())
872  Label_ += ", transp";
873  Label_ += ", ov = " + Ifpack_toString(OverlapLevel_)
874  + ", local solver = \n\t\t***** `" + std::string(Inverse_->Label()) + "'";
875 
876  IsInitialized_ = true;
877  ++NumInitialize_;
878  InitializeTime_ += Time_->ElapsedTime();
879 
880 #ifdef IFPACK_FLOPCOUNTERS
881  // count flops by summing up all the InitializeFlops() in each
882  // Inverse. Each Inverse() can only give its flops -- it acts on one
883  // process only
884  double partial = Inverse_->InitializeFlops();
885  double total;
886  Comm().SumAll(&partial, &total, 1);
887  InitializeFlops_ += total;
888 #endif
889 
890  return(0);
891 }
892 
893 //==============================================================================
894 template<typename T>
896 {
897  if (IsInitialized() == false)
898  IFPACK_CHK_GLOBAL_ERR(Initialize());
899 
900  Time_->ResetStartTime();
901  IsComputed_ = false;
902  Condest_ = -1.0;
903 
904  IFPACK_CHK_GLOBAL_ERR(Inverse_->Compute());
905 
906  IsComputed_ = true; // need this here for Condest(Ifpack_Cheap)
907  ++NumCompute_;
908  ComputeTime_ += Time_->ElapsedTime();
909 
910 #ifdef IFPACK_FLOPCOUNTERS
911  // sum up flops
912  double partial = Inverse_->ComputeFlops();
913  double total;
914  Comm().SumAll(&partial, &total, 1);
915  ComputeFlops_ += total;
916 #endif
917 
918  // reset the Label
919  std::string R = "";
920  if (UseReordering_)
921  R = ReorderingType_ + " reord, ";
922 
923  if (ComputeCondest_)
924  Condest(Ifpack_Cheap);
925 
926  // add Condest() to label
927  Label_ = "Ifpack_AdditiveSchwarz, ov = " + Ifpack_toString(OverlapLevel_)
928  + ", local solver = \n\t\t***** `" + std::string(Inverse_->Label()) + "'"
929  + "\n\t\t***** " + R + "Condition number estimate = "
930  + Ifpack_toString(Condest_);
931 
932  return(0);
933 }
934 
935 //==============================================================================
936 template<typename T>
938 {
939  // store the flag -- it will be set in Initialize() if Inverse_ does not
940  // exist.
941  UseTranspose_ = UseTranspose_in;
942 
943  // If Inverse_ exists, pass it right now.
944  if (Inverse_!=Teuchos::null)
945  IFPACK_CHK_ERR(Inverse_->SetUseTranspose(UseTranspose_in));
946  return(0);
947 }
948 
949 //==============================================================================
950 template<typename T>
953 {
954  IFPACK_CHK_ERR(Matrix_->Apply(X,Y));
955  return(0);
956 }
957 
958 //==============================================================================
959 template<typename T>
961 {
962  return(-1.0);
963 }
964 
965 //==============================================================================
966 template<typename T>
968 {
969  return(Label_.c_str());
970 }
971 
972 //==============================================================================
973 template<typename T>
975 {
976  return(UseTranspose_);
977 }
978 
979 //==============================================================================
980 template<typename T>
982 {
983  return(false);
984 }
985 
986 //==============================================================================
987 template<typename T>
989 {
990  return(Matrix_->Comm());
991 }
992 
993 //==============================================================================
994 template<typename T>
996 {
997  return(Matrix_->OperatorDomainMap());
998 }
999 
1000 //==============================================================================
1001 template<typename T>
1003 {
1004  return(Matrix_->OperatorRangeMap());
1005 }
1006 
1007 //==============================================================================
1008 template<typename T>
1011 {
1012  // compute the preconditioner is not done by the user
1013  if (!IsComputed())
1014  IFPACK_CHK_ERR(-3);
1015 
1016  int NumVectors = X.NumVectors();
1017 
1018  if (NumVectors != Y.NumVectors())
1019  IFPACK_CHK_ERR(-2); // wrong input
1020 
1021  Time_->ResetStartTime();
1022 
1023  Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingX;
1024  Teuchos::RefCountPtr<Epetra_MultiVector> OverlappingY;
1025  Teuchos::RefCountPtr<Epetra_MultiVector> Xtmp;
1026 
1027  // for flop count, see bottom of this function
1028 #ifdef IFPACK_FLOPCOUNTERS
1029  double pre_partial = Inverse_->ApplyInverseFlops();
1030  double pre_total;
1031  Comm().SumAll(&pre_partial, &pre_total, 1);
1032 #endif
1033 
1034  // process overlap, may need to create vectors and import data
1035  if (IsOverlapping()) {
1036 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
1037  if (OverlappingX == Teuchos::null) {
1038  OverlappingX = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(), X.NumVectors()) );
1039  if (OverlappingX == Teuchos::null) IFPACK_CHK_ERR(-5);
1040  } else assert(OverlappingX->NumVectors() == X.NumVectors());
1041  if (OverlappingY == Teuchos::null) {
1042  OverlappingY = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(), Y.NumVectors()) );
1043  if (OverlappingY == Teuchos::null) IFPACK_CHK_ERR(-5);
1044  } else assert(OverlappingY->NumVectors() == Y.NumVectors());
1045 #else
1046 # ifdef IFPACK_NODE_AWARE_CODE
1047  if (OverlappingX == Teuchos::null) {
1048  OverlappingX = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
1049  X.NumVectors()) );
1050  if (OverlappingX == Teuchos::null) IFPACK_CHK_ERR(-5);
1051  } else assert(OverlappingX->NumVectors() == X.NumVectors());
1052  if (OverlappingY == Teuchos::null) {
1053  OverlappingY = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
1054  Y.NumVectors()) );
1055  if (OverlappingY == Teuchos::null) IFPACK_CHK_ERR(-5);
1056  } else assert(OverlappingY->NumVectors() == Y.NumVectors());
1057 #else
1058  OverlappingX = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
1059  X.NumVectors()) );
1060  OverlappingY = Teuchos::rcp( new Epetra_MultiVector(OverlappingMatrix_->RowMatrixRowMap(),
1061  Y.NumVectors()) );
1062  if (OverlappingY == Teuchos::null) IFPACK_CHK_ERR(-5);
1063 # endif
1064 #endif
1065  OverlappingY->PutScalar(0.0);
1066  OverlappingX->PutScalar(0.0);
1067  IFPACK_CHK_ERR(OverlappingMatrix_->ImportMultiVector(X,*OverlappingX,Insert));
1068  // FIXME: this will not work with overlapping and non-zero starting
1069  // solutions. The same for other cases below.
1070  // IFPACK_CHK_ERR(OverlappingMatrix_->ImportMultiVector(Y,*OverlappingY,Insert));
1071  }
1072  else {
1073  Xtmp = Teuchos::rcp( new Epetra_MultiVector(X) );
1074  OverlappingX = Xtmp;
1075  OverlappingY = Teuchos::rcp( &Y, false );
1076  }
1077 
1078  if (FilterSingletons_) {
1079  // process singleton filter
1080  Epetra_MultiVector ReducedX(SingletonFilter_->Map(),NumVectors);
1081  Epetra_MultiVector ReducedY(SingletonFilter_->Map(),NumVectors);
1082  IFPACK_CHK_ERR(SingletonFilter_->SolveSingletons(*OverlappingX,*OverlappingY));
1083  IFPACK_CHK_ERR(SingletonFilter_->CreateReducedRHS(*OverlappingY,*OverlappingX,ReducedX));
1084 
1085  // process reordering
1086  if (!UseReordering_) {
1087  IFPACK_CHK_ERR(Inverse_->ApplyInverse(ReducedX,ReducedY));
1088  }
1089  else {
1090  Epetra_MultiVector ReorderedX(ReducedX);
1091  Epetra_MultiVector ReorderedY(ReducedY);
1092  IFPACK_CHK_ERR(Reordering_->P(ReducedX,ReorderedX));
1093  IFPACK_CHK_ERR(Inverse_->ApplyInverse(ReorderedX,ReorderedY));
1094  IFPACK_CHK_ERR(Reordering_->Pinv(ReorderedY,ReducedY));
1095  }
1096 
1097  // finish up with singletons
1098  IFPACK_CHK_ERR(SingletonFilter_->UpdateLHS(ReducedY,*OverlappingY));
1099  }
1100  else {
1101  // process reordering
1102  if (!UseReordering_) {
1103 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
1104  if (NumMpiProcsPerSubdomain_ > 1) {
1105  tempX_.reset(&((*RangeVectorReindexer_)(*OverlappingX)), false);
1106  tempY_.reset(&((*DomainVectorReindexer_)(*OverlappingY)), false);
1107  IFPACK_CHK_ERR(Inverse_->ApplyInverse(*tempX_,*tempY_));
1108  } else {
1109  IFPACK_CHK_ERR(Inverse_->ApplyInverse(*OverlappingX, *OverlappingY));
1110  }
1111 #else
1112  IFPACK_CHK_ERR(Inverse_->ApplyInverse(*OverlappingX,*OverlappingY));
1113 #endif
1114  }
1115  else {
1116  Epetra_MultiVector ReorderedX(*OverlappingX);
1117  Epetra_MultiVector ReorderedY(*OverlappingY);
1118  IFPACK_CHK_ERR(Reordering_->P(*OverlappingX,ReorderedX));
1119  IFPACK_CHK_ERR(Inverse_->ApplyInverse(ReorderedX,ReorderedY));
1120  IFPACK_CHK_ERR(Reordering_->Pinv(ReorderedY,*OverlappingY));
1121  }
1122  }
1123 
1124  if (IsOverlapping()) {
1125  IFPACK_CHK_ERR(OverlappingMatrix_->ExportMultiVector(*OverlappingY,Y,
1126  CombineMode_));
1127  }
1128 
1129 #ifdef IFPACK_FLOPCOUNTERS
1130  // add flops. Note the we only have to add the newly counted
1131  // flops -- and each Inverse returns the cumulative sum
1132  double partial = Inverse_->ApplyInverseFlops();
1133  double total;
1134  Comm().SumAll(&partial, &total, 1);
1135  ApplyInverseFlops_ += total - pre_total;
1136 #endif
1137 
1138  // FIXME: right now I am skipping the overlap and singletons
1139  ++NumApplyInverse_;
1140  ApplyInverseTime_ += Time_->ElapsedTime();
1141 
1142  return(0);
1143 
1144 }
1145 
1146 //==============================================================================
1147 template<typename T>
1148 std::ostream& Ifpack_AdditiveSchwarz<T>::
1149 Print(std::ostream& os) const
1150 {
1151  using std::endl;
1152 
1153 #ifdef IFPACK_FLOPCOUNTERS
1154  double IF = InitializeFlops();
1155  double CF = ComputeFlops();
1156  double AF = ApplyInverseFlops();
1157 
1158  double IFT = 0.0, CFT = 0.0, AFT = 0.0;
1159  if (InitializeTime() != 0.0)
1160  IFT = IF / InitializeTime();
1161  if (ComputeTime() != 0.0)
1162  CFT = CF / ComputeTime();
1163  if (ApplyInverseTime() != 0.0)
1164  AFT = AF / ApplyInverseTime();
1165 #endif
1166 
1167  if (Matrix().Comm().MyPID())
1168  return(os);
1169 
1170  os << endl;
1171  os << "================================================================================" << endl;
1172  os << "Ifpack_AdditiveSchwarz, overlap level = " << OverlapLevel_ << endl;
1173  if (CombineMode_ == Insert)
1174  os << "Combine mode = Insert" << endl;
1175  else if (CombineMode_ == Add)
1176  os << "Combine mode = Add" << endl;
1177  else if (CombineMode_ == Zero)
1178  os << "Combine mode = Zero" << endl;
1179  else if (CombineMode_ == Average)
1180  os << "Combine mode = Average" << endl;
1181  else if (CombineMode_ == AbsMax)
1182  os << "Combine mode = AbsMax" << endl;
1183 
1184  os << "Condition number estimate = " << Condest_ << endl;
1185  os << "Global number of rows = " << Matrix_->NumGlobalRows64() << endl;
1186 
1187 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
1188  os << endl;
1189  os << "================================================================================" << endl;
1190  os << "Subcommunicator stats" << endl;
1191  os << "Number of MPI processes in simulation: " << NumMpiProcs_ << endl;
1192  os << "Number of subdomains: " << NumSubdomains_ << endl;
1193  os << "Number of MPI processes per subdomain: " << NumMpiProcsPerSubdomain_ << endl;
1194 #endif
1195 
1196  os << endl;
1197  os << "Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
1198  os << "----- ------- -------------- ------------ --------" << endl;
1199  os << "Initialize() " << std::setw(5) << NumInitialize()
1200  << " " << std::setw(15) << InitializeTime()
1201 #ifdef IFPACK_FLOPCOUNTERS
1202  << " " << std::setw(15) << 1.0e-6 * IF
1203  << " " << std::setw(15) << 1.0e-6 * IFT
1204 #endif
1205  << endl;
1206  os << "Compute() " << std::setw(5) << NumCompute()
1207  << " " << std::setw(15) << ComputeTime()
1208 #ifdef IFPACK_FLOPCOUNTERS
1209  << " " << std::setw(15) << 1.0e-6 * CF
1210  << " " << std::setw(15) << 1.0e-6 * CFT
1211 #endif
1212  << endl;
1213  os << "ApplyInverse() " << std::setw(5) << NumApplyInverse()
1214  << " " << std::setw(15) << ApplyInverseTime()
1215 #ifdef IFPACK_FLOPCOUNTERS
1216  << " " << std::setw(15) << 1.0e-6 * AF
1217  << " " << std::setw(15) << 1.0e-6 * AFT
1218 #endif
1219  << endl;
1220  os << "================================================================================" << endl;
1221  os << endl;
1222 
1223  return(os);
1224 }
1225 
1226 #include "Ifpack_Condest.h"
1227 //==============================================================================
1228 template<typename T>
1230 Condest(const Ifpack_CondestType CT, const int MaxIters,
1231  const double Tol, Epetra_RowMatrix* Matrix_in)
1232 {
1233  if (!IsComputed()) // cannot compute right now
1234  return(-1.0);
1235 
1236  Condest_ = Ifpack_Condest(*this, CT, MaxIters, Tol, Matrix_in);
1237 
1238  return(Condest_);
1239 }
1240 
1241 #endif // IFPACK_ADDITIVESCHWARZ_H
virtual int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Applies the preconditioner to X, returns the result in Y.
int Setup()
Sets up the localized matrix and the singleton filter.
int OverlapLevel_
Level of overlap among the processors.
std::string ReorderingType_
Type of reordering of the local matrix.
Teuchos::RefCountPtr< const Epetra_RowMatrix > Matrix_
Pointers to the matrix to be preconditioned.
virtual const Epetra_Map & RowMatrixRowMap() const =0
double ComputeFlops_
Contains the number of flops for Compute().
virtual int SetUseTranspose(bool UseTranspose_in)
If set true, transpose of this operator will be applied (not implemented).
virtual const Epetra_Map & OperatorRangeMap() const
Returns the Epetra_Map object associated with the range of this operator.
Ifpack_AMDReordering: approximate minimum degree reordering.
bool UseTranspose_
If true, solve with the transpose (not supported by all solvers).
virtual double ComputeFlops() const
Returns the number of flops in the computation phase.
bool ComputeCondest_
If true, compute the condition number estimate each time Compute() is called.
double Condest_
Contains the estimated condition number.
virtual bool IsInitialized() const
Returns true if the preconditioner has been successfully initialized.
Ifpack_METISReordering: A class to reorder a graph using METIS.
double ApplyInverseFlops_
Contain sthe number of flops for ApplyInverse().
virtual bool IsComputed() const
Returns true if the preconditioner has been successfully computed.
Teuchos::RefCountPtr< Ifpack_OverlappingRowMatrix > OverlappingMatrix_
Pointers to the overlapping matrix.
virtual int OverlapLevel() const
Returns the level of overlap.
virtual double ApplyInverseTime() const
Returns the time spent in ApplyInverse().
virtual bool IsOverlapping() const
Returns true is an overlapping matrix is present.
virtual double ComputeTime() const
Returns the time spent in Compute().
Teuchos::RefCountPtr< Ifpack_Reordering > Reordering_
Pointer to a reordering object.
virtual double ApplyInverseFlops() const
Returns the number of flops in the application of the preconditioner.
Teuchos::RefCountPtr< Ifpack_ReorderFilter > ReorderedLocalizedMatrix_
Pointer to the reorderd matrix.
std::string Label_
Contains the label of this object.
virtual int NumInitialize() const
Returns the number of calls to Initialize().
bool IsOverlapping_
If true, overlapping is used.
virtual std::ostream & Print(std::ostream &) const
Prints major information about this preconditioner.
virtual int Initialize()
Initialized the preconditioner.
Ifpack_AdditiveSchwarz(const Ifpack_AdditiveSchwarz &RHS)
Copy constructor (should never be used)
double ComputeTime_
Contains the time for all successful calls to Compute().
Ifpack_RCMReordering: reverse Cuthill-McKee reordering.
Ifpack_AdditiveSchwarz: a class to define Additive Schwarz preconditioners of Epetra_RowMatrix&#39;s.
virtual int NumApplyInverse() const
Returns the number of calls to ApplyInverse().
virtual const Epetra_Map & OperatorDomainMap() const
Returns the Epetra_Map object associated with the domain of this operator.
Ifpack_Preconditioner: basic class for preconditioning in Ifpack.
virtual const Epetra_BlockMap & Map() const =0
virtual bool UseTranspose() const
Returns the current UseTranspose setting.
Ifpack_AdditiveSchwarz(Epetra_RowMatrix *Matrix_in, int OverlapLevel_in=0)
Ifpack_AdditiveSchwarz constructor with given Epetra_RowMatrix.
double InitializeFlops_
Contains the number of flops for Initialize().
virtual bool HasNormInf() const
Returns true if the this object can provide an approximate Inf-norm, false otherwise.
Ifpack_SingletonFilter: Filter based on matrix entries.
virtual int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Applies the matrix to X, returns the result in Y.
virtual ~Ifpack_AdditiveSchwarz()
Destructor.
Ifpack_OverlappingRowMatrix: matrix with ghost rows, based on Epetra_RowMatrix.
Ifpack_LocalFilter a class for light-weight extraction of the submatrix corresponding to local rows a...
bool IsInitialized_
If true, the preconditioner has been successfully initialized.
int NumInitialize_
Contains the number of successful calls to Initialize().
virtual int SetParameters(Teuchos::ParameterList &List)
Sets the parameters.
bool UseReordering_
If true, reorder the local matrix.
virtual int Compute()
Computes the preconditioner.
int NumApplyInverse_
Contains the number of successful call to ApplyInverse().
Teuchos::RefCountPtr< Ifpack_SingletonFilter > SingletonFilter_
filtering object.
double InitializeTime_
Contains the time for all successful calls to Initialize().
virtual double InitializeFlops() const
Returns the number of flops in the initialization phase.
bool IsComputed_
If true, the preconditioner has been successfully computed.
virtual const Teuchos::ParameterList & List() const
Returns a reference to the internally stored list.
Epetra_CombineMode
virtual const char * Label() const
Returns a character string describing the operator.
Teuchos::RefCountPtr< T > Inverse_
Pointer to the local solver.
int NumCompute_
Contains the number of successful call to Compute().
virtual double InitializeTime() const
Returns the time spent in Initialize().
virtual const Epetra_Comm & Comm() const
Returns a pointer to the Epetra_Comm communicator associated with this operator.
double ApplyInverseTime_
Contains the time for all successful calls to ApplyInverse().
Ifpack_ReorderFilter: a class for light-weight reorder of local rows and columns of an Epetra_RowMatr...
virtual double NormInf() const
Returns the infinity norm of the global matrix (not implemented)
std::string Ifpack_toString(const int &x)
Converts an integer to std::string.
Teuchos::ParameterList List_
Stores a copy of the list given in SetParameters()
Epetra_CombineMode CombineMode_
Combine mode for off-process elements (only if overlap is used)
virtual const Epetra_RowMatrix & Matrix() const
Returns a refernence to the internally stored matrix.
bool FilterSingletons_
Filter for singletons.
virtual double Condest() const
Returns the estimated condition number, or -1.0 if not computed.
virtual int NumCompute() const
Returns the number of calls to Compute().
Teuchos::RefCountPtr< Epetra_Time > Time_
Object used for timing purposes.
Teuchos::RefCountPtr< Ifpack_LocalFilter > LocalizedMatrix_
Localized version of Matrix_ or OverlappingMatrix_.