Actual source code: hyppilut.c

  1: /*$Id: bvec2.c,v 1.202 2001/09/12 03:26:24 bsmith Exp $*/
  2: /*

  4: */

 6:  #include src/sles/pc/pcimpl.h
  7: EXTERN_C_BEGIN
  8: #include "HYPRE.h"
  9: #include "IJ_mv.h"
 10: #include "HYPRE_parcsr_ls.h"
 11: EXTERN_C_END

 13: extern int MatHYPRE_IJMatrixCreate(Mat,HYPRE_IJMatrix*);
 14: extern int MatHYPRE_IJMatrixCopy(Mat,HYPRE_IJMatrix);
 15: extern int VecHYPRE_IJVectorCreate(Vec,HYPRE_IJVector*);

 17: /* 
 18:    Private context (data structure) for the  preconditioner.  
 19: */
 20: typedef struct {
 21:   HYPRE_Solver       hsolver;
 22:   HYPRE_IJMatrix     ij;
 23:   HYPRE_IJVector     b,x;

 25:   int (*destroy)(HYPRE_Solver);
 26:   int (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
 27:   int (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
 28: 
 29:   MPI_Comm          comm_hypre;

 31:   /* options for pilut and BoomerAMG*/
 32:   int                maxiter;
 33:   double             tol;

 35:   /* options for pilut */
 36:   int                factorrowsize;

 38:   /* options for parasails */
 39:   int                nlevels;
 40:   double             threshhold;
 41:   double             filter;
 42:   int                sym;
 43:   double             loadbal;
 44:   int                logging;
 45:   int                ruse;
 46:   int                symt;

 48:   /* options for euclid */
 49:   PetscTruth         bjilu;
 50:   int                levels;

 52:   /* options for euclid and BoomerAMG */
 53:   PetscTruth         printstatistics;

 55:   /* options for BoomerAMG */
 56:   int                maxlevels;
 57:   double             strongthreshold;
 58:   double             maxrowsum;
 59:   int                *gridsweeps;
 60:   int                coarsentype;
 61:   int                measuretype;
 62:   int                *relaxtype;
 63:   int                **gridrelaxpoints;
 64: } PC_HYPRE;


 69: static int PCSetUp_HYPRE(PC pc)
 70: {
 71:   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
 72:   int                ierr;
 73:   HYPRE_ParCSRMatrix hmat;
 74:   HYPRE_ParVector    bv,xv;

 77:   if (!jac->ij) { /* create the matrix the first time through */
 78:     MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);
 79:   }
 80:   if (!jac->b) {
 81:     VecHYPRE_IJVectorCreate(pc->vec,&jac->b);
 82:     VecHYPRE_IJVectorCreate(pc->vec,&jac->x);
 83:   }
 84:   MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);
 85:   HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);
 86:   HYPRE_IJVectorGetObject(jac->b,(void**)&bv);
 87:   HYPRE_IJVectorGetObject(jac->x,(void**)&xv);
 88:   (*jac->setup)(jac->hsolver,hmat,bv,xv);
 89:   if (ierr) SETERRQ1(1,"Error in HYPRE setup, error code %d",ierr);
 90:   return(0);
 91: }

 93: /*
 94:     Replaces the address where the HYPRE vector points to its data with the address of
 95:   PETSc's data. Saves the old address so it can be reset when we are finished with it.
 96:   Allows use to get the data into a HYPRE vector without the cost of memcopies 
 97: */
 98: #define HYPREReplacePointer(b,newvalue,savedvalue) {\
 99:    hypre_ParVector *par_vector   = (hypre_ParVector *)hypre_IJVectorObject(((hypre_IJVector*)b));\
100:    hypre_Vector    *local_vector = hypre_ParVectorLocalVector(par_vector);\
101:    savedvalue         = local_vector->data;\
102:    local_vector->data = newvalue;}

