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);

 29:   /* options for pilut and BoomerAMG*/
 30:   int                maxiter;
 31:   double             tol;

 33:   /* options for pilut */
 34:   int                factorrowsize;

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

 46:   /* options for euclid */
 47:   PetscTruth         bjilu;
 48:   int                levels;

 50:   /* options for euclid and BoomerAMG */
 51:   PetscTruth         printstatistics;

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


 65: static int PCSetUp_HYPRE(PC pc)
 66: {
 67:   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
 68:   int                ierr;
 69:   HYPRE_ParCSRMatrix hmat;
 70:   HYPRE_ParVector    bv,xv;

 73:   if (!jac->ij) { /* create the matrix the first time through */
 74:     MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);
 75:   }
 76:   if (!jac->b) {
 77:     VecHYPRE_IJVectorCreate(pc->vec,&jac->b);
 78:     VecHYPRE_IJVectorCreate(pc->vec,&jac->x);
 79:   }
 80:   MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);
 81:   HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);
 82:   HYPRE_IJVectorGetObject(jac->b,(void**)&bv);
 83:   HYPRE_IJVectorGetObject(jac->x,(void**)&xv);
 84:   (*jac->setup)(jac->hsolver,hmat,bv,xv);
 85:   return(0);
 86: }

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

 99: static int PCApply_HYPRE(PC pc,Vec b,Vec x)
100: {
101:   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
102:   int                ierr;
103:   HYPRE_ParCSRMatrix hmat;
104:   PetscScalar        *bv,*xv;
105:   HYPRE_ParVector    jbv,jxv;
106:   PetscScalar        *sbv,*sxv;

109:   VecGetArray(b,&bv);
110:   VecGetArray(x,&xv);
111:   HYPREReplacePointer(jac->b,bv,sbv);
112:   HYPREReplacePointer(jac->x,xv,sxv);

114:   HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);
115:   HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);
116:   HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);
117:   (*jac->solve)(jac->hsolver,hmat,jbv,jxv);

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

124:   return(0);
125: }

127: static int PCDestroy_HYPRE(PC pc)
128: {
129:   PC_HYPRE *jac = (PC_HYPRE*)pc->data;
130:   int      ierr;

133:   HYPRE_IJMatrixDestroy(jac->ij);
134:   HYPRE_IJVectorDestroy(jac->b);
135:   HYPRE_IJVectorDestroy(jac->x);
136:   (*jac->destroy)(jac->hsolver);
137:   PetscFree(jac);
138:   return(0);
139: }

141: /* --------------------------------------------------------------------------------------------*/
142: static int PCSetFromOptions_HYPRE_Pilut(PC pc)
143: {
144:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
145:   int        ierr;
146:   PetscTruth flag;

149:   PetscOptionsHead("HYPRE Pilut Options");
150:     PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);
151:     if (flag) {
152:       HYPRE_ParCSRPilutSetMaxIter(jac->hsolver,jac->maxiter);
153:     }
154:     PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);
155:     if (flag) {
156:       HYPRE_ParCSRPilutSetDropTolerance(jac->hsolver,jac->tol);
157:     }
158:     PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);
159:     if (flag) {
160:       HYPRE_ParCSRPilutSetFactorRowSize(jac->hsolver,jac->factorrowsize);
161:     }
162:   PetscOptionsTail();
163:   return(0);
164: }

166: static int PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)
167: {
168:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
169:   int         ierr;
170:   PetscTruth  isascii;

173:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
174:   if (isascii) {
175:     PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut preconditioningn");
176:     if (jac->maxiter != PETSC_DEFAULT) {
177:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: maximum number of iterations %dn",jac->maxiter);
178:     } else {
179:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default maximum number of iterations n");
180:     }
181:     if (jac->tol != PETSC_DEFAULT) {
182:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: drop tolerance %gn",jac->tol);
183:     } else {
184:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default drop tolerance n");
185:     }
186:     if (jac->factorrowsize != PETSC_DEFAULT) {
187:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: factor row size %dn",jac->factorrowsize);
188:     } else {
189:       PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default factor row size n");
190:     }
191:   }
192:   return(0);
193: }

