Ifpack Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hypre_UnitTest.cpp
Go to the documentation of this file.
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack: Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2002) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
43 #include "Ifpack.h"
44 #include "Ifpack_Hypre.h"
45 #include "AztecOO.h"
46 #include "Galeri_Maps.h"
47 #include "Galeri_CrsMatrices.h"
48 #include "Galeri_Utils.h"
49 #include "Epetra_MultiVector.h"
50 
51 #include "Teuchos_UnitTestHarness.hpp"
52 #include "Teuchos_RCP.hpp"
53 #include "Epetra_ConfigDefs.h"
54 #include "Epetra_Vector.h"
55 #include "Epetra_RowMatrix.h"
56 #include "Epetra_MultiVector.h"
57 #include "Epetra_CrsMatrix.h"
58 #include "Epetra_Map.h"
59 #ifdef HAVE_MPI
60 #include "mpi.h"
61 #include "Epetra_MpiComm.h"
62 #else
63 #include "Epetra_SerialComm.h"
64 #endif
65 
66 #include "hypre_Helpers.hpp"
67 
68 #include "Teuchos_Array.hpp"
69 #include <string>
70 #include <stdio.h>
71 #include <map>
72 
73 using Teuchos::RCP;
74 using Teuchos::rcp;
75 
76 
77 // Tests hypre interface's ability to initialize correctly
78 TEUCHOS_UNIT_TEST( Ifpack_Hypre, Construct ) {
79  const int N = 10;
80 
81  Epetra_MpiComm comm(MPI_COMM_WORLD);
82  Epetra_Map RowMap(N, 0, comm);
83  Epetra_CrsMatrix Matrix(Copy, RowMap, 1);
84  for(int i = 0; i < N; i++){
85  int indices[1];
86  double values[1];
87  indices[0] = i;
88  values[0] = 1.0;
89  Matrix.InsertGlobalValues(i, 1, values, indices);
90  }
91  Matrix.FillComplete();
92  Ifpack_Hypre preconditioner(&Matrix);
93  TEST_EQUALITY(preconditioner.Initialize(),0);
94 }
95 
96 
97 // Tests hypre's ability to work when A has a funky row map, but the vectors have
98 // a contiguous row map
99 TEUCHOS_UNIT_TEST( Ifpack_Hypre, ParameterList ){
100  const double tol = 1e-7;
101 
102  Epetra_MpiComm Comm(MPI_COMM_WORLD);
103 
104  Epetra_Map* Map;
105  // pointer to the matrix to be created
106  Epetra_CrsMatrix* Matrix;
107  // container for parameters
108  Teuchos::ParameterList GaleriList;
109  // here we specify the global dimension of the problem
110  int nx = 10 * Comm.NumProc();
111  int ny = 10 * Comm.NumProc();
112  GaleriList.set("nx", nx);
113  GaleriList.set("ny", ny);
114 
115  try
116  {
117  // Create the matrix
118  Map = Galeri::CreateMap("Cartesian2D", Comm, GaleriList);
119  Matrix = Galeri::CreateCrsMatrix("Biharmonic2D", Map, GaleriList);
120 
121  // Create the parameter list
122  Teuchos::ParameterList list("Preconditioner List");
123  RCP<FunctionParameter> functs[11];
124  functs[0] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetMaxIter, 1000)); // max iterations
125  functs[1] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTol, tol)); // conv. tolerance
126  functs[2] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTwoNorm, 1)); // use the two norm as the stopping criteria
127  functs[3] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetPrintLevel, 0)); // print solve info
128  functs[4] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetLogging, 1)); // needed to get run info later
129  functs[5] = rcp(new FunctionParameter(Preconditioner, &HYPRE_BoomerAMGSetPrintLevel, 1)); // print amg solution info
130  functs[6] = rcp(new FunctionParameter(Preconditioner, &HYPRE_BoomerAMGSetCoarsenType, 6));
131  functs[7] = rcp(new FunctionParameter(Preconditioner, &HYPRE_BoomerAMGSetRelaxType, 6)); //Sym G.S./Jacobi hybrid
132  functs[8] = rcp(new FunctionParameter(Preconditioner, &HYPRE_BoomerAMGSetNumSweeps, 1));
133  functs[9] = rcp(new FunctionParameter(Preconditioner, &HYPRE_BoomerAMGSetTol, 0.0)); // conv. tolerance zero
134  functs[10] = rcp(new FunctionParameter(Preconditioner, &HYPRE_BoomerAMGSetMaxIter, 1)); //do only one iteration!
135 
136  list.set("Solver", PCG);
137  list.set("Preconditioner", BoomerAMG);
138  list.set("SolveOrPrecondition", Solver);
139  list.set("SetPreconditioner", true);
140  list.set("NumFunctions", 11);
141  list.set<RCP<FunctionParameter>*>("Functions", functs);
142 
143  // Create the preconditioner
144  Ifpack_Hypre preconditioner(Matrix);
145  TEST_EQUALITY(preconditioner.SetParameters(list),0);
146  TEST_EQUALITY(preconditioner.Compute(),0);
147 
148  // Create the RHS and solution vector
149  int numVec = 2;
150  Epetra_MultiVector X(preconditioner.OperatorDomainMap(), numVec);
151  Epetra_MultiVector KnownX(preconditioner.OperatorDomainMap(), numVec);
152  TEST_EQUALITY(KnownX.Random(),0);
153  Epetra_MultiVector B(preconditioner.OperatorRangeMap(), numVec);
154  TEST_EQUALITY(preconditioner.Apply(KnownX, B),0);
155 
156  TEST_EQUALITY(preconditioner.ApplyInverse(B,X),0);
157  TEST_EQUALITY(EquivalentVectors(X, KnownX, tol*10*pow(10.0,Comm.NumProc())), true);
158 
159  //delete preconditioner;
160  delete Map;
161  delete Matrix;
162  }
163  catch (Galeri::Exception& rhs)
164  {
165  if (Comm.MyPID() == 0)
166  {
167  cerr << "Caught exception: ";
168  rhs.Print();
169  }
170  }
171 }
172 
173 
174 // Tests the hypre interface's ability to work with both a preconditioner and linear
175 // solver via ApplyInverse
176 TEUCHOS_UNIT_TEST( Ifpack_Hypre, Ifpack ){
177  const double tol = 1E-7;
178 
179  //
180  // Create Laplace2D with a contiguous row distribution
181  //
182  Epetra_CrsMatrix* Crs_Matrix = newCrsMatrix(4);
183 
184  //
185  // Create the hypre preconditioner
186  //
187  Ifpack Factory;
188  RCP<Ifpack_Preconditioner> preconditioner= rcp(Factory.Create("Hypre", Crs_Matrix));
189  TEST_EQUALITY(preconditioner->Initialize(), 0);
190  int NumProc = Crs_Matrix->Comm().NumProc();
191  int MyPID = Crs_Matrix->Comm().MyPID();
192 
193  //
194  // Create the solution vector and RHS
195  //
196  int numVec = 2;
197  Epetra_MultiVector X(preconditioner->OperatorRangeMap(), numVec);
198  Epetra_MultiVector KnownX(preconditioner->OperatorRangeMap(), numVec);
199  Epetra_MultiVector B(preconditioner->OperatorDomainMap(), numVec);
200  TEST_EQUALITY(KnownX.Random(), 0);
201  TEST_EQUALITY(preconditioner->Apply(KnownX, B), 0);
202 
203  Teuchos::ParameterList list("New List");
204  RCP<FunctionParameter> functs[5];
205  functs[0] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetMaxIter, 1000));
206  functs[1] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTol, 1e-9));
207  functs[2] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetLogging, 1));
208  functs[3] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetPrintLevel, 0));
209  functs[4] = rcp(new FunctionParameter(Preconditioner, &HYPRE_ParaSailsSetLogging, 0));
210  list.set("NumFunctions", 5);
211  list.set<RCP<FunctionParameter>*>("Functions", functs);
212  list.set("SolveOrPrecondition", Solver);
213  list.set("Solver", PCG);
214  list.set("Preconditioner", ParaSails);
215  list.set("SetPreconditioner", true);
216  TEST_EQUALITY(preconditioner->SetParameters(list), 0);
217  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(Solver, PCG); // Use a PCG Solver
218  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(Preconditioner, ParaSails); // Use a ParaSails Preconditioner
219  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(Solver, &HYPRE_ParCSRPCGSetMaxIter, 1000); // Set maximum iterations
220  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(Solver, &HYPRE_ParCSRPCGSetTol, 1e-9); // Set a tolerance
221  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(Solver); // Solve the problem
222  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(true); // Use the preconditioner
223  TEST_EQUALITY(preconditioner->Compute(),0);
224  preconditioner->Condest(Ifpack_Cheap, 1000, 1e-9, Crs_Matrix);
225  TEST_EQUALITY(preconditioner->ApplyInverse(B, X),0);
226  TEST_EQUALITY(EquivalentVectors(X, KnownX, tol*10*pow(10.0,NumProc)), true);
227  int numIters;
228  double residual;
229  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(Solver, &HYPRE_ParCSRPCGGetNumIterations, &numIters);
230  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->SetParameter(Solver, &HYPRE_ParCSRPCGGetFinalRelativeResidualNorm, &residual);
231  (dynamic_cast<Ifpack_Hypre*> (preconditioner.get()))->CallFunctions();
232  if(MyPID == 0) printf("It took %d iterations, and achieved %e residual.\n", numIters, residual);
233  delete Crs_Matrix;
234 }
235 
236 
237 // This example uses contiguous maps, so hypre should not have problems
238 TEUCHOS_UNIT_TEST( Ifpack_Hypre, DiagonalMatrixInOrder ) {
239  Epetra_MpiComm comm(MPI_COMM_WORLD);
240  int numProcs = comm.NumProc();
241  int myRank = comm.MyPID();
242 
243  //
244  // Construct the contiguous map
245  //
246  Epetra_Map accMap(2*numProcs,0,comm);
247 
248  //
249  // Construct the diagonal matrix
250  //
251  Epetra_CrsMatrix accMat(Copy,accMap,2,true);
252  int col;
253  double val;
254  col = 2*myRank;
255  val = 2*myRank+1;
256  accMat.InsertGlobalValues(col,1,&val,&col);
257  col = 2*myRank+1;
258  val = 2*myRank+2;
259  accMat.InsertGlobalValues(col,1,&val,&col);
260  accMat.FillComplete();
261 
262  //
263  // Create the initial guess and RHS
264  //
265  int numVec = 2;
266  Epetra_MultiVector X(accMap, numVec);
267  Epetra_MultiVector KnownX(accMap, numVec);
268  KnownX.Random();
269  Epetra_MultiVector B(accMap, numVec);
270  accMat.Apply(KnownX, B);
271 
272  //
273  // Create the parameter list
274  //
275  const double tol = 1e-7;
276  Teuchos::ParameterList list("Preconditioner List");
277  RCP<FunctionParameter> functs[5];
278  functs[0] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetMaxIter, 100)); // max iterations
279  functs[1] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTol, tol)); // conv. tolerance
280  functs[2] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTwoNorm, 1)); // use the two norm as the stopping criteria
281  functs[3] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetPrintLevel, 2)); // print solve info
282  functs[4] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetLogging, 1));
283  list.set("Solver", PCG);
284  list.set("SolveOrPrecondition", Solver);
285  list.set("SetPreconditioner", false);
286  list.set("NumFunctions", 5);
287  list.set<RCP<FunctionParameter>*>("Functions", functs);
288 
289  //
290  // Create the preconditioner (which is actually a PCG solver)
291  //
292  Ifpack_Hypre prec(&accMat);
293  TEST_EQUALITY(prec.SetParameters(list),0);
294  TEST_EQUALITY(prec.Compute(),0);
295 
296  //
297  // Solve the linear system
298  //
299  TEST_EQUALITY(prec.ApplyInverse(B,X),0);
300 
301  TEST_EQUALITY(EquivalentVectors(X, KnownX, tol*10*pow(10.0,numProcs)), true);
302 }
303 
304 
305 // hypre does not like the distribution of the vectors in this example.
306 // Our interface should detect that and remap as necessary.
307 TEUCHOS_UNIT_TEST( Ifpack_Hypre, DiagonalMatrixOutOfOrder ) {
308  Epetra_MpiComm comm(MPI_COMM_WORLD);
309  int numProcs = comm.NumProc();
310  int myRank = comm.MyPID();
311 
312  //
313  // Construct the map [0 0 1 1]
314  // Note that the rows will be out of order
315  //
316  int elementList[2];
317  elementList[0] = 2*myRank+1;
318  elementList[1] = 2*myRank;
319  Epetra_Map ncMap(2*numProcs,2,elementList,0,comm);
320 
321  //
322  // Construct the diagonal matrix
323  //
324  Epetra_CrsMatrix accMat(Copy,ncMap,2,true);
325  int col;
326  double val;
327  col = 2*myRank+1;
328  val = 2*myRank+2;
329  accMat.InsertGlobalValues(col,1,&val,&col);
330  col = 2*myRank;
331  val = 2*myRank+1;
332  accMat.InsertGlobalValues(col,1,&val,&col);
333  accMat.FillComplete();
334 
335  //
336  // Create the parameter list
337  //
338  const double tol = 1e-7;
339  Teuchos::ParameterList list("Preconditioner List");
340  RCP<FunctionParameter> functs[5];
341  functs[0] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetMaxIter, 100)); // max iterations
342  functs[1] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTol, tol)); // conv. tolerance
343  functs[2] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTwoNorm, 1)); // use the two norm as the stopping criteria
344  functs[3] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetPrintLevel, 2)); // print solve info
345  functs[4] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetLogging, 1));
346  list.set("Solver", PCG);
347  list.set("SolveOrPrecondition", Solver);
348  list.set("SetPreconditioner", false);
349  list.set("NumFunctions", 5);
350  list.set<RCP<FunctionParameter>*>("Functions", functs);
351 
352  //
353  // Create the preconditioner (which is actually a PCG solver)
354  //
355  Ifpack_Hypre prec(&accMat);
356  TEST_EQUALITY(prec.SetParameters(list),0);
357  TEST_EQUALITY(prec.Compute(),0);
358 
359  //
360  // Create the initial guess and RHS
361  // Note that these use non-contiguous maps
362  //
363  int numVec = 2;
364  Epetra_MultiVector X(ncMap, numVec);
365  Epetra_MultiVector KnownX(ncMap, numVec);
366  KnownX.Random();
367  Epetra_MultiVector B(ncMap, numVec);
368  accMat.Apply(KnownX, B);
369 
370  //
371  // Solve the linear system
372  //
373  TEST_EQUALITY(prec.ApplyInverse(RHS,X),0);
374 
375  TEST_EQUALITY(EquivalentVectors(X, RHS, tol*10*pow(10.0,numProcs)), true);
376 }
377 
378 
379 
380 // Creates the identity matrix with a non-contiguous row map
381 // Even though the Epetra identity matrix has a map that hypre should not be happy with,
382 // hypre should be able to redistribute it. It should also be able to accept the
383 // vectors we give it, since they're using the same distribution as the hypre matrix.
384 // This tests hypre's ability to perform as a linear solver via ApplyInverse.
385 TEUCHOS_UNIT_TEST( Ifpack_Hypre, NonContiguousRowMap ) {
386 
387  Epetra_MpiComm comm(MPI_COMM_WORLD);
388  int numProcs = comm.NumProc();
389  int myRank = comm.MyPID();
390 
391  //
392  // Construct the map [0 1 0 1]
393  //
394  int elementList[2];
395  elementList[0] = myRank;
396  elementList[1] = myRank+numProcs;
397  Epetra_Map badMap(2*numProcs,2,elementList,0,comm);
398  Epetra_Map goodMap(2*numProcs,0,comm);
399 
400  //
401  // Construct the identity matrix
402  //
403  Epetra_CrsMatrix badMat(Copy,badMap,2,true);
404  int col;
405  double val = 1.0;
406  col = myRank;
407  badMat.InsertGlobalValues(col,1,&val,&col);
408  col = myRank+numProcs;
409  badMat.InsertGlobalValues(col,1,&val,&col);
410  badMat.FillComplete();
411 
412  //
413  // Create the parameter list
414  //
415  const double tol = 1e-7;
416  Teuchos::ParameterList list("Preconditioner List");
417  RCP<FunctionParameter> functs[11];
418  functs[0] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetMaxIter, 1)); // max iterations
419  functs[1] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTol, tol)); // conv. tolerance
420  functs[2] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetTwoNorm, 1)); // use the two norm as the stopping criteria
421  functs[3] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetPrintLevel, 2)); // print solve info
422  functs[4] = rcp(new FunctionParameter(Solver, &HYPRE_PCGSetLogging, 1));
423  list.set("Solver", PCG);
424  list.set("SolveOrPrecondition", Solver);
425  list.set("SetPreconditioner", false);
426  list.set("NumFunctions", 5);
427  list.set<RCP<FunctionParameter>*>("Functions", functs);
428 
429  //
430  // Create the preconditioner (which is actually a PCG solver)
431  //
432  Ifpack_Hypre prec(&badMat);
433  TEST_EQUALITY(prec.SetParameters(list),0);
434  TEST_EQUALITY(prec.Compute(),0);
435 
436  //
437  // Create the initial guess and RHS
438  //
439  int numVec = 2;
440  Epetra_MultiVector X(goodMap, numVec);
441  Epetra_MultiVector RHS(goodMap, numVec);
442  RHS.Random();
443 
444  //
445  // Solve the linear system
446  //
447  TEST_EQUALITY(prec.ApplyInverse(RHS,X),0);
448 
449  TEST_EQUALITY(EquivalentVectors(X, RHS, tol*10*pow(10.0,numProcs)), true);
450 }
virtual double Condest(const Ifpack_CondestType CT=Ifpack_Cheap, const int MaxIters=1550, const double Tol=1e-9, Epetra_RowMatrix *Matrix=0)=0
Computes the condition number estimate, returns its value.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
int NumProc() const
bool EquivalentVectors(Epetra_MultiVector &Y1, Epetra_MultiVector &Y2, const double tol)
T * get() const
virtual const Epetra_Map & OperatorDomainMap() const =0
virtual int Initialize()=0
Computes all it is necessary to initialize the preconditioner.
virtual int MyPID() const =0
int FillComplete(bool OptimizeDataStorage=true)
static bool Solver
Definition: performance.cpp:70
virtual int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const =0
virtual const Epetra_Map & OperatorRangeMap() const =0
virtual int SetParameters(Teuchos::ParameterList &List)=0
Sets all parameters for the preconditioner.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
const double tol
virtual int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const =0
Applies the preconditioner to vector X, returns the result in Y.
virtual void Print(std::ostream &os) const
TEUCHOS_UNIT_TEST(Ifpack_Hypre, Construct)
const int N
cheap estimate
virtual int NumProc() const =0
Ifpack: a function class to define Ifpack preconditioners.
Definition: Ifpack.h:138
static Ifpack_Preconditioner * Create(EPrecType PrecType, Epetra_RowMatrix *Matrix, const int overlap=0, bool overrideSerialDefault=false)
Creates an instance of Ifpack_Preconditioner given the enum value of the preconditioner type (can not...
Definition: Ifpack.cpp:253
virtual int Compute()=0
Computes all it is necessary to apply the preconditioner.
#define TEST_EQUALITY(v1, v2)
Epetra_CrsMatrix * newCrsMatrix(int N)
const Epetra_Comm & Comm() const
int MyPID() const
#define RHS(a)
Definition: MatGenFD.c:60