106: static int PCApply_HYPRE(PC pc,Vec b,Vec x)
107: {
108:   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
109:   int                ierr;
110:   HYPRE_ParCSRMatrix hmat;
111:   PetscScalar        *bv,*xv;
112:   HYPRE_ParVector    jbv,jxv;
113:   PetscScalar        *sbv,*sxv;
114:   PetscScalar        zero=0.0;


118:   VecSet(&zero,x);
119:   VecGetArray(b,&bv);
120:   VecGetArray(x,&xv);
121:   HYPREReplacePointer(jac->b,bv,sbv);
122:   HYPREReplacePointer(jac->x,xv,sxv);

124:   HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);
125:   HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);
126:   HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);
127:   (*jac->solve)(jac->hsolver,hmat,jbv,jxv);
128:   /* error code of 1 in boomerAMG merely means convergence not achieved */
129:   if (ierr && (ierr != 1 || jac->solve != HYPRE_BoomerAMGSolve)) SETERRQ1(1,"Error in HYPRE solver, error code %d",ierr);
130: 

132:   HYPREReplacePointer(jac->b,sbv,bv);
133:   HYPREReplacePointer(jac->x,sxv,xv);
134:   VecRestoreArray(x,&xv);
135:   VecRestoreArray(b,&bv);

137:   return(0);
138: }

142: static int PCDestroy_HYPRE(PC pc)
143: {
144:   PC_HYPRE *jac = (PC_HYPRE*)pc->data;
145:   int      ierr;

148:   HYPRE_IJMatrixDestroy(jac->ij);
149:   HYPRE_IJVectorDestroy(jac->b);
150:   HYPRE_IJVectorDestroy(jac->x);
151:   MPI_Comm_free(&(jac->comm_hypre));
152:   (*jac->destroy)(jac->hsolver);
153:   PetscFree(jac);
154:   return(0);
155: }

157: /* --------------------------------------------------------------------------------------------*/
160: static int PCSetFromOptions_HYPRE_Pilut(PC pc)
161: {
162:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
163:   int        ierr;
164:   PetscTruth flag;

167:   PetscOptionsHead("HYPRE Pilut Options");
168:     PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);
169:     if (flag) {
170:       HYPRE_ParCSRPilutSetMaxIter(jac->hsolver,jac->maxiter);
171:     }
172:     PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);
173:     if (flag) {
174:       HYPRE_ParCSRPilutSetDropTolerance(jac->hsolver,jac->tol);
175:     }
176:     PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);
177:     if (flag) {
178:       HYPRE_ParCSRPilutSetFactorRowSize(jac->hsolver,jac->factorrowsize);
179:     }
180:   PetscOptionsTail();
181:   return(0);
182: }

186: static int PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)
187: {
188:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
189:   int         ierr;
190:   PetscTruth  isascii;

193:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
194:   if (isascii) {
195:     PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut preconditioning\n");
196:     if (jac->maxiter != PETSC_DEFAULT) {
197:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: maximum number of iterations %d\n",jac->maxiter);
198:     } else {
199:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default maximum number of iterations \n");
200:     }
201:     if (jac->tol != PETSC_DEFAULT) {
202:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: drop tolerance %g\n",jac->tol);
203:     } else {
204:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default drop tolerance \n");
205:     }
206:     if (jac->factorrowsize != PETSC_DEFAULT) {
207:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: factor row size %d\n",jac->factorrowsize);
208:     } else {
209:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default factor row size \n");
210:     }
211:   }
212:   return(0);
213: }

