int main(int argc, char *argv[]) { using std::cout; using std::endl; int ierr = 0, i, j; int nx, ny; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); //int size, rank; // Number of MPI processes, My process ID //MPI_Comm_size(MPI_COMM_WORLD, &size); //MPI_Comm_rank(MPI_COMM_WORLD, &rank); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else //int size = 1; // Serial case (not using MPI) //int rank = 0; Epetra_SerialComm Comm; #endif bool verbose = false; int nextarg = 1; // Check if we should print results to standard out if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') { verbose = true; nextarg++; } // char tmp; // if (rank==0) cout << "Press any key to continue..."<< endl; // if (rank==0) cin >> tmp; // Comm.Barrier(); int MyPID = Comm.MyPID(); int NumProc = Comm.NumProc(); if (verbose && MyPID==0) cout << Ifpack_Version() << endl << endl; if (verbose) cout << Comm <<endl; //int sqrtNumProc = (int) ceil(sqrt((double) NumProc)); bool verbose1 = verbose; verbose = verbose && (MyPID==0); if (verbose1 && argc != 4) { nx = 10; ny = 12*NumProc; cout << "Setting nx = " << nx << ", ny = " << ny << endl; } else if (!verbose1 && argc != 3) { nx = 10; ny = 12*NumProc; } else { nx = atoi(argv[nextarg++]); if (nx<3) {cout << "nx = " << nx << ": Must be greater than 2 for meaningful graph." << endl; exit(1);} ny = atoi(argv[nextarg++]); if (ny<3) {cout << "ny = " << ny << ": Must be greater than 2 for meaningful graph." << endl; exit(1);} } int NumGlobalPoints = nx*ny; int IndexBase = 0; if (verbose) cout << "\n\n*****Building 5 point matrix, Level 1 and 2 filled matrices for" << endl << " nx = " << nx << ", ny = " << ny << endl<< endl; // Create a 5 point stencil graph, level 1 fill of it and level 2 fill of it Epetra_Map Map(NumGlobalPoints, IndexBase, Comm); int NumMyPoints = Map.NumMyPoints(); Epetra_CrsGraph A(Copy, Map, 5); Epetra_CrsGraph L0(Copy, Map, Map, 2); Epetra_CrsGraph U0(Copy, Map, Map, 2); Epetra_CrsGraph L1(Copy, Map, Map, 3); Epetra_CrsGraph U1(Copy, Map, Map, 3); Epetra_CrsGraph L2(Copy, Map, Map, 4); Epetra_CrsGraph U2(Copy, Map, Map, 4); // Add rows one-at-a-time std::vector<int> Indices(4); // Work space for (j=0; j<ny; j++) { for (i=0; i<nx; i++) { int Row = i+j*nx; if (Map.MyGID(Row)) { // Only work on rows I own //**** Work on lower triangle of all three matrices **** // Define entries (i-1,j), (i,j-1) int k = 0; if (i>0) Indices[k++] = i-1 + j *nx; if (j>0) Indices[k++] = i +(j-1)*nx; // Define lower triangular terms of original matrix and L(0) assert(A.InsertGlobalIndices(Row, k, &Indices[0])>=0); assert(L0.InsertGlobalIndices(Row, k, &Indices[0])>=0); // Define entry (i+1,j-1) if ((i<nx-1) && (j>0 )) Indices[k++] = i+1 +(j-1)*nx; // Define lower triangle of level(1) fill matrix assert(L1.InsertGlobalIndices(Row, k, &Indices[0])>=0); // Define entry (i+2, j-1) if ((i<nx-2) && (j>0 )) Indices[k++] = i+2 +(j-1)*nx; // Define lower triangle of level(2) fill matrix assert(L2.InsertGlobalIndices(Row, k, &Indices[0])>=0); // Define main diagonal of original matrix assert(A.InsertGlobalIndices(Row, 1, &Row)>=0); k = 0; // Reset index counter //**** Work on upper triangle of all three matrices **** // Define entries (i+1,j), ( i,j+1) if (i<nx-1) Indices[k++] = i+1 + j *nx; if (j<ny-1) Indices[k++] = i +(j+1)*nx; // Define upper triangular terms of original matrix and L(0) assert(A.InsertGlobalIndices(Row, k, &Indices[0])>=0); assert(U0.InsertGlobalIndices(Row, k, &Indices[0])>=0); // Define entry (i-1,j+1) if ((i>0 ) && (j<ny-1)) Indices[k++] = i-1 +(j+1)*nx; // Define upper triangle of level(1) fill matrix assert(U1.InsertGlobalIndices(Row, k, &Indices[0])>=0); // Define entry (i-2, j+1) if ((i>1 ) && (j<ny-1)) Indices[k++] = i-2 +(j+1)*nx; // Define upper triangle of level(2) fill matrix assert(U2.InsertGlobalIndices(Row, k, &Indices[0])>=0); } } } // Finish up if (verbose) cout << "\n\nCompleting A" << endl<< endl; assert(A.FillComplete()==0); if (verbose) cout << "\n\nCompleting L0" << endl<< endl; assert(L0.FillComplete()==0); if (verbose) cout << "\n\nCompleting U0" << endl<< endl; assert(U0.FillComplete()==0); if (verbose) cout << "\n\nCompleting L1" << endl<< endl; assert(L1.FillComplete()==0); if (verbose) cout << "\n\nCompleting U1" << endl<< endl; assert(U1.FillComplete()==0); if (verbose) cout << "\n\nCompleting L2" << endl<< endl; assert(L2.FillComplete()==0); if (verbose) cout << "\n\nCompleting U2" << endl<< endl; assert(U2.FillComplete()==0); if (verbose) cout << "\n\n*****Testing ILU(0) constructor on A" << endl<< endl; Ifpack_IlukGraph ILU0(A, 0, 0); assert(ILU0.ConstructFilledGraph()==0); assert(check(L0, U0, ILU0, NumGlobalPoints, NumMyPoints, 0, verbose)==0); if (verbose) cout << "\n\n*****Testing ILU(1) constructor on A" << endl<< endl; Ifpack_IlukGraph ILU1(A, 1, 0); assert(ILU1.ConstructFilledGraph()==0); assert(check(L1, U1, ILU1, NumGlobalPoints, NumMyPoints, 1, verbose)==0); if (verbose) cout << "\n\n*****Testing ILU(2) constructor on A" << endl<< endl; Ifpack_IlukGraph ILU2(A, 2, 0); assert(ILU2.ConstructFilledGraph()==0); assert(check(L2, U2, ILU2, NumGlobalPoints, NumMyPoints, 2, verbose)==0); if (verbose) cout << "\n\n*****Testing copy constructor" << endl<< endl; Ifpack_IlukGraph ILUC(ILU2); assert(check(L2, U2, ILUC, NumGlobalPoints, NumMyPoints, 2, verbose)==0); if (verbose) cout << "\n\n*****Testing copy constructor" << endl<< endl; Teuchos::RefCountPtr<Ifpack_IlukGraph> OverlapGraph; for (int overlap = 1; overlap < 4; overlap++) { if (verbose) cout << "\n\n*********************************************" << endl; if (verbose) cout << "\n\nConstruct Level 1 fill with Overlap = " << overlap << ".\n\n" << endl; OverlapGraph = Teuchos::rcp( new Ifpack_IlukGraph(A, 1, overlap) ); assert(OverlapGraph->ConstructFilledGraph()==0); if (verbose) { cout << "Number of Global Rows = " << OverlapGraph->NumGlobalRows() << endl; cout << "Number of Global Nonzeros = " << OverlapGraph->NumGlobalNonzeros() << endl; cout << "Number of Local Rows = " << OverlapGraph->NumMyRows() << endl; cout << "Number of Local Nonzeros = " << OverlapGraph->NumMyNonzeros() << endl; } } if (verbose1) { // Test ostream << operator (if verbose1) // Construct a Map that puts 6 equations on each PE int NumElements1 = 6; int NumPoints1 = NumElements1; // Create an integer vector NumNz that is used to build the Petra Matrix. // NumNz[i] is the Number of terms for the ith global equation on this processor std::vector<int> NumNz1(NumPoints1); // We are building a tridiagonal matrix where each row has (-1 2 -1) // So we need 2 off-diagonal terms (except for the first and last equation) for (i=0; i<NumPoints1; i++) if (i==0 || i == NumPoints1-1) NumNz1[i] = 2; else NumNz1[i] = 3; // Create a Epetra_Matrix Epetra_Map Map1(NumPoints1, NumPoints1, 1, Comm); Epetra_CrsGraph A1(Copy, Map1, &NumNz1[0]); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 std::vector<int> Indices1(2); int NumEntries1; for (i=0; i<NumPoints1; i++) { if (i==0) { Indices1[0] = 2; NumEntries1 = 1; } else if (i == NumPoints1-1) { Indices1[0] = NumPoints1-1; NumEntries1 = 1; } else { Indices1[0] = i; Indices1[1] = i+2; NumEntries1 = 2; } assert(A1.InsertGlobalIndices(i+1, NumEntries1, &Indices1[0])==0); int ip1 = i+1; assert(A1.InsertGlobalIndices(ip1, 1, &ip1)==0); // Put in the diagonal entry } // Finish up assert(A1.FillComplete()==0); if (verbose) cout << "\n\nPrint out tridiagonal matrix with IndexBase = 1.\n\n" << endl; cout << A1 << endl; if (verbose) cout << "\n\nConstruct Level 1 fill with IndexBase = 1.\n\n" << endl; Ifpack_IlukGraph ILU11(A1, 1, 0); assert(ILU11.ConstructFilledGraph()==0); if (verbose) cout << "\n\nPrint out Level 1 ILU graph of tridiagonal matrix with IndexBase = 1.\n\n" << endl; if (verbose1) cout << ILU11 << endl; } #ifdef EPETRA_MPI MPI_Finalize() ; #endif /* end main */ return ierr ; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm (MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int MyPID = Comm.MyPID(); bool verbose = false; if (MyPID==0) verbose = true; Teuchos::ParameterList GaleriList; int nx = 30; GaleriList.set("nx", nx); GaleriList.set("ny", nx * Comm.NumProc()); GaleriList.set("mx", 1); GaleriList.set("my", Comm.NumProc()); Teuchos::RefCountPtr<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap("Cartesian2D", Comm, GaleriList) ); Teuchos::RefCountPtr<Epetra_CrsMatrix> A = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) ); Teuchos::RefCountPtr<Epetra_MultiVector> LHS = Teuchos::rcp( new Epetra_MultiVector(*Map, 1) ); Teuchos::RefCountPtr<Epetra_MultiVector> RHS = Teuchos::rcp( new Epetra_MultiVector(*Map, 1) ); LHS->PutScalar(0.0); RHS->Random(); // ============================ // // Construct ILU preconditioner // // ---------------------------- // // I wanna test funky values to be sure that they have the same // influence on the algorithms, both old and new int LevelFill = 2; double DropTol = 0.3333; double Athresh = 0.0123; double Rthresh = 0.9876; double Relax = 0.1; int Overlap = 2; Teuchos::RefCountPtr<Ifpack_IlukGraph> Graph; Teuchos::RefCountPtr<Ifpack_CrsRiluk> RILU; Graph = Teuchos::rcp( new Ifpack_IlukGraph(A->Graph(), LevelFill, Overlap) ); int ierr; ierr = Graph->ConstructFilledGraph(); IFPACK_CHK_ERR(ierr); RILU = Teuchos::rcp( new Ifpack_CrsRiluk(*Graph) ); RILU->SetAbsoluteThreshold(Athresh); RILU->SetRelativeThreshold(Rthresh); RILU->SetRelaxValue(Relax); int initerr = RILU->InitValues(*A); if (initerr!=0) cout << Comm << "*ERR* InitValues = " << initerr; RILU->Factor(); // Define label for printing out during the solve phase string label = "Ifpack_CrsRiluk Preconditioner: LevelFill = " + toString(LevelFill) + " Overlap = " + toString(Overlap) + " Athresh = " + toString(Athresh) + " Rthresh = " + toString(Rthresh); // Here we create an AztecOO object LHS->PutScalar(0.0); int Niters = 1200; AztecOO solver; solver.SetUserMatrix(&*A); solver.SetLHS(&*LHS); solver.SetRHS(&*RHS); solver.SetAztecOption(AZ_solver,AZ_gmres); solver.SetPrecOperator(&*RILU); solver.SetAztecOption(AZ_output, 16); solver.Iterate(Niters, 5.0e-5); int OldIters = solver.NumIters(); // now rebuild the same preconditioner using RILU, we expect the same // number of iterations Ifpack Factory; Teuchos::RefCountPtr<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create("ILU", &*A, Overlap) ); Teuchos::ParameterList List; List.get("fact: level-of-fill", LevelFill); List.get("fact: drop tolerance", DropTol); List.get("fact: absolute threshold", Athresh); List.get("fact: relative threshold", Rthresh); List.get("fact: relax value", Relax); IFPACK_CHK_ERR(Prec->SetParameters(List)); IFPACK_CHK_ERR(Prec->Compute()); // Here we create an AztecOO object LHS->PutScalar(0.0); solver.SetUserMatrix(&*A); solver.SetLHS(&*LHS); solver.SetRHS(&*RHS); solver.SetAztecOption(AZ_solver,AZ_gmres); solver.SetPrecOperator(&*Prec); solver.SetAztecOption(AZ_output, 16); solver.Iterate(Niters, 5.0e-5); int NewIters = solver.NumIters(); if (OldIters != NewIters) IFPACK_CHK_ERR(-1); #ifdef HAVE_IFPACK_SUPERLU // Now test w/ SuperLU's ILU, if we've got it Teuchos::RefCountPtr<Ifpack_Preconditioner> Prec2 = Teuchos::rcp( Factory.Create("SILU", &*A,0) ); Teuchos::ParameterList SList; SList.set("fact: drop tolerance",1e-4); SList.set("fact: zero pivot threshold",.1); SList.set("fact: maximum fill factor",10.0); // NOTE: There is a bug in SuperLU 4.0 which will crash the code if the maximum fill factor is set too low. // This bug was reported to Sherry Li on 4/8/10. SList.set("fact: silu drop rule",9); IFPACK_CHK_ERR(Prec2->SetParameters(SList)); IFPACK_CHK_ERR(Prec2->Compute()); LHS->PutScalar(0.0); solver.SetPrecOperator(&*Prec2); solver.Iterate(Niters, 5.0e-5); Prec2->Print(cout); #endif #ifdef HAVE_MPI MPI_Finalize() ; #endif return(EXIT_SUCCESS); }