xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision d2128fa29df0fa2690fd336850f944f8cb41bc4d)
116d9e3a6SLisandro Dalcin 
216d9e3a6SLisandro Dalcin /*
316d9e3a6SLisandro Dalcin    Provides an interface to the LLNL package hypre
416d9e3a6SLisandro Dalcin */
50f1074feSSatish Balay 
60f1074feSSatish Balay /* Must use hypre 2.0.0 or more recent. */
70f1074feSSatish Balay 
8b45d2f2cSJed Brown #include <petsc-private/pcimpl.h>          /*I "petscpc.h" I*/
9c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
1016d9e3a6SLisandro Dalcin 
1116d9e3a6SLisandro Dalcin /*
1216d9e3a6SLisandro Dalcin    Private context (data structure) for the  preconditioner.
1316d9e3a6SLisandro Dalcin */
1416d9e3a6SLisandro Dalcin typedef struct {
1516d9e3a6SLisandro Dalcin   HYPRE_Solver       hsolver;
1616d9e3a6SLisandro Dalcin   HYPRE_IJMatrix     ij;
1716d9e3a6SLisandro Dalcin   HYPRE_IJVector     b,x;
1816d9e3a6SLisandro Dalcin 
194ddd07fcSJed Brown   HYPRE_Int          (*destroy)(HYPRE_Solver);
204ddd07fcSJed Brown   HYPRE_Int          (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
214ddd07fcSJed Brown   HYPRE_Int          (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
2216d9e3a6SLisandro Dalcin 
2316d9e3a6SLisandro Dalcin   MPI_Comm           comm_hypre;
2416d9e3a6SLisandro Dalcin   char              *hypre_type;
2516d9e3a6SLisandro Dalcin 
2616d9e3a6SLisandro Dalcin   /* options for Pilut and BoomerAMG*/
274ddd07fcSJed Brown   PetscInt           maxiter;
2816d9e3a6SLisandro Dalcin   double             tol;
2916d9e3a6SLisandro Dalcin 
3016d9e3a6SLisandro Dalcin   /* options for Pilut */
314ddd07fcSJed Brown   PetscInt           factorrowsize;
3216d9e3a6SLisandro Dalcin 
3316d9e3a6SLisandro Dalcin   /* options for ParaSails */
344ddd07fcSJed Brown   PetscInt           nlevels;
3516d9e3a6SLisandro Dalcin   double             threshhold;
3616d9e3a6SLisandro Dalcin   double             filter;
374ddd07fcSJed Brown   PetscInt           sym;
3816d9e3a6SLisandro Dalcin   double             loadbal;
394ddd07fcSJed Brown   PetscInt           logging;
404ddd07fcSJed Brown   PetscInt           ruse;
414ddd07fcSJed Brown   PetscInt           symt;
4216d9e3a6SLisandro Dalcin 
4316d9e3a6SLisandro Dalcin   /* options for Euclid */
44ace3abfcSBarry Smith   PetscBool          bjilu;
454ddd07fcSJed Brown   PetscInt           levels;
4616d9e3a6SLisandro Dalcin 
4716d9e3a6SLisandro Dalcin   /* options for Euclid and BoomerAMG */
48ace3abfcSBarry Smith   PetscBool          printstatistics;
4916d9e3a6SLisandro Dalcin 
5016d9e3a6SLisandro Dalcin   /* options for BoomerAMG */
514ddd07fcSJed Brown   PetscInt           cycletype;
524ddd07fcSJed Brown   PetscInt           maxlevels;
5316d9e3a6SLisandro Dalcin   double             strongthreshold;
5416d9e3a6SLisandro Dalcin   double             maxrowsum;
554ddd07fcSJed Brown   PetscInt           gridsweeps[3];
564ddd07fcSJed Brown   PetscInt           coarsentype;
574ddd07fcSJed Brown   PetscInt           measuretype;
584ddd07fcSJed Brown   PetscInt           relaxtype[3];
5916d9e3a6SLisandro Dalcin   double             relaxweight;
6016d9e3a6SLisandro Dalcin   double             outerrelaxweight;
614ddd07fcSJed Brown   PetscInt           relaxorder;
6216d9e3a6SLisandro Dalcin   double             truncfactor;
63ace3abfcSBarry Smith   PetscBool          applyrichardson;
644ddd07fcSJed Brown   PetscInt           pmax;
654ddd07fcSJed Brown   PetscInt           interptype;
664ddd07fcSJed Brown   PetscInt           agg_nl;
674ddd07fcSJed Brown   PetscInt           agg_num_paths;
684ddd07fcSJed Brown   PetscInt           nodal_coarsen;
69ace3abfcSBarry Smith   PetscBool          nodal_relax;
704ddd07fcSJed Brown   PetscInt           nodal_relax_levels;
7116d9e3a6SLisandro Dalcin } PC_HYPRE;
7216d9e3a6SLisandro Dalcin 
73*d2128fa2SBarry Smith #undef __FUNCT__
74*d2128fa2SBarry Smith #define __FUNCT__ "PCHYPREGetSolver"
75*d2128fa2SBarry Smith PetscErrorCode PCHYPREGetSolver(PC pc,HYPRE_Solver *hsolver)
76*d2128fa2SBarry Smith {
77*d2128fa2SBarry Smith   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
78*d2128fa2SBarry Smith 
79*d2128fa2SBarry Smith   PetscFunctionBegin;
80*d2128fa2SBarry Smith   *hsolver = jac->hsolver;
81*d2128fa2SBarry Smith   PetscFunctionReturn(0);
82*d2128fa2SBarry Smith }
8316d9e3a6SLisandro Dalcin 
8416d9e3a6SLisandro Dalcin #undef __FUNCT__
8516d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetUp_HYPRE"
8616d9e3a6SLisandro Dalcin static PetscErrorCode PCSetUp_HYPRE(PC pc)
8716d9e3a6SLisandro Dalcin {
8816d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
8916d9e3a6SLisandro Dalcin   PetscErrorCode     ierr;
9016d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
9116d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv,xv;
9216d9e3a6SLisandro Dalcin   PetscInt           bs;
9316d9e3a6SLisandro Dalcin 
9416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9516d9e3a6SLisandro Dalcin   if (!jac->hypre_type) {
9602a17cd4SBarry Smith     ierr = PCHYPRESetType(pc,"boomeramg");CHKERRQ(ierr);
9716d9e3a6SLisandro Dalcin   }
985f5c5b43SBarry Smith 
995f5c5b43SBarry Smith   if (pc->setupcalled) {
1005f5c5b43SBarry Smith     /* always destroy the old matrix and create a new memory;
1015f5c5b43SBarry Smith        hope this does not churn the memory too much. The problem
1025f5c5b43SBarry Smith        is I do not know if it is possible to put the matrix back to
1035f5c5b43SBarry Smith        its initial state so that we can directly copy the values
1045f5c5b43SBarry Smith        the second time through. */
10530e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_IJMatrixDestroy,(jac->ij));
1065f5c5b43SBarry Smith     jac->ij = 0;
10716d9e3a6SLisandro Dalcin   }
1085f5c5b43SBarry Smith 
10916d9e3a6SLisandro Dalcin   if (!jac->ij) { /* create the matrix the first time through */
11016d9e3a6SLisandro Dalcin     ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr);
11116d9e3a6SLisandro Dalcin   }
11216d9e3a6SLisandro Dalcin   if (!jac->b) { /* create the vectors the first time through */
11316d9e3a6SLisandro Dalcin     Vec x,b;
11416d9e3a6SLisandro Dalcin     ierr = MatGetVecs(pc->pmat,&x,&b);CHKERRQ(ierr);
11516d9e3a6SLisandro Dalcin     ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr);
11616d9e3a6SLisandro Dalcin     ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr);
1176bf464f9SBarry Smith     ierr = VecDestroy(&x);CHKERRQ(ierr);
1186bf464f9SBarry Smith     ierr = VecDestroy(&b);CHKERRQ(ierr);
11916d9e3a6SLisandro Dalcin   }
1205f5c5b43SBarry Smith 
12116d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
12216d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
12316d9e3a6SLisandro Dalcin     ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
12416d9e3a6SLisandro Dalcin     if (bs > 1) {
12530e6f737SJed Brown       PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumFunctions,(jac->hsolver,bs));
12616d9e3a6SLisandro Dalcin     }
12716d9e3a6SLisandro Dalcin   };
12816d9e3a6SLisandro Dalcin   ierr = MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);CHKERRQ(ierr);
12930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat));
13030e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->b,(void**)&bv));
13130e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->x,(void**)&xv));
13230e6f737SJed Brown   PetscStackCallHypre("HYPRE_SetupXXX",(*jac->setup),(jac->hsolver,hmat,bv,xv));
13316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
13416d9e3a6SLisandro Dalcin }
13516d9e3a6SLisandro Dalcin 
13616d9e3a6SLisandro Dalcin /*
13716d9e3a6SLisandro Dalcin     Replaces the address where the HYPRE vector points to its data with the address of
13816d9e3a6SLisandro Dalcin   PETSc's data. Saves the old address so it can be reset when we are finished with it.
13916d9e3a6SLisandro Dalcin   Allows use to get the data into a HYPRE vector without the cost of memcopies
14016d9e3a6SLisandro Dalcin */
14116d9e3a6SLisandro Dalcin #define HYPREReplacePointer(b,newvalue,savedvalue) {\
14216d9e3a6SLisandro Dalcin    hypre_ParVector *par_vector   = (hypre_ParVector *)hypre_IJVectorObject(((hypre_IJVector*)b));\
14316d9e3a6SLisandro Dalcin    hypre_Vector    *local_vector = hypre_ParVectorLocalVector(par_vector);\
14416d9e3a6SLisandro Dalcin    savedvalue         = local_vector->data;\
14516d9e3a6SLisandro Dalcin    local_vector->data = newvalue;}
14616d9e3a6SLisandro Dalcin 
14716d9e3a6SLisandro Dalcin #undef __FUNCT__
14816d9e3a6SLisandro Dalcin #define __FUNCT__ "PCApply_HYPRE"
14916d9e3a6SLisandro Dalcin static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x)
15016d9e3a6SLisandro Dalcin {
15116d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
15216d9e3a6SLisandro Dalcin   PetscErrorCode     ierr;
15316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
15416d9e3a6SLisandro Dalcin   PetscScalar        *bv,*xv;
15516d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv,jxv;
15616d9e3a6SLisandro Dalcin   PetscScalar        *sbv,*sxv;
1574ddd07fcSJed Brown   PetscInt           hierr;
15816d9e3a6SLisandro Dalcin 
15916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
16016d9e3a6SLisandro Dalcin   if (!jac->applyrichardson) {ierr = VecSet(x,0.0);CHKERRQ(ierr);}
16116d9e3a6SLisandro Dalcin   ierr = VecGetArray(b,&bv);CHKERRQ(ierr);
16216d9e3a6SLisandro Dalcin   ierr = VecGetArray(x,&xv);CHKERRQ(ierr);
16316d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->b,bv,sbv);
16416d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->x,xv,sxv);
16516d9e3a6SLisandro Dalcin 
16630e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat));
16730e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->b,(void**)&jbv));
16830e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->x,(void**)&jxv));
16916d9e3a6SLisandro Dalcin   hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv);
17065e19b50SBarry Smith   if (hierr && hierr != HYPRE_ERROR_CONV) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
17116d9e3a6SLisandro Dalcin   if (hierr) hypre__global_error = 0;
17216d9e3a6SLisandro Dalcin 
17316d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->b,sbv,bv);
17416d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->x,sxv,xv);
17516d9e3a6SLisandro Dalcin   ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr);
17616d9e3a6SLisandro Dalcin   ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr);
17716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
17816d9e3a6SLisandro Dalcin }
17916d9e3a6SLisandro Dalcin 
18016d9e3a6SLisandro Dalcin #undef __FUNCT__
18116d9e3a6SLisandro Dalcin #define __FUNCT__ "PCDestroy_HYPRE"
18216d9e3a6SLisandro Dalcin static PetscErrorCode PCDestroy_HYPRE(PC pc)
18316d9e3a6SLisandro Dalcin {
18416d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
18516d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
18616d9e3a6SLisandro Dalcin 
18716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
18830e6f737SJed Brown   if (jac->ij) PetscStackCallHypre(0,HYPRE_IJMatrixDestroy,(jac->ij));
18930e6f737SJed Brown   if (jac->b)  PetscStackCallHypre(0,HYPRE_IJVectorDestroy,(jac->b));
19030e6f737SJed Brown   if (jac->x)  PetscStackCallHypre(0,HYPRE_IJVectorDestroy,(jac->x));
19130e6f737SJed Brown   if (jac->destroy) PetscStackCallHypre("HYPRE_DistroyXXX",(*jac->destroy),(jac->hsolver));
192503cfb0cSBarry Smith   ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr);
19316d9e3a6SLisandro Dalcin   if (jac->comm_hypre != MPI_COMM_NULL) { ierr = MPI_Comm_free(&(jac->comm_hypre));CHKERRQ(ierr);}
194c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
19516d9e3a6SLisandro Dalcin 
19616d9e3a6SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)pc,0);CHKERRQ(ierr);
19716d9e3a6SLisandro Dalcin   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","",PETSC_NULL);CHKERRQ(ierr);
19816d9e3a6SLisandro Dalcin   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","",PETSC_NULL);CHKERRQ(ierr);
19916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
20016d9e3a6SLisandro Dalcin }
20116d9e3a6SLisandro Dalcin 
20216d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
20316d9e3a6SLisandro Dalcin #undef __FUNCT__
20416d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE_Pilut"
20516d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc)
20616d9e3a6SLisandro Dalcin {
20716d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
20816d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
209ace3abfcSBarry Smith   PetscBool      flag;
21016d9e3a6SLisandro Dalcin 
21116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21216d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE Pilut Options");CHKERRQ(ierr);
21316d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);CHKERRQ(ierr);
21430e6f737SJed Brown   if (flag) PetscStackCallHypre(0,HYPRE_ParCSRPilutSetMaxIter,(jac->hsolver,jac->maxiter));
21516d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);CHKERRQ(ierr);
21630e6f737SJed Brown   if (flag) PetscStackCallHypre(0,HYPRE_ParCSRPilutSetDropTolerance,(jac->hsolver,jac->tol));
21716d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);CHKERRQ(ierr);
21830e6f737SJed Brown   if (flag) PetscStackCallHypre(0,HYPRE_ParCSRPilutSetFactorRowSize,(jac->hsolver,jac->factorrowsize));
21916d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
22016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
22116d9e3a6SLisandro Dalcin }
22216d9e3a6SLisandro Dalcin 
22316d9e3a6SLisandro Dalcin #undef __FUNCT__
22416d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_Pilut"
22516d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)
22616d9e3a6SLisandro Dalcin {
22716d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
22816d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
229ace3abfcSBarry Smith   PetscBool      iascii;
23016d9e3a6SLisandro Dalcin 
23116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
232251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
23316d9e3a6SLisandro Dalcin   if (iascii) {
23416d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut preconditioning\n");CHKERRQ(ierr);
23516d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
23616d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: maximum number of iterations %d\n",jac->maxiter);CHKERRQ(ierr);
23716d9e3a6SLisandro Dalcin     } else {
23816d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default maximum number of iterations \n");CHKERRQ(ierr);
23916d9e3a6SLisandro Dalcin     }
24016d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
24116d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: drop tolerance %G\n",jac->tol);CHKERRQ(ierr);
24216d9e3a6SLisandro Dalcin     } else {
24316d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default drop tolerance \n");CHKERRQ(ierr);
24416d9e3a6SLisandro Dalcin     }
24516d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
24616d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: factor row size %d\n",jac->factorrowsize);CHKERRQ(ierr);
24716d9e3a6SLisandro Dalcin     } else {
24816d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default factor row size \n");CHKERRQ(ierr);
24916d9e3a6SLisandro Dalcin     }
25016d9e3a6SLisandro Dalcin   }
25116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
25216d9e3a6SLisandro Dalcin }
25316d9e3a6SLisandro Dalcin 
25416d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
25516d9e3a6SLisandro Dalcin #undef __FUNCT__
25616d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE_Euclid"
25716d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc)
25816d9e3a6SLisandro Dalcin {
25916d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
26016d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
261ace3abfcSBarry Smith   PetscBool      flag;
262390e7148SBarry Smith   char           *args[8],levels[16];
263390e7148SBarry Smith   PetscInt       cnt = 0;
26416d9e3a6SLisandro Dalcin 
26516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
26616d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE Euclid Options");CHKERRQ(ierr);
26716d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);CHKERRQ(ierr);
26816d9e3a6SLisandro Dalcin   if (flag) {
26965e19b50SBarry Smith     if (jac->levels < 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be nonegative",jac->levels);
2704ddd07fcSJed Brown     ierr = PetscSNPrintf(levels,sizeof levels,"%D",jac->levels);CHKERRQ(ierr);
271390e7148SBarry Smith     args[cnt++] = (char*)"-level"; args[cnt++] = levels;
27216d9e3a6SLisandro Dalcin   }
273acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,PETSC_NULL);CHKERRQ(ierr);
27416d9e3a6SLisandro Dalcin   if (jac->bjilu) {
275390e7148SBarry Smith     args[cnt++] =(char*) "-bj"; args[cnt++] = (char*)"1";
27616d9e3a6SLisandro Dalcin   }
27716d9e3a6SLisandro Dalcin 
278acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);CHKERRQ(ierr);
27916d9e3a6SLisandro Dalcin   if (jac->printstatistics) {
280390e7148SBarry Smith     args[cnt++] = (char*)"-eu_stats"; args[cnt++] = (char*)"1";
281390e7148SBarry Smith     args[cnt++] = (char*)"-eu_mem"; args[cnt++] = (char*)"1";
28216d9e3a6SLisandro Dalcin   }
28316d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
28430e6f737SJed Brown   if (cnt) PetscStackCallHypre(0,HYPRE_EuclidSetParams,(jac->hsolver,cnt,args));
28516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
28616d9e3a6SLisandro Dalcin }
28716d9e3a6SLisandro Dalcin 
28816d9e3a6SLisandro Dalcin #undef __FUNCT__
28916d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_Euclid"
29016d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)
29116d9e3a6SLisandro Dalcin {
29216d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
29316d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
294ace3abfcSBarry Smith   PetscBool      iascii;
29516d9e3a6SLisandro Dalcin 
29616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
297251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
29816d9e3a6SLisandro Dalcin   if (iascii) {
29916d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid preconditioning\n");CHKERRQ(ierr);
30016d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: number of levels %d\n",jac->levels);CHKERRQ(ierr);
30116d9e3a6SLisandro Dalcin     if (jac->bjilu) {
30216d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: Using block Jacobi ILU instead of parallel ILU\n");CHKERRQ(ierr);
30316d9e3a6SLisandro Dalcin     }
30416d9e3a6SLisandro Dalcin   }
30516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
30616d9e3a6SLisandro Dalcin }
30716d9e3a6SLisandro Dalcin 
30816d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
30916d9e3a6SLisandro Dalcin 
31016d9e3a6SLisandro Dalcin #undef __FUNCT__
31116d9e3a6SLisandro Dalcin #define __FUNCT__ "PCApplyTranspose_HYPRE_BoomerAMG"
31216d9e3a6SLisandro Dalcin static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x)
31316d9e3a6SLisandro Dalcin {
31416d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
31516d9e3a6SLisandro Dalcin   PetscErrorCode     ierr;
31616d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
31716d9e3a6SLisandro Dalcin   PetscScalar        *bv,*xv;
31816d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv,jxv;
31916d9e3a6SLisandro Dalcin   PetscScalar        *sbv,*sxv;
3204ddd07fcSJed Brown   PetscInt           hierr;
32116d9e3a6SLisandro Dalcin 
32216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
32316d9e3a6SLisandro Dalcin   ierr = VecSet(x,0.0);CHKERRQ(ierr);
32416d9e3a6SLisandro Dalcin   ierr = VecGetArray(b,&bv);CHKERRQ(ierr);
32516d9e3a6SLisandro Dalcin   ierr = VecGetArray(x,&xv);CHKERRQ(ierr);
32616d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->b,bv,sbv);
32716d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->x,xv,sxv);
32816d9e3a6SLisandro Dalcin 
32930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat));
33030e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->b,(void**)&jbv));
33130e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->x,(void**)&jxv));
33216d9e3a6SLisandro Dalcin 
33316d9e3a6SLisandro Dalcin   hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jbv,jxv);
33416d9e3a6SLisandro Dalcin   /* error code of 1 in BoomerAMG merely means convergence not achieved */
335e32f2f54SBarry Smith   if (hierr && (hierr != 1)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
33616d9e3a6SLisandro Dalcin   if (hierr) hypre__global_error = 0;
33716d9e3a6SLisandro Dalcin 
33816d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->b,sbv,bv);
33916d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->x,sxv,xv);
34016d9e3a6SLisandro Dalcin   ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr);
34116d9e3a6SLisandro Dalcin   ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr);
34216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
34316d9e3a6SLisandro Dalcin }
34416d9e3a6SLisandro Dalcin 
34516d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"","V","W"};
3460f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout", "", "PMIS", "", "HMIS"};
34716d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local","global"};
3480f1074feSSatish Balay static const char *HYPREBoomerAMGRelaxType[]   = {"Jacobi","sequential-Gauss-Seidel","","SOR/Jacobi","backward-SOR/Jacobi","","symmetric-SOR/Jacobi",
3490f1074feSSatish Balay                                                   "","","Gaussian-elimination"};
3500f1074feSSatish Balay static const char *HYPREBoomerAMGInterpType[]  = {"classical", "", "", "direct", "multipass", "multipass-wts", "ext+i",
3510f1074feSSatish Balay                                                   "ext+i-cc", "standard", "standard-wts", "", "", "FF", "FF1"};
35216d9e3a6SLisandro Dalcin #undef __FUNCT__
35316d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE_BoomerAMG"
35416d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc)
35516d9e3a6SLisandro Dalcin {
35616d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
35716d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
3584ddd07fcSJed Brown   PetscInt       n,indx,level;
359ace3abfcSBarry Smith   PetscBool      flg, tmp_truth;
36016d9e3a6SLisandro Dalcin   double         tmpdbl, twodbl[2];
36116d9e3a6SLisandro Dalcin 
36216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
36316d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE BoomerAMG Options");CHKERRQ(ierr);
3644336a9eeSBarry Smith   ierr = PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType+1,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg);CHKERRQ(ierr);
36516d9e3a6SLisandro Dalcin   if (flg) {
3664336a9eeSBarry Smith     jac->cycletype = indx+1;
36730e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype));
36816d9e3a6SLisandro Dalcin   }
36916d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);CHKERRQ(ierr);
37016d9e3a6SLisandro Dalcin   if (flg) {
37165e19b50SBarry Smith     if (jac->maxlevels < 2) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be at least two",jac->maxlevels);
37230e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels));
37316d9e3a6SLisandro Dalcin   }
37416d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg);CHKERRQ(ierr);
37516d9e3a6SLisandro Dalcin   if (flg) {
37665e19b50SBarry Smith     if (jac->maxiter < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %d must be at least one",jac->maxiter);
37730e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter));
37816d9e3a6SLisandro Dalcin   }
3790f1074feSSatish Balay   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_tol","Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)","None",jac->tol,&jac->tol,&flg);CHKERRQ(ierr);
38016d9e3a6SLisandro Dalcin   if (flg) {
38165e19b50SBarry Smith     if (jac->tol < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Tolerance %G must be greater than or equal to zero",jac->tol);
38230e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol));
38316d9e3a6SLisandro Dalcin   }
38416d9e3a6SLisandro Dalcin 
3850f1074feSSatish Balay   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_truncfactor","Truncation factor for interpolation (0=no truncation)","None",jac->truncfactor,&jac->truncfactor,&flg);CHKERRQ(ierr);
38616d9e3a6SLisandro Dalcin   if (flg) {
38765e19b50SBarry Smith     if (jac->truncfactor < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Truncation factor %G must be great than or equal zero",jac->truncfactor);
38830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor));
38916d9e3a6SLisandro Dalcin   }
39016d9e3a6SLisandro Dalcin 
3910f1074feSSatish Balay  ierr = PetscOptionsInt("-pc_hypre_boomeramg_P_max","Max elements per row for interpolation operator ( 0=unlimited )","None",jac->pmax,&jac->pmax,&flg);CHKERRQ(ierr);
3920f1074feSSatish Balay   if (flg) {
39365e19b50SBarry Smith     if (jac->pmax < 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"P_max %G must be greater than or equal to zero",jac->pmax);
39430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax));
3950f1074feSSatish Balay   }
3960f1074feSSatish Balay 
3970f1074feSSatish Balay  ierr = PetscOptionsInt("-pc_hypre_boomeramg_agg_nl","Number of levels of aggressive coarsening","None",jac->agg_nl,&jac->agg_nl,&flg);CHKERRQ(ierr);
3980f1074feSSatish Balay   if (flg) {
39965e19b50SBarry Smith      if (jac->agg_nl < 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %G must be greater than or equal to zero",jac->agg_nl);
4000f1074feSSatish Balay 
40130e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl));
4020f1074feSSatish Balay   }
4030f1074feSSatish Balay 
4040f1074feSSatish Balay 
4050f1074feSSatish Balay  ierr = PetscOptionsInt("-pc_hypre_boomeramg_agg_num_paths","Number of paths for aggressive coarsening","None",jac->agg_num_paths,&jac->agg_num_paths,&flg);CHKERRQ(ierr);
4060f1074feSSatish Balay   if (flg) {
40765e19b50SBarry Smith      if (jac->agg_num_paths < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of paths %G must be greater than or equal to 1",jac->agg_num_paths);
4080f1074feSSatish Balay 
40930e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths));
4100f1074feSSatish Balay   }
4110f1074feSSatish Balay 
4120f1074feSSatish Balay 
41316d9e3a6SLisandro Dalcin   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);CHKERRQ(ierr);
41416d9e3a6SLisandro Dalcin   if (flg) {
41565e19b50SBarry Smith     if (jac->strongthreshold < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Strong threshold %G must be great than or equal zero",jac->strongthreshold);
41630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold));
41716d9e3a6SLisandro Dalcin   }
41816d9e3a6SLisandro Dalcin   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);CHKERRQ(ierr);
41916d9e3a6SLisandro Dalcin   if (flg) {
42065e19b50SBarry Smith     if (jac->maxrowsum < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be greater than zero",jac->maxrowsum);
42165e19b50SBarry Smith     if (jac->maxrowsum > 1.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be less than or equal one",jac->maxrowsum);
42230e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum));
42316d9e3a6SLisandro Dalcin   }
42416d9e3a6SLisandro Dalcin 
42516d9e3a6SLisandro Dalcin   /* Grid sweeps */
4260f1074feSSatish Balay   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_all","Number of sweeps for the up and down grid levels","None",jac->gridsweeps[0],&indx,&flg);CHKERRQ(ierr);
42716d9e3a6SLisandro Dalcin   if (flg) {
42830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver,indx));
42916d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
43016d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
4310f1074feSSatish Balay     jac->gridsweeps[1] = indx;
4320f1074feSSatish Balay     /*defaults coarse to 1 */
4330f1074feSSatish Balay     jac->gridsweeps[2] = 1;
43416d9e3a6SLisandro Dalcin   }
4350f1074feSSatish Balay 
4360f1074feSSatish Balay   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[0], &indx ,&flg);CHKERRQ(ierr);
43716d9e3a6SLisandro Dalcin   if (flg) {
43830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 1));
4390f1074feSSatish Balay     jac->gridsweeps[0] = indx;
44016d9e3a6SLisandro Dalcin   }
44116d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg);CHKERRQ(ierr);
44216d9e3a6SLisandro Dalcin   if (flg) {
44330e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 2));
4440f1074feSSatish Balay     jac->gridsweeps[1] = indx;
44516d9e3a6SLisandro Dalcin   }
4460f1074feSSatish Balay   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[2],&indx,&flg);CHKERRQ(ierr);
44716d9e3a6SLisandro Dalcin   if (flg) {
44830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 3));
4490f1074feSSatish Balay     jac->gridsweeps[2] = indx;
45016d9e3a6SLisandro Dalcin   }
45116d9e3a6SLisandro Dalcin 
45216d9e3a6SLisandro Dalcin   /* Relax type */
4530f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all","Relax type for the up and down cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
45416d9e3a6SLisandro Dalcin   if (flg) {
4550f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1]  = indx;
45630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, indx));
4570f1074feSSatish Balay     /* by default, coarse type set to 9 */
4580f1074feSSatish Balay     jac->relaxtype[2] = 9;
4590f1074feSSatish Balay 
46016d9e3a6SLisandro Dalcin   }
4610f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
46216d9e3a6SLisandro Dalcin   if (flg) {
46316d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
46430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 1));
46516d9e3a6SLisandro Dalcin   }
4660f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
46716d9e3a6SLisandro Dalcin   if (flg) {
4680f1074feSSatish Balay     jac->relaxtype[1] = indx;
46930e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 2));
47016d9e3a6SLisandro Dalcin   }
47116d9e3a6SLisandro Dalcin   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[9],&indx,&flg);CHKERRQ(ierr);
47216d9e3a6SLisandro Dalcin   if (flg) {
4730f1074feSSatish Balay     jac->relaxtype[2] = indx;
47430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 3));
47516d9e3a6SLisandro Dalcin   }
47616d9e3a6SLisandro Dalcin 
47716d9e3a6SLisandro Dalcin   /* Relaxation Weight */
47816d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_boomeramg_relax_weight_all","Relaxation weight for all levels (0 = hypre estimates, -k = determined with k CG steps)","None",jac->relaxweight, &tmpdbl ,&flg);CHKERRQ(ierr);
47916d9e3a6SLisandro Dalcin   if (flg) {
48030e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxWt,(jac->hsolver,tmpdbl));
48116d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
48216d9e3a6SLisandro Dalcin   }
48316d9e3a6SLisandro Dalcin 
48416d9e3a6SLisandro Dalcin   n=2;
48516d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
48616d9e3a6SLisandro Dalcin   ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level","Set the relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr);
48716d9e3a6SLisandro Dalcin   if (flg) {
48816d9e3a6SLisandro Dalcin     if (n == 2) {
48916d9e3a6SLisandro Dalcin       indx =  (int)PetscAbsReal(twodbl[1]);
49030e6f737SJed Brown       PetscStackCallHypre(0,HYPRE_BoomerAMGSetLevelRelaxWt,(jac->hsolver,twodbl[0],indx));
49116d9e3a6SLisandro Dalcin     } else {
49265e19b50SBarry Smith       SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %d",n);
49316d9e3a6SLisandro Dalcin     }
49416d9e3a6SLisandro Dalcin   }
49516d9e3a6SLisandro Dalcin 
49616d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
49716d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_boomeramg_outer_relax_weight_all","Outer relaxation weight for all levels ( -k = determined with k CG steps)","None",jac->outerrelaxweight, &tmpdbl ,&flg);CHKERRQ(ierr);
49816d9e3a6SLisandro Dalcin   if (flg) {
49930e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetOuterWt,( jac->hsolver, tmpdbl));
50016d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
50116d9e3a6SLisandro Dalcin   }
50216d9e3a6SLisandro Dalcin 
50316d9e3a6SLisandro Dalcin   n=2;
50416d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
50516d9e3a6SLisandro Dalcin   ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_outer_relax_weight_level","Set the outer relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr);
50616d9e3a6SLisandro Dalcin   if (flg) {
50716d9e3a6SLisandro Dalcin     if (n == 2) {
50816d9e3a6SLisandro Dalcin       indx =  (int)PetscAbsReal(twodbl[1]);
50930e6f737SJed Brown       PetscStackCallHypre(0,HYPRE_BoomerAMGSetLevelOuterWt,( jac->hsolver, twodbl[0], indx));
51016d9e3a6SLisandro Dalcin     } else {
51165e19b50SBarry Smith       SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %d",n);
51216d9e3a6SLisandro Dalcin     }
51316d9e3a6SLisandro Dalcin   }
51416d9e3a6SLisandro Dalcin 
51516d9e3a6SLisandro Dalcin   /* the Relax Order */
516acfcf0e5SJed Brown   ierr = PetscOptionsBool( "-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
51716d9e3a6SLisandro Dalcin 
51816d9e3a6SLisandro Dalcin   if (flg) {
51916d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
52030e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder));
52116d9e3a6SLisandro Dalcin   }
52216d9e3a6SLisandro Dalcin   ierr = PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,2,HYPREBoomerAMGMeasureType[0],&indx,&flg);CHKERRQ(ierr);
52316d9e3a6SLisandro Dalcin   if (flg) {
52416d9e3a6SLisandro Dalcin     jac->measuretype = indx;
52530e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype));
52616d9e3a6SLisandro Dalcin   }
5270f1074feSSatish Balay   /* update list length 3/07 */
5280f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,11,HYPREBoomerAMGCoarsenType[6],&indx,&flg);CHKERRQ(ierr);
52916d9e3a6SLisandro Dalcin   if (flg) {
53016d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
53130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype));
53216d9e3a6SLisandro Dalcin   }
5330f1074feSSatish Balay 
5340f1074feSSatish Balay   /* new 3/07 */
5350f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_interp_type","Interpolation type","None",HYPREBoomerAMGInterpType,14,HYPREBoomerAMGInterpType[0],&indx,&flg);CHKERRQ(ierr);
5360f1074feSSatish Balay   if (flg) {
5370f1074feSSatish Balay     jac->interptype = indx;
53830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype));
5390f1074feSSatish Balay   }
5400f1074feSSatish Balay 
541b96a4a96SBarry Smith   ierr = PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg);CHKERRQ(ierr);
54216d9e3a6SLisandro Dalcin   if (flg) {
543b96a4a96SBarry Smith     level = 3;
54416d9e3a6SLisandro Dalcin     ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,PETSC_NULL);CHKERRQ(ierr);
545b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
54630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetPrintLevel,(jac->hsolver,level));
5472ae77aedSBarry Smith   }
5482ae77aedSBarry Smith 
549b96a4a96SBarry Smith   ierr = PetscOptionsName("-pc_hypre_boomeramg_print_debug","Print debug information","None",&flg);CHKERRQ(ierr);
5502ae77aedSBarry Smith   if (flg) {
551b96a4a96SBarry Smith     level = 3;
5522ae77aedSBarry Smith     ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_debug","Print debug information","None",level,&level,PETSC_NULL);CHKERRQ(ierr);
553b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
55430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetDebugFlag,(jac->hsolver,level));
55516d9e3a6SLisandro Dalcin   }
5568f87f92bSBarry Smith 
557acfcf0e5SJed Brown   ierr = PetscOptionsBool( "-pc_hypre_boomeramg_nodal_coarsen", "HYPRE_BoomerAMGSetNodal()", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
5588f87f92bSBarry Smith   if (flg && tmp_truth) {
5598f87f92bSBarry Smith     jac->nodal_coarsen = 1;
56030e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetNodal,(jac->hsolver,1));
5618f87f92bSBarry Smith   }
5628f87f92bSBarry Smith 
563acfcf0e5SJed Brown   ierr = PetscOptionsBool( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
5648f87f92bSBarry Smith   if (flg && tmp_truth) {
5658f87f92bSBarry Smith     PetscInt tmp_int;
5668f87f92bSBarry Smith     ierr = PetscOptionsInt( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None",jac->nodal_relax_levels,&tmp_int,&flg);CHKERRQ(ierr);
5678f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
56830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetSmoothType,(jac->hsolver,6));
56930e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetDomainType,(jac->hsolver,1));
57030e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetOverlap,(jac->hsolver,0));
57130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetSmoothNumLevels,(jac->hsolver,jac->nodal_relax_levels));
5728f87f92bSBarry Smith   }
5738f87f92bSBarry Smith 
57416d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
57516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
57616d9e3a6SLisandro Dalcin }
57716d9e3a6SLisandro Dalcin 
57816d9e3a6SLisandro Dalcin #undef __FUNCT__
57916d9e3a6SLisandro Dalcin #define __FUNCT__ "PCApplyRichardson_HYPRE_BoomerAMG"
580ace3abfcSBarry Smith static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool  guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
58116d9e3a6SLisandro Dalcin {
58216d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
58316d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
5844ddd07fcSJed Brown   PetscInt       oits;
58516d9e3a6SLisandro Dalcin 
58616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
58730e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,its*jac->maxiter));
58830e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,rtol));
58916d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
59016d9e3a6SLisandro Dalcin   ierr = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr);
59116d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
59230e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_BoomerAMGGetNumIterations,(jac->hsolver,&oits));
5934d0a8057SBarry Smith   *outits = oits;
5944d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
5954d0a8057SBarry Smith   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
59630e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol));
59730e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter));
59816d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
59916d9e3a6SLisandro Dalcin }
60016d9e3a6SLisandro Dalcin 
60116d9e3a6SLisandro Dalcin 
60216d9e3a6SLisandro Dalcin #undef __FUNCT__
60316d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_BoomerAMG"
60416d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
60516d9e3a6SLisandro Dalcin {
60616d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
60716d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
608ace3abfcSBarry Smith   PetscBool      iascii;
60916d9e3a6SLisandro Dalcin 
61016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
611251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
61216d9e3a6SLisandro Dalcin   if (iascii) {
61316d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr);
61416d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr);
61516d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);CHKERRQ(ierr);
61616d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of iterations PER hypre call %d\n",jac->maxiter);CHKERRQ(ierr);
61716d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Convergence tolerance PER hypre call %G\n",jac->tol);CHKERRQ(ierr);
61816d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Threshold for strong coupling %G\n",jac->strongthreshold);CHKERRQ(ierr);
6190f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Interpolation truncation factor %G\n",jac->truncfactor);CHKERRQ(ierr);
6200f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Interpolation: max elements per row %d\n",jac->pmax);CHKERRQ(ierr);
6210f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Number of levels of aggressive coarsening %d\n",jac->agg_nl);CHKERRQ(ierr);
6220f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Number of paths for aggressive coarsening %d\n",jac->agg_num_paths);CHKERRQ(ierr);
6230f1074feSSatish Balay 
62416d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum row sums %G\n",jac->maxrowsum);CHKERRQ(ierr);
62516d9e3a6SLisandro Dalcin 
6260f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps down         %d\n",jac->gridsweeps[0]);CHKERRQ(ierr);
6270f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps up           %d\n",jac->gridsweeps[1]);CHKERRQ(ierr);
6280f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on coarse    %d\n",jac->gridsweeps[2]);CHKERRQ(ierr);
62916d9e3a6SLisandro Dalcin 
6300f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax down          %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr);
6310f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax up            %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr);
6320f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on coarse     %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr);
63316d9e3a6SLisandro Dalcin 
63416d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax weight  (all)      %G\n",jac->relaxweight);CHKERRQ(ierr);
63516d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Outer relax weight (all) %G\n",jac->outerrelaxweight);CHKERRQ(ierr);
63616d9e3a6SLisandro Dalcin 
63716d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
63816d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Using CF-relaxation\n");CHKERRQ(ierr);
63916d9e3a6SLisandro Dalcin     } else {
64016d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Not using CF-relaxation\n");CHKERRQ(ierr);
64116d9e3a6SLisandro Dalcin     }
64216d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Measure type        %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr);
64316d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Coarsen type        %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr);
6440f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Interpolation type  %s\n",HYPREBoomerAMGInterpType[jac->interptype]);CHKERRQ(ierr);
6458f87f92bSBarry Smith     if (jac->nodal_coarsen) {
6468f87f92bSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal coarsening (with HYPRE_BOOMERAMGSetNodal())\n");CHKERRQ(ierr);
6478f87f92bSBarry Smith     }
6488f87f92bSBarry Smith     if (jac->nodal_relax) {
6498f87f92bSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal relaxation via Schwarz smoothing on levels %d\n",jac->nodal_relax_levels);CHKERRQ(ierr);
6508f87f92bSBarry Smith     }
65116d9e3a6SLisandro Dalcin   }
65216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
65316d9e3a6SLisandro Dalcin }
65416d9e3a6SLisandro Dalcin 
65516d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
65616d9e3a6SLisandro Dalcin #undef __FUNCT__
65716d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE_ParaSails"
65816d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc)
65916d9e3a6SLisandro Dalcin {
66016d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
66116d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
6624ddd07fcSJed Brown   PetscInt       indx;
663ace3abfcSBarry Smith   PetscBool      flag;
66416d9e3a6SLisandro Dalcin   const char     *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
66516d9e3a6SLisandro Dalcin 
66616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
66716d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE ParaSails Options");CHKERRQ(ierr);
66816d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr);
66916d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,&flag);CHKERRQ(ierr);
67016d9e3a6SLisandro Dalcin   if (flag) {
67130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshhold,jac->nlevels));
67216d9e3a6SLisandro Dalcin   }
67316d9e3a6SLisandro Dalcin 
67416d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr);
67516d9e3a6SLisandro Dalcin   if (flag) {
67630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter));
67716d9e3a6SLisandro Dalcin   }
67816d9e3a6SLisandro Dalcin 
67916d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr);
68016d9e3a6SLisandro Dalcin   if (flag) {
68130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal));
68216d9e3a6SLisandro Dalcin   }
68316d9e3a6SLisandro Dalcin 
684acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_hypre_parasails_logging","Print info to screen","None",(PetscBool)jac->logging,(PetscBool*)&jac->logging,&flag);CHKERRQ(ierr);
68516d9e3a6SLisandro Dalcin   if (flag) {
68630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging));
68716d9e3a6SLisandro Dalcin   }
68816d9e3a6SLisandro Dalcin 
689acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscBool)jac->ruse,(PetscBool*)&jac->ruse,&flag);CHKERRQ(ierr);
69016d9e3a6SLisandro Dalcin   if (flag) {
69130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse));
69216d9e3a6SLisandro Dalcin   }
69316d9e3a6SLisandro Dalcin 
69416d9e3a6SLisandro Dalcin   ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],&indx,&flag);CHKERRQ(ierr);
69516d9e3a6SLisandro Dalcin   if (flag) {
69616d9e3a6SLisandro Dalcin     jac->symt = indx;
69730e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt));
69816d9e3a6SLisandro Dalcin   }
69916d9e3a6SLisandro Dalcin 
70016d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
70116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
70216d9e3a6SLisandro Dalcin }
70316d9e3a6SLisandro Dalcin 
70416d9e3a6SLisandro Dalcin #undef __FUNCT__
70516d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_ParaSails"
70616d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
70716d9e3a6SLisandro Dalcin {
70816d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
70916d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
710ace3abfcSBarry Smith   PetscBool      iascii;
71116d9e3a6SLisandro Dalcin   const char     *symt = 0;;
71216d9e3a6SLisandro Dalcin 
71316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
714251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
71516d9e3a6SLisandro Dalcin   if (iascii) {
71616d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails preconditioning\n");CHKERRQ(ierr);
71716d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: nlevels %d\n",jac->nlevels);CHKERRQ(ierr);
71816d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: threshold %G\n",jac->threshhold);CHKERRQ(ierr);
71916d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: filter %G\n",jac->filter);CHKERRQ(ierr);
72016d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: load balance %G\n",jac->loadbal);CHKERRQ(ierr);
721ace3abfcSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: reuse nonzero structure %s\n",PetscBools[jac->ruse]);CHKERRQ(ierr);
722ace3abfcSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: print info to screen %s\n",PetscBools[jac->logging]);CHKERRQ(ierr);
72316d9e3a6SLisandro Dalcin     if (!jac->symt) {
72416d9e3a6SLisandro Dalcin       symt = "nonsymmetric matrix and preconditioner";
72516d9e3a6SLisandro Dalcin     } else if (jac->symt == 1) {
72616d9e3a6SLisandro Dalcin       symt = "SPD matrix and preconditioner";
72716d9e3a6SLisandro Dalcin     } else if (jac->symt == 2) {
72816d9e3a6SLisandro Dalcin       symt = "nonsymmetric matrix but SPD preconditioner";
72916d9e3a6SLisandro Dalcin     } else {
73065e19b50SBarry Smith       SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt);
73116d9e3a6SLisandro Dalcin     }
73216d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: %s\n",symt);CHKERRQ(ierr);
73316d9e3a6SLisandro Dalcin   }
73416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
73516d9e3a6SLisandro Dalcin }
73616d9e3a6SLisandro Dalcin /* ---------------------------------------------------------------------------------*/
73716d9e3a6SLisandro Dalcin 
73816d9e3a6SLisandro Dalcin EXTERN_C_BEGIN
73916d9e3a6SLisandro Dalcin #undef __FUNCT__
74016d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPREGetType_HYPRE"
7417087cfbeSBarry Smith PetscErrorCode  PCHYPREGetType_HYPRE(PC pc,const char *name[])
74216d9e3a6SLisandro Dalcin {
74316d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
74416d9e3a6SLisandro Dalcin 
74516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
74616d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
74716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
74816d9e3a6SLisandro Dalcin }
74916d9e3a6SLisandro Dalcin EXTERN_C_END
75016d9e3a6SLisandro Dalcin 
75116d9e3a6SLisandro Dalcin EXTERN_C_BEGIN
75216d9e3a6SLisandro Dalcin #undef __FUNCT__
75316d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPRESetType_HYPRE"
7547087cfbeSBarry Smith PetscErrorCode  PCHYPRESetType_HYPRE(PC pc,const char name[])
75516d9e3a6SLisandro Dalcin {
75616d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
75716d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
758ace3abfcSBarry Smith   PetscBool      flag;
75916d9e3a6SLisandro Dalcin 
76016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
76116d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
76216d9e3a6SLisandro Dalcin     ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr);
763e7e72b3dSBarry Smith     if (!flag) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set");
76416d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
76516d9e3a6SLisandro Dalcin   } else {
76616d9e3a6SLisandro Dalcin     ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr);
76716d9e3a6SLisandro Dalcin   }
76816d9e3a6SLisandro Dalcin 
76916d9e3a6SLisandro Dalcin   jac->maxiter            = PETSC_DEFAULT;
77016d9e3a6SLisandro Dalcin   jac->tol                = PETSC_DEFAULT;
77116d9e3a6SLisandro Dalcin   jac->printstatistics    = PetscLogPrintInfo;
77216d9e3a6SLisandro Dalcin 
77316d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr);
77416d9e3a6SLisandro Dalcin   if (flag) {
77530e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParCSRPilutCreate,(jac->comm_hypre,&jac->hsolver));
77616d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
77716d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
77816d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
77916d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
78016d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
78116d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
78216d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
78316d9e3a6SLisandro Dalcin   }
78416d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr);
78516d9e3a6SLisandro Dalcin   if (flag) {
78630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsCreate,(jac->comm_hypre,&jac->hsolver));
78716d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
78816d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
78916d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
79016d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
79116d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
79216d9e3a6SLisandro Dalcin     /* initialize */
79316d9e3a6SLisandro Dalcin     jac->nlevels     = 1;
79416d9e3a6SLisandro Dalcin     jac->threshhold  = .1;
79516d9e3a6SLisandro Dalcin     jac->filter      = .1;
79616d9e3a6SLisandro Dalcin     jac->loadbal     = 0;
79716d9e3a6SLisandro Dalcin     if (PetscLogPrintInfo) {
79816d9e3a6SLisandro Dalcin       jac->logging     = (int) PETSC_TRUE;
79916d9e3a6SLisandro Dalcin     } else {
80016d9e3a6SLisandro Dalcin       jac->logging     = (int) PETSC_FALSE;
80116d9e3a6SLisandro Dalcin     }
80216d9e3a6SLisandro Dalcin     jac->ruse = (int) PETSC_FALSE;
80316d9e3a6SLisandro Dalcin     jac->symt   = 0;
80430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshhold,jac->nlevels));
80530e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter));
80630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal));
80730e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging));
80830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse));
80930e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt));
81016d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
81116d9e3a6SLisandro Dalcin   }
81216d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr);
81316d9e3a6SLisandro Dalcin   if (flag) {
81416d9e3a6SLisandro Dalcin     ierr                    = HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver);
81516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
81616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Euclid;
81716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_EuclidDestroy;
81816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_EuclidSetup;
81916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_EuclidSolve;
82016d9e3a6SLisandro Dalcin     /* initialization */
82116d9e3a6SLisandro Dalcin     jac->bjilu              = PETSC_FALSE;
82216d9e3a6SLisandro Dalcin     jac->levels             = 1;
82316d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
82416d9e3a6SLisandro Dalcin   }
82516d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr);
82616d9e3a6SLisandro Dalcin   if (flag) {
82716d9e3a6SLisandro Dalcin     ierr                     = HYPRE_BoomerAMGCreate(&jac->hsolver);
82816d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
82916d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
83016d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
83116d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
83216d9e3a6SLisandro Dalcin     jac->destroy             = HYPRE_BoomerAMGDestroy;
83316d9e3a6SLisandro Dalcin     jac->setup               = HYPRE_BoomerAMGSetup;
83416d9e3a6SLisandro Dalcin     jac->solve               = HYPRE_BoomerAMGSolve;
83516d9e3a6SLisandro Dalcin     jac->applyrichardson     = PETSC_FALSE;
83616d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
83716d9e3a6SLisandro Dalcin     jac->cycletype        = 1;
83816d9e3a6SLisandro Dalcin     jac->maxlevels        = 25;
83916d9e3a6SLisandro Dalcin     jac->maxiter          = 1;
8408f87f92bSBarry Smith     jac->tol              = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
84116d9e3a6SLisandro Dalcin     jac->truncfactor      = 0.0;
84216d9e3a6SLisandro Dalcin     jac->strongthreshold  = .25;
84316d9e3a6SLisandro Dalcin     jac->maxrowsum        = .9;
84416d9e3a6SLisandro Dalcin     jac->coarsentype      = 6;
84516d9e3a6SLisandro Dalcin     jac->measuretype      = 0;
8460f1074feSSatish Balay     jac->gridsweeps[0]    = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
8478f87f92bSBarry Smith     jac->relaxtype[0]     = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a a PC - most likely with CG */
8480f1074feSSatish Balay     jac->relaxtype[2]     = 9; /*G.E. */
84916d9e3a6SLisandro Dalcin     jac->relaxweight      = 1.0;
85016d9e3a6SLisandro Dalcin     jac->outerrelaxweight = 1.0;
85116d9e3a6SLisandro Dalcin     jac->relaxorder       = 1;
8520f1074feSSatish Balay     jac->interptype       = 0;
8530f1074feSSatish Balay     jac->agg_nl           = 0;
8540f1074feSSatish Balay     jac->pmax             = 0;
8550f1074feSSatish Balay     jac->truncfactor      = 0.0;
8560f1074feSSatish Balay     jac->agg_num_paths    = 1;
8578f87f92bSBarry Smith 
8588f87f92bSBarry Smith     jac->nodal_coarsen    = 0;
8598f87f92bSBarry Smith     jac->nodal_relax      = PETSC_FALSE;
8608f87f92bSBarry Smith     jac->nodal_relax_levels = 1;
86130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype));
86230e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels));
86330e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter));
86430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol));
86530e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor));
86630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold));
86730e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum));
86830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype));
86930e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype));
87030e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder));
87130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype));
87230e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl));
87330e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax));
87430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths));
87530e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, jac->relaxtype[0]));  /*defaults coarse to 9*/
87630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver, jac->gridsweeps[0])); /*defaults coarse to 1 */
87716d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
87816d9e3a6SLisandro Dalcin   }
879503cfb0cSBarry Smith   ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr);
88016d9e3a6SLisandro Dalcin   jac->hypre_type = PETSC_NULL;
88165e19b50SBarry Smith   SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name);
88216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
88316d9e3a6SLisandro Dalcin }
88416d9e3a6SLisandro Dalcin EXTERN_C_END
88516d9e3a6SLisandro Dalcin 
88616d9e3a6SLisandro Dalcin /*
88716d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
88816d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
88916d9e3a6SLisandro Dalcin */
89016d9e3a6SLisandro Dalcin #undef __FUNCT__
89116d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE"
89216d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE(PC pc)
89316d9e3a6SLisandro Dalcin {
89416d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
8954ddd07fcSJed Brown   PetscInt       indx;
89616d9e3a6SLisandro Dalcin   const char     *type[] = {"pilut","parasails","boomeramg","euclid"};
897ace3abfcSBarry Smith   PetscBool      flg;
89816d9e3a6SLisandro Dalcin 
89916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
90016d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr);
90102a17cd4SBarry Smith   ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"boomeramg",&indx,&flg);CHKERRQ(ierr);
90216d9e3a6SLisandro Dalcin   if (flg) {
90316d9e3a6SLisandro Dalcin     ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr);
90402a17cd4SBarry Smith   } else {
90502a17cd4SBarry Smith     ierr = PCHYPRESetType_HYPRE(pc,"boomeramg");CHKERRQ(ierr);
90616d9e3a6SLisandro Dalcin   }
90716d9e3a6SLisandro Dalcin   if (pc->ops->setfromoptions) {
90816d9e3a6SLisandro Dalcin     ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr);
90916d9e3a6SLisandro Dalcin   }
91016d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
91116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
91216d9e3a6SLisandro Dalcin }
91316d9e3a6SLisandro Dalcin 
91416d9e3a6SLisandro Dalcin #undef __FUNCT__
91516d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPRESetType"
91616d9e3a6SLisandro Dalcin /*@C
91716d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
91816d9e3a6SLisandro Dalcin 
91916d9e3a6SLisandro Dalcin    Input Parameters:
92016d9e3a6SLisandro Dalcin +     pc - the preconditioner context
92116d9e3a6SLisandro Dalcin -     name - either  pilut, parasails, boomeramg, euclid
92216d9e3a6SLisandro Dalcin 
92316d9e3a6SLisandro Dalcin    Options Database Keys:
92416d9e3a6SLisandro Dalcin    -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
92516d9e3a6SLisandro Dalcin 
92616d9e3a6SLisandro Dalcin    Level: intermediate
92716d9e3a6SLisandro Dalcin 
92816d9e3a6SLisandro Dalcin .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
92916d9e3a6SLisandro Dalcin            PCHYPRE
93016d9e3a6SLisandro Dalcin 
93116d9e3a6SLisandro Dalcin @*/
9327087cfbeSBarry Smith PetscErrorCode  PCHYPRESetType(PC pc,const char name[])
93316d9e3a6SLisandro Dalcin {
9344ac538c5SBarry Smith   PetscErrorCode ierr;
93516d9e3a6SLisandro Dalcin 
93616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9370700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
93816d9e3a6SLisandro Dalcin   PetscValidCharPointer(name,2);
9394ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCHYPRESetType_C",(PC,const char[]),(pc,name));CHKERRQ(ierr);
94016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
94116d9e3a6SLisandro Dalcin }
94216d9e3a6SLisandro Dalcin 
94316d9e3a6SLisandro Dalcin #undef __FUNCT__
94416d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPREGetType"
94516d9e3a6SLisandro Dalcin /*@C
94616d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
94716d9e3a6SLisandro Dalcin 
94816d9e3a6SLisandro Dalcin    Input Parameter:
94916d9e3a6SLisandro Dalcin .     pc - the preconditioner context
95016d9e3a6SLisandro Dalcin 
95116d9e3a6SLisandro Dalcin    Output Parameter:
95216d9e3a6SLisandro Dalcin .     name - either  pilut, parasails, boomeramg, euclid
95316d9e3a6SLisandro Dalcin 
95416d9e3a6SLisandro Dalcin    Level: intermediate
95516d9e3a6SLisandro Dalcin 
95616d9e3a6SLisandro Dalcin .seealso:  PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC,
95716d9e3a6SLisandro Dalcin            PCHYPRE
95816d9e3a6SLisandro Dalcin 
95916d9e3a6SLisandro Dalcin @*/
9607087cfbeSBarry Smith PetscErrorCode  PCHYPREGetType(PC pc,const char *name[])
96116d9e3a6SLisandro Dalcin {
9624ac538c5SBarry Smith   PetscErrorCode ierr;
96316d9e3a6SLisandro Dalcin 
96416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9650700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
96616d9e3a6SLisandro Dalcin   PetscValidPointer(name,2);
9674ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCHYPREGetType_C",(PC,const char*[]),(pc,name));CHKERRQ(ierr);
96816d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
96916d9e3a6SLisandro Dalcin }
97016d9e3a6SLisandro Dalcin 
97116d9e3a6SLisandro Dalcin /*MC
97216d9e3a6SLisandro Dalcin      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
97316d9e3a6SLisandro Dalcin 
97416d9e3a6SLisandro Dalcin    Options Database Keys:
97516d9e3a6SLisandro Dalcin +   -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
97616d9e3a6SLisandro Dalcin -   Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX
97716d9e3a6SLisandro Dalcin           preconditioner
97816d9e3a6SLisandro Dalcin 
97916d9e3a6SLisandro Dalcin    Level: intermediate
98016d9e3a6SLisandro Dalcin 
98116d9e3a6SLisandro Dalcin    Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()),
98216d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
98316d9e3a6SLisandro Dalcin           or with PetscOptionsSetValue(), there are no functions to set them)
98416d9e3a6SLisandro Dalcin 
98516d9e3a6SLisandro Dalcin           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations
9860f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
9870f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
9880f1074feSSatish Balay           (-pc_hypre_boomeramg_rtol should be set to 0.0 - the default - to strictly use a fixed number of
9898f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
9900f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
9910f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
99216d9e3a6SLisandro Dalcin 
9930f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
9940f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
9950f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
99616d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
99716d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
99816d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
99916d9e3a6SLisandro Dalcin 
100016d9e3a6SLisandro Dalcin 	  2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
100116d9e3a6SLisandro Dalcin 	  -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
100216d9e3a6SLisandro Dalcin 
10039e5bc791SBarry Smith           See PCPFMG for access to the hypre Struct PFMG solver
10049e5bc791SBarry Smith 
100516d9e3a6SLisandro Dalcin .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
10069e5bc791SBarry Smith            PCHYPRESetType(), PCPFMG
100716d9e3a6SLisandro Dalcin 
100816d9e3a6SLisandro Dalcin M*/
100916d9e3a6SLisandro Dalcin 
101016d9e3a6SLisandro Dalcin EXTERN_C_BEGIN
101116d9e3a6SLisandro Dalcin #undef __FUNCT__
101216d9e3a6SLisandro Dalcin #define __FUNCT__ "PCCreate_HYPRE"
10137087cfbeSBarry Smith PetscErrorCode  PCCreate_HYPRE(PC pc)
101416d9e3a6SLisandro Dalcin {
101516d9e3a6SLisandro Dalcin   PC_HYPRE       *jac;
101616d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
101716d9e3a6SLisandro Dalcin 
101816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
101938f2d2fdSLisandro Dalcin   ierr = PetscNewLog(pc,PC_HYPRE,&jac);CHKERRQ(ierr);
102016d9e3a6SLisandro Dalcin   pc->data                 = jac;
102116d9e3a6SLisandro Dalcin   pc->ops->destroy         = PCDestroy_HYPRE;
102216d9e3a6SLisandro Dalcin   pc->ops->setfromoptions  = PCSetFromOptions_HYPRE;
102316d9e3a6SLisandro Dalcin   pc->ops->setup           = PCSetUp_HYPRE;
102416d9e3a6SLisandro Dalcin   pc->ops->apply           = PCApply_HYPRE;
102516d9e3a6SLisandro Dalcin   jac->comm_hypre          = MPI_COMM_NULL;
102616d9e3a6SLisandro Dalcin   jac->hypre_type          = PETSC_NULL;
102716d9e3a6SLisandro Dalcin   /* duplicate communicator for hypre */
10287adad957SLisandro Dalcin   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(jac->comm_hypre));CHKERRQ(ierr);
102916d9e3a6SLisandro Dalcin   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr);
103016d9e3a6SLisandro Dalcin   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr);
103116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
103216d9e3a6SLisandro Dalcin }
103316d9e3a6SLisandro Dalcin EXTERN_C_END
1034ebc551c0SBarry Smith 
1035f91d8e95SBarry Smith /* ---------------------------------------------------------------------------------------------------------------------------------*/
1036f91d8e95SBarry Smith 
1037b862ddfaSBarry Smith /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */
1038b45d2f2cSJed Brown #include <petsc-private/matimpl.h>
1039ebc551c0SBarry Smith 
1040ebc551c0SBarry Smith typedef struct {
104168326731SBarry Smith   MPI_Comm            hcomm;       /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
1042f91d8e95SBarry Smith   HYPRE_StructSolver  hsolver;
10439e5bc791SBarry Smith 
10449e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
10454ddd07fcSJed Brown   PetscInt            its;
10469e5bc791SBarry Smith   double              tol;
10474ddd07fcSJed Brown   PetscInt            relax_type;
10484ddd07fcSJed Brown   PetscInt            rap_type;
10494ddd07fcSJed Brown   PetscInt            num_pre_relax,num_post_relax;
10504ddd07fcSJed Brown   PetscInt            max_levels;
1051ebc551c0SBarry Smith } PC_PFMG;
1052ebc551c0SBarry Smith 
1053ebc551c0SBarry Smith #undef __FUNCT__
1054ebc551c0SBarry Smith #define __FUNCT__ "PCDestroy_PFMG"
1055ebc551c0SBarry Smith PetscErrorCode PCDestroy_PFMG(PC pc)
1056ebc551c0SBarry Smith {
1057ebc551c0SBarry Smith   PetscErrorCode ierr;
1058f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
1059ebc551c0SBarry Smith 
1060ebc551c0SBarry Smith   PetscFunctionBegin;
106130e6f737SJed Brown   if (ex->hsolver) {PetscStackCallHypre(0,HYPRE_StructPFMGDestroy,(ex->hsolver));}
1062f91d8e95SBarry Smith   ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr);
1063c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1064ebc551c0SBarry Smith   PetscFunctionReturn(0);
1065ebc551c0SBarry Smith }
1066ebc551c0SBarry Smith 
10679e5bc791SBarry Smith static const char *PFMGRelaxType[]   = {"Jacobi","Weighted-Jacobi","symmetric-Red/Black-Gauss-Seidel","Red/Black-Gauss-Seidel"};
10689e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin","non-Galerkin"};
10699e5bc791SBarry Smith 
1070ebc551c0SBarry Smith #undef __FUNCT__
1071ebc551c0SBarry Smith #define __FUNCT__ "PCView_PFMG"
1072ebc551c0SBarry Smith PetscErrorCode PCView_PFMG(PC pc,PetscViewer viewer)
1073ebc551c0SBarry Smith {
1074ebc551c0SBarry Smith   PetscErrorCode ierr;
1075ace3abfcSBarry Smith   PetscBool      iascii;
1076f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
1077ebc551c0SBarry Smith 
1078ebc551c0SBarry Smith   PetscFunctionBegin;
1079251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
10809e5bc791SBarry Smith   if (iascii) {
10819e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG preconditioning\n");CHKERRQ(ierr);
10829e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: max iterations %d\n",ex->its);CHKERRQ(ierr);
10839e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr);
10849e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr);
10859e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: RAP type %s\n",PFMGRAPType[ex->rap_type]);CHKERRQ(ierr);
10869e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr);
10873b46a515SGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: max levels %d\n",ex->max_levels);CHKERRQ(ierr);
10889e5bc791SBarry Smith   }
1089ebc551c0SBarry Smith   PetscFunctionReturn(0);
1090ebc551c0SBarry Smith }
1091ebc551c0SBarry Smith 
10929e5bc791SBarry Smith 
1093ebc551c0SBarry Smith #undef __FUNCT__
1094ebc551c0SBarry Smith #define __FUNCT__ "PCSetFromOptions_PFMG"
1095ebc551c0SBarry Smith PetscErrorCode PCSetFromOptions_PFMG(PC pc)
1096ebc551c0SBarry Smith {
1097ebc551c0SBarry Smith   PetscErrorCode ierr;
1098f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
1099ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
1100ebc551c0SBarry Smith 
1101ebc551c0SBarry Smith   PetscFunctionBegin;
1102ebc551c0SBarry Smith   ierr = PetscOptionsHead("PFMG options");CHKERRQ(ierr);
1103acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_pfmg_print_statistics","Print statistics","HYPRE_StructPFMGSetPrintLevel",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
110468326731SBarry Smith   if (flg) {
1105a0324ebeSBarry Smith     int level=3;
110630e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_StructPFMGSetPrintLevel,(ex->hsolver,level));
110768326731SBarry Smith   }
11089e5bc791SBarry Smith   ierr = PetscOptionsInt("-pc_pfmg_its","Number of iterations of PFMG to use as preconditioner","HYPRE_StructPFMGSetMaxIter",ex->its,&ex->its,PETSC_NULL);CHKERRQ(ierr);
110930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxIter,(ex->hsolver,ex->its));
11109e5bc791SBarry Smith   ierr = PetscOptionsInt("-pc_pfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_StructPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,PETSC_NULL);CHKERRQ(ierr);
111130e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetNumPreRelax,(ex->hsolver,ex->num_pre_relax));
11129e5bc791SBarry Smith   ierr = PetscOptionsInt("-pc_pfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_StructPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,PETSC_NULL);CHKERRQ(ierr);
111330e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetNumPostRelax,(ex->hsolver,ex->num_post_relax));
11149e5bc791SBarry Smith 
11153b46a515SGlenn Hammond   ierr = PetscOptionsInt("-pc_pfmg_max_levels","Max Levels for MG hierarchy","HYPRE_StructPFMGSetMaxLevels",ex->max_levels,&ex->max_levels,PETSC_NULL);CHKERRQ(ierr);
111630e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxLevels,(ex->hsolver,ex->max_levels));
11173b46a515SGlenn Hammond 
11189e5bc791SBarry Smith   ierr = PetscOptionsReal("-pc_pfmg_tol","Tolerance of PFMG","HYPRE_StructPFMGSetTol",ex->tol,&ex->tol,PETSC_NULL);CHKERRQ(ierr);
111930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetTol,(ex->hsolver,ex->tol));
11209e5bc791SBarry Smith   ierr = PetscOptionsEList("-pc_pfmg_relax_type","Relax type for the up and down cycles","HYPRE_StructPFMGSetRelaxType",PFMGRelaxType,4,PFMGRelaxType[ex->relax_type],&ex->relax_type,PETSC_NULL);CHKERRQ(ierr);
112130e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetRelaxType,(ex->hsolver, ex->relax_type));
11229e5bc791SBarry Smith   ierr = PetscOptionsEList("-pc_pfmg_rap_type","RAP type","HYPRE_StructPFMGSetRAPType",PFMGRAPType,2,PFMGRAPType[ex->rap_type],&ex->rap_type,PETSC_NULL);CHKERRQ(ierr);
112330e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetRAPType,(ex->hsolver, ex->rap_type));
1124ebc551c0SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
1125ebc551c0SBarry Smith   PetscFunctionReturn(0);
1126ebc551c0SBarry Smith }
1127ebc551c0SBarry Smith 
1128f91d8e95SBarry Smith #undef __FUNCT__
1129f91d8e95SBarry Smith #define __FUNCT__ "PCApply_PFMG"
1130f91d8e95SBarry Smith PetscErrorCode PCApply_PFMG(PC pc,Vec x,Vec y)
1131f91d8e95SBarry Smith {
1132f91d8e95SBarry Smith   PetscErrorCode  ierr;
1133f91d8e95SBarry Smith   PC_PFMG         *ex = (PC_PFMG*) pc->data;
1134f91d8e95SBarry Smith   PetscScalar     *xx,*yy;
11354ddd07fcSJed Brown   PetscInt        ilower[3],iupper[3];
113668326731SBarry Smith   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
1137f91d8e95SBarry Smith 
1138f91d8e95SBarry Smith   PetscFunctionBegin;
1139aa219208SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
1140f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
1141f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
1142f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
1143f91d8e95SBarry Smith 
1144f91d8e95SBarry Smith   /* copy x values over to hypre */
114530e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructVectorSetConstantValues,(mx->hb,0.0));
1146f91d8e95SBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
114730e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructVectorSetBoxValues,(mx->hb,ilower,iupper,xx));
1148f91d8e95SBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
114930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructVectorAssemble,(mx->hb));
115030e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSolve,(ex->hsolver,mx->hmat,mx->hb,mx->hx));
1151f91d8e95SBarry Smith 
1152f91d8e95SBarry Smith   /* copy solution values back to PETSc */
1153f91d8e95SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
115430e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructVectorGetBoxValues,(mx->hx,ilower,iupper,yy));
1155f91d8e95SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1156f91d8e95SBarry Smith   PetscFunctionReturn(0);
1157f91d8e95SBarry Smith }
1158f91d8e95SBarry Smith 
11599e5bc791SBarry Smith #undef __FUNCT__
11609e5bc791SBarry Smith #define __FUNCT__ "PCApplyRichardson_PFMG"
1161ace3abfcSBarry Smith static PetscErrorCode PCApplyRichardson_PFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool  guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
11629e5bc791SBarry Smith {
11639e5bc791SBarry Smith   PC_PFMG        *jac = (PC_PFMG*)pc->data;
11649e5bc791SBarry Smith   PetscErrorCode ierr;
11654ddd07fcSJed Brown   PetscInt       oits;
11669e5bc791SBarry Smith 
11679e5bc791SBarry Smith   PetscFunctionBegin;
116830e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxIter,(jac->hsolver,its*jac->its));
116930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetTol,(jac->hsolver,rtol));
11709e5bc791SBarry Smith 
11719e5bc791SBarry Smith   ierr = PCApply_PFMG(pc,b,y);CHKERRQ(ierr);
117230e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGGetNumIterations,(jac->hsolver,&oits));
11739e5bc791SBarry Smith   *outits = oits;
11749e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
11759e5bc791SBarry Smith   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
117630e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetTol,(jac->hsolver,jac->tol));
117730e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxIter,(jac->hsolver,jac->its));
11789e5bc791SBarry Smith   PetscFunctionReturn(0);
11799e5bc791SBarry Smith }
11809e5bc791SBarry Smith 
11819e5bc791SBarry Smith 
11823a32d3dbSGlenn Hammond #undef __FUNCT__
11833a32d3dbSGlenn Hammond #define __FUNCT__ "PCSetUp_PFMG"
11843a32d3dbSGlenn Hammond PetscErrorCode PCSetUp_PFMG(PC pc)
11853a32d3dbSGlenn Hammond {
11863a32d3dbSGlenn Hammond   PetscErrorCode  ierr;
11873a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG*) pc->data;
11883a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
1189ace3abfcSBarry Smith   PetscBool       flg;
11903a32d3dbSGlenn Hammond 
11913a32d3dbSGlenn Hammond   PetscFunctionBegin;
1192251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg);CHKERRQ(ierr);
1193e7e72b3dSBarry Smith   if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner");
11943a32d3dbSGlenn Hammond 
11953a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
11963a32d3dbSGlenn Hammond   if (ex->hsolver) {
119730e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_StructPFMGDestroy,(ex->hsolver));
11983a32d3dbSGlenn Hammond   }
119930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver));
12003a32d3dbSGlenn Hammond   ierr = PCSetFromOptions_PFMG(pc);CHKERRQ(ierr);
120130e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetup,(ex->hsolver,mx->hmat,mx->hb,mx->hx));
120230e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGSetZeroGuess,(ex->hsolver));
12033a32d3dbSGlenn Hammond   PetscFunctionReturn(0);
12043a32d3dbSGlenn Hammond }
12053a32d3dbSGlenn Hammond 
1206ebc551c0SBarry Smith 
1207ebc551c0SBarry Smith /*MC
1208ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
1209ebc551c0SBarry Smith 
1210ebc551c0SBarry Smith    Level: advanced
1211ebc551c0SBarry Smith 
12129e5bc791SBarry Smith    Options Database:
12139e5bc791SBarry Smith + -pc_pfmg_its <its> number of iterations of PFMG to use as preconditioner
12149e5bc791SBarry Smith . -pc_pfmg_num_pre_relax <steps> number of smoothing steps before coarse grid
12159e5bc791SBarry Smith . -pc_pfmg_num_post_relax <steps> number of smoothing steps after coarse grid
12169e5bc791SBarry Smith . -pc_pfmg_tol <tol> tolerance of PFMG
12179e5bc791SBarry Smith . -pc_pfmg_relax_type -relaxation type for the up and down cycles, one of Jacobi,Weighted-Jacobi,symmetric-Red/Black-Gauss-Seidel,Red/Black-Gauss-Seidel
12189e5bc791SBarry Smith - -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
1219f91d8e95SBarry Smith 
12209e5bc791SBarry Smith    Notes:  This is for CELL-centered descretizations
12219e5bc791SBarry Smith 
12228e395302SJed Brown            This must be used with the MATHYPRESTRUCT matrix type.
1223aa219208SBarry Smith            This is less general than in hypre, it supports only one block per process defined by a PETSc DMDA.
12249e5bc791SBarry Smith 
12259e5bc791SBarry Smith .seealso:  PCMG, MATHYPRESTRUCT
1226ebc551c0SBarry Smith M*/
1227ebc551c0SBarry Smith 
1228ebc551c0SBarry Smith EXTERN_C_BEGIN
1229ebc551c0SBarry Smith #undef __FUNCT__
1230ebc551c0SBarry Smith #define __FUNCT__ "PCCreate_PFMG"
12317087cfbeSBarry Smith PetscErrorCode  PCCreate_PFMG(PC pc)
1232ebc551c0SBarry Smith {
1233ebc551c0SBarry Smith   PetscErrorCode ierr;
1234ebc551c0SBarry Smith   PC_PFMG        *ex;
1235ebc551c0SBarry Smith 
1236ebc551c0SBarry Smith   PetscFunctionBegin;
1237ebc551c0SBarry Smith   ierr = PetscNew(PC_PFMG,&ex);CHKERRQ(ierr);\
123868326731SBarry Smith   pc->data = ex;
1239ebc551c0SBarry Smith 
12409e5bc791SBarry Smith   ex->its            = 1;
12419e5bc791SBarry Smith   ex->tol            = 1.e-8;
12429e5bc791SBarry Smith   ex->relax_type     = 1;
12439e5bc791SBarry Smith   ex->rap_type       = 0;
12449e5bc791SBarry Smith   ex->num_pre_relax  = 1;
12459e5bc791SBarry Smith   ex->num_post_relax = 1;
12463b46a515SGlenn Hammond   ex->max_levels     = 0;
12479e5bc791SBarry Smith 
1248ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
1249ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
1250ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
1251f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
12529e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
125368326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
1254f91d8e95SBarry Smith   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(ex->hcomm));CHKERRQ(ierr);
125530e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver));
1256ebc551c0SBarry Smith   PetscFunctionReturn(0);
1257ebc551c0SBarry Smith }
1258ebc551c0SBarry Smith EXTERN_C_END
1259d851a50bSGlenn Hammond 
1260325fc9f4SBarry Smith /* ---------------------------------------------------------------------------------------------------------------------------------------------------*/
1261325fc9f4SBarry Smith 
1262d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
1263d851a50bSGlenn Hammond typedef struct {
1264d851a50bSGlenn Hammond   MPI_Comm            hcomm;       /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
1265d851a50bSGlenn Hammond   HYPRE_SStructSolver  ss_solver;
1266d851a50bSGlenn Hammond 
1267d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
12684ddd07fcSJed Brown   PetscInt            its;
1269d851a50bSGlenn Hammond   double              tol;
12704ddd07fcSJed Brown   PetscInt            relax_type;
12714ddd07fcSJed Brown   PetscInt            num_pre_relax,num_post_relax;
1272d851a50bSGlenn Hammond } PC_SysPFMG;
1273d851a50bSGlenn Hammond 
1274d851a50bSGlenn Hammond #undef __FUNCT__
1275d851a50bSGlenn Hammond #define __FUNCT__ "PCDestroy_SysPFMG"
1276d851a50bSGlenn Hammond PetscErrorCode PCDestroy_SysPFMG(PC pc)
1277d851a50bSGlenn Hammond {
1278d851a50bSGlenn Hammond   PetscErrorCode ierr;
1279d851a50bSGlenn Hammond   PC_SysPFMG    *ex = (PC_SysPFMG*) pc->data;
1280d851a50bSGlenn Hammond 
1281d851a50bSGlenn Hammond   PetscFunctionBegin;
128230e6f737SJed Brown   if (ex->ss_solver) {PetscStackCallHypre(0,HYPRE_SStructSysPFMGDestroy,(ex->ss_solver));}
1283d851a50bSGlenn Hammond   ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr);
1284c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1285d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1286d851a50bSGlenn Hammond }
1287d851a50bSGlenn Hammond 
1288d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[]   = {"Weighted-Jacobi","Red/Black-Gauss-Seidel"};
1289d851a50bSGlenn Hammond 
1290d851a50bSGlenn Hammond #undef __FUNCT__
1291d851a50bSGlenn Hammond #define __FUNCT__ "PCView_SysPFMG"
1292d851a50bSGlenn Hammond PetscErrorCode PCView_SysPFMG(PC pc,PetscViewer viewer)
1293d851a50bSGlenn Hammond {
1294d851a50bSGlenn Hammond   PetscErrorCode ierr;
1295ace3abfcSBarry Smith   PetscBool      iascii;
1296d851a50bSGlenn Hammond   PC_SysPFMG    *ex = (PC_SysPFMG*) pc->data;
1297d851a50bSGlenn Hammond 
1298d851a50bSGlenn Hammond   PetscFunctionBegin;
1299251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1300d851a50bSGlenn Hammond   if (iascii) {
1301d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG preconditioning\n");CHKERRQ(ierr);
1302d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: max iterations %d\n",ex->its);CHKERRQ(ierr);
1303d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr);
1304d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr);
1305d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr);
1306d851a50bSGlenn Hammond   }
1307d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1308d851a50bSGlenn Hammond }
1309d851a50bSGlenn Hammond 
1310d851a50bSGlenn Hammond 
1311d851a50bSGlenn Hammond #undef __FUNCT__
1312d851a50bSGlenn Hammond #define __FUNCT__ "PCSetFromOptions_SysPFMG"
1313d851a50bSGlenn Hammond PetscErrorCode PCSetFromOptions_SysPFMG(PC pc)
1314d851a50bSGlenn Hammond {
1315d851a50bSGlenn Hammond   PetscErrorCode ierr;
1316d851a50bSGlenn Hammond   PC_SysPFMG    *ex = (PC_SysPFMG*) pc->data;
1317ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
1318d851a50bSGlenn Hammond 
1319d851a50bSGlenn Hammond   PetscFunctionBegin;
1320d851a50bSGlenn Hammond   ierr = PetscOptionsHead("SysPFMG options");CHKERRQ(ierr);
1321acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_syspfmg_print_statistics","Print statistics","HYPRE_SStructSysPFMGSetPrintLevel",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
1322d851a50bSGlenn Hammond   if (flg) {
1323d851a50bSGlenn Hammond     int level=3;
132430e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetPrintLevel,(ex->ss_solver,level));
1325d851a50bSGlenn Hammond   }
1326d851a50bSGlenn Hammond   ierr = PetscOptionsInt("-pc_syspfmg_its","Number of iterations of SysPFMG to use as preconditioner","HYPRE_SStructSysPFMGSetMaxIter",ex->its,&ex->its,PETSC_NULL);CHKERRQ(ierr);
132730e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetMaxIter,(ex->ss_solver,ex->its));
1328d851a50bSGlenn Hammond   ierr = PetscOptionsInt("-pc_syspfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_SStructSysPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,PETSC_NULL);CHKERRQ(ierr);
132930e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetNumPreRelax,(ex->ss_solver,ex->num_pre_relax));
1330d851a50bSGlenn Hammond   ierr = PetscOptionsInt("-pc_syspfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_SStructSysPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,PETSC_NULL);CHKERRQ(ierr);
133130e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetNumPostRelax,(ex->ss_solver,ex->num_post_relax));
1332d851a50bSGlenn Hammond 
1333d851a50bSGlenn Hammond   ierr = PetscOptionsReal("-pc_syspfmg_tol","Tolerance of SysPFMG","HYPRE_SStructSysPFMGSetTol",ex->tol,&ex->tol,PETSC_NULL);CHKERRQ(ierr);
133430e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetTol,(ex->ss_solver,ex->tol));
1335d851a50bSGlenn Hammond   ierr = PetscOptionsEList("-pc_syspfmg_relax_type","Relax type for the up and down cycles","HYPRE_SStructSysPFMGSetRelaxType",SysPFMGRelaxType,4,SysPFMGRelaxType[ex->relax_type],&ex->relax_type,PETSC_NULL);CHKERRQ(ierr);
133630e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetRelaxType,(ex->ss_solver, ex->relax_type));
1337d851a50bSGlenn Hammond   ierr = PetscOptionsTail();CHKERRQ(ierr);
1338d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1339d851a50bSGlenn Hammond }
1340d851a50bSGlenn Hammond 
1341d851a50bSGlenn Hammond #undef __FUNCT__
1342d851a50bSGlenn Hammond #define __FUNCT__ "PCApply_SysPFMG"
1343d851a50bSGlenn Hammond PetscErrorCode PCApply_SysPFMG(PC pc,Vec x,Vec y)
1344d851a50bSGlenn Hammond {
1345d851a50bSGlenn Hammond   PetscErrorCode    ierr;
1346d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG*) pc->data;
1347d851a50bSGlenn Hammond   PetscScalar      *xx,*yy;
13484ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
1349d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
13504ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
13514ddd07fcSJed Brown   PetscInt          nvars= mx->nvars;
13524ddd07fcSJed Brown   PetscInt          part= 0;
13534ddd07fcSJed Brown   PetscInt          size;
13544ddd07fcSJed Brown   PetscInt          i;
1355d851a50bSGlenn Hammond 
1356d851a50bSGlenn Hammond   PetscFunctionBegin;
1357aa219208SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
1358d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
1359d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
1360d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
1361d851a50bSGlenn Hammond 
1362d851a50bSGlenn Hammond   size= 1;
1363d851a50bSGlenn Hammond   for (i= 0; i< 3; i++) {
1364d851a50bSGlenn Hammond      size*= (iupper[i]-ilower[i]+1);
1365d851a50bSGlenn Hammond   }
1366d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
1367d851a50bSGlenn Hammond   if (ordering) {
136830e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
1369d851a50bSGlenn Hammond      ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
1370d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
137130e6f737SJed Brown        PetscStackCallHypre(0,HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,xx+(size*i)));
1372d851a50bSGlenn Hammond      }
1373d851a50bSGlenn Hammond      ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
137430e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_SStructVectorAssemble,(mx->ss_b));
137530e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
137630e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x));
1377d851a50bSGlenn Hammond 
1378d851a50bSGlenn Hammond      /* copy solution values back to PETSc */
1379d851a50bSGlenn Hammond      ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
1380d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
138130e6f737SJed Brown        PetscStackCallHypre(0,HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,yy+(size*i)));
1382d851a50bSGlenn Hammond      }
1383d851a50bSGlenn Hammond      ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1384a65764d7SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
1385d851a50bSGlenn Hammond      PetscScalar     *z;
13864ddd07fcSJed Brown      PetscInt         j, k;
1387d851a50bSGlenn Hammond 
1388d851a50bSGlenn Hammond      ierr = PetscMalloc(nvars*size*sizeof(PetscScalar),&z);CHKERRQ(ierr);
138930e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
1390d851a50bSGlenn Hammond      ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
1391d851a50bSGlenn Hammond 
1392d851a50bSGlenn Hammond      /* transform nodal to hypre's variable ordering for sys_pfmg */
1393d851a50bSGlenn Hammond      for (i= 0; i< size; i++) {
1394d851a50bSGlenn Hammond         k= i*nvars;
1395d851a50bSGlenn Hammond         for (j= 0; j< nvars; j++) {
1396d851a50bSGlenn Hammond            z[j*size+i]= xx[k+j];
1397d851a50bSGlenn Hammond         }
1398d851a50bSGlenn Hammond      }
1399d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
140030e6f737SJed Brown        PetscStackCallHypre(0,HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,z+(size*i)));
1401d851a50bSGlenn Hammond      }
1402d851a50bSGlenn Hammond      ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
140330e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_SStructVectorAssemble,(mx->ss_b));
140430e6f737SJed Brown      PetscStackCallHypre(0,HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x));
1405d851a50bSGlenn Hammond 
1406d851a50bSGlenn Hammond      /* copy solution values back to PETSc */
1407d851a50bSGlenn Hammond      ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
1408d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
140930e6f737SJed Brown        PetscStackCallHypre(0,HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,z+(size*i)));
1410d851a50bSGlenn Hammond      }
1411d851a50bSGlenn Hammond      /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
1412d851a50bSGlenn Hammond      for (i= 0; i< size; i++) {
1413d851a50bSGlenn Hammond         k= i*nvars;
1414d851a50bSGlenn Hammond         for (j= 0; j< nvars; j++) {
1415d851a50bSGlenn Hammond            yy[k+j]= z[j*size+i];
1416d851a50bSGlenn Hammond         }
1417d851a50bSGlenn Hammond      }
1418d851a50bSGlenn Hammond      ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1419d851a50bSGlenn Hammond      ierr = PetscFree(z);CHKERRQ(ierr);
1420d851a50bSGlenn Hammond   }
1421d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1422d851a50bSGlenn Hammond }
1423d851a50bSGlenn Hammond 
1424d851a50bSGlenn Hammond #undef __FUNCT__
1425d851a50bSGlenn Hammond #define __FUNCT__ "PCApplyRichardson_SysPFMG"
1426ace3abfcSBarry Smith static PetscErrorCode PCApplyRichardson_SysPFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool  guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
1427d851a50bSGlenn Hammond {
1428d851a50bSGlenn Hammond   PC_SysPFMG    *jac = (PC_SysPFMG*)pc->data;
1429d851a50bSGlenn Hammond   PetscErrorCode ierr;
14304ddd07fcSJed Brown   PetscInt       oits;
1431d851a50bSGlenn Hammond 
1432d851a50bSGlenn Hammond   PetscFunctionBegin;
143330e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,its*jac->its));
143430e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,rtol));
1435d851a50bSGlenn Hammond   ierr = PCApply_SysPFMG(pc,b,y);CHKERRQ(ierr);
143630e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGGetNumIterations,(jac->ss_solver,&oits));
1437d851a50bSGlenn Hammond   *outits = oits;
1438d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
1439d851a50bSGlenn Hammond   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
144030e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,jac->tol));
144130e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,jac->its));
1442d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1443d851a50bSGlenn Hammond }
1444d851a50bSGlenn Hammond 
1445d851a50bSGlenn Hammond 
1446d851a50bSGlenn Hammond #undef __FUNCT__
1447d851a50bSGlenn Hammond #define __FUNCT__ "PCSetUp_SysPFMG"
1448d851a50bSGlenn Hammond PetscErrorCode PCSetUp_SysPFMG(PC pc)
1449d851a50bSGlenn Hammond {
1450d851a50bSGlenn Hammond   PetscErrorCode    ierr;
1451d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG*) pc->data;
1452d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
1453ace3abfcSBarry Smith   PetscBool         flg;
1454d851a50bSGlenn Hammond 
1455d851a50bSGlenn Hammond   PetscFunctionBegin;
1456251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESSTRUCT,&flg);CHKERRQ(ierr);
1457e7e72b3dSBarry Smith   if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESSTRUCT with this preconditioner");
1458d851a50bSGlenn Hammond 
1459d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
1460d851a50bSGlenn Hammond   if (ex->ss_solver) {
146130e6f737SJed Brown     PetscStackCallHypre(0,HYPRE_SStructSysPFMGDestroy,(ex->ss_solver));
1462d851a50bSGlenn Hammond   }
146330e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver));
1464d851a50bSGlenn Hammond   ierr = PCSetFromOptions_SysPFMG(pc);CHKERRQ(ierr);
146530e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetZeroGuess,(ex->ss_solver));
146630e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetup,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x));
1467d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1468d851a50bSGlenn Hammond }
1469d851a50bSGlenn Hammond 
1470d851a50bSGlenn Hammond 
1471d851a50bSGlenn Hammond /*MC
1472d851a50bSGlenn Hammond      PCSysPFMG - the hypre SysPFMG multigrid solver
1473d851a50bSGlenn Hammond 
1474d851a50bSGlenn Hammond    Level: advanced
1475d851a50bSGlenn Hammond 
1476d851a50bSGlenn Hammond    Options Database:
1477d851a50bSGlenn Hammond + -pc_syspfmg_its <its> number of iterations of SysPFMG to use as preconditioner
1478d851a50bSGlenn Hammond . -pc_syspfmg_num_pre_relax <steps> number of smoothing steps before coarse grid
1479d851a50bSGlenn Hammond . -pc_syspfmg_num_post_relax <steps> number of smoothing steps after coarse grid
1480d851a50bSGlenn Hammond . -pc_syspfmg_tol <tol> tolerance of SysPFMG
1481d851a50bSGlenn Hammond . -pc_syspfmg_relax_type -relaxation type for the up and down cycles, one of Weighted-Jacobi,Red/Black-Gauss-Seidel
1482d851a50bSGlenn Hammond 
1483d851a50bSGlenn Hammond    Notes:  This is for CELL-centered descretizations
1484d851a50bSGlenn Hammond 
1485f6680f47SSatish Balay            This must be used with the MATHYPRESSTRUCT matrix type.
1486aa219208SBarry Smith            This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DMDA.
1487d851a50bSGlenn Hammond            Also, only cell-centered variables.
1488d851a50bSGlenn Hammond 
1489d851a50bSGlenn Hammond .seealso:  PCMG, MATHYPRESSTRUCT
1490d851a50bSGlenn Hammond M*/
1491d851a50bSGlenn Hammond 
1492d851a50bSGlenn Hammond EXTERN_C_BEGIN
1493d851a50bSGlenn Hammond #undef __FUNCT__
1494d851a50bSGlenn Hammond #define __FUNCT__ "PCCreate_SysPFMG"
14957087cfbeSBarry Smith PetscErrorCode  PCCreate_SysPFMG(PC pc)
1496d851a50bSGlenn Hammond {
1497d851a50bSGlenn Hammond   PetscErrorCode     ierr;
1498d851a50bSGlenn Hammond   PC_SysPFMG        *ex;
1499d851a50bSGlenn Hammond 
1500d851a50bSGlenn Hammond   PetscFunctionBegin;
1501d851a50bSGlenn Hammond   ierr = PetscNew(PC_SysPFMG,&ex);CHKERRQ(ierr);\
1502d851a50bSGlenn Hammond   pc->data = ex;
1503d851a50bSGlenn Hammond 
1504d851a50bSGlenn Hammond   ex->its            = 1;
1505d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
1506d851a50bSGlenn Hammond   ex->relax_type     = 1;
1507d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
1508d851a50bSGlenn Hammond   ex->num_post_relax = 1;
1509d851a50bSGlenn Hammond 
1510d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
1511d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
1512d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
1513d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
1514d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
1515d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
1516d851a50bSGlenn Hammond   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(ex->hcomm));CHKERRQ(ierr);
151730e6f737SJed Brown   PetscStackCallHypre(0,HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver));
1518d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1519d851a50bSGlenn Hammond }
1520d851a50bSGlenn Hammond EXTERN_C_END
1521