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/ksp/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 const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout"};
278: static const char *HYPREBoomerAMGMeasureType[] = {"local","global"};
279: static const 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,indx;
287: PetscTruth flg;
290: jac->maxlevels = 25;
291: jac->maxiter = 20;
292: jac->tol = 1.e-7;
293: jac->strongthreshold = .25;
294: jac->maxrowsum = .9;
295: jac->coarsentype = 6;
296: jac->measuretype = 0;
297:
299: /* this is terrible; HYPRE frees this array so we have to malloc it */
300: jac->gridsweeps = (int*)malloc(4*sizeof(int));
301: jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 2;
302: jac->gridsweeps[3] = 1;
304: jac->relaxtype = (int*)malloc(4*sizeof(int));
305: jac->relaxtype[0] = jac->relaxtype[1] = jac->relaxtype[2] = 3;
306: jac->relaxtype[3] = 9;
308: PetscOptionsHead("HYPRE BoomerAMG Options");
309: PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);
310: if (flg) {
311: if (jac->maxlevels < 2) SETERRQ1(1,"Number of levels %d must be at least two",jac->maxlevels);
312: HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);
313: }
314: PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used","None",jac->maxiter,&jac->maxiter,&flg);
315: if (flg) {
316: if (jac->maxiter < 1) SETERRQ1(1,"Number of iterations %d must be at least one",jac->maxiter);
317: HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);
318: }
319: PetscOptionsScalar("-pc_hypre_boomeramg_tol","Convergence tolerance","None",jac->tol,&jac->tol,&flg);
320: if (flg) {
321: if (jac->tol < 0.0) SETERRQ1(1,"Tolerance %g must be great than or equal zero",jac->tol);
322: HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);
323: }
324: PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);
325: if (flg) {
326: if (jac->strongthreshold < 0.0) SETERRQ1(1,"Strong threshold %g must be great than or equal zero",jac->strongthreshold);
327: HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);
328: }
329: PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);
330: if (flg) {
331: if (jac->maxrowsum < 0.0) SETERRQ1(1,"Maximum row sum %g must be greater than zero",jac->maxrowsum);
332: if (jac->maxrowsum > 1.0) SETERRQ1(1,"Maximum row sum %g must be less than or equal one",jac->maxrowsum);
333: HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);
334: }
335:
336: n = 4;
337: PetscOptionsIntArray("-pc_hypre_boomeramg_grid_sweeps","Grid sweeps for fine,down,up,coarse","None",jac->gridsweeps,&n,&flg);
338: if (flg) {
339: if (n == 1) {
340: jac->gridsweeps[1] = jac->gridsweeps[2] = jac->gridsweeps[3] = jac->gridsweeps[0];
341: n = 4;
342: }
343: if (n != 4) SETERRQ1(1,"You must provide either 1 or 4 values seperated by commas, you provided %d",n);
344: HYPRE_BoomerAMGSetNumGridSweeps(jac->hsolver,jac->gridsweeps);
345: CHKMEMQ;
346: }
348: /*
349: Suggested by QUANDALLE Philippe <Philippe.QUANDALLE@ifp.fr>
351: gridrelaxpoints[i][j] are for i=0,1,2,3 (fine,down,up,coarse) and j=sweep number
352: 0 indicates smooth all points
353: 1 indicates smooth coarse points
354: -1 indicates smooth fine points
356: Here when j=1 it first smooths all the coarse points, then all the fine points.
357: */
358: jac->gridrelaxpoints = (int**)malloc(4*sizeof(int*));
359: if(jac->gridsweeps[0]>0) jac->gridrelaxpoints[0] = (int*)malloc(jac->gridsweeps[0]*sizeof(int));
360: if(jac->gridsweeps[1]>0) jac->gridrelaxpoints[1] = (int*)malloc(jac->gridsweeps[1]*sizeof(int));
361: if(jac->gridsweeps[2]>0) jac->gridrelaxpoints[2] = (int*)malloc(jac->gridsweeps[2]*sizeof(int));
362: if(jac->gridsweeps[3]>0) jac->gridrelaxpoints[3] = (int*)malloc(jac->gridsweeps[3]*sizeof(int));
364: PetscOptionsLogical("-pc_hypre_boomeramg_sweep_all","Sweep all points","None",PETSC_FALSE,&flg,0);
365: if(jac->gridsweeps[0] == 1) jac->gridrelaxpoints[0][0] = 0;
366: else if(jac->gridsweeps[0] == 2) {
367: if (flg) {
368: jac->gridrelaxpoints[0][0] = 0; jac->gridrelaxpoints[0][1] = 0;
369: } else {
370: jac->gridrelaxpoints[0][0] = 1; jac->gridrelaxpoints[0][1] = -1;
371: }
372: } else if (jac->gridsweeps[0] > 2) {
373: SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
374: }
375:
376: if(jac->gridsweeps[1] == 1) jac->gridrelaxpoints[1][0] = 0;
377: else if(jac->gridsweeps[1] == 2) {
378: if (flg) {
379: jac->gridrelaxpoints[1][0] = 0; jac->gridrelaxpoints[1][1] = 0;
380: } else {
381: jac->gridrelaxpoints[1][0] = 1; jac->gridrelaxpoints[1][1] = -1;
382: }
383: } else if (jac->gridsweeps[1] > 2) {
384: SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
385: }
387: if(jac->gridsweeps[2] == 1) jac->gridrelaxpoints[2][0] = 0;
388: else if(jac->gridsweeps[2] == 2) {
389: if (flg) {
390: jac->gridrelaxpoints[2][0] = 0; jac->gridrelaxpoints[2][1] = 0;
391: } else {
392: jac->gridrelaxpoints[2][0] = -1; jac->gridrelaxpoints[2][1] = 1;
393: }
394: } else if (jac->gridsweeps[2] > 2) {
395: SETERRQ(1,"Grid sweeps can only be 0, 1, or 2");
396: }
398: for (i=0; i<jac->gridsweeps[3]; i++) {
399: jac->gridrelaxpoints[3][i] = 0;
400: }
401: HYPRE_BoomerAMGSetGridRelaxPoints(jac->hsolver,jac->gridrelaxpoints);
404: PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,2,HYPREBoomerAMGMeasureType[0],&indx,&flg);
405: if (flg) {
406: jac->measuretype = indx;
407: }
408: HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);
409: PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,7,HYPREBoomerAMGCoarsenType[6],&indx,&flg);
410: if (flg) {
411: jac->coarsentype = indx;
412: }
413: HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);
414: PetscOptionsEList("-pc_hypre_boomeramg_relax_type","Relax type","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);
415: if (flg) {
416: jac->relaxtype[0] = jac->relaxtype[1] = jac->relaxtype[2] = indx;
417: }
418: PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);
419: if (flg) {
420: jac->relaxtype[3] = indx;
421: }
422: HYPRE_BoomerAMGSetGridRelaxType(jac->hsolver,jac->relaxtype);
423: PetscOptionsLogical("-pc_hypre_boomeramg_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);
424: if (jac->printstatistics) {
425: HYPRE_BoomerAMGSetDebugFlag(jac->hsolver,3);
426: }
427: PetscOptionsTail();
428: return(0);
429: }
433: static int PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
434: {
435: PC_HYPRE *jac = (PC_HYPRE*)pc->data;
436: int ierr;
437: PetscTruth isascii;
440: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
441: if (isascii) {
442: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG preconditioning\n");
443: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);
444: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of iterations %d\n",jac->maxiter);
445: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Convergence tolerance %g\n",jac->tol);
446: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Threshold for strong coupling %g\n",jac->strongthreshold);
447: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum row sums %g\n",jac->maxrowsum);
448: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps on fine grid %d\n",jac->gridsweeps[0]);
449: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps down %d\n",jac->gridsweeps[1]);
450: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps up %d\n",jac->gridsweeps[2]);
451: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps on coarse %d\n",jac->gridsweeps[3]);
453: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax on fine grid %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);
454: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax down %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);
455: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax up %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);
456: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax on coarse %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[3]]);
458: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Measure type %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);
459: PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Coarsen type %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);
460: }
461: return(0);
462: }
464: /* --------------------------------------------------------------------------------------------*/
467: static int PCSetFromOptions_HYPRE_ParaSails(PC pc)
468: {
469: PC_HYPRE *jac = (PC_HYPRE*)pc->data;
470: int indx,ierr;
471: PetscTruth flag;
472: const char *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
475: jac->nlevels = 1;
476: jac->threshhold = .1;
477: jac->filter = .1;
478: jac->loadbal = 0;
479: if (PetscLogPrintInfo) {
480: jac->logging = (int) PETSC_TRUE;
481: } else {
482: jac->logging = (int) PETSC_FALSE;
483: }
484: jac->ruse = (int) PETSC_FALSE;
485: jac->symt = 0;
487: PetscOptionsHead("HYPRE ParaSails Options");
488: PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);
489: PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,0);
490: HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);
492: PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,0);
493: HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);
495: PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,0);
496: HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);
498: PetscOptionsLogical("-pc_hypre_parasails_logging","Print info to screen","None",(PetscTruth)jac->logging,(PetscTruth*)&jac->logging,0);
499: HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);
501: PetscOptionsLogical("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscTruth)jac->ruse,(PetscTruth*)&jac->ruse,0);
502: HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);
504: PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],&indx,&flag);
505: if (flag) {
506: jac->symt = indx;
507: }
508: HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);
510: PetscOptionsTail();
511: return(0);
512: }
516: static int PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
517: {
518: PC_HYPRE *jac = (PC_HYPRE*)pc->data;
519: int ierr;
520: PetscTruth isascii;
521: char *symt;
524: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
525: if (isascii) {
526: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails preconditioning\n");
527: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: nlevels %d\n",jac->nlevels);
528: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: threshold %g\n",jac->threshhold);
529: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: filter %g\n",jac->filter);
530: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: load balance %g\n",jac->loadbal);
531: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: reuse nonzero structure %s\n",jac->ruse ? "true" : "false");
532: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: print info to screen %s\n",jac->logging ? "true" : "false");
533: if (jac->symt == 0) {
534: symt = "nonsymmetric matrix and preconditioner";
535: } else if (jac->symt == 1) {
536: symt = "SPD matrix and preconditioner";
537: } else if (jac->symt == 2) {
538: symt = "nonsymmetric matrix but SPD preconditioner";
539: } else {
540: SETERRQ1(1,"Unknown HYPRE ParaSails sym option %d",jac->symt);
541: }
542: PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: %s\n",symt);
543: }
544: return(0);
545: }
546: /* ---------------------------------------------------------------------------------*/
550: static int PCHYPRESetType_HYPRE(PC pc,const char name[])
551: {
552: PC_HYPRE *jac = (PC_HYPRE*)pc->data;
553: int ierr;
554: PetscTruth flag;
557: if (pc->ops->setup) {
558: SETERRQ(1,"Cannot set the HYPRE preconditioner type once it has been set");
559: }
561: pc->ops->setup = PCSetUp_HYPRE;
562: pc->ops->apply = PCApply_HYPRE;
563: pc->ops->destroy = PCDestroy_HYPRE;
565: jac->maxiter = PETSC_DEFAULT;
566: jac->tol = PETSC_DEFAULT;
567: jac->printstatistics = PetscLogPrintInfo;
569: PetscStrcmp("pilut",name,&flag);
570: if (flag) {
571: HYPRE_ParCSRPilutCreate(jac->comm_hypre,&jac->hsolver);
572: pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
573: pc->ops->view = PCView_HYPRE_Pilut;
574: jac->destroy = HYPRE_ParCSRPilutDestroy;
575: jac->setup = HYPRE_ParCSRPilutSetup;
576: jac->solve = HYPRE_ParCSRPilutSolve;
577: jac->factorrowsize = PETSC_DEFAULT;
578: return(0);
579: }
580: PetscStrcmp("parasails",name,&flag);
581: if (flag) {
582: HYPRE_ParaSailsCreate(jac->comm_hypre,&jac->hsolver);
583: pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
584: pc->ops->view = PCView_HYPRE_ParaSails;
585: jac->destroy = HYPRE_ParaSailsDestroy;
586: jac->setup = HYPRE_ParaSailsSetup;
587: jac->solve = HYPRE_ParaSailsSolve;
588: return(0);
589: }
590: PetscStrcmp("euclid",name,&flag);
591: if (flag) {
592: HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver);
593: pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
594: pc->ops->view = PCView_HYPRE_Euclid;
595: jac->destroy = HYPRE_EuclidDestroy;
596: jac->setup = HYPRE_EuclidSetup;
597: jac->solve = HYPRE_EuclidSolve;
598: return(0);
599: }
600: PetscStrcmp("boomeramg",name,&flag);
601: if (flag) {
602: HYPRE_BoomerAMGCreate(&jac->hsolver);
603: pc->ops->setfromoptions = PCSetFromOptions_HYPRE_BoomerAMG;
604: pc->ops->view = PCView_HYPRE_BoomerAMG;
605: jac->destroy = HYPRE_BoomerAMGDestroy;
606: jac->setup = HYPRE_BoomerAMGSetup;
607: jac->solve = HYPRE_BoomerAMGSolve;
608: return(0);
609: }
610: SETERRQ1(1,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name);
611: return(0);
612: }
614: /*
615: It only gets here if the HYPRE type has not been set before the call to
616: ...SetFromOptions() which actually is most of the time
617: */
620: static int PCSetFromOptions_HYPRE(PC pc)
621: {
622: int indx,ierr;
623: const char *type[] = {"pilut","parasails","boomeramg","euclid"};
624: PetscTruth flg;
627: PetscOptionsHead("HYPRE preconditioner options");
628: PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"pilut",&indx,&flg);
629: if (PetscOptionsPublishCount) { /* force the default if it was not yet set and user did not set with option */
630: if (!flg && !pc->ops->apply) {
631: flg = PETSC_TRUE;
632: indx = 0;
633: }
634: }
635: if (flg) {
636: PCHYPRESetType_HYPRE(pc,type[indx]);
637: }
638: if (pc->ops->setfromoptions) {
639: pc->ops->setfromoptions(pc);
640: }
641: PetscOptionsTail();
642: return(0);
643: }
647: /*@
648: PCHYPRESetType - Sets which hypre preconditioner you wish to use
650: Input Parameters:
651: + pc - the preconditioner context
652: - name - either pilut, parasails, boomeramg, euclid
654: Options Database Keys:
655: -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
656:
657: Level: intermediate
659: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC,
660: PCHYPRE
662: @*/
663: int PCHYPRESetType(PC pc,const char name[])
664: {
665: int ierr,(*f)(PC,const char[]);
670: PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);
671: if (f) {
672: (*f)(pc,name);
673: }
674: return(0);
675: }
677: /*MC
678: PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
680: Options Database Keys:
681: + -pc_hypre_type - One of pilut, parasails, boomerAMG, euclid
682: - Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX
683: preconditioner
684:
685: Level: intermediate
687: Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()),
688: the many hypre options can ONLY be set via the options database (e.g. the command line
689: or with PetscOptionsSetValue(), there are no functions to set them)
691: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC,
692: PCHYPRESetType()
694: M*/
696: EXTERN_C_BEGIN
699: int PCCreate_HYPRE(PC pc)
700: {
701: PC_HYPRE *jac;
702: int ierr;
705: PetscNew(PC_HYPRE,&jac);
706: PetscMemzero(jac,sizeof(PC_HYPRE));
707: pc->data = jac;
708: pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
709: /* Com_dup for hypre */
710: MPI_Comm_dup(pc->comm,&(jac->comm_hypre));
711: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C",
712: "PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);
713: return(0);
714: }
715: EXTERN_C_END