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