215: /* --------------------------------------------------------------------------------------------*/
218: static int PCSetFromOptions_HYPRE_Euclid(PC pc)
219: {
220:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
221:   int        ierr;
222:   PetscTruth flag;
223:   char       *args[2];

226:   jac->bjilu              = PETSC_FALSE;
227:   jac->levels             = 1;

229:   PetscOptionsHead("HYPRE Euclid Options");
230:     PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);
231:     if (flag) {
232:       char levels[16];
233:       if (jac->levels < 0) SETERRQ1(1,"Number of levels %d must be nonegative",jac->levels);
234:       sprintf(levels,"%d",jac->levels);
235:       args[0] = "-level"; args[1] = levels;
236:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
237:     }
238:     PetscOptionsLogical("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,PETSC_NULL);
239:     if (jac->bjilu) {
240:       args[0] = "-bj"; args[1] = "1";
241:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
242:     }
243: 
244:     PetscOptionsLogical("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);
245:     if (jac->printstatistics) {
246:       args[0] = "-eu_stats"; args[1] = "1";
247:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
248:       args[0] = "-eu_mem"; args[1] = "1";
249:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
250:     }
251:   PetscOptionsTail();
252:   return(0);
253: }

257: static int PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)
258: {
259:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
260:   int         ierr;
261:   PetscTruth  isascii;

264:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
265:   if (isascii) {
266:     PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid preconditioning\n");
267:     PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: number of levels %d\n",jac->levels);
268:     if (jac->bjilu) {
269:       PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: Using block Jacobi ILU instead of parallel ILU\n");
270:     }
271:   }
272:   return(0);
273: }

275: /* --------------------------------------------------------------------------------------------*/

277: static char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout"};
278: static char *HYPREBoomerAMGMeasureType[] = {"local","global"};
279: static char *HYPREBoomerAMGRelaxType[]   = {"Jacobi","sequential-Gauss-Seidel","","Gauss-Seidel/Jacobi","","","symmetric-Gauss-Seidel/Jacobi",
280:                                             "","","Gaussian-elimination"};
283: static int PCSetFromOptions_HYPRE_BoomerAMG(PC pc)
284: {
285:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
286:   int        ierr,n = 4,i;
287:   PetscTruth flg;
288:   char       result[32];

291:   jac->maxlevels       = 25;
292:   jac->maxiter         = 20;
293:   jac->tol             = 1.e-7;
294:   jac->strongthreshold = .25;
295:   jac->maxrowsum       = .9;
296:   jac->coarsentype     = 6;
297:   jac->measuretype     = 0;
298: 

300:   /* this is terrible; HYPRE frees this array so we have to malloc it */
301:   jac->gridsweeps    = (int*)malloc(4*sizeof(int));
302:   jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 2;
303:   jac->gridsweeps[3] = 1;

305:   jac->relaxtype     = (int*)malloc(4*sizeof(int));
306:   jac->relaxtype[0]  = jac->relaxtype[1] = jac->relaxtype[2] = 3;
307:   jac->relaxtype[3]  = 9;

309:   PetscOptionsHead("HYPRE BoomerAMG Options");
310:     PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);
311:     if (flg) {
312:       if (jac->maxlevels < 2) SETERRQ1(1,"Number of levels %d must be at least two",jac->maxlevels);
313:       HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);
314:     }
315:     PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used","None",jac->maxiter,&jac->maxiter,&flg);
316:     if (flg) {
317:       if (jac->maxiter < 1) SETERRQ1(1,"Number of iterations %d must be at least one",jac->maxiter);
318:       HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);
319:     }
320:     PetscOptionsScalar("-pc_hypre_boomeramg_tol","Convergence tolerance","None",jac->tol,&jac->tol,&flg);
321:     if (flg) {
322:       if (jac->tol < 0.0) SETERRQ1(1,"Tolerance %g must be great than or equal zero",jac->tol);
323:       HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);
324:     }
325:     PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);
326:     if (flg) {
327:       if (jac->strongthreshold < 0.0) SETERRQ1(1,"Strong threshold %g must be great than or equal zero",jac->strongthreshold);
328:       HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);
329:     }
330:     PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);
331:     if (flg) {
332:       if (jac->maxrowsum < 0.0) SETERRQ1(1,"Maximum row sum %g must be greater than zero",jac->maxrowsum);
333:       if (jac->maxrowsum > 1.0) SETERRQ1(1,"Maximum row sum %g must be less than or equal one",jac->maxrowsum);
334:       HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);
335:     }
336: 
337:     n = 4;
338:     PetscOptionsIntArray("-pc_hypre_boomeramg_grid_sweeps","Grid sweeps for fine,down,up,coarse","None",jac->gridsweeps,&n,&flg);
339:     if (flg) {
340:       if (n == 1) {
341:         jac->gridsweeps[1] = jac->gridsweeps[2] =  jac->gridsweeps[3] = jac->gridsweeps[0];
342:         n = 4;
343:       }
344:       if (n != 4) SETERRQ1(1,"You must provide either 1 or 4 values seperated by commas, you provided %d",n);
345:       HYPRE_BoomerAMGSetNumGridSweeps(jac->hsolver,jac->gridsweeps);
346:       CHKMEMQ;
347:     }

