xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 0c24e6a1e7d892dc3a9be60cfbbff2f1d2c50e14)
1 #define PETSCKSP_DLL
2 
3 /*
4    Provides an interface to the LLNL package hypre
5 */
6 #include "private/pcimpl.h"          /*I "petscpc.h" I*/
7 EXTERN_C_BEGIN
8 #include "HYPRE.h"
9 #include "IJ_mv.h"
10 #include "parcsr_ls.h"
11 EXTERN_C_END
12 
13 EXTERN PetscErrorCode MatHYPRE_IJMatrixCreate(Mat,HYPRE_IJMatrix*);
14 EXTERN PetscErrorCode MatHYPRE_IJMatrixCopy(Mat,HYPRE_IJMatrix);
15 EXTERN PetscErrorCode VecHYPRE_IJVectorCreate(Vec,HYPRE_IJVector*);
16 
17 /*
18    Private context (data structure) for the  preconditioner.
19 */
20 typedef struct {
21   HYPRE_Solver       hsolver;
22   HYPRE_IJMatrix     ij;
23   HYPRE_IJVector     b,x;
24 
25   PetscErrorCode     (*destroy)(HYPRE_Solver);
26   PetscErrorCode     (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
27   PetscErrorCode     (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
28 
29   MPI_Comm           comm_hypre;
30   char              *hypre_type;
31 
32   /* options for Pilut and BoomerAMG*/
33   int                maxiter;
34   double             tol;
35 
36   /* options for Pilut */
37   int                factorrowsize;
38 
39   /* options for ParaSails */
40   int                nlevels;
41   double             threshhold;
42   double             filter;
43   int                sym;
44   double             loadbal;
45   int                logging;
46   int                ruse;
47   int                symt;
48 
49   /* options for Euclid */
50   PetscTruth         bjilu;
51   int                levels;
52 
53   /* options for Euclid and BoomerAMG */
54   PetscTruth         printstatistics;
55 
56   /* options for BoomerAMG */
57   int                cycletype;
58   int                maxlevels;
59   double             strongthreshold;
60   double             maxrowsum;
61   int                gridsweeps[4];
62   int                coarsentype;
63   int                measuretype;
64   int                relaxtype[4];
65   double             relaxweight;
66   double             outerrelaxweight;
67   int                relaxorder;
68   double             truncfactor;
69   PetscTruth         applyrichardson;
70 
71 } PC_HYPRE;
72 
73 
74 #undef __FUNCT__
75 #define __FUNCT__ "PCSetUp_HYPRE"
76 static PetscErrorCode PCSetUp_HYPRE(PC pc)
77 {
78   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
79   PetscErrorCode     ierr;
80   HYPRE_ParCSRMatrix hmat;
81   HYPRE_ParVector    bv,xv;
82   PetscInt           bs;
83   int                hierr;
84 
85   PetscFunctionBegin;
86   if (!jac->hypre_type) {
87     ierr = PCHYPRESetType(pc,"pilut");CHKERRQ(ierr);
88   }
89 #if 1
90   if (!pc->setupcalled) {
91     /* create the matrix and vectors the first time through */
92     Vec x,b;
93     ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr);
94     ierr = MatGetVecs(pc->pmat,&x,&b);CHKERRQ(ierr);
95     ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr);
96     ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr);
97     ierr = VecDestroy(x);CHKERRQ(ierr);
98     ierr = VecDestroy(b);CHKERRQ(ierr);
99   } else if (pc->flag != SAME_NONZERO_PATTERN) {
100     /* rebuild the matrix from scratch */
101     ierr = HYPRE_IJMatrixDestroy(jac->ij);CHKERRQ(ierr);
102     ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr);
103   }
104 #else
105   if (!jac->ij) { /* create the matrix the first time through */
106     ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr);
107   }
108   if (!jac->b) { /* create the vectors the first time through */
109     Vec x,b;
110     ierr = MatGetVecs(pc->pmat,&x,&b);CHKERRQ(ierr);
111     ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr);
112     ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr);
113     ierr = VecDestroy(x);CHKERRQ(ierr);
114     ierr = VecDestroy(b);CHKERRQ(ierr);
115   }
116 #endif
117   /* special case for BoomerAMG */
118   if (jac->setup == HYPRE_BoomerAMGSetup) {
119     ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
120     if (bs > 1) {
121       ierr = HYPRE_BoomerAMGSetNumFunctions(jac->hsolver,bs);CHKERRQ(ierr);
122     }
123   };
124   ierr = MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);CHKERRQ(ierr);
125   ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr);
126   ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&bv);CHKERRQ(ierr);
127   ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&xv);CHKERRQ(ierr);
128   hierr = (*jac->setup)(jac->hsolver,hmat,bv,xv);
129   if (hierr) SETERRQ1(PETSC_ERR_LIB,"Error in HYPRE setup, error code %d",hierr);
130   PetscFunctionReturn(0);
131 }
132 
133 /*
134     Replaces the address where the HYPRE vector points to its data with the address of
135   PETSc's data. Saves the old address so it can be reset when we are finished with it.
136   Allows use to get the data into a HYPRE vector without the cost of memcopies
137 */
138 #define HYPREReplacePointer(b,newvalue,savedvalue) {\
139    hypre_ParVector *par_vector   = (hypre_ParVector *)hypre_IJVectorObject(((hypre_IJVector*)b));\
140    hypre_Vector    *local_vector = hypre_ParVectorLocalVector(par_vector);\
141    savedvalue         = local_vector->data;\
142    local_vector->data = newvalue;}
143 
144 #undef __FUNCT__
145 #define __FUNCT__ "PCApply_HYPRE"
146 static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x)
147 {
148   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
149   PetscErrorCode     ierr;
150   HYPRE_ParCSRMatrix hmat;
151   PetscScalar        *bv,*xv;
152   HYPRE_ParVector    jbv,jxv;
153   PetscScalar        *sbv,*sxv;
154   int                hierr;
155 
156   PetscFunctionBegin;
157   if (!jac->applyrichardson) {ierr = VecSet(x,0.0);CHKERRQ(ierr);}
158   ierr = VecGetArray(b,&bv);CHKERRQ(ierr);
159   ierr = VecGetArray(x,&xv);CHKERRQ(ierr);
160   HYPREReplacePointer(jac->b,bv,sbv);
161   HYPREReplacePointer(jac->x,xv,sxv);
162 
163   ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr);
164   ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);CHKERRQ(ierr);
165   ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);CHKERRQ(ierr);
166   hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv);
167   /* error code of 1 in BoomerAMG merely means convergence not achieved */
168   if (hierr && (hierr != 1 || jac->solve != HYPRE_BoomerAMGSolve)) SETERRQ1(PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
169   if (hierr) hypre__global_error = 0;
170 
171   HYPREReplacePointer(jac->b,sbv,bv);
172   HYPREReplacePointer(jac->x,sxv,xv);
173   ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr);
174   ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr);
175   PetscFunctionReturn(0);
176 }
177 
178 #undef __FUNCT__
179 #define __FUNCT__ "PCDestroy_HYPRE"
180 static PetscErrorCode PCDestroy_HYPRE(PC pc)
181 {
182   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
183   PetscErrorCode ierr;
184 
185   PetscFunctionBegin;
186   if (jac->ij) { ierr = HYPRE_IJMatrixDestroy(jac->ij);CHKERRQ(ierr); }
187   if (jac->b)  { ierr = HYPRE_IJVectorDestroy(jac->b);CHKERRQ(ierr);  }
188   if (jac->x)  { ierr = HYPRE_IJVectorDestroy(jac->x);CHKERRQ(ierr);  }
189   if (jac->destroy) { ierr = (*jac->destroy)(jac->hsolver);CHKERRQ(ierr); }
190   ierr = PetscStrfree(jac->hypre_type);CHKERRQ(ierr);
191   if (jac->comm_hypre != MPI_COMM_NULL) { ierr = MPI_Comm_free(&(jac->comm_hypre));CHKERRQ(ierr);}
192   ierr = PetscFree(jac);CHKERRQ(ierr);
193 
194   ierr = PetscObjectChangeTypeName((PetscObject)pc,0);CHKERRQ(ierr);
195   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","",PETSC_NULL);CHKERRQ(ierr);
196   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","",PETSC_NULL);CHKERRQ(ierr);
197   PetscFunctionReturn(0);
198 }
199 
200 /* --------------------------------------------------------------------------------------------*/
201 #undef __FUNCT__
202 #define __FUNCT__ "PCSetFromOptions_HYPRE_Pilut"
203 static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc)
204 {
205   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
206   PetscErrorCode ierr;
207   PetscTruth     flag;
208 
209   PetscFunctionBegin;
210   ierr = PetscOptionsHead("HYPRE Pilut Options");CHKERRQ(ierr);
211   ierr = PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);CHKERRQ(ierr);
212   if (flag) {
213     ierr = HYPRE_ParCSRPilutSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
214   }
215   ierr = PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);CHKERRQ(ierr);
216   if (flag) {
217     ierr = HYPRE_ParCSRPilutSetDropTolerance(jac->hsolver,jac->tol);CHKERRQ(ierr);
218   }
219   ierr = PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);CHKERRQ(ierr);
220   if (flag) {
221     ierr = HYPRE_ParCSRPilutSetFactorRowSize(jac->hsolver,jac->factorrowsize);CHKERRQ(ierr);
222   }
223   ierr = PetscOptionsTail();CHKERRQ(ierr);
224   PetscFunctionReturn(0);
225 }
226 
227 #undef __FUNCT__
228 #define __FUNCT__ "PCView_HYPRE_Pilut"
229 static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)
230 {
231   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
232   PetscErrorCode ierr;
233   PetscTruth     iascii;
234 
235   PetscFunctionBegin;
236   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
237   if (iascii) {
238     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut preconditioning\n");CHKERRQ(ierr);
239     if (jac->maxiter != PETSC_DEFAULT) {
240       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: maximum number of iterations %d\n",jac->maxiter);CHKERRQ(ierr);
241     } else {
242       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default maximum number of iterations \n");CHKERRQ(ierr);
243     }
244     if (jac->tol != PETSC_DEFAULT) {
245       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: drop tolerance %G\n",jac->tol);CHKERRQ(ierr);
246     } else {
247       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default drop tolerance \n");CHKERRQ(ierr);
248     }
249     if (jac->factorrowsize != PETSC_DEFAULT) {
250       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: factor row size %d\n",jac->factorrowsize);CHKERRQ(ierr);
251     } else {
252       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default factor row size \n");CHKERRQ(ierr);
253     }
254   }
255   PetscFunctionReturn(0);
256 }
257 
258 /* --------------------------------------------------------------------------------------------*/
259 #undef __FUNCT__
260 #define __FUNCT__ "PCSetFromOptions_HYPRE_Euclid"
261 static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc)
262 {
263   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
264   PetscErrorCode ierr;
265   PetscTruth     flag;
266   char           *args[2];
267 
268   PetscFunctionBegin;
269   ierr = PetscOptionsHead("HYPRE Euclid Options");CHKERRQ(ierr);
270   ierr = PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);CHKERRQ(ierr);
271   if (flag) {
272     char levels[16];
273     if (jac->levels < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be nonegative",jac->levels);
274     sprintf(levels,"%d",jac->levels);
275     args[0] = (char*)"-level"; args[1] = levels;
276     ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr);
277   }
278   ierr = PetscOptionsTruth("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,PETSC_NULL);CHKERRQ(ierr);
279   if (jac->bjilu) {
280     args[0] =(char*) "-bj"; args[1] = (char*)"1";
281     ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr);
282   }
283 
284   ierr = PetscOptionsTruth("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);CHKERRQ(ierr);
285   if (jac->printstatistics) {
286     args[0] = (char*)"-eu_stats"; args[1] = (char*)"1";
287     ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr);
288     args[0] = (char*)"-eu_mem"; args[1] = (char*)"1";
289     ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr);
290   }
291   ierr = PetscOptionsTail();CHKERRQ(ierr);
292   PetscFunctionReturn(0);
293 }
294 
295 #undef __FUNCT__
296 #define __FUNCT__ "PCView_HYPRE_Euclid"
297 static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)
298 {
299   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
300   PetscErrorCode ierr;
301   PetscTruth     iascii;
302 
303   PetscFunctionBegin;
304   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
305   if (iascii) {
306     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid preconditioning\n");CHKERRQ(ierr);
307     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: number of levels %d\n",jac->levels);CHKERRQ(ierr);
308     if (jac->bjilu) {
309       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: Using block Jacobi ILU instead of parallel ILU\n");CHKERRQ(ierr);
310     }
311   }
312   PetscFunctionReturn(0);
313 }
314 
315 /* --------------------------------------------------------------------------------------------*/
316 
317 #undef __FUNCT__
318 #define __FUNCT__ "PCApplyTranspose_HYPRE_BoomerAMG"
319 static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x)
320 {
321   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
322   PetscErrorCode     ierr;
323   HYPRE_ParCSRMatrix hmat;
324   PetscScalar        *bv,*xv;
325   HYPRE_ParVector    jbv,jxv;
326   PetscScalar        *sbv,*sxv;
327   int                hierr;
328 
329   PetscFunctionBegin;
330   ierr = VecSet(x,0.0);CHKERRQ(ierr);
331   ierr = VecGetArray(b,&bv);CHKERRQ(ierr);
332   ierr = VecGetArray(x,&xv);CHKERRQ(ierr);
333   HYPREReplacePointer(jac->b,bv,sbv);
334   HYPREReplacePointer(jac->x,xv,sxv);
335 
336   ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr);
337   ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);CHKERRQ(ierr);
338   ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);CHKERRQ(ierr);
339 
340   hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jbv,jxv);
341   /* error code of 1 in BoomerAMG merely means convergence not achieved */
342   if (hierr && (hierr != 1)) SETERRQ1(PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
343   if (hierr) hypre__global_error = 0;
344 
345   HYPREReplacePointer(jac->b,sbv,bv);
346   HYPREReplacePointer(jac->x,sxv,xv);
347   ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr);
348   ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr);
349   PetscFunctionReturn(0);
350 }
351 
352 static const char *HYPREBoomerAMGCycleType[]   = {"","V","W"};
353 static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout"};
354 static const char *HYPREBoomerAMGMeasureType[] = {"local","global"};
355 static const char *HYPREBoomerAMGRelaxType[]   = {"Jacobi","sequential-Gauss-Seidel","","SOR/Jacobi","backward-SOR/Jacobi","","symmetric-SOR/Jacobi","","","Gaussian-elimination"};
356 
357 #undef __FUNCT__
358 #define __FUNCT__ "PCSetFromOptions_HYPRE_BoomerAMG"
359 static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc)
360 {
361   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
362   PetscErrorCode ierr;
363   int            n,indx;
364   PetscTruth     flg, tmp_truth;
365   double         tmpdbl, twodbl[2];
366 
367   PetscFunctionBegin;
368   ierr = PetscOptionsHead("HYPRE BoomerAMG Options");CHKERRQ(ierr);
369   ierr = PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg);CHKERRQ(ierr);
370   if (flg) {
371     jac->cycletype = indx;
372     ierr = HYPRE_BoomerAMGSetCycleType(jac->hsolver,jac->cycletype);CHKERRQ(ierr);
373   }
374   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);CHKERRQ(ierr);
375   if (flg) {
376     if (jac->maxlevels < 2) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be at least two",jac->maxlevels);
377     ierr = HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);CHKERRQ(ierr);
378   }
379   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg);CHKERRQ(ierr);
380   if (flg) {
381     if (jac->maxiter < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %d must be at least one",jac->maxiter);
382     ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
383   }
384   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_tol","Convergence tolerance PER hypre call","None",jac->tol,&jac->tol,&flg);CHKERRQ(ierr);
385   if (flg) {
386     if (jac->tol < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Tolerance %G must be great than or equal zero",jac->tol);
387     ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr);
388   }
389 
390   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_truncfactor","Truncation factor","None",jac->truncfactor,&jac->truncfactor,&flg);CHKERRQ(ierr);
391   if (flg) {
392     if (jac->truncfactor < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Truncation factor %G must be great than or equal zero",jac->truncfactor);
393     ierr = HYPRE_BoomerAMGSetTruncFactor(jac->hsolver,jac->truncfactor);CHKERRQ(ierr);
394   }
395 
396   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);CHKERRQ(ierr);
397   if (flg) {
398     if (jac->strongthreshold < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Strong threshold %G must be great than or equal zero",jac->strongthreshold);
399     ierr = HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);CHKERRQ(ierr);
400   }
401   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);CHKERRQ(ierr);
402   if (flg) {
403     if (jac->maxrowsum < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be greater than zero",jac->maxrowsum);
404     if (jac->maxrowsum > 1.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be less than or equal one",jac->maxrowsum);
405     ierr = HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);CHKERRQ(ierr);
406   }
407 
408   /* Grid sweeps */
409   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_all","Number of sweeps for all grid levels (fine, up, and down)","None",jac->gridsweeps[0],&indx,&flg);CHKERRQ(ierr);
410   if (flg) {
411     ierr = HYPRE_BoomerAMGSetNumSweeps(jac->hsolver,indx);CHKERRQ(ierr);
412     /* modify the jac structure so we can view the updated options with PC_View */
413     jac->gridsweeps[0] = indx;
414     jac->gridsweeps[1] = jac->gridsweeps[2] = jac->gridsweeps[0];
415     jac->gridsweeps[3] = 1;  /*The coarse level is not affected by this function - hypre code sets to 1*/
416   }
417   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_fine","Number of sweeps for the fine level","None",jac->gridsweeps[0],&indx,&flg);CHKERRQ(ierr);
418   if (flg) {
419     ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 0);CHKERRQ(ierr);
420     jac->gridsweeps[0] = indx;
421   }
422   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[2],&indx,&flg);CHKERRQ(ierr);
423   if (flg) {
424     ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 1);CHKERRQ(ierr);
425     jac->gridsweeps[1] = indx;
426   }
427   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg);CHKERRQ(ierr);
428   if (flg) {
429     ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 2);CHKERRQ(ierr);
430     jac->gridsweeps[2] = indx;
431   }
432   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[3],&indx,&flg);CHKERRQ(ierr);
433   if (flg) {
434     ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 3);CHKERRQ(ierr);
435     jac->gridsweeps[3] = indx;
436   }
437 
438   /* Relax type */
439   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all","Relax type for fine, up, and down cycles (coarse level set to gaussian elimination)","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr);
440   if (flg) {
441     jac->relaxtype[0] = jac->relaxtype[1] = jac->relaxtype[2] = indx;
442     jac->relaxtype[3] = 9; /* hypre code sets coarse grid to 9 (G.E.)*/
443     ierr = HYPRE_BoomerAMGSetRelaxType(jac->hsolver, indx);CHKERRQ(ierr);
444   }
445   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_fine","Relax type on fine grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr);
446   if (flg) {
447     jac->relaxtype[0] = indx;
448     ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 0);CHKERRQ(ierr);
449   }
450   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr);
451   if (flg) {
452     jac->relaxtype[1] = indx;
453     ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 1);CHKERRQ(ierr);
454   }
455   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr);
456   if (flg) {
457     jac->relaxtype[2] = indx;
458     ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 2);CHKERRQ(ierr);
459   }
460   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[9],&indx,&flg);CHKERRQ(ierr);
461   if (flg) {
462     jac->relaxtype[3] = indx;
463     ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 3);CHKERRQ(ierr);
464   }
465 
466   /* Relaxation Weight */
467   ierr = PetscOptionsReal("-pc_hypre_boomeramg_relax_weight_all","Relaxation weight for all levels (0 = hypre estimates, -k = determined with k CG steps)","None",jac->relaxweight, &tmpdbl ,&flg);CHKERRQ(ierr);
468   if (flg) {
469     ierr = HYPRE_BoomerAMGSetRelaxWt(jac->hsolver,tmpdbl);CHKERRQ(ierr);
470     jac->relaxweight = tmpdbl;
471   }
472 
473   n=2;
474   twodbl[0] = twodbl[1] = 1.0;
475   ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level","Set the relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr);
476   if (flg) {
477     if (n == 2) {
478       indx =  (int)PetscAbsReal(twodbl[1]);
479       ierr = HYPRE_BoomerAMGSetLevelRelaxWt(jac->hsolver,twodbl[0],indx);CHKERRQ(ierr);
480     } else {
481       SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %d",n);
482     }
483   }
484 
485   /* Outer relaxation Weight */
486   ierr = PetscOptionsReal("-pc_hypre_boomeramg_outer_relax_weight_all","Outer relaxation weight for all levels ( -k = determined with k CG steps)","None",jac->outerrelaxweight, &tmpdbl ,&flg);CHKERRQ(ierr);
487   if (flg) {
488     ierr = HYPRE_BoomerAMGSetOuterWt( jac->hsolver, tmpdbl);CHKERRQ(ierr);
489     jac->outerrelaxweight = tmpdbl;
490   }
491 
492   n=2;
493   twodbl[0] = twodbl[1] = 1.0;
494   ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_outer_relax_weight_level","Set the outer relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr);
495   if (flg) {
496     if (n == 2) {
497       indx =  (int)PetscAbsReal(twodbl[1]);
498       ierr = HYPRE_BoomerAMGSetLevelOuterWt( jac->hsolver, twodbl[0], indx);CHKERRQ(ierr);
499     } else {
500       SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %d",n);
501     }
502   }
503 
504   /* the Relax Order */
505   /* ierr = PetscOptionsName("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", &flg);CHKERRQ(ierr); */
506   ierr = PetscOptionsTruth( "-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
507 
508   if (flg) {
509     jac->relaxorder = 0;
510     ierr = HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, jac->relaxorder);CHKERRQ(ierr);
511   }
512   ierr = PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,2,HYPREBoomerAMGMeasureType[0],&indx,&flg);CHKERRQ(ierr);
513   if (flg) {
514     jac->measuretype = indx;
515     ierr = HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);CHKERRQ(ierr);
516   }
517   ierr = PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,7,HYPREBoomerAMGCoarsenType[6],&indx,&flg);CHKERRQ(ierr);
518   if (flg) {
519     jac->coarsentype = indx;
520     ierr = HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);CHKERRQ(ierr);
521   }
522   ierr = PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg);CHKERRQ(ierr);
523   if (flg) {
524     int level=3;
525     jac->printstatistics = PETSC_TRUE;
526     ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,PETSC_NULL);CHKERRQ(ierr);
527     ierr = HYPRE_BoomerAMGSetPrintLevel(jac->hsolver,level);CHKERRQ(ierr);
528     ierr = HYPRE_BoomerAMGSetDebugFlag(jac->hsolver,level);CHKERRQ(ierr);
529   }
530   ierr = PetscOptionsTail();CHKERRQ(ierr);
531   PetscFunctionReturn(0);
532 }
533 
534 #undef __FUNCT__
535 #define __FUNCT__ "PCApplyRichardson_HYPRE_BoomerAMG"
536 static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its)
537 {
538   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
539   PetscErrorCode ierr;
540 
541   PetscFunctionBegin;
542   ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,its*jac->maxiter);CHKERRQ(ierr);
543   ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,PetscMin(rtol,jac->tol));CHKERRQ(ierr);
544   jac->applyrichardson = PETSC_TRUE;
545   ierr = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr);
546   jac->applyrichardson = PETSC_FALSE;
547   ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr);
548   ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
549   PetscFunctionReturn(0);
550 }
551 
552 
553 #undef __FUNCT__
554 #define __FUNCT__ "PCView_HYPRE_BoomerAMG"
555 static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
556 {
557   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
558   PetscErrorCode ierr;
559   PetscTruth     iascii;
560 
561   PetscFunctionBegin;
562   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
563   if (iascii) {
564     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr);
565     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr);
566     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);CHKERRQ(ierr);
567     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of iterations PER hypre call %d\n",jac->maxiter);CHKERRQ(ierr);
568     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Convergence tolerance PER hypre call %G\n",jac->tol);CHKERRQ(ierr);
569     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Threshold for strong coupling %G\n",jac->strongthreshold);CHKERRQ(ierr);
570     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum row sums %G\n",jac->maxrowsum);CHKERRQ(ierr);
571 
572     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on fine grid %d\n",jac->gridsweeps[0]);CHKERRQ(ierr);
573     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps down         %d\n",jac->gridsweeps[1]);CHKERRQ(ierr);
574     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps up           %d\n",jac->gridsweeps[2]);CHKERRQ(ierr);
575     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on coarse    %d\n",jac->gridsweeps[3]);CHKERRQ(ierr);
576 
577     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on fine grid  %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr);
578     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax down          %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr);
579     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax up            %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr);
580     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on coarse     %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[3]]);CHKERRQ(ierr);
581 
582     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax weight  (all)      %G\n",jac->relaxweight);CHKERRQ(ierr);
583     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Outer relax weight (all) %G\n",jac->outerrelaxweight);CHKERRQ(ierr);
584 
585     if (jac->relaxorder) {
586       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Using CF-relaxation\n");CHKERRQ(ierr);
587     } else {
588       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Not using CF-relaxation\n");CHKERRQ(ierr);
589     }
590     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Measure type        %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr);
591     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Coarsen type        %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr);
592   }
593   PetscFunctionReturn(0);
594 }
595 
596 /* --------------------------------------------------------------------------------------------*/
597 #undef __FUNCT__
598 #define __FUNCT__ "PCSetFromOptions_HYPRE_ParaSails"
599 static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc)
600 {
601   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
602   PetscErrorCode ierr;
603   int            indx;
604   PetscTruth     flag;
605   const char     *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
606 
607   PetscFunctionBegin;
608   ierr = PetscOptionsHead("HYPRE ParaSails Options");CHKERRQ(ierr);
609   ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr);
610   ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,&flag);CHKERRQ(ierr);
611   if (flag) {
612     ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr);
613   }
614 
615   ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr);
616   if (flag) {
617     ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr);
618   }
619 
620   ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr);
621   if (flag) {
622     ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr);
623   }
624 
625   ierr = PetscOptionsTruth("-pc_hypre_parasails_logging","Print info to screen","None",(PetscTruth)jac->logging,(PetscTruth*)&jac->logging,&flag);CHKERRQ(ierr);
626   if (flag) {
627     ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr);
628   }
629 
630   ierr = PetscOptionsTruth("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscTruth)jac->ruse,(PetscTruth*)&jac->ruse,&flag);CHKERRQ(ierr);
631   if (flag) {
632     ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr);
633   }
634 
635   ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],&indx,&flag);CHKERRQ(ierr);
636   if (flag) {
637     jac->symt = indx;
638     ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr);
639   }
640 
641   ierr = PetscOptionsTail();CHKERRQ(ierr);
642   PetscFunctionReturn(0);
643 }
644 
645 #undef __FUNCT__
646 #define __FUNCT__ "PCView_HYPRE_ParaSails"
647 static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
648 {
649   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
650   PetscErrorCode ierr;
651   PetscTruth     iascii;
652   const char     *symt = 0;;
653 
654   PetscFunctionBegin;
655   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
656   if (iascii) {
657     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails preconditioning\n");CHKERRQ(ierr);
658     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: nlevels %d\n",jac->nlevels);CHKERRQ(ierr);
659     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: threshold %G\n",jac->threshhold);CHKERRQ(ierr);
660     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: filter %G\n",jac->filter);CHKERRQ(ierr);
661     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: load balance %G\n",jac->loadbal);CHKERRQ(ierr);
662     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: reuse nonzero structure %s\n",PetscTruths[jac->ruse]);CHKERRQ(ierr);
663     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: print info to screen %s\n",PetscTruths[jac->logging]);CHKERRQ(ierr);
664     if (!jac->symt) {
665       symt = "nonsymmetric matrix and preconditioner";
666     } else if (jac->symt == 1) {
667       symt = "SPD matrix and preconditioner";
668     } else if (jac->symt == 2) {
669       symt = "nonsymmetric matrix but SPD preconditioner";
670     } else {
671       SETERRQ1(PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt);
672     }
673     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: %s\n",symt);CHKERRQ(ierr);
674   }
675   PetscFunctionReturn(0);
676 }
677 /* ---------------------------------------------------------------------------------*/
678 
679 EXTERN_C_BEGIN
680 #undef __FUNCT__
681 #define __FUNCT__ "PCHYPREGetType_HYPRE"
682 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType_HYPRE(PC pc,const char *name[])
683 {
684   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
685 
686   PetscFunctionBegin;
687   *name = jac->hypre_type;
688   PetscFunctionReturn(0);
689 }
690 EXTERN_C_END
691 
692 EXTERN_C_BEGIN
693 #undef __FUNCT__
694 #define __FUNCT__ "PCHYPRESetType_HYPRE"
695 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType_HYPRE(PC pc,const char name[])
696 {
697   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
698   PetscErrorCode ierr;
699   PetscTruth     flag;
700 
701   PetscFunctionBegin;
702   if (jac->hypre_type) {
703     ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr);
704     if (!flag) SETERRQ(PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set");
705     PetscFunctionReturn(0);
706   } else {
707     ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr);
708   }
709 
710   jac->maxiter            = PETSC_DEFAULT;
711   jac->tol                = PETSC_DEFAULT;
712   jac->printstatistics    = PetscLogPrintInfo;
713 
714   ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr);
715   if (flag) {
716     ierr                    = HYPRE_ParCSRPilutCreate(jac->comm_hypre,&jac->hsolver);
717     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
718     pc->ops->view           = PCView_HYPRE_Pilut;
719     jac->destroy            = HYPRE_ParCSRPilutDestroy;
720     jac->setup              = HYPRE_ParCSRPilutSetup;
721     jac->solve              = HYPRE_ParCSRPilutSolve;
722     jac->factorrowsize      = PETSC_DEFAULT;
723     PetscFunctionReturn(0);
724   }
725   ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr);
726   if (flag) {
727     ierr                    = HYPRE_ParaSailsCreate(jac->comm_hypre,&jac->hsolver);
728     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
729     pc->ops->view           = PCView_HYPRE_ParaSails;
730     jac->destroy            = HYPRE_ParaSailsDestroy;
731     jac->setup              = HYPRE_ParaSailsSetup;
732     jac->solve              = HYPRE_ParaSailsSolve;
733     /* initialize */
734     jac->nlevels     = 1;
735     jac->threshhold  = .1;
736     jac->filter      = .1;
737     jac->loadbal     = 0;
738     if (PetscLogPrintInfo) {
739       jac->logging     = (int) PETSC_TRUE;
740     } else {
741       jac->logging     = (int) PETSC_FALSE;
742     }
743     jac->ruse = (int) PETSC_FALSE;
744     jac->symt   = 0;
745     ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr);
746     ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr);
747     ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr);
748     ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr);
749     ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr);
750     ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr);
751     PetscFunctionReturn(0);
752   }
753   ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr);
754   if (flag) {
755     ierr                    = HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver);
756     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
757     pc->ops->view           = PCView_HYPRE_Euclid;
758     jac->destroy            = HYPRE_EuclidDestroy;
759     jac->setup              = HYPRE_EuclidSetup;
760     jac->solve              = HYPRE_EuclidSolve;
761     /* initialization */
762     jac->bjilu              = PETSC_FALSE;
763     jac->levels             = 1;
764     PetscFunctionReturn(0);
765   }
766   ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr);
767   if (flag) {
768     ierr                     = HYPRE_BoomerAMGCreate(&jac->hsolver);
769     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
770     pc->ops->view            = PCView_HYPRE_BoomerAMG;
771     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
772     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
773     jac->destroy             = HYPRE_BoomerAMGDestroy;
774     jac->setup               = HYPRE_BoomerAMGSetup;
775     jac->solve               = HYPRE_BoomerAMGSolve;
776     jac->applyrichardson     = PETSC_FALSE;
777     /* these defaults match the hypre defaults */
778     jac->cycletype        = 1;
779     jac->maxlevels        = 25;
780     jac->maxiter          = 1;
781     jac->tol              = 1.e-7;
782     jac->truncfactor      = 0.0;
783     jac->strongthreshold  = .25;
784     jac->maxrowsum        = .9;
785     jac->coarsentype      = 6;
786     jac->measuretype      = 0;
787     jac->gridsweeps[0]    = jac->gridsweeps[1] = jac->gridsweeps[2] = jac->gridsweeps[3]  = 1;
788     jac->relaxtype[0]     = jac->relaxtype[1]  = jac->relaxtype[2]  = 3;
789     jac->relaxtype[3]     = 9;
790     jac->relaxweight      = 1.0;
791     jac->outerrelaxweight = 1.0;
792     jac->relaxorder       = 1;
793     ierr = HYPRE_BoomerAMGSetCycleType(jac->hsolver,jac->cycletype);CHKERRQ(ierr);
794     ierr = HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);CHKERRQ(ierr);
795     ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
796     ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr);
797     ierr = HYPRE_BoomerAMGSetTruncFactor(jac->hsolver,jac->truncfactor);CHKERRQ(ierr);
798     ierr = HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);CHKERRQ(ierr);
799     ierr = HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);CHKERRQ(ierr);
800     ierr = HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);CHKERRQ(ierr);
801     ierr = HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);CHKERRQ(ierr);
802     ierr = HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, jac->relaxorder);CHKERRQ(ierr);
803     PetscFunctionReturn(0);
804   }
805   ierr = PetscStrfree(jac->hypre_type);CHKERRQ(ierr);
806   jac->hypre_type = PETSC_NULL;
807   SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name);
808   PetscFunctionReturn(0);
809 }
810 EXTERN_C_END
811 
812 /*
813     It only gets here if the HYPRE type has not been set before the call to
814    ...SetFromOptions() which actually is most of the time
815 */
816 #undef __FUNCT__
817 #define __FUNCT__ "PCSetFromOptions_HYPRE"
818 static PetscErrorCode PCSetFromOptions_HYPRE(PC pc)
819 {
820   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
821   PetscErrorCode ierr;
822   int            indx;
823   const char     *type[] = {"pilut","parasails","boomeramg","euclid"};
824   PetscTruth     flg;
825 
826   PetscFunctionBegin;
827   ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr);
828   ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"pilut",&indx,&flg);CHKERRQ(ierr);
829   if (PetscOptionsPublishCount) {   /* force the default if it was not yet set and user did not set with option */
830     if (!flg && !jac->hypre_type) {
831       flg   = PETSC_TRUE;
832       indx = 0;
833     }
834   }
835   if (flg) {
836     ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr);
837   }
838   if (pc->ops->setfromoptions) {
839     ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr);
840   }
841   ierr = PetscOptionsTail();CHKERRQ(ierr);
842   PetscFunctionReturn(0);
843 }
844 
845 #undef __FUNCT__
846 #define __FUNCT__ "PCHYPRESetType"
847 /*@C
848      PCHYPRESetType - Sets which hypre preconditioner you wish to use
849 
850    Input Parameters:
851 +     pc - the preconditioner context
852 -     name - either  pilut, parasails, boomeramg, euclid
853 
854    Options Database Keys:
855    -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
856 
857    Level: intermediate
858 
859 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
860            PCHYPRE
861 
862 @*/
863 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType(PC pc,const char name[])
864 {
865   PetscErrorCode ierr,(*f)(PC,const char[]);
866 
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
869   PetscValidCharPointer(name,2);
870   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);CHKERRQ(ierr);
871   if (f) {
872     ierr = (*f)(pc,name);CHKERRQ(ierr);
873   }
874   PetscFunctionReturn(0);
875 }
876 
877 #undef __FUNCT__
878 #define __FUNCT__ "PCHYPREGetType"
879 /*@C
880      PCHYPREGetType - Gets which hypre preconditioner you are using
881 
882    Input Parameter:
883 .     pc - the preconditioner context
884 
885    Output Parameter:
886 .     name - either  pilut, parasails, boomeramg, euclid
887 
888    Level: intermediate
889 
890 .seealso:  PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC,
891            PCHYPRE
892 
893 @*/
894 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType(PC pc,const char *name[])
895 {
896   PetscErrorCode ierr,(*f)(PC,const char*[]);
897 
898   PetscFunctionBegin;
899   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
900   PetscValidPointer(name,2);
901   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPREGetType_C",(void (**)(void))&f);CHKERRQ(ierr);
902   if (f) {
903     ierr = (*f)(pc,name);CHKERRQ(ierr);
904   }
905   PetscFunctionReturn(0);
906 }
907 
908 /*MC
909      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
910 
911    Options Database Keys:
912 +   -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
913 -   Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX
914           preconditioner
915 
916    Level: intermediate
917 
918    Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()),
919           the many hypre options can ONLY be set via the options database (e.g. the command line
920           or with PetscOptionsSetValue(), there are no functions to set them)
921 
922           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations
923           (V-cycles) that boomeramg does EACH time it is called. So for example, if it is set to 2 then
924           2-V-cycles are being used to define the preconditioner. -ksp_max_iter and -ksp_rtol STILL determine
925           the total number of iterations and tolerance for the Krylov solver. For example, if
926           -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10 then AT MOST twenty V-cycles of boomeramg
927           will be called.
928 
929           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
930           and use -ksp_max_it to control the number of V-cycles.
931           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
932 
933 	  2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
934 	  -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
935 
936 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
937            PCHYPRESetType()
938 
939 M*/
940 
941 EXTERN_C_BEGIN
942 #undef __FUNCT__
943 #define __FUNCT__ "PCCreate_HYPRE"
944 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_HYPRE(PC pc)
945 {
946   PC_HYPRE       *jac;
947   PetscErrorCode ierr;
948 
949   PetscFunctionBegin;
950   ierr = PetscNew(PC_HYPRE,&jac);CHKERRQ(ierr);
951   ierr = PetscLogObjectMemory(pc,sizeof(PC_HYPRE));CHKERRQ(ierr);
952   pc->data                 = jac;
953   pc->ops->destroy         = PCDestroy_HYPRE;
954   pc->ops->setfromoptions  = PCSetFromOptions_HYPRE;
955   pc->ops->setup           = PCSetUp_HYPRE;
956   pc->ops->apply           = PCApply_HYPRE;
957   jac->comm_hypre          = MPI_COMM_NULL;
958   jac->hypre_type          = PETSC_NULL;
959   /* duplicate communicator for hypre */
960   ierr = MPI_Comm_dup(pc->comm,&(jac->comm_hypre));CHKERRQ(ierr);
961   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr);
962   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr);
963   PetscFunctionReturn(0);
964 }
965 EXTERN_C_END
966