195: /* --------------------------------------------------------------------------------------------*/
196: static int PCSetFromOptions_HYPRE_Euclid(PC pc)
197: {
198:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
199:   int        ierr;
200:   PetscTruth flag;
201:   char       *args[2];

204:   jac->bjilu              = PETSC_FALSE;
205:   jac->levels             = 1;

207:   PetscOptionsHead("HYPRE Euclid Options");
208:     PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);
209:     if (flag) {
210:       char levels[16];
211:       if (jac->levels < 0) SETERRQ1(1,"Number of levels %d must be nonegative",jac->levels);
212:       sprintf(levels,"%d",jac->levels);
213:       args[0] = "-level"; args[1] = levels;
214:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
215:     }
216:     PetscOptionsLogical("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,PETSC_NULL);
217:     if (jac->bjilu) {
218:       args[0] = "-bj"; args[1] = "1";
219:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
220:     }
221: 
222:     PetscOptionsLogical("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);
223:     if (jac->printstatistics) {
224:       args[0] = "-eu_stats"; args[1] = "1";
225:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
226:       args[0] = "-eu_mem"; args[1] = "1";
227:       HYPRE_EuclidSetParams(jac->hsolver,2,args);
228:     }
229:   PetscOptionsTail();
230:   return(0);
231: }

233: static int PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)
234: {
235:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
236:   int         ierr;
237:   PetscTruth  isascii;

240:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
241:   if (isascii) {
242:     PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid preconditioningn");
243:     PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: number of levels %dn",jac->levels);
244:     if (jac->bjilu) {
245:       PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: Using block Jacobi ILU instead of parallel ILUn");
246:     }
247:   }
248:   return(0);
249: }

251: /* --------------------------------------------------------------------------------------------*/