349:     /*
350:          Suggested by QUANDALLE Philippe <Philippe.QUANDALLE@ifp.fr>

352:         gridrelaxpoints[i][j] are for i=0,1,2,3 (fine,down,up,coarse) and j=sweep number
353:         0 indicates smooth all points
354:         1 indicates smooth coarse points
355:        -1 indicates smooth fine points

357:          Here when j=1 it first smooths all the coarse points, then all the fine points.
358:     */
359:     jac->gridrelaxpoints    = (int**)malloc(4*sizeof(int*));
360:     if(jac->gridsweeps[0]>0) jac->gridrelaxpoints[0] = (int*)malloc(jac->gridsweeps[0]*sizeof(int));
361:     if(jac->gridsweeps[1]>0) jac->gridrelaxpoints[1] = (int*)malloc(jac->gridsweeps[1]*sizeof(int));
362:     if(jac->gridsweeps[2]>0) jac->gridrelaxpoints[2] = (int*)malloc(jac->gridsweeps[2]*sizeof(int));
363:     if(jac->gridsweeps[3]>0) jac->gridrelaxpoints[3] = (int*)malloc(jac->gridsweeps[3]*sizeof(int));

365:     PetscOptionsLogical("-pc_hypre_boomeramg_sweep_all","Sweep all points","None",PETSC_FALSE,&flg,0);
366:     if(jac->gridsweeps[0] == 1) jac->gridrelaxpoints[0][0] = 0;
367:     else if(jac->gridsweeps[0] == 2) {
368:       if (flg) {
369:         jac->gridrelaxpoints[0][0] = 0; jac->gridrelaxpoints[0][1] = 0;
370:       } else {
371:         jac->gridrelaxpoints[0][0] = 1; jac->gridrelaxpoints[0][1] = -1;
372:       }
373:     } else if (jac->gridsweeps[0] > 2) {
374:       SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
375:     }
376: 
377:     if(jac->gridsweeps[1] == 1) jac->gridrelaxpoints[1][0] = 0;
378:     else if(jac->gridsweeps[1] == 2) {
379:       if (flg) {
380:         jac->gridrelaxpoints[1][0] = 0;  jac->gridrelaxpoints[1][1] = 0;
381:       } else {
382:         jac->gridrelaxpoints[1][0] = 1; jac->gridrelaxpoints[1][1] = -1;
383:       }
384:     } else if (jac->gridsweeps[1] > 2) {
385:       SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
386:     }

388:     if(jac->gridsweeps[2] == 1) jac->gridrelaxpoints[2][0] = 0;
389:     else if(jac->gridsweeps[2] == 2) {
390:       if (flg) {
391:         jac->gridrelaxpoints[2][0] = 0; jac->gridrelaxpoints[2][1] = 0;
392:       } else {
393:         jac->gridrelaxpoints[2][0] = -1; jac->gridrelaxpoints[2][1] = 1;
394:       }
395:     } else if (jac->gridsweeps[2] > 2) {
396:       SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
397:     }

399:     for (i=0; i<jac->gridsweeps[3]; i++) {
400:       jac->gridrelaxpoints[3][i] = 0;
401:     }
402:     HYPRE_BoomerAMGSetGridRelaxPoints(jac->hsolver,jac->gridrelaxpoints);


