44 #ifndef IFPACK_BLOCKPRECONDITIONER_H
45 #define IFPACK_BLOCKPRECONDITIONER_H
47 #include "Ifpack_ConfigDefs.h"
48 #include "Ifpack_Preconditioner.h"
49 #include "Ifpack_Partitioner.h"
50 #include "Ifpack_LinePartitioner.h"
51 #include "Ifpack_LinearPartitioner.h"
52 #include "Ifpack_GreedyPartitioner.h"
53 #include "Ifpack_METISPartitioner.h"
54 #include "Ifpack_EquationPartitioner.h"
55 #include "Ifpack_UserPartitioner.h"
56 #include "Ifpack_Graph_Epetra_RowMatrix.h"
57 #include "Ifpack_DenseContainer.h"
59 #include "Teuchos_ParameterList.hpp"
60 #include "Teuchos_RefCountPtr.hpp"
62 #include "Epetra_Map.h"
63 #include "Epetra_RowMatrix.h"
64 #include "Epetra_MultiVector.h"
65 #include "Epetra_Vector.h"
66 #include "Epetra_Time.h"
67 #include "Epetra_Import.h"
69 static const int IFPACK_JACOBI = 0;
70 static const int IFPACK_GS = 1;
71 static const int IFPACK_SGS = 2;
192 virtual int SetUseTranspose(
bool UseTranspose_in)
199 virtual const char* Label()
const;
226 return(NumLocalBlocks_);
232 return(IsInitialized_);
255 virtual double Condest(
const Ifpack_CondestType CT = Ifpack_Cheap,
256 const int MaxIters = 1550,
257 const double Tol = 1e-9,
268 std::ostream&
Print(std::ostream& os)
const;
273 return(NumInitialize_);
285 return(NumApplyInverse_);
291 return(InitializeTime_);
297 return(ComputeTime_);
303 return(ApplyInverseTime_);
309 #ifdef IFPACK_FLOPCOUNTERS
310 if (Containers_.size() == 0)
316 double total = InitializeFlops_;
317 for (
unsigned int i = 0 ; i < Containers_.size() ; ++i)
318 if(Containers_[i]) total += Containers_[i]->InitializeFlops();
327 #ifdef IFPACK_FLOPCOUNTERS
328 if (Containers_.size() == 0)
331 double total = ComputeFlops_;
332 for (
unsigned int i = 0 ; i < Containers_.size() ; ++i)
333 if(Containers_[i]) total += Containers_[i]->ComputeFlops();
342 #ifdef IFPACK_FLOPCOUNTERS
343 if (Containers_.size() == 0)
346 double total = ApplyInverseFlops_;
347 for (
unsigned int i = 0 ; i < Containers_.size() ; ++i) {
348 if(Containers_[i]) total += Containers_[i]->ApplyInverseFlops();
386 int ExtractSubmatrices();
399 mutable int NumApplyInverse_;
401 double InitializeTime_;
405 mutable double ApplyInverseTime_;
407 double InitializeFlops_;
409 double ComputeFlops_;
411 mutable double ApplyInverseFlops_;
418 double DampingFactor_;
422 Teuchos::ParameterList List_;
428 Teuchos::RefCountPtr< const Epetra_RowMatrix > Matrix_;
429 mutable std::vector<Teuchos::RefCountPtr<T> > Containers_;
433 Teuchos::RefCountPtr<Ifpack_Partitioner> Partitioner_;
434 std::string PartitionerType_;
439 bool ZeroStartingSolution_;
440 Teuchos::RefCountPtr<Ifpack_Graph> Graph_;
442 Teuchos::RefCountPtr<Epetra_Vector> W_;
447 Teuchos::RefCountPtr<Epetra_Import> Importer_;
456 IsInitialized_(false),
461 InitializeTime_(0.0),
463 ApplyInverseTime_(0.0),
464 InitializeFlops_(0.0),
466 ApplyInverseFlops_(0.0),
470 Matrix_(Teuchos::rcp(Matrix_in,false)),
471 Diagonal_( Matrix_in->Map()),
472 PartitionerType_(
"greedy"),
473 PrecType_(IFPACK_JACOBI),
474 ZeroStartingSolution_(true),
493 return(Label_.c_str());
501 int ierr = Matrix().
Apply(X,Y);
510 return(Matrix().Comm());
518 return(Matrix().OperatorDomainMap());
526 return(Matrix().OperatorRangeMap());
534 if (Partitioner_ == Teuchos::null)
537 NumLocalBlocks_ = Partitioner_->NumLocalParts();
539 Containers_.resize(NumLocalBlocks());
542 Matrix_->ExtractDiagonalCopy(Diagonal_);
544 for (
int i = 0 ; i < NumLocalBlocks() ; ++i) {
546 int rows = Partitioner_->NumRowsInPart(i);
551 Containers_[i] = Teuchos::rcp(
new T(rows) );
553 IFPACK_CHK_ERR(Containers_[i]->SetParameters(List_));
554 IFPACK_CHK_ERR(Containers_[i]->Initialize());
558 for (
int j = 0 ; j < rows ; ++j) {
559 int LRID = (*Partitioner_)(i,j);
560 Containers_[i]->ID(j) = LRID;
563 IFPACK_CHK_ERR(Containers_[i]->Compute(*Matrix_));
568 #ifdef SINGLETON_DEBUG
571 for (
int i = 0 ; i < NumLocalBlocks() ; ++i)
572 issing += (
int) ( Partitioner_->NumRowsInPart(i) == 1);
573 printf(
" %d of %d containers are singleton \n",issing,NumLocalBlocks());
584 if (!IsInitialized())
585 IFPACK_CHK_ERR(Initialize());
587 Time_.ResetStartTime();
591 if (Matrix().NumGlobalRows64() != Matrix().NumGlobalCols64())
594 IFPACK_CHK_ERR(ExtractSubmatrices());
596 if (IsParallel_ && PrecType_ != IFPACK_JACOBI) {
598 Importer_ = Teuchos::rcp(
new Epetra_Import(Matrix().RowMatrixColMap(),
599 Matrix().RowMatrixRowMap()) );
601 if (Importer_ == Teuchos::null) IFPACK_CHK_ERR(-5);
604 ComputeTime_ += Time_.ElapsedTime();
622 Time_.ResetStartTime();
626 Teuchos::RefCountPtr< const Epetra_MultiVector > Xcopy;
630 Xcopy = Teuchos::rcp( &X,
false );
634 IFPACK_CHK_ERR(ApplyInverseJacobi(*Xcopy,Y));
637 IFPACK_CHK_ERR(ApplyInverseGS(*Xcopy,Y));
640 IFPACK_CHK_ERR(ApplyInverseSGS(*Xcopy,Y));
644 ApplyInverseTime_ += Time_.ElapsedTime();
660 if (ZeroStartingSolution_)
664 if (NumSweeps_ == 1 && ZeroStartingSolution_) {
665 int ierr = DoJacobi(X,Y);
671 for (
int j = 0; j < NumSweeps_ ; j++) {
672 IFPACK_CHK_ERR(Apply(Y,AX));
673 ApplyInverseFlops_ += X.
NumVectors() * 2 * Matrix_->NumGlobalNonzeros64();
674 IFPACK_CHK_ERR(AX.Update(1.0,X,-1.0));
675 ApplyInverseFlops_ += X.
NumVectors() * 2 * Matrix_->NumGlobalRows64();
676 IFPACK_CHK_ERR(DoJacobi(AX,Y));
691 if (OverlapLevel_ == 0) {
693 for (
int i = 0 ; i < NumLocalBlocks() ; ++i) {
695 int rows = Partitioner_->NumRowsInPart(i);
704 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
705 LID = Containers_[i]->ID(j);
706 for (
int k = 0 ; k < NumVectors ; ++k) {
707 Containers_[i]->RHS(j,k) = X[k][LID];
715 IFPACK_CHK_ERR(Containers_[i]->ApplyInverse());
718 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
719 LID = Containers_[i]->ID(j);
720 for (
int k = 0 ; k < NumVectors ; ++k) {
721 Y[k][LID] += DampingFactor_ * Containers_[i]->LHS(j,k);
727 int LRID = (*Partitioner_)(i,0);
728 double b = X[0][LRID];
729 double a = Diagonal_[LRID];
730 Y[0][LRID] += DampingFactor_* b/a;
734 #ifdef IFPACK_FLOPCOUNTERS
735 ApplyInverseFlops_ += NumVectors * 2 * Matrix_->NumGlobalRows();
742 for (
int i = 0 ; i < NumLocalBlocks() ; ++i) {
744 int rows = Partitioner_->NumRowsInPart(i);
753 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
754 LID = Containers_[i]->ID(j);
755 for (
int k = 0 ; k < NumVectors ; ++k) {
756 Containers_[i]->RHS(j,k) = (*W_)[LID] * X[k][LID];
762 IFPACK_CHK_ERR(Containers_[i]->ApplyInverse());
765 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
766 LID = Containers_[i]->ID(j);
767 for (
int k = 0 ; k < NumVectors ; ++k) {
768 Y[k][LID] += DampingFactor_ * (*W_)[LID] * Containers_[i]->LHS(j,k);
773 int LRID = (*Partitioner_)(i,0);
774 double w = (*W_)[LRID];
775 double b = w * X[0][LRID];
776 double a = Diagonal_[LRID];
778 Y[0][LRID] += DampingFactor_ * w * b / a;
784 #ifdef IFPACK_FLOPCOUNTERS
785 ApplyInverseFlops_ += NumVectors * 4 * Matrix_->NumGlobalRows();
799 if (ZeroStartingSolution_)
803 for (
int j = 0; j < NumSweeps_ ; j++) {
804 IFPACK_CHK_ERR(DoGaussSeidel(Xcopy,Y));
805 if (j != NumSweeps_ - 1)
822 std::vector<int> Indices(Length);
823 std::vector<double> Values(Length);
831 Teuchos::RefCountPtr< Epetra_MultiVector > Y2;
835 Y2 = Teuchos::rcp( &Y,
false );
840 Y2->ExtractView(&y2_ptr);
844 IFPACK_CHK_ERR(Y2->Import(Y,*Importer_,Insert));
846 for (
int i = 0 ; i < NumLocalBlocks() ; ++i) {
847 int rows = Partitioner_->NumRowsInPart(i);
850 if (rows!=1 && Containers_[i]->NumRows() == 0)
857 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
858 LID = (*Partitioner_)(i,j);
861 IFPACK_CHK_ERR(Matrix().ExtractMyRowCopy(LID, Length,NumEntries,
862 &Values[0], &Indices[0]));
864 for (
int k = 0 ; k < NumEntries ; ++k) {
865 int col = Indices[k];
867 for (
int kk = 0 ; kk < NumVectors ; ++kk) {
868 X[kk][LID] -= Values[k] * y2_ptr[kk][col];
876 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
877 LID = Containers_[i]->ID(j);
878 for (
int k = 0 ; k < NumVectors ; ++k) {
879 Containers_[i]->RHS(j,k) = X[k][LID];
883 IFPACK_CHK_ERR(Containers_[i]->ApplyInverse());
884 #ifdef IFPACK_FLOPCOUNTERS
885 ApplyInverseFlops_ += Containers_[i]->ApplyInverseFlops();
888 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
889 LID = Containers_[i]->ID(j);
890 for (
int k = 0 ; k < NumVectors ; ++k) {
891 double temp = DampingFactor_ * Containers_[i]->LHS(j,k);
892 y2_ptr[k][LID] += temp;
897 int LRID = (*Partitioner_)(i,0);
898 double b = X[0][LRID];
899 double a = Diagonal_[LRID];
900 y2_ptr[0][LRID]+= DampingFactor_* b/a;
906 #ifdef IFPACK_FLOPCOUNTERS
907 ApplyInverseFlops_ += NumVectors * 2 * Matrix_->NumGlobalNonzeros();
908 ApplyInverseFlops_ += NumVectors * 2 * Matrix_->NumGlobalRows();
914 for (
int m = 0 ; m < NumVectors ; ++m)
915 for (
int i = 0 ; i < NumMyRows ; ++i)
916 y_ptr[m][i] = y2_ptr[m][i];
927 if (ZeroStartingSolution_)
931 for (
int j = 0; j < NumSweeps_ ; j++) {
932 IFPACK_CHK_ERR(DoSGS(X,Xcopy,Y));
933 if (j != NumSweeps_ - 1)
950 std::vector<int> Indices;
951 std::vector<double> Values;
952 Indices.resize(Length);
953 Values.resize(Length);
958 Teuchos::RefCountPtr< Epetra_MultiVector > Y2;
962 Y2 = Teuchos::rcp( &Y,
false );
967 Y2->ExtractView(&y2_ptr);
971 IFPACK_CHK_ERR(Y2->Import(Y,*Importer_,Insert));
973 for (
int i = 0 ; i < NumLocalBlocks() ; ++i) {
974 int rows = Partitioner_->NumRowsInPart(i);
976 if (rows !=1 && Containers_[i]->NumRows() == 0)
983 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
984 LID = (*Partitioner_)(i,j);
986 IFPACK_CHK_ERR(Matrix().ExtractMyRowCopy(LID, Length,NumEntries,
987 &Values[0], &Indices[0]));
989 for (
int k = 0 ; k < NumEntries ; ++k) {
990 int col = Indices[k];
992 for (
int kk = 0 ; kk < NumVectors ; ++kk) {
993 Xcopy[kk][LID] -= Values[k] * y2_ptr[kk][col];
1001 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
1002 LID = Containers_[i]->ID(j);
1003 for (
int k = 0 ; k < NumVectors ; ++k) {
1004 Containers_[i]->RHS(j,k) = Xcopy[k][LID];
1008 IFPACK_CHK_ERR(Containers_[i]->ApplyInverse());
1009 #ifdef IFPACK_FLOPCOUNTERS
1010 ApplyInverseFlops_ += Containers_[i]->ApplyInverseFlops();
1013 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
1014 LID = Containers_[i]->ID(j);
1015 for (
int k = 0 ; k < NumVectors ; ++k) {
1016 y2_ptr[k][LID] += DampingFactor_ * Containers_[i]->LHS(j,k);
1021 int LRID = (*Partitioner_)(i,0);
1022 double b = Xcopy[0][LRID];
1023 double a = Diagonal_[LRID];
1024 y2_ptr[0][LRID]+= DampingFactor_* b/a;
1028 #ifdef IFPACK_FLOPCOUNTERS
1030 ApplyInverseFlops_ += NumVectors * 2 * Matrix_->NumGlobalNonzeros();
1031 ApplyInverseFlops_ += NumVectors * 2 * Matrix_->NumGlobalRows();
1036 for (
int i = NumLocalBlocks() - 1; i >=0 ; --i) {
1037 int rows = Partitioner_->NumRowsInPart(i);
1038 if (rows != 1 &&Containers_[i]->NumRows() == 0)
1045 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
1046 LID = (*Partitioner_)(i,j);
1049 IFPACK_CHK_ERR(Matrix().ExtractMyRowCopy(LID, Length,NumEntries,
1050 &Values[0], &Indices[0]));
1052 for (
int k = 0 ; k < NumEntries ; ++k) {
1053 int col = Indices[k];
1055 for (
int kk = 0 ; kk < NumVectors ; ++kk) {
1056 Xcopy[kk][LID] -= Values[k] * y2_ptr[kk][col];
1063 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
1064 LID = Containers_[i]->ID(j);
1065 for (
int k = 0 ; k < NumVectors ; ++k) {
1066 Containers_[i]->RHS(j,k) = Xcopy[k][LID];
1070 IFPACK_CHK_ERR(Containers_[i]->ApplyInverse());
1071 #ifdef IFPACK_FLOPCOUNTERS
1072 ApplyInverseFlops_ += Containers_[i]->ApplyInverseFlops();
1075 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
1076 LID = Containers_[i]->ID(j);
1077 for (
int k = 0 ; k < NumVectors ; ++k) {
1078 y2_ptr[k][LID] += DampingFactor_ * Containers_[i]->LHS(j,k);
1083 int LRID = (*Partitioner_)(i,0);
1084 double b = Xcopy[0][LRID];
1085 double a = Diagonal_[LRID];
1086 y2_ptr[0][LRID]+= DampingFactor_* b/a;
1090 #ifdef IFPACK_FLOPCOUNTERS
1092 ApplyInverseFlops_ += NumVectors * 2 * Matrix_->NumGlobalNonzeros();
1093 ApplyInverseFlops_ += NumVectors * 2 * Matrix_->NumGlobalRows();
1099 for (
int m = 0 ; m < NumVectors ; ++m)
1100 for (
int i = 0 ; i < NumMyRows ; ++i)
1101 y_ptr[m][i] = y2_ptr[m][i];
1107 template<
typename T>
1113 if (PrecType_ == IFPACK_JACOBI)
1115 else if (PrecType_ == IFPACK_GS)
1116 PT =
"Gauss-Seidel";
1117 else if (PrecType_ == IFPACK_SGS)
1118 PT =
"symmetric Gauss-Seidel";
1120 if (!Comm().MyPID()) {
1122 os <<
"================================================================================" << endl;
1123 os <<
"Ifpack_BlockRelaxation, " << PT << endl;
1124 os <<
"Sweeps = " << NumSweeps_ << endl;
1125 os <<
"Damping factor = " << DampingFactor_;
1126 if (ZeroStartingSolution_)
1127 os <<
", using zero starting solution" << endl;
1129 os <<
", using input starting solution" << endl;
1130 os <<
"Number of local blocks = " << Partitioner_->NumLocalParts() << endl;
1132 os <<
"Global number of rows = " << Matrix_->NumGlobalRows64() << endl;
1134 os <<
"Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
1135 os <<
"----- ------- -------------- ------------ --------" << endl;
1136 os <<
"Initialize() " << std::setw(5) << NumInitialize()
1137 <<
" " << std::setw(15) << InitializeTime()
1138 <<
" " << std::setw(15) << 1.0e-6 * InitializeFlops();
1139 if (InitializeTime() != 0.0)
1140 os <<
" " << std::setw(15) << 1.0e-6 * InitializeFlops() / InitializeTime() << endl;
1142 os <<
" " << std::setw(15) << 0.0 << endl;
1143 os <<
"Compute() " << std::setw(5) << NumCompute()
1144 <<
" " << std::setw(15) << ComputeTime()
1145 <<
" " << std::setw(15) << 1.0e-6 * ComputeFlops();
1146 if (ComputeTime() != 0.0)
1147 os <<
" " << std::setw(15) << 1.0e-6 * ComputeFlops() / ComputeTime() << endl;
1149 os <<
" " << std::setw(15) << 0.0 << endl;
1150 os <<
"ApplyInverse() " << std::setw(5) << NumApplyInverse()
1151 <<
" " << std::setw(15) << ApplyInverseTime()
1152 <<
" " << std::setw(15) << 1.0e-6 * ApplyInverseFlops();
1153 if (ApplyInverseTime() != 0.0)
1154 os <<
" " << std::setw(15) << 1.0e-6 * ApplyInverseFlops() / ApplyInverseTime() << endl;
1156 os <<
" " << std::setw(15) << 0.0 << endl;
1157 os <<
"================================================================================" << endl;
1165 template<
typename T>
1172 if (PrecType_ == IFPACK_JACOBI)
1174 else if (PrecType_ == IFPACK_GS)
1175 PT =
"Gauss-Seidel";
1176 else if (PrecType_ == IFPACK_SGS)
1177 PT =
"symmetric Gauss-Seidel";
1179 PT = List.get(
"relaxation: type", PT);
1181 if (PT ==
"Jacobi") {
1182 PrecType_ = IFPACK_JACOBI;
1184 else if (PT ==
"Gauss-Seidel") {
1185 PrecType_ = IFPACK_GS;
1187 else if (PT ==
"symmetric Gauss-Seidel") {
1188 PrecType_ = IFPACK_SGS;
1190 cerr <<
"Option `relaxation: type' has an incorrect value ("
1191 << PT <<
")'" << endl;
1192 cerr <<
"(file " << __FILE__ <<
", line " << __LINE__ <<
")" << endl;
1196 NumSweeps_ = List.get(
"relaxation: sweeps", NumSweeps_);
1197 DampingFactor_ = List.get(
"relaxation: damping factor",
1199 ZeroStartingSolution_ = List.get(
"relaxation: zero starting solution",
1200 ZeroStartingSolution_);
1201 PartitionerType_ = List.get(
"partitioner: type",
1203 NumLocalBlocks_ = List.get(
"partitioner: local parts",
1206 OverlapLevel_ = List.get(
"partitioner: overlap",
1210 if (PrecType_ != IFPACK_JACOBI)
1212 if (NumLocalBlocks_ < 0)
1213 NumLocalBlocks_ = Matrix().
NumMyRows() / (-NumLocalBlocks_);
1222 if (PrecType_ == IFPACK_JACOBI)
1224 else if (PrecType_ == IFPACK_GS)
1226 else if (PrecType_ == IFPACK_SGS)
1228 Label_ =
"IFPACK (" + PT2 +
", sweeps="
1237 template<
typename T>
1240 IsInitialized_ =
false;
1241 Time_.ResetStartTime();
1244 if (Graph_ == Teuchos::null) IFPACK_CHK_ERR(-5);
1246 if (PartitionerType_ ==
"linear")
1248 else if (PartitionerType_ ==
"greedy")
1250 else if (PartitionerType_ ==
"metis")
1252 else if (PartitionerType_ ==
"equation")
1254 else if (PartitionerType_ ==
"user")
1256 else if (PartitionerType_ ==
"line")
1261 if (Partitioner_ == Teuchos::null) IFPACK_CHK_ERR(-5);
1264 IFPACK_CHK_ERR(Partitioner_->SetParameters(List_));
1265 IFPACK_CHK_ERR(Partitioner_->Compute());
1268 NumLocalBlocks_ = Partitioner_->NumLocalParts();
1271 W_ = Teuchos::rcp(
new Epetra_Vector(Matrix().RowMatrixRowMap()) );
1274 for (
int i = 0 ; i < NumLocalBlocks() ; ++i) {
1276 for (
int j = 0 ; j < Partitioner_->NumRowsInPart(i) ; ++j) {
1277 int LID = (*Partitioner_)(i,j);
1281 W_->Reciprocal(*W_);
1284 if (PartitionerType_ ==
"line") {
1287 if (PrecType_ == IFPACK_JACOBI)
1289 else if (PrecType_ == IFPACK_GS)
1291 else if (PrecType_ == IFPACK_SGS)
1293 Label_ =
"IFPACK (" + PT2 +
", auto-line, sweeps="
1299 InitializeTime_ += Time_.ElapsedTime();
1300 IsInitialized_ =
true;
1307 #endif // IFPACK_BLOCKPRECONDITIONER_H