253: static char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout"};
254: static char *HYPREBoomerAMGMeasureType[] = {"local","global"};
255: static char *HYPREBoomerAMGRelaxType[]   = {"Jacobi","sequential-Gauss-Seidel","","Gauss-Seidel/Jacobi","","","symmetric-Gauss-Seidel/Jacobi",
256:                                             "","","Gaussian-elimination"};
257: static int PCSetFromOptions_HYPRE_BoomerAMG(PC pc)
258: {
259:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
260:   int        ierr,n = 4,i;
261:   PetscTruth flg;
262:   char       result[32];

265:   jac->maxlevels       = 25;
266:   jac->maxiter         = 20;
267:   jac->tol             = 1.e-7;
268:   jac->strongthreshold = .25;
269:   jac->maxrowsum       = .9;
270:   jac->coarsentype     = 6;
271:   jac->measuretype     = 0;
272: 

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

279:   jac->relaxtype     = (int*)malloc(4*sizeof(int));
280:   jac->relaxtype[0]  = jac->relaxtype[1] = jac->relaxtype[2] = jac->relaxtype[3] = 3;

282:   PetscOptionsHead("HYPRE BoomerAMG Options");
283:     PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);
284:     if (flg) {
285:       if (jac->maxlevels < 2) SETERRQ1(1,"Number of levels %d must be at least one",jac->maxlevels);
286:       HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);
287:     }
288:     PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used","None",jac->maxiter,&jac->maxiter,&flg);
289:     if (flg) {
290:       if (jac->maxiter < 2) SETERRQ1(1,"Number of iterations %d must be at least two",jac->maxlevels);
291:       HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);
292:     }
293:     PetscOptionsScalar("-pc_hypre_boomeramg_tol","Convergence tolerance","None",jac->tol,&jac->tol,&flg);
294:     if (flg) {
295:       if (jac->tol < 0.0) SETERRQ1(1,"Tolerance %g must be great than or equal zero",jac->tol);
296:       HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);
297:     }
298:     PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);
299:     if (flg) {
300:       if (jac->strongthreshold < 0.0) SETERRQ1(1,"Strong threshold %g must be great than or equal zero",jac->strongthreshold);
301:       HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);
302:     }
303:     PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);
304:     if (flg) {
305:       if (jac->maxrowsum < 0.0) SETERRQ1(1,"Maximum row sum %g must be greater than zero",jac->maxrowsum);
306:       if (jac->maxrowsum > 1.0) SETERRQ1(1,"Maximum row sum %g must be less than or equal one",jac->maxrowsum);
307:       HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);
308:     }
309: 
310:     n = 4;
311:     PetscOptionsIntArray("-pc_hypre_boomeramg_grid_sweeps","Grid sweeps for fine,down,up,coarse","None",jac->gridsweeps,&n,&flg);
312:     if (flg) {
313:       if (n == 1) {
314:         jac->gridsweeps[1] = jac->gridsweeps[2] =  jac->gridsweeps[3] = jac->gridsweeps[0];
315:         n = 4;
316:       }
317:       if (n != 4) SETERRQ1(1,"You must provide either 1 or 4 values seperated by commas, you provided %d",n);
318:       HYPRE_BoomerAMGSetNumGridSweeps(jac->hsolver,jac->gridsweeps);
319:       CHKMEMQ;
320:     }
321:     /*
322:          Suggested by QUANDALLE Philippe <Philippe.QUANDALLE@ifp.fr>

324:         gridrelaxpoints[i][j] are for i=0,1,2,3 (fine,up,down,coarse) and j=sweep number
325:         0 indicates smooth all points
326:         1 indicates smooth coarse points
327:        -1 indicates smooth fine points

329:          Here when j=1 it first smooths all the coarse points, then all the fine points.
330:     */
331:     jac->gridrelaxpoints    = (int**)malloc(4*sizeof(int*));
332:     if(jac->gridsweeps[0]>0) jac->gridrelaxpoints[0] = (int*)malloc(jac->gridsweeps[0]*sizeof(int));
333:     if(jac->gridsweeps[1]>0) jac->gridrelaxpoints[1] = (int*)malloc(jac->gridsweeps[1]*sizeof(int));
334:     if(jac->gridsweeps[2]>0) jac->gridrelaxpoints[2] = (int*)malloc(jac->gridsweeps[2]*sizeof(int));
335:     if(jac->gridsweeps[3]>0) jac->gridrelaxpoints[3] = (int*)malloc(jac->gridsweeps[3]*sizeof(int));

337:     PetscOptionsLogical("-pc_hypre_boomeramg_sweep_all","Sweep all points","None",PETSC_FALSE,&flg,0);
338:     if(jac->gridsweeps[0] == 1) jac->gridrelaxpoints[0][0] = 0;
339:     else if(jac->gridsweeps[0] == 2) {
340:       if (flg) {
341:         jac->gridrelaxpoints[0][0] = 0; jac->gridrelaxpoints[0][1] = 0;
342:       } else {
343:         jac->gridrelaxpoints[0][0] = 1; jac->gridrelaxpoints[0][1] = -1;
344:       }
345:     } else if (jac->gridsweeps[0] > 2) {
346:       SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
347:     }
348: 
349:     if(jac->gridsweeps[1] == 1) jac->gridrelaxpoints[1][0] = 0;
350:     else if(jac->gridsweeps[1] == 2) {
351:       if (flg) {
352:         jac->gridrelaxpoints[1][0] = 0; jac->gridrelaxpoints[1][1] = 0;
353:       } else {
354:         jac->gridrelaxpoints[1][0] = 1; jac->gridrelaxpoints[1][1] = -1;
355:       }
356:     } else if (jac->gridsweeps[1] > 2) {
357:       SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
358:     }