405:     PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,2,HYPREBoomerAMGMeasureType[0],result,16,&flg);
406:     if (flg) {
407:       int type = -1;
408:       for (i=0; i<2; i++) {
409:         PetscStrcmp(result,HYPREBoomerAMGMeasureType[i],&flg);
410:         if (flg) {
411:           type = i;
412:           break;
413:         }
414:       }
415:       if (type == -1) SETERRQ1(1,"Unknown measure type %s",result);
416:       jac->measuretype = type;
417:       HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);
418:     }
419:     PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,7,HYPREBoomerAMGCoarsenType[6],result,25,&flg);
420:     if (flg) {
421:       int type = -1;
422:       for (i=0; i<7; i++) {
423:         PetscStrcmp(result,HYPREBoomerAMGCoarsenType[i],&flg);
424:         if (flg) {
425:           type = i;
426:           break;
427:         }
428:       }
429:       if (type == -1) SETERRQ1(1,"Unknown coarsen type %s",result);
430:       jac->coarsentype = type;
431:       HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);
432:     }
433:     PetscOptionsEList("-pc_hypre_boomeramg_relax_type","Relax type","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],result,32,&flg);
434:     if (flg) {
435:       int type = -1;
436:       for (i=0; i<10; i++) {
437:         PetscStrcmp(result,HYPREBoomerAMGRelaxType[i],&flg);
438:         if (flg) {
439:           type = i;
440:           break;
441:         }
442:       }
443:       if (type == -1) SETERRQ1(1,"Unknown relax type %s",result);
444:       jac->relaxtype[0] = jac->relaxtype[1] = jac->relaxtype[2] = type;
445:     }
446:     PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],result,32,&flg);
447:     if (flg) {
448:       int type = -1;
449:       for (i=0; i<10; i++) {
450:         PetscStrcmp(result,HYPREBoomerAMGRelaxType[i],&flg);
451:         if (flg) {
452:           type = i;
453:           break;
454:         }
455:       }
456:       if (type == -1) SETERRQ1(1,"Unknown relax type %s",result);
457:       jac->relaxtype[3] = type;
458:     }
459:     HYPRE_BoomerAMGSetGridRelaxType(jac->hsolver,jac->relaxtype);
460:     PetscOptionsLogical("-pc_hypre_boomeramg_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);
461:     if (jac->printstatistics) {
462:       HYPRE_BoomerAMGSetDebugFlag(jac->hsolver,3);
463:       }
464:   PetscOptionsTail();
465:   return(0);
466: }

470: static int PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
471: {
472:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
473:   int         ierr;
474:   PetscTruth  isascii;

477:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
478:   if (isascii) {
479:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG preconditioning\n");
480:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);
481:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of iterations %d\n",jac->maxiter);
482:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Convergence tolerance %g\n",jac->tol);
483:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Threshold for strong coupling %g\n",jac->strongthreshold);
484:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum row sums %g\n",jac->maxrowsum);
485:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on fine grid %d\n",jac->gridsweeps[0]);
486:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps down         %d\n",jac->gridsweeps[1]);
487:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps up           %d\n",jac->gridsweeps[2]);
488:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on coarse    %d\n",jac->gridsweeps[3]);

490:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on fine grid %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);
491:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax down         %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);
492:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax up           %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);
493:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on coarse    %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[3]]);

495:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Measure type    %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);
496:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Coarsen type    %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);
497:   }
498:   return(0);
499: }

501: /* --------------------------------------------------------------------------------------------*/
504: static int PCSetFromOptions_HYPRE_ParaSails(PC pc)
505: {
506:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
507:   int        ierr;
508:   PetscTruth flag;
509:   char       *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"},buff[32];

512:   jac->nlevels     = 1;
513:   jac->threshhold  = .1;
514:   jac->filter      = .1;
515:   jac->loadbal     = 0;
516:   if (PetscLogPrintInfo) {
517:     jac->logging     = (int) PETSC_TRUE;
518:   } else {
519:     jac->logging     = (int) PETSC_FALSE;
520:   }
521:   jac->ruse = (int) PETSC_FALSE;
522:   jac->symt   = 0;

524:   PetscOptionsHead("HYPRE ParaSails Options");
525:     PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);
526:     PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,0);
527:     HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);

