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