360:     if(jac->gridsweeps[2] == 1) jac->gridrelaxpoints[2][0] = 0;
361:     else if(jac->gridsweeps[2] == 2) {
362:       if (flg) {
363:         jac->gridrelaxpoints[2][0] = 0; jac->gridrelaxpoints[2][1] = 0;
364:       } else {
365:         jac->gridrelaxpoints[2][0] = 1; jac->gridrelaxpoints[2][1] = -1;
366:       }
367:     } else if (jac->gridsweeps[2] > 2) {
368:       SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
369:     }

371:     for (i=0; i<jac->gridsweeps[3]; i++) {
372:       jac->gridrelaxpoints[3][i] = 0;
373:     }
374:     HYPRE_BoomerAMGSetGridRelaxPoints(jac->hsolver,jac->gridrelaxpoints);


377:     PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,2,HYPREBoomerAMGMeasureType[0],result,16,&flg);
378:     if (flg) {
379:       int i,type = -1;
380:       for (i=0; i<2; i++) {
381:         PetscStrcmp(result,HYPREBoomerAMGMeasureType[i],&flg);
382:         if (flg) {
383:           type = i;
384:           break;
385:         }
386:       }
387:       if (type == -1) SETERRQ1(1,"Unknown measure type %s",result);
388:       HYPRE_BoomerAMGSetMeasureType(jac->hsolver,type);
389:     }
390:     PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,7,HYPREBoomerAMGCoarsenType[6],result,16,&flg);
391:     if (flg) {
392:       int i,type = -1;
393:       for (i=0; i<7; i++) {
394:         PetscStrcmp(result,HYPREBoomerAMGCoarsenType[i],&flg);
395:         if (flg) {
396:           type = i;
397:           break;
398:         }
399:       }
400:       if (type == -1) SETERRQ1(1,"Unknown coarsen type %s",result);
401:       HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,type);
402:     }
403:     PetscOptionsEList("-pc_hypre_boomeramg_relax_type","Relax type","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],result,32,&flg);
404:     if (flg) {
405:       int i,type = -1;
406:       for (i=0; i<10; i++) {
407:         PetscStrcmp(result,HYPREBoomerAMGRelaxType[i],&flg);
408:         if (flg) {
409:           type = i;
410:           break;
411:         }
412:       }
413:       if (type == -1) SETERRQ1(1,"Unknown relax type %s",result);
414:       jac->relaxtype[0] = jac->relaxtype[1] = jac->relaxtype[2] = type;
415:     }
416:     PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],result,32,&flg);
417:     if (flg) {
418:       int i,type = -1;
419:       for (i=0; i<10; i++) {
420:         PetscStrcmp(result,HYPREBoomerAMGRelaxType[i],&flg);
421:         if (flg) {
422:           type = i;
423:           break;
424:         }
425:       }
426:       if (type == -1) SETERRQ1(1,"Unknown relax type %s",result);
427:       jac->relaxtype[3] = type;
428:     }
429:     HYPRE_BoomerAMGSetGridRelaxType(jac->hsolver,jac->relaxtype);
430: 
431:     PetscOptionsLogical("-pc_hypre_boomeramg_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);
432:     if (jac->printstatistics) {
433:       HYPRE_BoomerAMGSetIOutDat(jac->hsolver,3);
434:     }
435:   PetscOptionsTail();
436:   return(0);
437: }