529:     PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,0);
530:     HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);

532:     PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,0);
533:     HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);

535:     PetscOptionsLogical("-pc_hypre_parasails_logging","Print info to screen","None",(PetscTruth)jac->logging,(PetscTruth*)&jac->logging,0);
536:     HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);

538:     PetscOptionsLogical("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscTruth)jac->ruse,(PetscTruth*)&jac->ruse,0);
539:     HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);

541:     PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],buff,32,&flag);
542:     while (flag) {
543:       PetscStrcmp(symtlist[0],buff,&flag);
544:       if (flag) {
545:         jac->symt = 0;
546:         break;
547:       }
548:       PetscStrcmp(symtlist[1],buff,&flag);
549:       if (flag) {
550:         jac->symt = 1;
551:         break;
552:       }
553:       PetscStrcmp(symtlist[2],buff,&flag);
554:       if (flag) {
555:         jac->symt = 2;
556:         break;
557:       }
558:       SETERRQ1(1,"Unknown HYPRE ParaSails Sym option %s",buff);
559:     }
560:     HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);

562:   PetscOptionsTail();
563:   return(0);
564: }

568: static int PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
569: {
570:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
571:   int         ierr;
572:   PetscTruth  isascii;
573:   char        *symt;

576:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
577:   if (isascii) {
578:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails preconditioning\n");
579:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: nlevels %d\n",jac->nlevels);
580:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: threshold %g\n",jac->threshhold);
581:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: filter %g\n",jac->filter);
582:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: load balance %g\n",jac->loadbal);
583:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: reuse nonzero structure %s\n",jac->ruse ? "true" : "false");
584:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: print info to screen %s\n",jac->logging ? "true" : "false");
585:     if (jac->symt == 0) {
586:       symt = "nonsymmetric matrix and preconditioner";
587:     } else if (jac->symt == 1) {
588:       symt = "SPD matrix and preconditioner";
589:     } else if (jac->symt == 2) {
590:       symt = "nonsymmetric matrix but SPD preconditioner";
591:     } else {
592:       SETERRQ1(1,"Unknown HYPRE ParaSails sym option %d",jac->symt);
593:     }
594:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: %s\n",symt);
595:   }
596:   return(0);
597: }
598: /* ---------------------------------------------------------------------------------*/

602: static int PCHYPRESetType_HYPRE(PC pc,const char name[])
603: {
604:   PC_HYPRE   *jac = (PC_HYPRE*)pc->data;
605:   int        ierr;
606:   PetscTruth flag;

609:   if (pc->ops->setup) {
610:     SETERRQ(1,"Cannot set the HYPRE preconditioner type once it has been set");
611:   }

613:   pc->ops->setup          = PCSetUp_HYPRE;
614:   pc->ops->apply          = PCApply_HYPRE;
615:   pc->ops->destroy        = PCDestroy_HYPRE;

617:   jac->maxiter            = PETSC_DEFAULT;
618:   jac->tol                = PETSC_DEFAULT;
619:   jac->printstatistics    = PetscLogPrintInfo;

621:   PetscStrcmp("pilut",name,&flag);
622:   if (flag) {
623:     HYPRE_ParCSRPilutCreate(jac->comm_hypre,&jac->hsolver);
624:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
625:     pc->ops->view           = PCView_HYPRE_Pilut;
626:     jac->destroy            = HYPRE_ParCSRPilutDestroy;
627:     jac->setup              = HYPRE_ParCSRPilutSetup;
628:     jac->solve              = HYPRE_ParCSRPilutSolve;
629:     jac->factorrowsize      = PETSC_DEFAULT;
630:     return(0);
631:   }
632:   PetscStrcmp("parasails",name,&flag);
633:   if (flag) {
634:     HYPRE_ParaSailsCreate(jac->comm_hypre,&jac->hsolver);
635:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
636:     pc->ops->view           = PCView_HYPRE_ParaSails;
637:     jac->destroy            = HYPRE_ParaSailsDestroy;
638:     jac->setup              = HYPRE_ParaSailsSetup;
639:     jac->solve              = HYPRE_ParaSailsSolve;
640:     return(0);
641:   }
642:   PetscStrcmp("euclid",name,&flag);
643:   if (flag) {
644:     HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver);
645:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
646:     pc->ops->view           = PCView_HYPRE_Euclid;
647:     jac->destroy            = HYPRE_EuclidDestroy;
648:     jac->setup              = HYPRE_EuclidSetup;
649:     jac->solve              = HYPRE_EuclidSolve;
650:     return(0);
651:   }
652:   PetscStrcmp("boomeramg",name,&flag);
653:   if (flag) {
654:     HYPRE_BoomerAMGCreate(&jac->hsolver);
655:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_BoomerAMG;
656:     pc->ops->view           = PCView_HYPRE_BoomerAMG;
657:     jac->destroy            = HYPRE_BoomerAMGDestroy;
658:     jac->setup              = HYPRE_BoomerAMGSetup;
659:     jac->solve              = HYPRE_BoomerAMGSolve;
660:     return(0);
661:   }
662:   SETERRQ1(1,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name);
663:   return(0);
664: }

