xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 1086b0692845c998bbb8fcece0fee6b3fb8909cd)
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,"pilut");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   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
907   PetscErrorCode ierr;
908   int            indx;
909   const char     *type[] = {"pilut","parasails","boomeramg","euclid"};
910   PetscTruth     flg;
911 
912   PetscFunctionBegin;
913   ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr);
914   ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"pilut",&indx,&flg);CHKERRQ(ierr);
915   if (PetscOptionsPublishCount) {   /* force the default if it was not yet set and user did not set with option */
916     if (!flg && !jac->hypre_type) {
917       flg   = PETSC_TRUE;
918       indx = 0;
919     }
920   }
921   if (flg) {
922     ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr);
923   }
924   if (pc->ops->setfromoptions) {
925     ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr);
926   }
927   ierr = PetscOptionsTail();CHKERRQ(ierr);
928   PetscFunctionReturn(0);
929 }
930 
931 #undef __FUNCT__
932 #define __FUNCT__ "PCHYPRESetType"
933 /*@C
934      PCHYPRESetType - Sets which hypre preconditioner you wish to use
935 
936    Input Parameters:
937 +     pc - the preconditioner context
938 -     name - either  pilut, parasails, boomeramg, euclid
939 
940    Options Database Keys:
941    -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
942 
943    Level: intermediate
944 
945 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
946            PCHYPRE
947 
948 @*/
949 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType(PC pc,const char name[])
950 {
951   PetscErrorCode ierr,(*f)(PC,const char[]);
952 
953   PetscFunctionBegin;
954   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
955   PetscValidCharPointer(name,2);
956   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);CHKERRQ(ierr);
957   if (f) {
958     ierr = (*f)(pc,name);CHKERRQ(ierr);
959   }
960   PetscFunctionReturn(0);
961 }
962 
963 #undef __FUNCT__
964 #define __FUNCT__ "PCHYPREGetType"
965 /*@C
966      PCHYPREGetType - Gets which hypre preconditioner you are using
967 
968    Input Parameter:
969 .     pc - the preconditioner context
970 
971    Output Parameter:
972 .     name - either  pilut, parasails, boomeramg, euclid
973 
974    Level: intermediate
975 
976 .seealso:  PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC,
977            PCHYPRE
978 
979 @*/
980 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType(PC pc,const char *name[])
981 {
982   PetscErrorCode ierr,(*f)(PC,const char*[]);
983 
984   PetscFunctionBegin;
985   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
986   PetscValidPointer(name,2);
987   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPREGetType_C",(void (**)(void))&f);CHKERRQ(ierr);
988   if (f) {
989     ierr = (*f)(pc,name);CHKERRQ(ierr);
990   }
991   PetscFunctionReturn(0);
992 }
993 
994 /*MC
995      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
996 
997    Options Database Keys:
998 +   -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
999 -   Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX
1000           preconditioner
1001 
1002    Level: intermediate
1003 
1004    Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()),
1005           the many hypre options can ONLY be set via the options database (e.g. the command line
1006           or with PetscOptionsSetValue(), there are no functions to set them)
1007 
1008           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations
1009           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
1010           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
1011           (-pc_hypre_boomeramg_rtol should be set to 0.0 - the default - to strictly use a fixed number of
1012           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
1013           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
1014           then AT MOST twenty V-cycles of boomeramg will be called.
1015 
1016            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
1017            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
1018            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
1019           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
1020           and use -ksp_max_it to control the number of V-cycles.
1021           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
1022 
1023 	  2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
1024 	  -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
1025 
1026 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
1027            PCHYPRESetType()
1028 
1029 M*/
1030 
1031 EXTERN_C_BEGIN
1032 #undef __FUNCT__
1033 #define __FUNCT__ "PCCreate_HYPRE"
1034 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_HYPRE(PC pc)
1035 {
1036   PC_HYPRE       *jac;
1037   PetscErrorCode ierr;
1038 
1039   PetscFunctionBegin;
1040   ierr = PetscNewLog(pc,PC_HYPRE,&jac);CHKERRQ(ierr);
1041   pc->data                 = jac;
1042   pc->ops->destroy         = PCDestroy_HYPRE;
1043   pc->ops->setfromoptions  = PCSetFromOptions_HYPRE;
1044   pc->ops->setup           = PCSetUp_HYPRE;
1045   pc->ops->apply           = PCApply_HYPRE;
1046   jac->comm_hypre          = MPI_COMM_NULL;
1047   jac->hypre_type          = PETSC_NULL;
1048   /* duplicate communicator for hypre */
1049   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(jac->comm_hypre));CHKERRQ(ierr);
1050   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr);
1051   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr);
1052   PetscFunctionReturn(0);
1053 }
1054 EXTERN_C_END
1055