439: static int PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
440: {
441:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
442:   int         ierr;
443:   PetscTruth  isascii;

446:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
447:   if (isascii) {
448:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG preconditioningn");
449:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of levels %dn",jac->maxlevels);
450:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of iterations %dn",jac->maxiter);
451:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Convergence tolerance %gn",jac->tol);
452:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Threshold for strong coupling %gn",jac->strongthreshold);
453:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum row sums %gn",jac->maxrowsum);
454:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on fine grid %dn",jac->gridsweeps[0]);
455:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps down         %dn",jac->gridsweeps[1]);
456:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps up           %dn",jac->gridsweeps[2]);
457:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on coarse    %dn",jac->gridsweeps[3]);

459:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on fine grid %sn",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);
460:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax down         %sn",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);
461:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax up           %sn",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);
462:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on coarse    %sn",HYPREBoomerAMGRelaxType[jac->relaxtype[3]]);

464:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Measure type    %sn",HYPREBoomerAMGMeasureType[jac->measuretype]);
465:     PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Coarsen type    %sn",HYPREBoomerAMGCoarsenType[jac->coarsentype]);
466:   }
467:   return(0);
468: }

470: /* --------------------------------------------------------------------------------------------*/
471: static int PCSetFromOptions_HYPRE_ParaSails(PC pc)
472: {
473:   PC_HYPRE  *jac = (PC_HYPRE*)pc->data;
474:   int        ierr;
475:   PetscTruth flag;
476:   char       *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"},buff[32];

479:   jac->nlevels     = 1;
480:   jac->threshhold  = .1;
481:   jac->filter      = .1;
482:   jac->loadbal     = 0;
483:   if (PetscLogPrintInfo) {
484:     jac->logging     = (int) PETSC_TRUE;
485:   } else {
486:     jac->logging     = (int) PETSC_FALSE;
487:   }
488:   jac->ruse = (int) PETSC_TRUE;
489:   jac->symt   = 0;

491:   PetscOptionsHead("HYPRE ParaSails Options");
492:     PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);
493:     PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,0);
494:     HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);

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

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

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

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

508:     PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],buff,32,&flag);
509:     while (flag) {
510:       PetscStrcmp(symtlist[0],buff,&flag);
511:       if (flag) {
512:         jac->symt = 0;
513:         break;
514:       }
515:       PetscStrcmp(symtlist[1],buff,&flag);
516:       if (flag) {
517:         jac->symt = 1;
518:         break;
519:       }
520:       PetscStrcmp(symtlist[2],buff,&flag);
521:       if (flag) {
522:         jac->symt = 2;
523:         break;
524:       }
525:       SETERRQ1(1,"Unknown HYPRE ParaSails Sym option %s",buff);
526:     }
527:     HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);

529:   PetscOptionsTail();
530:   return(0);
531: }

533: static int PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
534: {
535:   PC_HYPRE    *jac = (PC_HYPRE*)pc->data;
536:   int         ierr;
537:   PetscTruth  isascii;
538:   char        *symt;

541:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
542:   if (isascii) {
543:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails preconditioningn");
544:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: nlevels %dn",jac->nlevels);
545:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: threshold %gn",jac->threshhold);
546:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: filter %gn",jac->filter);
547:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: load balance %gn",jac->loadbal);
548:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: reuse nonzero structure %sn",jac->ruse ? "true" : "false");
549:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: print info to screen %sn",jac->logging ? "true" : "false");
550:     if (jac->symt == 0) {
551:       symt = "nonsymmetric matrix and preconditioner";
552:     } else if (jac->symt == 1) {
553:       symt = "SPD matrix and preconditioner";
554:     } else if (jac->symt == 2) {
555:       symt = "nonsymmetric matrix but SPD preconditioner";
556:     } else {
557:       SETERRQ1(1,"Unknown HYPRE ParaSails sym option %d",jac->symt);
558:     }
559:     PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: %sn",symt);
560:   }
561:   return(0);
562: }
563: /* ---------------------------------------------------------------------------------*/

