IFPACK Development
Loading...
Searching...
No Matches
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
147template<typename T>
149
150public:
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
381protected:
382
383 // @}
384
385 // @{ Internal merhods.
386
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
410 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
447 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_;
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//==============================================================================
513template<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
559extern int ML_NODE_ID;
560#endif
561
562//==============================================================================
563template<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//==============================================================================
724template<typename T>
725int 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//==============================================================================
802template<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//==============================================================================
894template<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//==============================================================================
936template<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//==============================================================================
950template<typename T>
953{
954 IFPACK_CHK_ERR(Matrix_->Apply(X,Y));
955 return(0);
956}
957
958//==============================================================================
959template<typename T>
961{
962 return(-1.0);
963}
964
965//==============================================================================
966template<typename T>
968{
969 return(Label_.c_str());
970}
971
972//==============================================================================
973template<typename T>
975{
976 return(UseTranspose_);
977}
978
979//==============================================================================
980template<typename T>
982{
983 return(false);
984}
985
986//==============================================================================
987template<typename T>
989{
990 return(Matrix_->Comm());
991}
992
993//==============================================================================
994template<typename T>
996{
997 return(Matrix_->OperatorDomainMap());
998}
999
1000//==============================================================================
1001template<typename T>
1003{
1004 return(Matrix_->OperatorRangeMap());
1005}
1006
1007//==============================================================================
1008template<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//==============================================================================
1147template<typename T>
1149Print(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//==============================================================================
1228template<typename T>
1230Condest(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
Epetra_CombineMode
Insert
Add
AbsMax
InsertAdd
Average
Zero
Copy
int NumVectors() const
virtual const Epetra_Map & RowMatrixRowMap() const=0
virtual const Epetra_BlockMap & Map() const=0
Ifpack_AMDReordering: approximate minimum degree reordering.
Ifpack_AdditiveSchwarz: a class to define Additive Schwarz preconditioners of Epetra_RowMatrix's.
int NumCompute_
Contains the number of successful call to Compute().
Ifpack_AdditiveSchwarz(Epetra_RowMatrix *Matrix_in, int OverlapLevel_in=0)
Ifpack_AdditiveSchwarz constructor with given Epetra_RowMatrix.
Teuchos::RefCountPtr< Ifpack_Reordering > Reordering_
Pointer to a reordering object.
virtual const Epetra_Map & OperatorDomainMap() const
Returns the Epetra_Map object associated with the domain of this operator.
bool FilterSingletons_
Filter for singletons.
virtual double NormInf() const
Returns the infinity norm of the global matrix (not implemented)
virtual double ComputeTime() const
Returns the time spent in Compute().
virtual int SetUseTranspose(bool UseTranspose_in)
If set true, transpose of this operator will be applied (not implemented).
virtual int NumCompute() const
Returns the number of calls to Compute().
virtual const Teuchos::ParameterList & List() const
Returns a reference to the internally stored list.
virtual double ApplyInverseTime() const
Returns the time spent in ApplyInverse().
bool ComputeCondest_
If true, compute the condition number estimate each time Compute() is called.
double InitializeFlops_
Contains the number of flops for Initialize().
virtual const Epetra_RowMatrix & Matrix() const
Returns a refernence to the internally stored matrix.
bool IsComputed_
If true, the preconditioner has been successfully computed.
virtual bool UseTranspose() const
Returns the current UseTranspose setting.
Ifpack_AdditiveSchwarz(const Ifpack_AdditiveSchwarz &RHS)
Copy constructor (should never be used)
virtual bool IsInitialized() const
Returns true if the preconditioner has been successfully initialized.
int NumInitialize_
Contains the number of successful calls to Initialize().
Epetra_CombineMode CombineMode_
Combine mode for off-process elements (only if overlap is used)
std::string Label_
Contains the label of this object.
virtual int SetParameters(Teuchos::ParameterList &List)
Sets the parameters.
virtual const Epetra_Comm & Comm() const
Returns a pointer to the Epetra_Comm communicator associated with this operator.
Teuchos::RefCountPtr< Ifpack_OverlappingRowMatrix > OverlappingMatrix_
Pointers to the overlapping matrix.
int OverlapLevel_
Level of overlap among the processors.
double InitializeTime_
Contains the time for all successful calls to Initialize().
virtual double InitializeTime() const
Returns the time spent in Initialize().
virtual double ApplyInverseFlops() const
Returns the number of flops in the application of the preconditioner.
virtual bool HasNormInf() const
Returns true if the this object can provide an approximate Inf-norm, false otherwise.
Teuchos::ParameterList List_
Stores a copy of the list given in SetParameters()
std::string ReorderingType_
Type of reordering of the local matrix.
virtual int NumApplyInverse() const
Returns the number of calls to ApplyInverse().
int NumApplyInverse_
Contains the number of successful call to ApplyInverse().
double ComputeFlops_
Contains the number of flops for Compute().
Teuchos::RefCountPtr< Ifpack_ReorderFilter > ReorderedLocalizedMatrix_
Pointer to the reorderd matrix.
virtual int Compute()
Computes the preconditioner.
double ApplyInverseFlops_
Contain sthe number of flops for ApplyInverse().
virtual int Initialize()
Initialized the preconditioner.
Teuchos::RefCountPtr< Epetra_Time > Time_
Object used for timing purposes.
bool UseTranspose_
If true, solve with the transpose (not supported by all solvers).
Teuchos::RefCountPtr< Ifpack_SingletonFilter > SingletonFilter_
filtering object.
virtual bool IsOverlapping() const
Returns true is an overlapping matrix is present.
Teuchos::RefCountPtr< T > Inverse_
Pointer to the local solver.
virtual int OverlapLevel() const
Returns the level of overlap.
virtual const Epetra_Map & OperatorRangeMap() const
Returns the Epetra_Map object associated with the range of this operator.
double ApplyInverseTime_
Contains the time for all successful calls to ApplyInverse().
virtual std::ostream & Print(std::ostream &) const
Prints major information about this preconditioner.
virtual const char * Label() const
Returns a character string describing the operator.
virtual bool IsComputed() const
Returns true if the preconditioner has been successfully computed.
double Condest_
Contains the estimated condition number.
double ComputeTime_
Contains the time for all successful calls to Compute().
virtual int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Applies the matrix to X, returns the result in Y.
virtual double InitializeFlops() const
Returns the number of flops in the initialization phase.
Teuchos::RefCountPtr< Ifpack_LocalFilter > LocalizedMatrix_
Localized version of Matrix_ or OverlappingMatrix_.
bool IsInitialized_
If true, the preconditioner has been successfully initialized.
virtual double ComputeFlops() const
Returns the number of flops in the computation phase.
virtual ~Ifpack_AdditiveSchwarz()
Destructor.
bool IsOverlapping_
If true, overlapping is used.
bool UseReordering_
If true, reorder the local matrix.
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.
virtual int NumInitialize() const
Returns the number of calls to Initialize().
Teuchos::RefCountPtr< const Epetra_RowMatrix > Matrix_
Pointers to the matrix to be preconditioned.
virtual double Condest() const
Returns the estimated condition number, or -1.0 if not computed.
Ifpack_LocalFilter a class for light-weight extraction of the submatrix corresponding to local rows a...
Ifpack_METISReordering: A class to reorder a graph using METIS.
Ifpack_OverlappingRowMatrix: matrix with ghost rows, based on Epetra_RowMatrix.
Ifpack_Preconditioner: basic class for preconditioning in Ifpack.
Ifpack_RCMReordering: reverse Cuthill-McKee reordering.
Ifpack_ReorderFilter: a class for light-weight reorder of local rows and columns of an Epetra_RowMatr...
Ifpack_SingletonFilter: Filter based on matrix entries.