666: /*
667:     It only gets here if the HYPRE type has not been set before the call to 
668:    ...SetFromOptions() which actually is most of the time
669: */
672: static int PCSetFromOptions_HYPRE(PC pc)
673: {
674:   int        ierr;
675:   char       buff[32],*type[] = {"pilut","parasails","boomerAMG","euclid"};
676:   PetscTruth flg;

679:   PetscOptionsHead("HYPRE preconditioner options");
680:     PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"pilut",buff,32,&flg);

682: 
683:     if (PetscOptionsPublishCount) {   /* force the default if it was not yet set and user did not set with option */
684:       if (!flg && !pc->ops->apply) {
685:         flg  = PETSC_TRUE;
686:         PetscStrcpy(buff,"pilut");
687:       }
688:     }

690:     if (flg) {
691:       PCHYPRESetType_HYPRE(pc,buff);
692:     }
693:     if (pc->ops->setfromoptions) {
694:       pc->ops->setfromoptions(pc);
695:     }
696:   PetscOptionsTail();
697:   return(0);
698: }

702: /*@
703:      PCHYPRESetType - Sets which hypre preconditioner you wish to use

705:    Input Parameters:
706: +     pc - the preconditioner context
707: -     name - either  pilut, parasails, boomeramg, euclid

709:    Options Database Keys:
710:    -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
711:  
712:    Level: intermediate

714: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
715:            PCHYPRE

717: @*/
718: int PCHYPRESetType(PC pc,const char name[])
719: {
720:   int ierr,(*f)(PC,const char[]);

724:   PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);
725:   if (f) {
726:     (*f)(pc,name);
727:   }
728:   return(0);
729: }

731: /*MC
732:      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre

734:    Options Database Keys:
735: +   -pc_hypre_type - One of pilut, parasails, boomerAMG, euclid
736: -   Too many others to list, run with -pc_type hypre -pc_hypre_type XXX to see options for the XXX
737:           preconditioner
738:  
739:    Level: intermediate

741:    Notes: The many hypre options can ONLY be set via the options database (e.g. the command line
742:           or with PetscOptionsSetValue(), there are no functions to set them)

744: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
745:            PCHYPRESetType()

747: M*/

749: EXTERN_C_BEGIN
752: int PCCreate_HYPRE(PC pc)
753: {
754:   PC_HYPRE *jac;
755:   int       ierr;

758:   PetscNew(PC_HYPRE,&jac);
759:   PetscMemzero(jac,sizeof(PC_HYPRE));
760:   pc->data                 = jac;
761:   pc->ops->setfromoptions  = PCSetFromOptions_HYPRE;
762:   /* Com_dup for hypre */
763:   MPI_Comm_dup(pc->comm,&(jac->comm_hypre));
764:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C",
765:                                     "PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);
766:   return(0);
767: }
768: EXTERN_C_END