565: static int PCHYPRESetType_HYPRE(PC pc,char *name)
566: {
567:   PC_HYPRE   *jac = (PC_HYPRE*)pc->data;
568:   int        ierr;
569:   PetscTruth flag;

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

576:   pc->ops->setup          = PCSetUp_HYPRE;
577:   pc->ops->apply          = PCApply_HYPRE;
578:   pc->ops->destroy        = PCDestroy_HYPRE;

580:   jac->maxiter            = PETSC_DEFAULT;
581:   jac->tol                = PETSC_DEFAULT;
582:   jac->printstatistics    = PetscLogPrintInfo;

584:   PetscStrcmp("pilut",name,&flag);
585:   if (flag) {
586:     ierr                    = HYPRE_ParCSRPilutCreate(pc->comm,&jac->hsolver);
587:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
588:     pc->ops->view           = PCView_HYPRE_Pilut;
589:     jac->destroy            = HYPRE_ParCSRPilutDestroy;
590:     jac->setup              = HYPRE_ParCSRPilutSetup;
591:     jac->solve              = HYPRE_ParCSRPilutSolve;
592:     jac->factorrowsize      = PETSC_DEFAULT;
593:     return(0);
594:   }
595:   PetscStrcmp("parasails",name,&flag);
596:   if (flag) {
597:     ierr                    = HYPRE_ParaSailsCreate(pc->comm,&jac->hsolver);
598:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
599:     pc->ops->view           = PCView_HYPRE_ParaSails;
600:     jac->destroy            = HYPRE_ParaSailsDestroy;
601:     jac->setup              = HYPRE_ParaSailsSetup;
602:     jac->solve              = HYPRE_ParaSailsSolve;
603:     return(0);
604:   }
605:   PetscStrcmp("euclid",name,&flag);
606:   if (flag) {
607:     ierr                    = HYPRE_EuclidCreate(pc->comm,&jac->hsolver);
608:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
609:     pc->ops->view           = PCView_HYPRE_Euclid;
610:     jac->destroy            = HYPRE_EuclidDestroy;
611:     jac->setup              = HYPRE_EuclidSetup;
612:     jac->solve              = HYPRE_EuclidSolve;
613:     return(0);
614:   }
615:   PetscStrcmp("boomeramg",name,&flag);
616:   if (flag) {
617:     ierr                    = HYPRE_BoomerAMGCreate(&jac->hsolver);
618:     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_BoomerAMG;
619:     pc->ops->view           = PCView_HYPRE_BoomerAMG;
620:     jac->destroy            = HYPRE_BoomerAMGDestroy;
621:     jac->setup              = HYPRE_BoomerAMGSetup;
622:     jac->solve              = HYPRE_BoomerAMGSolve;
623:     return(0);
624:   }
625:   SETERRQ1(1,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name);
626:   return(0);
627: }

629: /*
630:     It only gets here if the HYPRE type has not been set before the call to 
631:    ...SetFromOptions() which actually is most of the time
632: */
633: static int PCSetFromOptions_HYPRE(PC pc)
634: {
635:   int        ierr;
636:   char       buff[32],*type[] = {"pilut","parasails","boomerAMG","euclid"};
637:   PetscTruth flg;

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

643: 
644:     if (PetscOptionsPublishCount) {   /* force the default if it was not yet set and user did not set with option */
645:       if (!flg && !pc->ops->apply) {
646:         flg  = PETSC_TRUE;
647:         PetscStrcpy(buff,"pilut");
648:       }
649:     }

651:     if (flg) {
652:       PCHYPRESetType_HYPRE(pc,buff);
653:     }
654:     if (pc->ops->setfromoptions) {
655:       pc->ops->setfromoptions(pc);
656:     }
657:   PetscOptionsTail();
658:   return(0);
659: }

661: EXTERN_C_BEGIN
662: int PCCreate_HYPRE(PC pc)
663: {
664:   PC_HYPRE *jac;
665:   int       ierr;

668:   ierr                    = PetscNew(PC_HYPRE,&jac);
669:   ierr                    = PetscMemzero(jac,sizeof(PC_HYPRE));
670:   pc->data                = jac;

672:   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
673:   return(0);
674: }
675: EXTERN_C_END