xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 9f73f8ec7a9a0ff9c488c15e8fe2771386f6e173)
116d9e3a6SLisandro Dalcin #define PETSCKSP_DLL
216d9e3a6SLisandro Dalcin 
316d9e3a6SLisandro Dalcin /*
416d9e3a6SLisandro Dalcin    Provides an interface to the LLNL package hypre
516d9e3a6SLisandro Dalcin */
60f1074feSSatish Balay 
70f1074feSSatish Balay /* Must use hypre 2.0.0 or more recent. */
80f1074feSSatish Balay 
916d9e3a6SLisandro Dalcin #include "private/pcimpl.h"          /*I "petscpc.h" I*/
10*9f73f8ecSBarry Smith #include "../src/dm/da/utils/mhyp.h"
1116d9e3a6SLisandro Dalcin 
1216d9e3a6SLisandro Dalcin /*
1316d9e3a6SLisandro Dalcin    Private context (data structure) for the  preconditioner.
1416d9e3a6SLisandro Dalcin */
1516d9e3a6SLisandro Dalcin typedef struct {
1616d9e3a6SLisandro Dalcin   HYPRE_Solver       hsolver;
1716d9e3a6SLisandro Dalcin   HYPRE_IJMatrix     ij;
1816d9e3a6SLisandro Dalcin   HYPRE_IJVector     b,x;
1916d9e3a6SLisandro Dalcin 
2016d9e3a6SLisandro Dalcin   PetscErrorCode     (*destroy)(HYPRE_Solver);
2116d9e3a6SLisandro Dalcin   PetscErrorCode     (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
2216d9e3a6SLisandro Dalcin   PetscErrorCode     (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
2316d9e3a6SLisandro Dalcin 
2416d9e3a6SLisandro Dalcin   MPI_Comm           comm_hypre;
2516d9e3a6SLisandro Dalcin   char              *hypre_type;
2616d9e3a6SLisandro Dalcin 
2716d9e3a6SLisandro Dalcin   /* options for Pilut and BoomerAMG*/
2816d9e3a6SLisandro Dalcin   int                maxiter;
2916d9e3a6SLisandro Dalcin   double             tol;
3016d9e3a6SLisandro Dalcin 
3116d9e3a6SLisandro Dalcin   /* options for Pilut */
3216d9e3a6SLisandro Dalcin   int                factorrowsize;
3316d9e3a6SLisandro Dalcin 
3416d9e3a6SLisandro Dalcin   /* options for ParaSails */
3516d9e3a6SLisandro Dalcin   int                nlevels;
3616d9e3a6SLisandro Dalcin   double             threshhold;
3716d9e3a6SLisandro Dalcin   double             filter;
3816d9e3a6SLisandro Dalcin   int                sym;
3916d9e3a6SLisandro Dalcin   double             loadbal;
4016d9e3a6SLisandro Dalcin   int                logging;
4116d9e3a6SLisandro Dalcin   int                ruse;
4216d9e3a6SLisandro Dalcin   int                symt;
4316d9e3a6SLisandro Dalcin 
4416d9e3a6SLisandro Dalcin   /* options for Euclid */
4516d9e3a6SLisandro Dalcin   PetscTruth         bjilu;
4616d9e3a6SLisandro Dalcin   int                levels;
4716d9e3a6SLisandro Dalcin 
4816d9e3a6SLisandro Dalcin   /* options for Euclid and BoomerAMG */
4916d9e3a6SLisandro Dalcin   PetscTruth         printstatistics;
5016d9e3a6SLisandro Dalcin 
5116d9e3a6SLisandro Dalcin   /* options for BoomerAMG */
5216d9e3a6SLisandro Dalcin   int                cycletype;
5316d9e3a6SLisandro Dalcin   int                maxlevels;
5416d9e3a6SLisandro Dalcin   double             strongthreshold;
5516d9e3a6SLisandro Dalcin   double             maxrowsum;
560f1074feSSatish Balay   int                gridsweeps[3];
5716d9e3a6SLisandro Dalcin   int                coarsentype;
5816d9e3a6SLisandro Dalcin   int                measuretype;
590f1074feSSatish Balay   int                relaxtype[3];
6016d9e3a6SLisandro Dalcin   double             relaxweight;
6116d9e3a6SLisandro Dalcin   double             outerrelaxweight;
6216d9e3a6SLisandro Dalcin   int                relaxorder;
6316d9e3a6SLisandro Dalcin   double             truncfactor;
6416d9e3a6SLisandro Dalcin   PetscTruth         applyrichardson;
650f1074feSSatish Balay   int                pmax;
660f1074feSSatish Balay   int                interptype;
670f1074feSSatish Balay   int                agg_nl;
680f1074feSSatish Balay   int                agg_num_paths;
698f87f92bSBarry Smith   int                nodal_coarsen;
708f87f92bSBarry Smith   PetscTruth         nodal_relax;
718f87f92bSBarry Smith   int                nodal_relax_levels;
7216d9e3a6SLisandro Dalcin } PC_HYPRE;
7316d9e3a6SLisandro Dalcin 
7416d9e3a6SLisandro Dalcin 
7516d9e3a6SLisandro Dalcin #undef __FUNCT__
7616d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetUp_HYPRE"
7716d9e3a6SLisandro Dalcin static PetscErrorCode PCSetUp_HYPRE(PC pc)
7816d9e3a6SLisandro Dalcin {
7916d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
8016d9e3a6SLisandro Dalcin   PetscErrorCode     ierr;
8116d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
8216d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv,xv;
8316d9e3a6SLisandro Dalcin   PetscInt           bs;
8416d9e3a6SLisandro Dalcin   int                hierr;
8516d9e3a6SLisandro Dalcin 
8616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
8716d9e3a6SLisandro Dalcin   if (!jac->hypre_type) {
8802a17cd4SBarry Smith     ierr = PCHYPRESetType(pc,"boomeramg");CHKERRQ(ierr);
8916d9e3a6SLisandro Dalcin   }
905f5c5b43SBarry Smith 
915f5c5b43SBarry Smith   if (pc->setupcalled) {
925f5c5b43SBarry Smith     /* always destroy the old matrix and create a new memory;
935f5c5b43SBarry Smith        hope this does not churn the memory too much. The problem
945f5c5b43SBarry Smith        is I do not know if it is possible to put the matrix back to
955f5c5b43SBarry Smith        its initial state so that we can directly copy the values
965f5c5b43SBarry Smith        the second time through. */
9716d9e3a6SLisandro Dalcin     ierr = HYPRE_IJMatrixDestroy(jac->ij);CHKERRQ(ierr);
985f5c5b43SBarry Smith     jac->ij = 0;
9916d9e3a6SLisandro Dalcin   }
1005f5c5b43SBarry Smith 
10116d9e3a6SLisandro Dalcin   if (!jac->ij) { /* create the matrix the first time through */
10216d9e3a6SLisandro Dalcin     ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr);
10316d9e3a6SLisandro Dalcin   }
10416d9e3a6SLisandro Dalcin   if (!jac->b) { /* create the vectors the first time through */
10516d9e3a6SLisandro Dalcin     Vec x,b;
10616d9e3a6SLisandro Dalcin     ierr = MatGetVecs(pc->pmat,&x,&b);CHKERRQ(ierr);
10716d9e3a6SLisandro Dalcin     ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr);
10816d9e3a6SLisandro Dalcin     ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr);
10916d9e3a6SLisandro Dalcin     ierr = VecDestroy(x);CHKERRQ(ierr);
11016d9e3a6SLisandro Dalcin     ierr = VecDestroy(b);CHKERRQ(ierr);
11116d9e3a6SLisandro Dalcin   }
1125f5c5b43SBarry Smith 
11316d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
11416d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
11516d9e3a6SLisandro Dalcin     ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
11616d9e3a6SLisandro Dalcin     if (bs > 1) {
11716d9e3a6SLisandro Dalcin       ierr = HYPRE_BoomerAMGSetNumFunctions(jac->hsolver,bs);CHKERRQ(ierr);
11816d9e3a6SLisandro Dalcin     }
11916d9e3a6SLisandro Dalcin   };
12016d9e3a6SLisandro Dalcin   ierr = MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);CHKERRQ(ierr);
12116d9e3a6SLisandro Dalcin   ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr);
12216d9e3a6SLisandro Dalcin   ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&bv);CHKERRQ(ierr);
12316d9e3a6SLisandro Dalcin   ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&xv);CHKERRQ(ierr);
12416d9e3a6SLisandro Dalcin   hierr = (*jac->setup)(jac->hsolver,hmat,bv,xv);
125e32f2f54SBarry Smith   if (hierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE setup, error code %d",hierr);
12616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
12716d9e3a6SLisandro Dalcin }
12816d9e3a6SLisandro Dalcin 
12916d9e3a6SLisandro Dalcin /*
13016d9e3a6SLisandro Dalcin     Replaces the address where the HYPRE vector points to its data with the address of
13116d9e3a6SLisandro Dalcin   PETSc's data. Saves the old address so it can be reset when we are finished with it.
13216d9e3a6SLisandro Dalcin   Allows use to get the data into a HYPRE vector without the cost of memcopies
13316d9e3a6SLisandro Dalcin */
13416d9e3a6SLisandro Dalcin #define HYPREReplacePointer(b,newvalue,savedvalue) {\
13516d9e3a6SLisandro Dalcin    hypre_ParVector *par_vector   = (hypre_ParVector *)hypre_IJVectorObject(((hypre_IJVector*)b));\
13616d9e3a6SLisandro Dalcin    hypre_Vector    *local_vector = hypre_ParVectorLocalVector(par_vector);\
13716d9e3a6SLisandro Dalcin    savedvalue         = local_vector->data;\
13816d9e3a6SLisandro Dalcin    local_vector->data = newvalue;}
13916d9e3a6SLisandro Dalcin 
14016d9e3a6SLisandro Dalcin #undef __FUNCT__
14116d9e3a6SLisandro Dalcin #define __FUNCT__ "PCApply_HYPRE"
14216d9e3a6SLisandro Dalcin static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x)
14316d9e3a6SLisandro Dalcin {
14416d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
14516d9e3a6SLisandro Dalcin   PetscErrorCode     ierr;
14616d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
14716d9e3a6SLisandro Dalcin   PetscScalar        *bv,*xv;
14816d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv,jxv;
14916d9e3a6SLisandro Dalcin   PetscScalar        *sbv,*sxv;
15016d9e3a6SLisandro Dalcin   int                hierr;
15116d9e3a6SLisandro Dalcin 
15216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
15316d9e3a6SLisandro Dalcin   if (!jac->applyrichardson) {ierr = VecSet(x,0.0);CHKERRQ(ierr);}
15416d9e3a6SLisandro Dalcin   ierr = VecGetArray(b,&bv);CHKERRQ(ierr);
15516d9e3a6SLisandro Dalcin   ierr = VecGetArray(x,&xv);CHKERRQ(ierr);
15616d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->b,bv,sbv);
15716d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->x,xv,sxv);
15816d9e3a6SLisandro Dalcin 
15916d9e3a6SLisandro Dalcin   ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr);
16016d9e3a6SLisandro Dalcin   ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);CHKERRQ(ierr);
16116d9e3a6SLisandro Dalcin   ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);CHKERRQ(ierr);
16216d9e3a6SLisandro Dalcin   hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv);
1630f1074feSSatish Balay 
164e32f2f54SBarry Smith   /*if (hierr && (hierr != HYPRE_ERROR_CONV || jac->solve != HYPRE_BoomerAMGSolve))SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
1650f1074feSSatish Balay    */
1660f1074feSSatish Balay  /* error code of HYPRE_ERROR_CONV means convergence not achieved - if
1670f1074feSSatish Balay     the tolerance is set to 0.0 (the default), a convergence error will
1680f1074feSSatish Balay     not occur (so we may not want to overide the conv. error here?*/
16965e19b50SBarry Smith  if (hierr && hierr != HYPRE_ERROR_CONV) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
17016d9e3a6SLisandro Dalcin  if (hierr) hypre__global_error = 0;
17116d9e3a6SLisandro Dalcin 
1720f1074feSSatish Balay 
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;
18816d9e3a6SLisandro Dalcin   if (jac->ij) { ierr = HYPRE_IJMatrixDestroy(jac->ij);CHKERRQ(ierr); }
18916d9e3a6SLisandro Dalcin   if (jac->b)  { ierr = HYPRE_IJVectorDestroy(jac->b);CHKERRQ(ierr);  }
19016d9e3a6SLisandro Dalcin   if (jac->x)  { ierr = HYPRE_IJVectorDestroy(jac->x);CHKERRQ(ierr);  }
19116d9e3a6SLisandro Dalcin   if (jac->destroy) { ierr = (*jac->destroy)(jac->hsolver);CHKERRQ(ierr); }
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);}
19416d9e3a6SLisandro Dalcin   ierr = PetscFree(jac);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;
20916d9e3a6SLisandro Dalcin   PetscTruth     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);
21416d9e3a6SLisandro Dalcin   if (flag) {
21516d9e3a6SLisandro Dalcin     ierr = HYPRE_ParCSRPilutSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
21616d9e3a6SLisandro Dalcin   }
21716d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);CHKERRQ(ierr);
21816d9e3a6SLisandro Dalcin   if (flag) {
21916d9e3a6SLisandro Dalcin     ierr = HYPRE_ParCSRPilutSetDropTolerance(jac->hsolver,jac->tol);CHKERRQ(ierr);
22016d9e3a6SLisandro Dalcin   }
22116d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);CHKERRQ(ierr);
22216d9e3a6SLisandro Dalcin   if (flag) {
22316d9e3a6SLisandro Dalcin     ierr = HYPRE_ParCSRPilutSetFactorRowSize(jac->hsolver,jac->factorrowsize);CHKERRQ(ierr);
22416d9e3a6SLisandro Dalcin   }
22516d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
22616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
22716d9e3a6SLisandro Dalcin }
22816d9e3a6SLisandro Dalcin 
22916d9e3a6SLisandro Dalcin #undef __FUNCT__
23016d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_Pilut"
23116d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)
23216d9e3a6SLisandro Dalcin {
23316d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
23416d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
23516d9e3a6SLisandro Dalcin   PetscTruth     iascii;
23616d9e3a6SLisandro Dalcin 
23716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2382692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
23916d9e3a6SLisandro Dalcin   if (iascii) {
24016d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut preconditioning\n");CHKERRQ(ierr);
24116d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
24216d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: maximum number of iterations %d\n",jac->maxiter);CHKERRQ(ierr);
24316d9e3a6SLisandro Dalcin     } else {
24416d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default maximum number of iterations \n");CHKERRQ(ierr);
24516d9e3a6SLisandro Dalcin     }
24616d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
24716d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: drop tolerance %G\n",jac->tol);CHKERRQ(ierr);
24816d9e3a6SLisandro Dalcin     } else {
24916d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default drop tolerance \n");CHKERRQ(ierr);
25016d9e3a6SLisandro Dalcin     }
25116d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
25216d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: factor row size %d\n",jac->factorrowsize);CHKERRQ(ierr);
25316d9e3a6SLisandro Dalcin     } else {
25416d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut: default factor row size \n");CHKERRQ(ierr);
25516d9e3a6SLisandro Dalcin     }
25616d9e3a6SLisandro Dalcin   }
25716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
25816d9e3a6SLisandro Dalcin }
25916d9e3a6SLisandro Dalcin 
26016d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
26116d9e3a6SLisandro Dalcin #undef __FUNCT__
26216d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE_Euclid"
26316d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc)
26416d9e3a6SLisandro Dalcin {
26516d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
26616d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
26716d9e3a6SLisandro Dalcin   PetscTruth     flag;
268390e7148SBarry Smith   char           *args[8],levels[16];
269390e7148SBarry Smith   PetscInt       cnt = 0;
27016d9e3a6SLisandro Dalcin 
27116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
27216d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE Euclid Options");CHKERRQ(ierr);
27316d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);CHKERRQ(ierr);
27416d9e3a6SLisandro Dalcin   if (flag) {
27565e19b50SBarry Smith     if (jac->levels < 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be nonegative",jac->levels);
27616d9e3a6SLisandro Dalcin     sprintf(levels,"%d",jac->levels);
277390e7148SBarry Smith     args[cnt++] = (char*)"-level"; args[cnt++] = levels;
27816d9e3a6SLisandro Dalcin   }
27916d9e3a6SLisandro Dalcin   ierr = PetscOptionsTruth("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,PETSC_NULL);CHKERRQ(ierr);
28016d9e3a6SLisandro Dalcin   if (jac->bjilu) {
281390e7148SBarry Smith     args[cnt++] =(char*) "-bj"; args[cnt++] = (char*)"1";
28216d9e3a6SLisandro Dalcin   }
28316d9e3a6SLisandro Dalcin 
28416d9e3a6SLisandro Dalcin   ierr = PetscOptionsTruth("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);CHKERRQ(ierr);
28516d9e3a6SLisandro Dalcin   if (jac->printstatistics) {
286390e7148SBarry Smith     args[cnt++] = (char*)"-eu_stats"; args[cnt++] = (char*)"1";
287390e7148SBarry Smith     args[cnt++] = (char*)"-eu_mem"; args[cnt++] = (char*)"1";
28816d9e3a6SLisandro Dalcin   }
28916d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
290390e7148SBarry Smith   if (cnt) {
291390e7148SBarry Smith     ierr = HYPRE_EuclidSetParams(jac->hsolver,cnt,args);CHKERRQ(ierr);
292390e7148SBarry Smith   }
29316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
29416d9e3a6SLisandro Dalcin }
29516d9e3a6SLisandro Dalcin 
29616d9e3a6SLisandro Dalcin #undef __FUNCT__
29716d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_Euclid"
29816d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)
29916d9e3a6SLisandro Dalcin {
30016d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
30116d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
30216d9e3a6SLisandro Dalcin   PetscTruth     iascii;
30316d9e3a6SLisandro Dalcin 
30416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
3052692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
30616d9e3a6SLisandro Dalcin   if (iascii) {
30716d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid preconditioning\n");CHKERRQ(ierr);
30816d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: number of levels %d\n",jac->levels);CHKERRQ(ierr);
30916d9e3a6SLisandro Dalcin     if (jac->bjilu) {
31016d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid: Using block Jacobi ILU instead of parallel ILU\n");CHKERRQ(ierr);
31116d9e3a6SLisandro Dalcin     }
31216d9e3a6SLisandro Dalcin   }
31316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
31416d9e3a6SLisandro Dalcin }
31516d9e3a6SLisandro Dalcin 
31616d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
31716d9e3a6SLisandro Dalcin 
31816d9e3a6SLisandro Dalcin #undef __FUNCT__
31916d9e3a6SLisandro Dalcin #define __FUNCT__ "PCApplyTranspose_HYPRE_BoomerAMG"
32016d9e3a6SLisandro Dalcin static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x)
32116d9e3a6SLisandro Dalcin {
32216d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
32316d9e3a6SLisandro Dalcin   PetscErrorCode     ierr;
32416d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
32516d9e3a6SLisandro Dalcin   PetscScalar        *bv,*xv;
32616d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv,jxv;
32716d9e3a6SLisandro Dalcin   PetscScalar        *sbv,*sxv;
32816d9e3a6SLisandro Dalcin   int                hierr;
32916d9e3a6SLisandro Dalcin 
33016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
33116d9e3a6SLisandro Dalcin   ierr = VecSet(x,0.0);CHKERRQ(ierr);
33216d9e3a6SLisandro Dalcin   ierr = VecGetArray(b,&bv);CHKERRQ(ierr);
33316d9e3a6SLisandro Dalcin   ierr = VecGetArray(x,&xv);CHKERRQ(ierr);
33416d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->b,bv,sbv);
33516d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->x,xv,sxv);
33616d9e3a6SLisandro Dalcin 
33716d9e3a6SLisandro Dalcin   ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr);
33816d9e3a6SLisandro Dalcin   ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);CHKERRQ(ierr);
33916d9e3a6SLisandro Dalcin   ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);CHKERRQ(ierr);
34016d9e3a6SLisandro Dalcin 
34116d9e3a6SLisandro Dalcin   hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jbv,jxv);
34216d9e3a6SLisandro Dalcin   /* error code of 1 in BoomerAMG merely means convergence not achieved */
343e32f2f54SBarry Smith   if (hierr && (hierr != 1)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
34416d9e3a6SLisandro Dalcin   if (hierr) hypre__global_error = 0;
34516d9e3a6SLisandro Dalcin 
34616d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->b,sbv,bv);
34716d9e3a6SLisandro Dalcin   HYPREReplacePointer(jac->x,sxv,xv);
34816d9e3a6SLisandro Dalcin   ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr);
34916d9e3a6SLisandro Dalcin   ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr);
35016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
35116d9e3a6SLisandro Dalcin }
35216d9e3a6SLisandro Dalcin 
35316d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"","V","W"};
3540f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout", "", "PMIS", "", "HMIS"};
35516d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local","global"};
3560f1074feSSatish Balay static const char *HYPREBoomerAMGRelaxType[]   = {"Jacobi","sequential-Gauss-Seidel","","SOR/Jacobi","backward-SOR/Jacobi","","symmetric-SOR/Jacobi",
3570f1074feSSatish Balay                                                   "","","Gaussian-elimination"};
3580f1074feSSatish Balay static const char *HYPREBoomerAMGInterpType[]  = {"classical", "", "", "direct", "multipass", "multipass-wts", "ext+i",
3590f1074feSSatish Balay                                                   "ext+i-cc", "standard", "standard-wts", "", "", "FF", "FF1"};
36016d9e3a6SLisandro Dalcin #undef __FUNCT__
36116d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE_BoomerAMG"
36216d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc)
36316d9e3a6SLisandro Dalcin {
36416d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
36516d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
36616d9e3a6SLisandro Dalcin   int            n,indx;
36716d9e3a6SLisandro Dalcin   PetscTruth     flg, tmp_truth;
36816d9e3a6SLisandro Dalcin   double         tmpdbl, twodbl[2];
36916d9e3a6SLisandro Dalcin 
37016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
37116d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE BoomerAMG Options");CHKERRQ(ierr);
37216d9e3a6SLisandro Dalcin   ierr = PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg);CHKERRQ(ierr);
37316d9e3a6SLisandro Dalcin   if (flg) {
37416d9e3a6SLisandro Dalcin     jac->cycletype = indx;
37516d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleType(jac->hsolver,jac->cycletype);CHKERRQ(ierr);
37616d9e3a6SLisandro Dalcin   }
37716d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);CHKERRQ(ierr);
37816d9e3a6SLisandro Dalcin   if (flg) {
37965e19b50SBarry Smith     if (jac->maxlevels < 2) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be at least two",jac->maxlevels);
38016d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);CHKERRQ(ierr);
38116d9e3a6SLisandro Dalcin   }
38216d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg);CHKERRQ(ierr);
38316d9e3a6SLisandro Dalcin   if (flg) {
38465e19b50SBarry Smith     if (jac->maxiter < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %d must be at least one",jac->maxiter);
38516d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
38616d9e3a6SLisandro Dalcin   }
3870f1074feSSatish 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);
38816d9e3a6SLisandro Dalcin   if (flg) {
38965e19b50SBarry 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);
39016d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr);
39116d9e3a6SLisandro Dalcin   }
39216d9e3a6SLisandro Dalcin 
3930f1074feSSatish Balay   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_truncfactor","Truncation factor for interpolation (0=no truncation)","None",jac->truncfactor,&jac->truncfactor,&flg);CHKERRQ(ierr);
39416d9e3a6SLisandro Dalcin   if (flg) {
39565e19b50SBarry 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);
39616d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetTruncFactor(jac->hsolver,jac->truncfactor);CHKERRQ(ierr);
39716d9e3a6SLisandro Dalcin   }
39816d9e3a6SLisandro Dalcin 
3990f1074feSSatish 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);
4000f1074feSSatish Balay   if (flg) {
40165e19b50SBarry 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);
4020f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetPMaxElmts(jac->hsolver,jac->pmax);CHKERRQ(ierr);
4030f1074feSSatish Balay   }
4040f1074feSSatish Balay 
4050f1074feSSatish Balay  ierr = PetscOptionsInt("-pc_hypre_boomeramg_agg_nl","Number of levels of aggressive coarsening","None",jac->agg_nl,&jac->agg_nl,&flg);CHKERRQ(ierr);
4060f1074feSSatish Balay   if (flg) {
40765e19b50SBarry 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);
4080f1074feSSatish Balay 
4090f1074feSSatish Balay      ierr = HYPRE_BoomerAMGSetAggNumLevels(jac->hsolver,jac->agg_nl);CHKERRQ(ierr);
4100f1074feSSatish Balay   }
4110f1074feSSatish Balay 
4120f1074feSSatish Balay 
4130f1074feSSatish 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);
4140f1074feSSatish Balay   if (flg) {
41565e19b50SBarry 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);
4160f1074feSSatish Balay 
4170f1074feSSatish Balay      ierr = HYPRE_BoomerAMGSetNumPaths(jac->hsolver,jac->agg_num_paths);CHKERRQ(ierr);
4180f1074feSSatish Balay   }
4190f1074feSSatish Balay 
4200f1074feSSatish Balay 
42116d9e3a6SLisandro Dalcin   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);CHKERRQ(ierr);
42216d9e3a6SLisandro Dalcin   if (flg) {
42365e19b50SBarry 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);
42416d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);CHKERRQ(ierr);
42516d9e3a6SLisandro Dalcin   }
42616d9e3a6SLisandro Dalcin   ierr = PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);CHKERRQ(ierr);
42716d9e3a6SLisandro Dalcin   if (flg) {
42865e19b50SBarry 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);
42965e19b50SBarry 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);
43016d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);CHKERRQ(ierr);
43116d9e3a6SLisandro Dalcin   }
43216d9e3a6SLisandro Dalcin 
43316d9e3a6SLisandro Dalcin   /* Grid sweeps */
4340f1074feSSatish 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);
43516d9e3a6SLisandro Dalcin   if (flg) {
43616d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetNumSweeps(jac->hsolver,indx);CHKERRQ(ierr);
43716d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
43816d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
4390f1074feSSatish Balay     jac->gridsweeps[1] = indx;
4400f1074feSSatish Balay     /*defaults coarse to 1 */
4410f1074feSSatish Balay     jac->gridsweeps[2] = 1;
44216d9e3a6SLisandro Dalcin   }
4430f1074feSSatish Balay 
4440f1074feSSatish Balay   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[0], &indx ,&flg);CHKERRQ(ierr);
44516d9e3a6SLisandro Dalcin   if (flg) {
44616d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 1);CHKERRQ(ierr);
4470f1074feSSatish Balay     jac->gridsweeps[0] = indx;
44816d9e3a6SLisandro Dalcin   }
44916d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg);CHKERRQ(ierr);
45016d9e3a6SLisandro Dalcin   if (flg) {
45116d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 2);CHKERRQ(ierr);
4520f1074feSSatish Balay     jac->gridsweeps[1] = indx;
45316d9e3a6SLisandro Dalcin   }
4540f1074feSSatish Balay   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[2],&indx,&flg);CHKERRQ(ierr);
45516d9e3a6SLisandro Dalcin   if (flg) {
45616d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 3);CHKERRQ(ierr);
4570f1074feSSatish Balay     jac->gridsweeps[2] = indx;
45816d9e3a6SLisandro Dalcin   }
45916d9e3a6SLisandro Dalcin 
46016d9e3a6SLisandro Dalcin   /* Relax type */
4610f1074feSSatish 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);
46216d9e3a6SLisandro Dalcin   if (flg) {
4630f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1]  = indx;
46416d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetRelaxType(jac->hsolver, indx);CHKERRQ(ierr);
4650f1074feSSatish Balay     /* by default, coarse type set to 9 */
4660f1074feSSatish Balay     jac->relaxtype[2] = 9;
4670f1074feSSatish Balay 
46816d9e3a6SLisandro Dalcin   }
4690f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
47016d9e3a6SLisandro Dalcin   if (flg) {
47116d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
47216d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 1);CHKERRQ(ierr);
47316d9e3a6SLisandro Dalcin   }
4740f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
47516d9e3a6SLisandro Dalcin   if (flg) {
4760f1074feSSatish Balay     jac->relaxtype[1] = indx;
47716d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 2);CHKERRQ(ierr);
47816d9e3a6SLisandro Dalcin   }
47916d9e3a6SLisandro Dalcin   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[9],&indx,&flg);CHKERRQ(ierr);
48016d9e3a6SLisandro Dalcin   if (flg) {
4810f1074feSSatish Balay     jac->relaxtype[2] = indx;
48216d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 3);CHKERRQ(ierr);
48316d9e3a6SLisandro Dalcin   }
48416d9e3a6SLisandro Dalcin 
48516d9e3a6SLisandro Dalcin   /* Relaxation Weight */
48616d9e3a6SLisandro 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);
48716d9e3a6SLisandro Dalcin   if (flg) {
48816d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetRelaxWt(jac->hsolver,tmpdbl);CHKERRQ(ierr);
48916d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
49016d9e3a6SLisandro Dalcin   }
49116d9e3a6SLisandro Dalcin 
49216d9e3a6SLisandro Dalcin   n=2;
49316d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
49416d9e3a6SLisandro 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);
49516d9e3a6SLisandro Dalcin   if (flg) {
49616d9e3a6SLisandro Dalcin     if (n == 2) {
49716d9e3a6SLisandro Dalcin       indx =  (int)PetscAbsReal(twodbl[1]);
49816d9e3a6SLisandro Dalcin       ierr = HYPRE_BoomerAMGSetLevelRelaxWt(jac->hsolver,twodbl[0],indx);CHKERRQ(ierr);
49916d9e3a6SLisandro Dalcin     } else {
50065e19b50SBarry 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);
50116d9e3a6SLisandro Dalcin     }
50216d9e3a6SLisandro Dalcin   }
50316d9e3a6SLisandro Dalcin 
50416d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
50516d9e3a6SLisandro 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);
50616d9e3a6SLisandro Dalcin   if (flg) {
50716d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetOuterWt( jac->hsolver, tmpdbl);CHKERRQ(ierr);
50816d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
50916d9e3a6SLisandro Dalcin   }
51016d9e3a6SLisandro Dalcin 
51116d9e3a6SLisandro Dalcin   n=2;
51216d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
51316d9e3a6SLisandro 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);
51416d9e3a6SLisandro Dalcin   if (flg) {
51516d9e3a6SLisandro Dalcin     if (n == 2) {
51616d9e3a6SLisandro Dalcin       indx =  (int)PetscAbsReal(twodbl[1]);
51716d9e3a6SLisandro Dalcin       ierr = HYPRE_BoomerAMGSetLevelOuterWt( jac->hsolver, twodbl[0], indx);CHKERRQ(ierr);
51816d9e3a6SLisandro Dalcin     } else {
51965e19b50SBarry 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);
52016d9e3a6SLisandro Dalcin     }
52116d9e3a6SLisandro Dalcin   }
52216d9e3a6SLisandro Dalcin 
52316d9e3a6SLisandro Dalcin   /* the Relax Order */
52416d9e3a6SLisandro Dalcin   ierr = PetscOptionsTruth( "-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
52516d9e3a6SLisandro Dalcin 
52616d9e3a6SLisandro Dalcin   if (flg) {
52716d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
52816d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, jac->relaxorder);CHKERRQ(ierr);
52916d9e3a6SLisandro Dalcin   }
53016d9e3a6SLisandro Dalcin   ierr = PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,2,HYPREBoomerAMGMeasureType[0],&indx,&flg);CHKERRQ(ierr);
53116d9e3a6SLisandro Dalcin   if (flg) {
53216d9e3a6SLisandro Dalcin     jac->measuretype = indx;
53316d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);CHKERRQ(ierr);
53416d9e3a6SLisandro Dalcin   }
5350f1074feSSatish Balay   /* update list length 3/07 */
5360f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,11,HYPREBoomerAMGCoarsenType[6],&indx,&flg);CHKERRQ(ierr);
53716d9e3a6SLisandro Dalcin   if (flg) {
53816d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
53916d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);CHKERRQ(ierr);
54016d9e3a6SLisandro Dalcin   }
5410f1074feSSatish Balay 
5420f1074feSSatish Balay   /* new 3/07 */
5430f1074feSSatish Balay   ierr = PetscOptionsEList("-pc_hypre_boomeramg_interp_type","Interpolation type","None",HYPREBoomerAMGInterpType,14,HYPREBoomerAMGInterpType[0],&indx,&flg);CHKERRQ(ierr);
5440f1074feSSatish Balay   if (flg) {
5450f1074feSSatish Balay     jac->interptype = indx;
5460f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetInterpType(jac->hsolver,jac->interptype);CHKERRQ(ierr);
5470f1074feSSatish Balay   }
5480f1074feSSatish Balay 
54990d69ab7SBarry Smith   flg  = PETSC_FALSE;
55090d69ab7SBarry Smith   ierr = PetscOptionsTruth("-pc_hypre_boomeramg_print_statistics","Print statistics","None",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
55116d9e3a6SLisandro Dalcin   if (flg) {
55216d9e3a6SLisandro Dalcin     int level=3;
55316d9e3a6SLisandro Dalcin     jac->printstatistics = PETSC_TRUE;
55416d9e3a6SLisandro Dalcin     ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,PETSC_NULL);CHKERRQ(ierr);
55516d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetPrintLevel(jac->hsolver,level);CHKERRQ(ierr);
5562ae77aedSBarry Smith   }
5572ae77aedSBarry Smith 
55890d69ab7SBarry Smith   flg  = PETSC_FALSE;
55990d69ab7SBarry Smith   ierr = PetscOptionsTruth("-pc_hypre_boomeramg_print_debug","Print debug information","None",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
5602ae77aedSBarry Smith   if (flg) {
5612ae77aedSBarry Smith     int level=3;
5622ae77aedSBarry Smith     jac->printstatistics = PETSC_TRUE;
5632ae77aedSBarry Smith     ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_debug","Print debug information","None",level,&level,PETSC_NULL);CHKERRQ(ierr);
56416d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetDebugFlag(jac->hsolver,level);CHKERRQ(ierr);
56516d9e3a6SLisandro Dalcin   }
5668f87f92bSBarry Smith 
5678f87f92bSBarry Smith   ierr = PetscOptionsTruth( "-pc_hypre_boomeramg_nodal_coarsen", "HYPRE_BoomerAMGSetNodal()", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
5688f87f92bSBarry Smith   if (flg && tmp_truth) {
5698f87f92bSBarry Smith     jac->nodal_coarsen = 1;
5708f87f92bSBarry Smith     ierr = HYPRE_BoomerAMGSetNodal(jac->hsolver,1);CHKERRQ(ierr);
5718f87f92bSBarry Smith   }
5728f87f92bSBarry Smith 
5738f87f92bSBarry Smith   ierr = PetscOptionsTruth( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
5748f87f92bSBarry Smith   if (flg && tmp_truth) {
5758f87f92bSBarry Smith     PetscInt tmp_int;
5768f87f92bSBarry Smith     ierr = PetscOptionsInt( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None",jac->nodal_relax_levels,&tmp_int,&flg);CHKERRQ(ierr);
5778f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
5788f87f92bSBarry Smith     ierr = HYPRE_BoomerAMGSetSmoothType(jac->hsolver,6);CHKERRQ(ierr);
5798f87f92bSBarry Smith     ierr = HYPRE_BoomerAMGSetDomainType(jac->hsolver,1);CHKERRQ(ierr);
5808f87f92bSBarry Smith     ierr = HYPRE_BoomerAMGSetOverlap(jac->hsolver,0);CHKERRQ(ierr);
5818f87f92bSBarry Smith     ierr = HYPRE_BoomerAMGSetSmoothNumLevels(jac->hsolver,jac->nodal_relax_levels);CHKERRQ(ierr);
5828f87f92bSBarry Smith   }
5838f87f92bSBarry Smith 
58416d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
58516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
58616d9e3a6SLisandro Dalcin }
58716d9e3a6SLisandro Dalcin 
58816d9e3a6SLisandro Dalcin #undef __FUNCT__
58916d9e3a6SLisandro Dalcin #define __FUNCT__ "PCApplyRichardson_HYPRE_BoomerAMG"
5907319c654SBarry Smith static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscTruth guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
59116d9e3a6SLisandro Dalcin {
59216d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
59316d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
5944d0a8057SBarry Smith   int            oits;
59516d9e3a6SLisandro Dalcin 
59616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
59716d9e3a6SLisandro Dalcin   ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,its*jac->maxiter);CHKERRQ(ierr);
5984d0a8057SBarry Smith   ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,rtol);CHKERRQ(ierr);
59916d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
60016d9e3a6SLisandro Dalcin   ierr = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr);
60116d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
6024d0a8057SBarry Smith   ierr = HYPRE_BoomerAMGGetNumIterations(jac->hsolver,&oits);CHKERRQ(ierr);
6034d0a8057SBarry Smith   *outits = oits;
6044d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
6054d0a8057SBarry Smith   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
60616d9e3a6SLisandro Dalcin   ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr);
60716d9e3a6SLisandro Dalcin   ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
60816d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
60916d9e3a6SLisandro Dalcin }
61016d9e3a6SLisandro Dalcin 
61116d9e3a6SLisandro Dalcin 
61216d9e3a6SLisandro Dalcin #undef __FUNCT__
61316d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_BoomerAMG"
61416d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
61516d9e3a6SLisandro Dalcin {
61616d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
61716d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
61816d9e3a6SLisandro Dalcin   PetscTruth     iascii;
61916d9e3a6SLisandro Dalcin 
62016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6212692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
62216d9e3a6SLisandro Dalcin   if (iascii) {
62316d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr);
62416d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr);
62516d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);CHKERRQ(ierr);
62616d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum number of iterations PER hypre call %d\n",jac->maxiter);CHKERRQ(ierr);
62716d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Convergence tolerance PER hypre call %G\n",jac->tol);CHKERRQ(ierr);
62816d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Threshold for strong coupling %G\n",jac->strongthreshold);CHKERRQ(ierr);
6290f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Interpolation truncation factor %G\n",jac->truncfactor);CHKERRQ(ierr);
6300f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Interpolation: max elements per row %d\n",jac->pmax);CHKERRQ(ierr);
6310f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Number of levels of aggressive coarsening %d\n",jac->agg_nl);CHKERRQ(ierr);
6320f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Number of paths for aggressive coarsening %d\n",jac->agg_num_paths);CHKERRQ(ierr);
6330f1074feSSatish Balay 
63416d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Maximum row sums %G\n",jac->maxrowsum);CHKERRQ(ierr);
63516d9e3a6SLisandro Dalcin 
6360f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps down         %d\n",jac->gridsweeps[0]);CHKERRQ(ierr);
6370f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps up           %d\n",jac->gridsweeps[1]);CHKERRQ(ierr);
6380f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Sweeps on coarse    %d\n",jac->gridsweeps[2]);CHKERRQ(ierr);
63916d9e3a6SLisandro Dalcin 
6400f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax down          %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr);
6410f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax up            %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr);
6420f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax on coarse     %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr);
64316d9e3a6SLisandro Dalcin 
64416d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Relax weight  (all)      %G\n",jac->relaxweight);CHKERRQ(ierr);
64516d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Outer relax weight (all) %G\n",jac->outerrelaxweight);CHKERRQ(ierr);
64616d9e3a6SLisandro Dalcin 
64716d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
64816d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Using CF-relaxation\n");CHKERRQ(ierr);
64916d9e3a6SLisandro Dalcin     } else {
65016d9e3a6SLisandro Dalcin       ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Not using CF-relaxation\n");CHKERRQ(ierr);
65116d9e3a6SLisandro Dalcin     }
65216d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Measure type        %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr);
65316d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Coarsen type        %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr);
6540f1074feSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG: Interpolation type  %s\n",HYPREBoomerAMGInterpType[jac->interptype]);CHKERRQ(ierr);
6558f87f92bSBarry Smith     if (jac->nodal_coarsen) {
6568f87f92bSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal coarsening (with HYPRE_BOOMERAMGSetNodal())\n");CHKERRQ(ierr);
6578f87f92bSBarry Smith     }
6588f87f92bSBarry Smith     if (jac->nodal_relax) {
6598f87f92bSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal relaxation via Schwarz smoothing on levels %d\n",jac->nodal_relax_levels);CHKERRQ(ierr);
6608f87f92bSBarry Smith     }
66116d9e3a6SLisandro Dalcin   }
66216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
66316d9e3a6SLisandro Dalcin }
66416d9e3a6SLisandro Dalcin 
66516d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
66616d9e3a6SLisandro Dalcin #undef __FUNCT__
66716d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE_ParaSails"
66816d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc)
66916d9e3a6SLisandro Dalcin {
67016d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
67116d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
67216d9e3a6SLisandro Dalcin   int            indx;
67316d9e3a6SLisandro Dalcin   PetscTruth     flag;
67416d9e3a6SLisandro Dalcin   const char     *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
67516d9e3a6SLisandro Dalcin 
67616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
67716d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE ParaSails Options");CHKERRQ(ierr);
67816d9e3a6SLisandro Dalcin   ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr);
67916d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,&flag);CHKERRQ(ierr);
68016d9e3a6SLisandro Dalcin   if (flag) {
68116d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr);
68216d9e3a6SLisandro Dalcin   }
68316d9e3a6SLisandro Dalcin 
68416d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr);
68516d9e3a6SLisandro Dalcin   if (flag) {
68616d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr);
68716d9e3a6SLisandro Dalcin   }
68816d9e3a6SLisandro Dalcin 
68916d9e3a6SLisandro Dalcin   ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr);
69016d9e3a6SLisandro Dalcin   if (flag) {
69116d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr);
69216d9e3a6SLisandro Dalcin   }
69316d9e3a6SLisandro Dalcin 
69416d9e3a6SLisandro Dalcin   ierr = PetscOptionsTruth("-pc_hypre_parasails_logging","Print info to screen","None",(PetscTruth)jac->logging,(PetscTruth*)&jac->logging,&flag);CHKERRQ(ierr);
69516d9e3a6SLisandro Dalcin   if (flag) {
69616d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr);
69716d9e3a6SLisandro Dalcin   }
69816d9e3a6SLisandro Dalcin 
69916d9e3a6SLisandro Dalcin   ierr = PetscOptionsTruth("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscTruth)jac->ruse,(PetscTruth*)&jac->ruse,&flag);CHKERRQ(ierr);
70016d9e3a6SLisandro Dalcin   if (flag) {
70116d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr);
70216d9e3a6SLisandro Dalcin   }
70316d9e3a6SLisandro Dalcin 
70416d9e3a6SLisandro Dalcin   ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],&indx,&flag);CHKERRQ(ierr);
70516d9e3a6SLisandro Dalcin   if (flag) {
70616d9e3a6SLisandro Dalcin     jac->symt = indx;
70716d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr);
70816d9e3a6SLisandro Dalcin   }
70916d9e3a6SLisandro Dalcin 
71016d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
71116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
71216d9e3a6SLisandro Dalcin }
71316d9e3a6SLisandro Dalcin 
71416d9e3a6SLisandro Dalcin #undef __FUNCT__
71516d9e3a6SLisandro Dalcin #define __FUNCT__ "PCView_HYPRE_ParaSails"
71616d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
71716d9e3a6SLisandro Dalcin {
71816d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
71916d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
72016d9e3a6SLisandro Dalcin   PetscTruth     iascii;
72116d9e3a6SLisandro Dalcin   const char     *symt = 0;;
72216d9e3a6SLisandro Dalcin 
72316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
7242692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
72516d9e3a6SLisandro Dalcin   if (iascii) {
72616d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails preconditioning\n");CHKERRQ(ierr);
72716d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: nlevels %d\n",jac->nlevels);CHKERRQ(ierr);
72816d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: threshold %G\n",jac->threshhold);CHKERRQ(ierr);
72916d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: filter %G\n",jac->filter);CHKERRQ(ierr);
73016d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: load balance %G\n",jac->loadbal);CHKERRQ(ierr);
73116d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: reuse nonzero structure %s\n",PetscTruths[jac->ruse]);CHKERRQ(ierr);
73216d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: print info to screen %s\n",PetscTruths[jac->logging]);CHKERRQ(ierr);
73316d9e3a6SLisandro Dalcin     if (!jac->symt) {
73416d9e3a6SLisandro Dalcin       symt = "nonsymmetric matrix and preconditioner";
73516d9e3a6SLisandro Dalcin     } else if (jac->symt == 1) {
73616d9e3a6SLisandro Dalcin       symt = "SPD matrix and preconditioner";
73716d9e3a6SLisandro Dalcin     } else if (jac->symt == 2) {
73816d9e3a6SLisandro Dalcin       symt = "nonsymmetric matrix but SPD preconditioner";
73916d9e3a6SLisandro Dalcin     } else {
74065e19b50SBarry Smith       SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt);
74116d9e3a6SLisandro Dalcin     }
74216d9e3a6SLisandro Dalcin     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails: %s\n",symt);CHKERRQ(ierr);
74316d9e3a6SLisandro Dalcin   }
74416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
74516d9e3a6SLisandro Dalcin }
74616d9e3a6SLisandro Dalcin /* ---------------------------------------------------------------------------------*/
74716d9e3a6SLisandro Dalcin 
74816d9e3a6SLisandro Dalcin EXTERN_C_BEGIN
74916d9e3a6SLisandro Dalcin #undef __FUNCT__
75016d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPREGetType_HYPRE"
75116d9e3a6SLisandro Dalcin PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType_HYPRE(PC pc,const char *name[])
75216d9e3a6SLisandro Dalcin {
75316d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
75416d9e3a6SLisandro Dalcin 
75516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
75616d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
75716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
75816d9e3a6SLisandro Dalcin }
75916d9e3a6SLisandro Dalcin EXTERN_C_END
76016d9e3a6SLisandro Dalcin 
76116d9e3a6SLisandro Dalcin EXTERN_C_BEGIN
76216d9e3a6SLisandro Dalcin #undef __FUNCT__
76316d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPRESetType_HYPRE"
76416d9e3a6SLisandro Dalcin PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType_HYPRE(PC pc,const char name[])
76516d9e3a6SLisandro Dalcin {
76616d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
76716d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
76816d9e3a6SLisandro Dalcin   PetscTruth     flag;
76916d9e3a6SLisandro Dalcin 
77016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
77116d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
77216d9e3a6SLisandro Dalcin     ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr);
773e7e72b3dSBarry Smith     if (!flag) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set");
77416d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
77516d9e3a6SLisandro Dalcin   } else {
77616d9e3a6SLisandro Dalcin     ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr);
77716d9e3a6SLisandro Dalcin   }
77816d9e3a6SLisandro Dalcin 
77916d9e3a6SLisandro Dalcin   jac->maxiter            = PETSC_DEFAULT;
78016d9e3a6SLisandro Dalcin   jac->tol                = PETSC_DEFAULT;
78116d9e3a6SLisandro Dalcin   jac->printstatistics    = PetscLogPrintInfo;
78216d9e3a6SLisandro Dalcin 
78316d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr);
78416d9e3a6SLisandro Dalcin   if (flag) {
78516d9e3a6SLisandro Dalcin     ierr                    = HYPRE_ParCSRPilutCreate(jac->comm_hypre,&jac->hsolver);
78616d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
78716d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
78816d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
78916d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
79016d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
79116d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
79216d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
79316d9e3a6SLisandro Dalcin   }
79416d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr);
79516d9e3a6SLisandro Dalcin   if (flag) {
79616d9e3a6SLisandro Dalcin     ierr                    = HYPRE_ParaSailsCreate(jac->comm_hypre,&jac->hsolver);
79716d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
79816d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
79916d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
80016d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
80116d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
80216d9e3a6SLisandro Dalcin     /* initialize */
80316d9e3a6SLisandro Dalcin     jac->nlevels     = 1;
80416d9e3a6SLisandro Dalcin     jac->threshhold  = .1;
80516d9e3a6SLisandro Dalcin     jac->filter      = .1;
80616d9e3a6SLisandro Dalcin     jac->loadbal     = 0;
80716d9e3a6SLisandro Dalcin     if (PetscLogPrintInfo) {
80816d9e3a6SLisandro Dalcin       jac->logging     = (int) PETSC_TRUE;
80916d9e3a6SLisandro Dalcin     } else {
81016d9e3a6SLisandro Dalcin       jac->logging     = (int) PETSC_FALSE;
81116d9e3a6SLisandro Dalcin     }
81216d9e3a6SLisandro Dalcin     jac->ruse = (int) PETSC_FALSE;
81316d9e3a6SLisandro Dalcin     jac->symt   = 0;
81416d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr);
81516d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr);
81616d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr);
81716d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr);
81816d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr);
81916d9e3a6SLisandro Dalcin     ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr);
82016d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
82116d9e3a6SLisandro Dalcin   }
82216d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr);
82316d9e3a6SLisandro Dalcin   if (flag) {
82416d9e3a6SLisandro Dalcin     ierr                    = HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver);
82516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
82616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Euclid;
82716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_EuclidDestroy;
82816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_EuclidSetup;
82916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_EuclidSolve;
83016d9e3a6SLisandro Dalcin     /* initialization */
83116d9e3a6SLisandro Dalcin     jac->bjilu              = PETSC_FALSE;
83216d9e3a6SLisandro Dalcin     jac->levels             = 1;
83316d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
83416d9e3a6SLisandro Dalcin   }
83516d9e3a6SLisandro Dalcin   ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr);
83616d9e3a6SLisandro Dalcin   if (flag) {
83716d9e3a6SLisandro Dalcin     ierr                     = HYPRE_BoomerAMGCreate(&jac->hsolver);
83816d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
83916d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
84016d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
84116d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
84216d9e3a6SLisandro Dalcin     jac->destroy             = HYPRE_BoomerAMGDestroy;
84316d9e3a6SLisandro Dalcin     jac->setup               = HYPRE_BoomerAMGSetup;
84416d9e3a6SLisandro Dalcin     jac->solve               = HYPRE_BoomerAMGSolve;
84516d9e3a6SLisandro Dalcin     jac->applyrichardson     = PETSC_FALSE;
84616d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
84716d9e3a6SLisandro Dalcin     jac->cycletype        = 1;
84816d9e3a6SLisandro Dalcin     jac->maxlevels        = 25;
84916d9e3a6SLisandro Dalcin     jac->maxiter          = 1;
8508f87f92bSBarry Smith     jac->tol              = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
85116d9e3a6SLisandro Dalcin     jac->truncfactor      = 0.0;
85216d9e3a6SLisandro Dalcin     jac->strongthreshold  = .25;
85316d9e3a6SLisandro Dalcin     jac->maxrowsum        = .9;
85416d9e3a6SLisandro Dalcin     jac->coarsentype      = 6;
85516d9e3a6SLisandro Dalcin     jac->measuretype      = 0;
8560f1074feSSatish Balay     jac->gridsweeps[0]    = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
8578f87f92bSBarry Smith     jac->relaxtype[0]     = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a a PC - most likely with CG */
8580f1074feSSatish Balay     jac->relaxtype[2]     = 9; /*G.E. */
85916d9e3a6SLisandro Dalcin     jac->relaxweight      = 1.0;
86016d9e3a6SLisandro Dalcin     jac->outerrelaxweight = 1.0;
86116d9e3a6SLisandro Dalcin     jac->relaxorder       = 1;
8620f1074feSSatish Balay     jac->interptype       = 0;
8630f1074feSSatish Balay     jac->agg_nl           = 0;
8640f1074feSSatish Balay     jac->pmax             = 0;
8650f1074feSSatish Balay     jac->truncfactor      = 0.0;
8660f1074feSSatish Balay     jac->agg_num_paths    = 1;
8678f87f92bSBarry Smith 
8688f87f92bSBarry Smith     jac->nodal_coarsen    = 0;
8698f87f92bSBarry Smith     jac->nodal_relax      = PETSC_FALSE;
8708f87f92bSBarry Smith     jac->nodal_relax_levels = 1;
87116d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCycleType(jac->hsolver,jac->cycletype);CHKERRQ(ierr);
87216d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);CHKERRQ(ierr);
87316d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr);
87416d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr);
87516d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetTruncFactor(jac->hsolver,jac->truncfactor);CHKERRQ(ierr);
87616d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);CHKERRQ(ierr);
87716d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);CHKERRQ(ierr);
87816d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);CHKERRQ(ierr);
87916d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);CHKERRQ(ierr);
88016d9e3a6SLisandro Dalcin     ierr = HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, jac->relaxorder);CHKERRQ(ierr);
8810f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetInterpType(jac->hsolver,jac->interptype);CHKERRQ(ierr);
8820f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetAggNumLevels(jac->hsolver,jac->agg_nl);
8830f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetPMaxElmts(jac->hsolver,jac->pmax);CHKERRQ(ierr);
8840f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetNumPaths(jac->hsolver,jac->agg_num_paths);CHKERRQ(ierr);
8850f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetRelaxType(jac->hsolver, jac->relaxtype[0]);  /*defaults coarse to 9*/
8860f1074feSSatish Balay     ierr = HYPRE_BoomerAMGSetNumSweeps(jac->hsolver, jac->gridsweeps[0]); /*defaults coarse to 1 */
88716d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
88816d9e3a6SLisandro Dalcin   }
889503cfb0cSBarry Smith   ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr);
89016d9e3a6SLisandro Dalcin   jac->hypre_type = PETSC_NULL;
89165e19b50SBarry Smith   SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name);
89216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
89316d9e3a6SLisandro Dalcin }
89416d9e3a6SLisandro Dalcin EXTERN_C_END
89516d9e3a6SLisandro Dalcin 
89616d9e3a6SLisandro Dalcin /*
89716d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
89816d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
89916d9e3a6SLisandro Dalcin */
90016d9e3a6SLisandro Dalcin #undef __FUNCT__
90116d9e3a6SLisandro Dalcin #define __FUNCT__ "PCSetFromOptions_HYPRE"
90216d9e3a6SLisandro Dalcin static PetscErrorCode PCSetFromOptions_HYPRE(PC pc)
90316d9e3a6SLisandro Dalcin {
90416d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
90516d9e3a6SLisandro Dalcin   int            indx;
90616d9e3a6SLisandro Dalcin   const char     *type[] = {"pilut","parasails","boomeramg","euclid"};
90716d9e3a6SLisandro Dalcin   PetscTruth     flg;
90816d9e3a6SLisandro Dalcin 
90916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
91016d9e3a6SLisandro Dalcin   ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr);
91102a17cd4SBarry Smith   ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"boomeramg",&indx,&flg);CHKERRQ(ierr);
91216d9e3a6SLisandro Dalcin   if (flg) {
91316d9e3a6SLisandro Dalcin     ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr);
91402a17cd4SBarry Smith   } else {
91502a17cd4SBarry Smith     ierr = PCHYPRESetType_HYPRE(pc,"boomeramg");CHKERRQ(ierr);
91616d9e3a6SLisandro Dalcin   }
91716d9e3a6SLisandro Dalcin   if (pc->ops->setfromoptions) {
91816d9e3a6SLisandro Dalcin     ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr);
91916d9e3a6SLisandro Dalcin   }
92016d9e3a6SLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
92116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
92216d9e3a6SLisandro Dalcin }
92316d9e3a6SLisandro Dalcin 
92416d9e3a6SLisandro Dalcin #undef __FUNCT__
92516d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPRESetType"
92616d9e3a6SLisandro Dalcin /*@C
92716d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
92816d9e3a6SLisandro Dalcin 
92916d9e3a6SLisandro Dalcin    Input Parameters:
93016d9e3a6SLisandro Dalcin +     pc - the preconditioner context
93116d9e3a6SLisandro Dalcin -     name - either  pilut, parasails, boomeramg, euclid
93216d9e3a6SLisandro Dalcin 
93316d9e3a6SLisandro Dalcin    Options Database Keys:
93416d9e3a6SLisandro Dalcin    -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
93516d9e3a6SLisandro Dalcin 
93616d9e3a6SLisandro Dalcin    Level: intermediate
93716d9e3a6SLisandro Dalcin 
93816d9e3a6SLisandro Dalcin .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
93916d9e3a6SLisandro Dalcin            PCHYPRE
94016d9e3a6SLisandro Dalcin 
94116d9e3a6SLisandro Dalcin @*/
94216d9e3a6SLisandro Dalcin PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType(PC pc,const char name[])
94316d9e3a6SLisandro Dalcin {
94416d9e3a6SLisandro Dalcin   PetscErrorCode ierr,(*f)(PC,const char[]);
94516d9e3a6SLisandro Dalcin 
94616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9470700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
94816d9e3a6SLisandro Dalcin   PetscValidCharPointer(name,2);
94916d9e3a6SLisandro Dalcin   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);CHKERRQ(ierr);
95016d9e3a6SLisandro Dalcin   if (f) {
95116d9e3a6SLisandro Dalcin     ierr = (*f)(pc,name);CHKERRQ(ierr);
95216d9e3a6SLisandro Dalcin   }
95316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
95416d9e3a6SLisandro Dalcin }
95516d9e3a6SLisandro Dalcin 
95616d9e3a6SLisandro Dalcin #undef __FUNCT__
95716d9e3a6SLisandro Dalcin #define __FUNCT__ "PCHYPREGetType"
95816d9e3a6SLisandro Dalcin /*@C
95916d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
96016d9e3a6SLisandro Dalcin 
96116d9e3a6SLisandro Dalcin    Input Parameter:
96216d9e3a6SLisandro Dalcin .     pc - the preconditioner context
96316d9e3a6SLisandro Dalcin 
96416d9e3a6SLisandro Dalcin    Output Parameter:
96516d9e3a6SLisandro Dalcin .     name - either  pilut, parasails, boomeramg, euclid
96616d9e3a6SLisandro Dalcin 
96716d9e3a6SLisandro Dalcin    Level: intermediate
96816d9e3a6SLisandro Dalcin 
96916d9e3a6SLisandro Dalcin .seealso:  PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC,
97016d9e3a6SLisandro Dalcin            PCHYPRE
97116d9e3a6SLisandro Dalcin 
97216d9e3a6SLisandro Dalcin @*/
97316d9e3a6SLisandro Dalcin PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType(PC pc,const char *name[])
97416d9e3a6SLisandro Dalcin {
97516d9e3a6SLisandro Dalcin   PetscErrorCode ierr,(*f)(PC,const char*[]);
97616d9e3a6SLisandro Dalcin 
97716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9780700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
97916d9e3a6SLisandro Dalcin   PetscValidPointer(name,2);
98016d9e3a6SLisandro Dalcin   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPREGetType_C",(void (**)(void))&f);CHKERRQ(ierr);
98116d9e3a6SLisandro Dalcin   if (f) {
98216d9e3a6SLisandro Dalcin     ierr = (*f)(pc,name);CHKERRQ(ierr);
98316d9e3a6SLisandro Dalcin   }
98416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
98516d9e3a6SLisandro Dalcin }
98616d9e3a6SLisandro Dalcin 
98716d9e3a6SLisandro Dalcin /*MC
98816d9e3a6SLisandro Dalcin      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
98916d9e3a6SLisandro Dalcin 
99016d9e3a6SLisandro Dalcin    Options Database Keys:
99116d9e3a6SLisandro Dalcin +   -pc_hypre_type - One of pilut, parasails, boomeramg, euclid
99216d9e3a6SLisandro Dalcin -   Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX
99316d9e3a6SLisandro Dalcin           preconditioner
99416d9e3a6SLisandro Dalcin 
99516d9e3a6SLisandro Dalcin    Level: intermediate
99616d9e3a6SLisandro Dalcin 
99716d9e3a6SLisandro Dalcin    Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()),
99816d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
99916d9e3a6SLisandro Dalcin           or with PetscOptionsSetValue(), there are no functions to set them)
100016d9e3a6SLisandro Dalcin 
100116d9e3a6SLisandro Dalcin           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations
10020f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
10030f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
10040f1074feSSatish Balay           (-pc_hypre_boomeramg_rtol should be set to 0.0 - the default - to strictly use a fixed number of
10058f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
10060f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
10070f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
100816d9e3a6SLisandro Dalcin 
10090f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
10100f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
10110f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
101216d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
101316d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
101416d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
101516d9e3a6SLisandro Dalcin 
101616d9e3a6SLisandro Dalcin 	  2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
101716d9e3a6SLisandro Dalcin 	  -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
101816d9e3a6SLisandro Dalcin 
10199e5bc791SBarry Smith           See PCPFMG for access to the hypre Struct PFMG solver
10209e5bc791SBarry Smith 
102116d9e3a6SLisandro Dalcin .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
10229e5bc791SBarry Smith            PCHYPRESetType(), PCPFMG
102316d9e3a6SLisandro Dalcin 
102416d9e3a6SLisandro Dalcin M*/
102516d9e3a6SLisandro Dalcin 
102616d9e3a6SLisandro Dalcin EXTERN_C_BEGIN
102716d9e3a6SLisandro Dalcin #undef __FUNCT__
102816d9e3a6SLisandro Dalcin #define __FUNCT__ "PCCreate_HYPRE"
102916d9e3a6SLisandro Dalcin PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_HYPRE(PC pc)
103016d9e3a6SLisandro Dalcin {
103116d9e3a6SLisandro Dalcin   PC_HYPRE       *jac;
103216d9e3a6SLisandro Dalcin   PetscErrorCode ierr;
103316d9e3a6SLisandro Dalcin 
103416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
103538f2d2fdSLisandro Dalcin   ierr = PetscNewLog(pc,PC_HYPRE,&jac);CHKERRQ(ierr);
103616d9e3a6SLisandro Dalcin   pc->data                 = jac;
103716d9e3a6SLisandro Dalcin   pc->ops->destroy         = PCDestroy_HYPRE;
103816d9e3a6SLisandro Dalcin   pc->ops->setfromoptions  = PCSetFromOptions_HYPRE;
103916d9e3a6SLisandro Dalcin   pc->ops->setup           = PCSetUp_HYPRE;
104016d9e3a6SLisandro Dalcin   pc->ops->apply           = PCApply_HYPRE;
104116d9e3a6SLisandro Dalcin   jac->comm_hypre          = MPI_COMM_NULL;
104216d9e3a6SLisandro Dalcin   jac->hypre_type          = PETSC_NULL;
104316d9e3a6SLisandro Dalcin   /* duplicate communicator for hypre */
10447adad957SLisandro Dalcin   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(jac->comm_hypre));CHKERRQ(ierr);
104516d9e3a6SLisandro Dalcin   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr);
104616d9e3a6SLisandro Dalcin   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr);
104716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
104816d9e3a6SLisandro Dalcin }
104916d9e3a6SLisandro Dalcin EXTERN_C_END
1050ebc551c0SBarry Smith 
1051f91d8e95SBarry Smith /* ---------------------------------------------------------------------------------------------------------------------------------*/
1052f91d8e95SBarry Smith 
1053b862ddfaSBarry Smith /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */
105468326731SBarry Smith #include "private/matimpl.h"
1055ebc551c0SBarry Smith 
1056ebc551c0SBarry Smith typedef struct {
105768326731SBarry Smith   MPI_Comm            hcomm;       /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
1058f91d8e95SBarry Smith   HYPRE_StructSolver  hsolver;
10599e5bc791SBarry Smith 
10609e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
10619e5bc791SBarry Smith   int                 its;
10629e5bc791SBarry Smith   double              tol;
10639e5bc791SBarry Smith   int                 relax_type;
10649e5bc791SBarry Smith   int                 rap_type;
10659e5bc791SBarry Smith   int                 num_pre_relax,num_post_relax;
10663b46a515SGlenn Hammond   int                 max_levels;
1067ebc551c0SBarry Smith } PC_PFMG;
1068ebc551c0SBarry Smith 
1069ebc551c0SBarry Smith #undef __FUNCT__
1070ebc551c0SBarry Smith #define __FUNCT__ "PCDestroy_PFMG"
1071ebc551c0SBarry Smith PetscErrorCode PCDestroy_PFMG(PC pc)
1072ebc551c0SBarry Smith {
1073ebc551c0SBarry Smith   PetscErrorCode ierr;
1074f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
1075ebc551c0SBarry Smith 
1076ebc551c0SBarry Smith   PetscFunctionBegin;
1077f91d8e95SBarry Smith   if (ex->hsolver) {ierr = HYPRE_StructPFMGDestroy(ex->hsolver);CHKERRQ(ierr);}
1078f91d8e95SBarry Smith   ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr);
1079f91d8e95SBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
1080ebc551c0SBarry Smith   PetscFunctionReturn(0);
1081ebc551c0SBarry Smith }
1082ebc551c0SBarry Smith 
10839e5bc791SBarry Smith static const char *PFMGRelaxType[]   = {"Jacobi","Weighted-Jacobi","symmetric-Red/Black-Gauss-Seidel","Red/Black-Gauss-Seidel"};
10849e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin","non-Galerkin"};
10859e5bc791SBarry Smith 
1086ebc551c0SBarry Smith #undef __FUNCT__
1087ebc551c0SBarry Smith #define __FUNCT__ "PCView_PFMG"
1088ebc551c0SBarry Smith PetscErrorCode PCView_PFMG(PC pc,PetscViewer viewer)
1089ebc551c0SBarry Smith {
1090ebc551c0SBarry Smith   PetscErrorCode ierr;
1091ebc551c0SBarry Smith   PetscTruth     iascii;
1092f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
1093ebc551c0SBarry Smith 
1094ebc551c0SBarry Smith   PetscFunctionBegin;
10952692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
10969e5bc791SBarry Smith   if (iascii) {
10979e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG preconditioning\n");CHKERRQ(ierr);
10989e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: max iterations %d\n",ex->its);CHKERRQ(ierr);
10999e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr);
11009e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr);
11019e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: RAP type %s\n",PFMGRAPType[ex->rap_type]);CHKERRQ(ierr);
11029e5bc791SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr);
11033b46a515SGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG: max levels %d\n",ex->max_levels);CHKERRQ(ierr);
11049e5bc791SBarry Smith   }
1105ebc551c0SBarry Smith   PetscFunctionReturn(0);
1106ebc551c0SBarry Smith }
1107ebc551c0SBarry Smith 
11089e5bc791SBarry Smith 
1109ebc551c0SBarry Smith #undef __FUNCT__
1110ebc551c0SBarry Smith #define __FUNCT__ "PCSetFromOptions_PFMG"
1111ebc551c0SBarry Smith PetscErrorCode PCSetFromOptions_PFMG(PC pc)
1112ebc551c0SBarry Smith {
1113ebc551c0SBarry Smith   PetscErrorCode ierr;
1114f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
1115886061d4SBarry Smith   PetscTruth     flg = PETSC_FALSE;
1116ebc551c0SBarry Smith 
1117ebc551c0SBarry Smith   PetscFunctionBegin;
1118ebc551c0SBarry Smith   ierr = PetscOptionsHead("PFMG options");CHKERRQ(ierr);
11199e5bc791SBarry Smith   ierr = PetscOptionsTruth("-pc_pfmg_print_statistics","Print statistics","HYPRE_StructPFMGSetPrintLevel",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
112068326731SBarry Smith   if (flg) {
1121a0324ebeSBarry Smith     int level=3;
112268326731SBarry Smith     ierr = HYPRE_StructPFMGSetPrintLevel(ex->hsolver,level);CHKERRQ(ierr);
112368326731SBarry Smith   }
11249e5bc791SBarry 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);
11259e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetMaxIter(ex->hsolver,ex->its);CHKERRQ(ierr);
11269e5bc791SBarry 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);
11279e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetNumPreRelax(ex->hsolver,ex->num_pre_relax);CHKERRQ(ierr);
11289e5bc791SBarry 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);
11299e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetNumPostRelax(ex->hsolver,ex->num_post_relax);CHKERRQ(ierr);
11309e5bc791SBarry Smith 
11313b46a515SGlenn Hammond   ierr = PetscOptionsInt("-pc_pfmg_max_levels","Max Levels for MG hierarchy","HYPRE_StructPFMGSetMaxLevels",ex->max_levels,&ex->max_levels,PETSC_NULL);CHKERRQ(ierr);
11323b46a515SGlenn Hammond   ierr = HYPRE_StructPFMGSetMaxLevels(ex->hsolver,ex->max_levels);CHKERRQ(ierr);
11333b46a515SGlenn Hammond 
11349e5bc791SBarry Smith   ierr = PetscOptionsReal("-pc_pfmg_tol","Tolerance of PFMG","HYPRE_StructPFMGSetTol",ex->tol,&ex->tol,PETSC_NULL);CHKERRQ(ierr);
11359e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetTol(ex->hsolver,ex->tol);CHKERRQ(ierr);
11369e5bc791SBarry 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);
11379e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetRelaxType(ex->hsolver, ex->relax_type);CHKERRQ(ierr);
11389e5bc791SBarry Smith   ierr = PetscOptionsEList("-pc_pfmg_rap_type","RAP type","HYPRE_StructPFMGSetRAPType",PFMGRAPType,2,PFMGRAPType[ex->rap_type],&ex->rap_type,PETSC_NULL);CHKERRQ(ierr);
11399e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetRAPType(ex->hsolver, ex->rap_type);CHKERRQ(ierr);
1140ebc551c0SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
1141ebc551c0SBarry Smith   PetscFunctionReturn(0);
1142ebc551c0SBarry Smith }
1143ebc551c0SBarry Smith 
1144f91d8e95SBarry Smith #undef __FUNCT__
1145f91d8e95SBarry Smith #define __FUNCT__ "PCApply_PFMG"
1146f91d8e95SBarry Smith PetscErrorCode PCApply_PFMG(PC pc,Vec x,Vec y)
1147f91d8e95SBarry Smith {
1148f91d8e95SBarry Smith   PetscErrorCode  ierr;
1149f91d8e95SBarry Smith   PC_PFMG         *ex = (PC_PFMG*) pc->data;
1150f91d8e95SBarry Smith   PetscScalar     *xx,*yy;
1151f91d8e95SBarry Smith   int             ilower[3],iupper[3];
115268326731SBarry Smith   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
1153f91d8e95SBarry Smith 
1154f91d8e95SBarry Smith   PetscFunctionBegin;
115568326731SBarry Smith   ierr = DAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
1156f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
1157f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
1158f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
1159f91d8e95SBarry Smith 
1160f91d8e95SBarry Smith   /* copy x values over to hypre */
1161c7ef6ce2SGlenn Hammond   ierr = HYPRE_StructVectorSetConstantValues(mx->hb,0.0);CHKERRQ(ierr);
1162f91d8e95SBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
116368326731SBarry Smith   ierr = HYPRE_StructVectorSetBoxValues(mx->hb,ilower,iupper,xx);CHKERRQ(ierr);
1164f91d8e95SBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
116568326731SBarry Smith   ierr = HYPRE_StructVectorAssemble(mx->hb);CHKERRQ(ierr);
1166f91d8e95SBarry Smith 
116768326731SBarry Smith   ierr = HYPRE_StructPFMGSolve(ex->hsolver,mx->hmat,mx->hb,mx->hx);CHKERRQ(ierr);
1168f91d8e95SBarry Smith 
1169f91d8e95SBarry Smith   /* copy solution values back to PETSc */
1170f91d8e95SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
1171a0324ebeSBarry Smith   ierr = HYPRE_StructVectorGetBoxValues(mx->hx,ilower,iupper,yy);CHKERRQ(ierr);
1172f91d8e95SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1173f91d8e95SBarry Smith   PetscFunctionReturn(0);
1174f91d8e95SBarry Smith }
1175f91d8e95SBarry Smith 
11769e5bc791SBarry Smith #undef __FUNCT__
11779e5bc791SBarry Smith #define __FUNCT__ "PCApplyRichardson_PFMG"
11787319c654SBarry Smith static PetscErrorCode PCApplyRichardson_PFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscTruth guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
11799e5bc791SBarry Smith {
11809e5bc791SBarry Smith   PC_PFMG        *jac = (PC_PFMG*)pc->data;
11819e5bc791SBarry Smith   PetscErrorCode ierr;
11829e5bc791SBarry Smith   int            oits;
11839e5bc791SBarry Smith 
11849e5bc791SBarry Smith   PetscFunctionBegin;
11859e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetMaxIter(jac->hsolver,its*jac->its);CHKERRQ(ierr);
11869e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetTol(jac->hsolver,rtol);CHKERRQ(ierr);
11879e5bc791SBarry Smith 
11889e5bc791SBarry Smith   ierr = PCApply_PFMG(pc,b,y);CHKERRQ(ierr);
11899e5bc791SBarry Smith   ierr = HYPRE_StructPFMGGetNumIterations(jac->hsolver,&oits);CHKERRQ(ierr);
11909e5bc791SBarry Smith   *outits = oits;
11919e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
11929e5bc791SBarry Smith   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
11939e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr);
11949e5bc791SBarry Smith   ierr = HYPRE_StructPFMGSetMaxIter(jac->hsolver,jac->its);CHKERRQ(ierr);
11959e5bc791SBarry Smith   PetscFunctionReturn(0);
11969e5bc791SBarry Smith }
11979e5bc791SBarry Smith 
11989e5bc791SBarry Smith 
11993a32d3dbSGlenn Hammond #undef __FUNCT__
12003a32d3dbSGlenn Hammond #define __FUNCT__ "PCSetUp_PFMG"
12013a32d3dbSGlenn Hammond PetscErrorCode PCSetUp_PFMG(PC pc)
12023a32d3dbSGlenn Hammond {
12033a32d3dbSGlenn Hammond   PetscErrorCode  ierr;
12043a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG*) pc->data;
12053a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
12063a32d3dbSGlenn Hammond   PetscTruth      flg;
12073a32d3dbSGlenn Hammond 
12083a32d3dbSGlenn Hammond   PetscFunctionBegin;
12093a32d3dbSGlenn Hammond   ierr = PetscTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg);CHKERRQ(ierr);
1210e7e72b3dSBarry Smith   if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner");
12113a32d3dbSGlenn Hammond 
12123a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
12133a32d3dbSGlenn Hammond   if (ex->hsolver) {
12143a32d3dbSGlenn Hammond     ierr = HYPRE_StructPFMGDestroy(ex->hsolver);CHKERRQ(ierr);
12153a32d3dbSGlenn Hammond   }
12163a32d3dbSGlenn Hammond   ierr = HYPRE_StructPFMGCreate(ex->hcomm,&ex->hsolver);CHKERRQ(ierr);
12173a32d3dbSGlenn Hammond   ierr = PCSetFromOptions_PFMG(pc);CHKERRQ(ierr);
12183a32d3dbSGlenn Hammond   ierr = HYPRE_StructPFMGSetup(ex->hsolver,mx->hmat,mx->hb,mx->hx);CHKERRQ(ierr);
12193a32d3dbSGlenn Hammond   ierr = HYPRE_StructPFMGSetZeroGuess(ex->hsolver);CHKERRQ(ierr);
12203a32d3dbSGlenn Hammond 
12213a32d3dbSGlenn Hammond   PetscFunctionReturn(0);
12223a32d3dbSGlenn Hammond }
12233a32d3dbSGlenn Hammond 
1224ebc551c0SBarry Smith 
1225ebc551c0SBarry Smith /*MC
1226ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
1227ebc551c0SBarry Smith 
1228ebc551c0SBarry Smith    Level: advanced
1229ebc551c0SBarry Smith 
12309e5bc791SBarry Smith    Options Database:
12319e5bc791SBarry Smith + -pc_pfmg_its <its> number of iterations of PFMG to use as preconditioner
12329e5bc791SBarry Smith . -pc_pfmg_num_pre_relax <steps> number of smoothing steps before coarse grid
12339e5bc791SBarry Smith . -pc_pfmg_num_post_relax <steps> number of smoothing steps after coarse grid
12349e5bc791SBarry Smith . -pc_pfmg_tol <tol> tolerance of PFMG
12359e5bc791SBarry 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
12369e5bc791SBarry Smith - -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
1237f91d8e95SBarry Smith 
12389e5bc791SBarry Smith    Notes:  This is for CELL-centered descretizations
12399e5bc791SBarry Smith 
12408e395302SJed Brown            This must be used with the MATHYPRESTRUCT matrix type.
12419e5bc791SBarry Smith            This is less general than in hypre, it supports only one block per process defined by a PETSc DA.
12429e5bc791SBarry Smith 
12439e5bc791SBarry Smith .seealso:  PCMG, MATHYPRESTRUCT
1244ebc551c0SBarry Smith M*/
1245ebc551c0SBarry Smith 
1246ebc551c0SBarry Smith EXTERN_C_BEGIN
1247ebc551c0SBarry Smith #undef __FUNCT__
1248ebc551c0SBarry Smith #define __FUNCT__ "PCCreate_PFMG"
1249ebc551c0SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_PFMG(PC pc)
1250ebc551c0SBarry Smith {
1251ebc551c0SBarry Smith   PetscErrorCode ierr;
1252ebc551c0SBarry Smith   PC_PFMG        *ex;
1253ebc551c0SBarry Smith 
1254ebc551c0SBarry Smith   PetscFunctionBegin;
1255ebc551c0SBarry Smith   ierr = PetscNew(PC_PFMG,&ex);CHKERRQ(ierr);\
125668326731SBarry Smith   pc->data = ex;
1257ebc551c0SBarry Smith 
12589e5bc791SBarry Smith   ex->its            = 1;
12599e5bc791SBarry Smith   ex->tol            = 1.e-8;
12609e5bc791SBarry Smith   ex->relax_type     = 1;
12619e5bc791SBarry Smith   ex->rap_type       = 0;
12629e5bc791SBarry Smith   ex->num_pre_relax  = 1;
12639e5bc791SBarry Smith   ex->num_post_relax = 1;
12643b46a515SGlenn Hammond   ex->max_levels     = 0;
12659e5bc791SBarry Smith 
1266ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
1267ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
1268ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
1269f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
12709e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
127168326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
1272f91d8e95SBarry Smith   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(ex->hcomm));CHKERRQ(ierr);
127368326731SBarry Smith   ierr = HYPRE_StructPFMGCreate(ex->hcomm,&ex->hsolver);CHKERRQ(ierr);
1274ebc551c0SBarry Smith   PetscFunctionReturn(0);
1275ebc551c0SBarry Smith }
1276ebc551c0SBarry Smith EXTERN_C_END
1277d851a50bSGlenn Hammond 
1278d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
1279d851a50bSGlenn Hammond typedef struct {
1280d851a50bSGlenn Hammond   MPI_Comm            hcomm;       /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
1281d851a50bSGlenn Hammond   HYPRE_SStructSolver  ss_solver;
1282d851a50bSGlenn Hammond 
1283d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
1284d851a50bSGlenn Hammond   int                 its;
1285d851a50bSGlenn Hammond   double              tol;
1286d851a50bSGlenn Hammond   int                 relax_type;
1287d851a50bSGlenn Hammond   int                 num_pre_relax,num_post_relax;
1288d851a50bSGlenn Hammond } PC_SysPFMG;
1289d851a50bSGlenn Hammond 
1290d851a50bSGlenn Hammond #undef __FUNCT__
1291d851a50bSGlenn Hammond #define __FUNCT__ "PCDestroy_SysPFMG"
1292d851a50bSGlenn Hammond PetscErrorCode PCDestroy_SysPFMG(PC pc)
1293d851a50bSGlenn Hammond {
1294d851a50bSGlenn Hammond   PetscErrorCode ierr;
1295d851a50bSGlenn Hammond   PC_SysPFMG    *ex = (PC_SysPFMG*) pc->data;
1296d851a50bSGlenn Hammond 
1297d851a50bSGlenn Hammond   PetscFunctionBegin;
1298d851a50bSGlenn Hammond   if (ex->ss_solver) {ierr = HYPRE_SStructSysPFMGDestroy(ex->ss_solver);CHKERRQ(ierr);}
1299d851a50bSGlenn Hammond   ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr);
1300d851a50bSGlenn Hammond   ierr = PetscFree(ex);CHKERRQ(ierr);
1301d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1302d851a50bSGlenn Hammond }
1303d851a50bSGlenn Hammond 
1304d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[]   = {"Weighted-Jacobi","Red/Black-Gauss-Seidel"};
1305d851a50bSGlenn Hammond 
1306d851a50bSGlenn Hammond #undef __FUNCT__
1307d851a50bSGlenn Hammond #define __FUNCT__ "PCView_SysPFMG"
1308d851a50bSGlenn Hammond PetscErrorCode PCView_SysPFMG(PC pc,PetscViewer viewer)
1309d851a50bSGlenn Hammond {
1310d851a50bSGlenn Hammond   PetscErrorCode ierr;
1311d851a50bSGlenn Hammond   PetscTruth     iascii;
1312d851a50bSGlenn Hammond   PC_SysPFMG    *ex = (PC_SysPFMG*) pc->data;
1313d851a50bSGlenn Hammond 
1314d851a50bSGlenn Hammond   PetscFunctionBegin;
13152692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1316d851a50bSGlenn Hammond   if (iascii) {
1317d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG preconditioning\n");CHKERRQ(ierr);
1318d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: max iterations %d\n",ex->its);CHKERRQ(ierr);
1319d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr);
1320d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr);
1321d851a50bSGlenn Hammond     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr);
1322d851a50bSGlenn Hammond   }
1323d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1324d851a50bSGlenn Hammond }
1325d851a50bSGlenn Hammond 
1326d851a50bSGlenn Hammond 
1327d851a50bSGlenn Hammond #undef __FUNCT__
1328d851a50bSGlenn Hammond #define __FUNCT__ "PCSetFromOptions_SysPFMG"
1329d851a50bSGlenn Hammond PetscErrorCode PCSetFromOptions_SysPFMG(PC pc)
1330d851a50bSGlenn Hammond {
1331d851a50bSGlenn Hammond   PetscErrorCode ierr;
1332d851a50bSGlenn Hammond   PC_SysPFMG    *ex = (PC_SysPFMG*) pc->data;
1333d851a50bSGlenn Hammond   PetscTruth     flg = PETSC_FALSE;
1334d851a50bSGlenn Hammond 
1335d851a50bSGlenn Hammond   PetscFunctionBegin;
1336d851a50bSGlenn Hammond   ierr = PetscOptionsHead("SysPFMG options");CHKERRQ(ierr);
1337d851a50bSGlenn Hammond   ierr = PetscOptionsTruth("-pc_syspfmg_print_statistics","Print statistics","HYPRE_SStructSysPFMGSetPrintLevel",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
1338d851a50bSGlenn Hammond   if (flg) {
1339d851a50bSGlenn Hammond     int level=3;
1340d851a50bSGlenn Hammond     ierr = HYPRE_SStructSysPFMGSetPrintLevel(ex->ss_solver,level);CHKERRQ(ierr);
1341d851a50bSGlenn Hammond   }
1342d851a50bSGlenn 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);
1343d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetMaxIter(ex->ss_solver,ex->its);CHKERRQ(ierr);
1344d851a50bSGlenn 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);
1345d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetNumPreRelax(ex->ss_solver,ex->num_pre_relax);CHKERRQ(ierr);
1346d851a50bSGlenn 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);
1347d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetNumPostRelax(ex->ss_solver,ex->num_post_relax);CHKERRQ(ierr);
1348d851a50bSGlenn Hammond 
1349d851a50bSGlenn Hammond   ierr = PetscOptionsReal("-pc_syspfmg_tol","Tolerance of SysPFMG","HYPRE_SStructSysPFMGSetTol",ex->tol,&ex->tol,PETSC_NULL);CHKERRQ(ierr);
1350d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetTol(ex->ss_solver,ex->tol);CHKERRQ(ierr);
1351d851a50bSGlenn 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);
1352d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetRelaxType(ex->ss_solver, ex->relax_type);CHKERRQ(ierr);
1353d851a50bSGlenn Hammond   ierr = PetscOptionsTail();CHKERRQ(ierr);
1354d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1355d851a50bSGlenn Hammond }
1356d851a50bSGlenn Hammond 
1357d851a50bSGlenn Hammond #undef __FUNCT__
1358d851a50bSGlenn Hammond #define __FUNCT__ "PCApply_SysPFMG"
1359d851a50bSGlenn Hammond PetscErrorCode PCApply_SysPFMG(PC pc,Vec x,Vec y)
1360d851a50bSGlenn Hammond {
1361d851a50bSGlenn Hammond   PetscErrorCode    ierr;
1362d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG*) pc->data;
1363d851a50bSGlenn Hammond   PetscScalar      *xx,*yy;
1364d851a50bSGlenn Hammond   int               ilower[3],iupper[3];
1365d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
1366d851a50bSGlenn Hammond   int               ordering= mx->dofs_order;
1367d851a50bSGlenn Hammond   int               nvars= mx->nvars;
1368d851a50bSGlenn Hammond   int               part= 0;
1369d851a50bSGlenn Hammond   int               size;
1370d851a50bSGlenn Hammond   int               i;
1371d851a50bSGlenn Hammond 
1372d851a50bSGlenn Hammond   PetscFunctionBegin;
1373d851a50bSGlenn Hammond   ierr = DAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
1374d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
1375d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
1376d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
1377d851a50bSGlenn Hammond 
1378d851a50bSGlenn Hammond   size= 1;
1379d851a50bSGlenn Hammond   for (i= 0; i< 3; i++) {
1380d851a50bSGlenn Hammond      size*= (iupper[i]-ilower[i]+1);
1381d851a50bSGlenn Hammond   }
1382d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
1383d851a50bSGlenn Hammond   if (ordering) {
1384d851a50bSGlenn Hammond      ierr = HYPRE_SStructVectorSetConstantValues(mx->ss_b,0.0);CHKERRQ(ierr);
1385d851a50bSGlenn Hammond      ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
1386d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
1387d851a50bSGlenn Hammond         ierr = HYPRE_SStructVectorSetBoxValues(mx->ss_b,part,ilower,iupper,i,xx+(size*i));CHKERRQ(ierr);
1388d851a50bSGlenn Hammond      }
1389d851a50bSGlenn Hammond      ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
1390d851a50bSGlenn Hammond      ierr = HYPRE_SStructVectorAssemble(mx->ss_b);CHKERRQ(ierr);
1391d851a50bSGlenn Hammond 
1392d851a50bSGlenn Hammond      ierr = HYPRE_SStructMatrixMatvec(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);CHKERRQ(ierr);
1393d851a50bSGlenn Hammond      ierr = HYPRE_SStructSysPFMGSolve(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x);CHKERRQ(ierr);
1394d851a50bSGlenn Hammond 
1395d851a50bSGlenn Hammond      /* copy solution values back to PETSc */
1396d851a50bSGlenn Hammond      ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
1397d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
1398d851a50bSGlenn Hammond         ierr = HYPRE_SStructVectorGetBoxValues(mx->ss_x,part,ilower,iupper,i,yy+(size*i));CHKERRQ(ierr);
1399d851a50bSGlenn Hammond      }
1400d851a50bSGlenn Hammond      ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1401d851a50bSGlenn Hammond   }
1402d851a50bSGlenn Hammond 
1403d851a50bSGlenn Hammond   else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
1404d851a50bSGlenn Hammond      PetscScalar     *z;
1405d851a50bSGlenn Hammond      int              j, k;
1406d851a50bSGlenn Hammond 
1407d851a50bSGlenn Hammond      ierr = PetscMalloc(nvars*size*sizeof(PetscScalar),&z);CHKERRQ(ierr);
1408d851a50bSGlenn Hammond      ierr = HYPRE_SStructVectorSetConstantValues(mx->ss_b,0.0);CHKERRQ(ierr);
1409d851a50bSGlenn Hammond      ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
1410d851a50bSGlenn Hammond 
1411d851a50bSGlenn Hammond      /* transform nodal to hypre's variable ordering for sys_pfmg */
1412d851a50bSGlenn Hammond      for (i= 0; i< size; i++) {
1413d851a50bSGlenn Hammond         k= i*nvars;
1414d851a50bSGlenn Hammond         for (j= 0; j< nvars; j++) {
1415d851a50bSGlenn Hammond            z[j*size+i]= xx[k+j];
1416d851a50bSGlenn Hammond         }
1417d851a50bSGlenn Hammond      }
1418d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
1419d851a50bSGlenn Hammond         ierr = HYPRE_SStructVectorSetBoxValues(mx->ss_b,part,ilower,iupper,i,z+(size*i));CHKERRQ(ierr);
1420d851a50bSGlenn Hammond      }
1421d851a50bSGlenn Hammond      ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
1422d851a50bSGlenn Hammond 
1423d851a50bSGlenn Hammond      ierr = HYPRE_SStructVectorAssemble(mx->ss_b);CHKERRQ(ierr);
1424d851a50bSGlenn Hammond 
1425d851a50bSGlenn Hammond      ierr = HYPRE_SStructSysPFMGSolve(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x);CHKERRQ(ierr);
1426d851a50bSGlenn Hammond 
1427d851a50bSGlenn Hammond      /* copy solution values back to PETSc */
1428d851a50bSGlenn Hammond      ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
1429d851a50bSGlenn Hammond      for (i= 0; i< nvars; i++) {
1430d851a50bSGlenn Hammond         ierr = HYPRE_SStructVectorGetBoxValues(mx->ss_x,part,ilower,iupper,i,z+(size*i));CHKERRQ(ierr);
1431d851a50bSGlenn Hammond      }
1432d851a50bSGlenn Hammond      /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
1433d851a50bSGlenn Hammond      for (i= 0; i< size; i++) {
1434d851a50bSGlenn Hammond         k= i*nvars;
1435d851a50bSGlenn Hammond         for (j= 0; j< nvars; j++) {
1436d851a50bSGlenn Hammond            yy[k+j]= z[j*size+i];
1437d851a50bSGlenn Hammond         }
1438d851a50bSGlenn Hammond      }
1439d851a50bSGlenn Hammond      ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1440d851a50bSGlenn Hammond 
1441d851a50bSGlenn Hammond      ierr = PetscFree(z);CHKERRQ(ierr);
1442d851a50bSGlenn Hammond   }
1443d851a50bSGlenn Hammond 
1444d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1445d851a50bSGlenn Hammond }
1446d851a50bSGlenn Hammond 
1447d851a50bSGlenn Hammond #undef __FUNCT__
1448d851a50bSGlenn Hammond #define __FUNCT__ "PCApplyRichardson_SysPFMG"
1449d851a50bSGlenn Hammond static PetscErrorCode PCApplyRichardson_SysPFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscTruth guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
1450d851a50bSGlenn Hammond {
1451d851a50bSGlenn Hammond   PC_SysPFMG    *jac = (PC_SysPFMG*)pc->data;
1452d851a50bSGlenn Hammond   PetscErrorCode ierr;
1453d851a50bSGlenn Hammond   int            oits;
1454d851a50bSGlenn Hammond 
1455d851a50bSGlenn Hammond   PetscFunctionBegin;
1456d851a50bSGlenn Hammond 
1457d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetMaxIter(jac->ss_solver,its*jac->its);CHKERRQ(ierr);
1458d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetTol(jac->ss_solver,rtol);CHKERRQ(ierr);
1459d851a50bSGlenn Hammond 
1460d851a50bSGlenn Hammond   ierr = PCApply_SysPFMG(pc,b,y);CHKERRQ(ierr);
1461d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGGetNumIterations(jac->ss_solver,&oits);CHKERRQ(ierr);
1462d851a50bSGlenn Hammond   *outits = oits;
1463d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
1464d851a50bSGlenn Hammond   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
1465d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetTol(jac->ss_solver,jac->tol);CHKERRQ(ierr);
1466d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetMaxIter(jac->ss_solver,jac->its);CHKERRQ(ierr);
1467d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1468d851a50bSGlenn Hammond }
1469d851a50bSGlenn Hammond 
1470d851a50bSGlenn Hammond 
1471d851a50bSGlenn Hammond #undef __FUNCT__
1472d851a50bSGlenn Hammond #define __FUNCT__ "PCSetUp_SysPFMG"
1473d851a50bSGlenn Hammond PetscErrorCode PCSetUp_SysPFMG(PC pc)
1474d851a50bSGlenn Hammond {
1475d851a50bSGlenn Hammond   PetscErrorCode    ierr;
1476d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG*) pc->data;
1477d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
1478d851a50bSGlenn Hammond   PetscTruth        flg;
1479d851a50bSGlenn Hammond 
1480d851a50bSGlenn Hammond   PetscFunctionBegin;
1481d851a50bSGlenn Hammond   ierr = PetscTypeCompare((PetscObject)pc->pmat,MATHYPRESSTRUCT,&flg);CHKERRQ(ierr);
1482e7e72b3dSBarry Smith   if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESSTRUCT with this preconditioner");
1483d851a50bSGlenn Hammond 
1484d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
1485d851a50bSGlenn Hammond   if (ex->ss_solver) {
1486d851a50bSGlenn Hammond     ierr = HYPRE_SStructSysPFMGDestroy(ex->ss_solver);CHKERRQ(ierr);
1487d851a50bSGlenn Hammond   }
1488d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGCreate(ex->hcomm,&ex->ss_solver);CHKERRQ(ierr);
1489d851a50bSGlenn Hammond   ierr = PCSetFromOptions_SysPFMG(pc);CHKERRQ(ierr);
1490d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetZeroGuess(ex->ss_solver);CHKERRQ(ierr);
1491d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGSetup(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x);CHKERRQ(ierr);
1492d851a50bSGlenn Hammond 
1493d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1494d851a50bSGlenn Hammond }
1495d851a50bSGlenn Hammond 
1496d851a50bSGlenn Hammond 
1497d851a50bSGlenn Hammond /*MC
1498d851a50bSGlenn Hammond      PCSysPFMG - the hypre SysPFMG multigrid solver
1499d851a50bSGlenn Hammond 
1500d851a50bSGlenn Hammond    Level: advanced
1501d851a50bSGlenn Hammond 
1502d851a50bSGlenn Hammond    Options Database:
1503d851a50bSGlenn Hammond + -pc_syspfmg_its <its> number of iterations of SysPFMG to use as preconditioner
1504d851a50bSGlenn Hammond . -pc_syspfmg_num_pre_relax <steps> number of smoothing steps before coarse grid
1505d851a50bSGlenn Hammond . -pc_syspfmg_num_post_relax <steps> number of smoothing steps after coarse grid
1506d851a50bSGlenn Hammond . -pc_syspfmg_tol <tol> tolerance of SysPFMG
1507d851a50bSGlenn Hammond . -pc_syspfmg_relax_type -relaxation type for the up and down cycles, one of Weighted-Jacobi,Red/Black-Gauss-Seidel
1508d851a50bSGlenn Hammond 
1509d851a50bSGlenn Hammond    Notes:  This is for CELL-centered descretizations
1510d851a50bSGlenn Hammond 
1511f6680f47SSatish Balay            This must be used with the MATHYPRESSTRUCT matrix type.
1512d851a50bSGlenn Hammond            This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DA.
1513d851a50bSGlenn Hammond            Also, only cell-centered variables.
1514d851a50bSGlenn Hammond 
1515d851a50bSGlenn Hammond .seealso:  PCMG, MATHYPRESSTRUCT
1516d851a50bSGlenn Hammond M*/
1517d851a50bSGlenn Hammond 
1518d851a50bSGlenn Hammond EXTERN_C_BEGIN
1519d851a50bSGlenn Hammond #undef __FUNCT__
1520d851a50bSGlenn Hammond #define __FUNCT__ "PCCreate_SysPFMG"
1521d851a50bSGlenn Hammond PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_SysPFMG(PC pc)
1522d851a50bSGlenn Hammond {
1523d851a50bSGlenn Hammond   PetscErrorCode     ierr;
1524d851a50bSGlenn Hammond   PC_SysPFMG        *ex;
1525d851a50bSGlenn Hammond 
1526d851a50bSGlenn Hammond   PetscFunctionBegin;
1527d851a50bSGlenn Hammond   ierr = PetscNew(PC_SysPFMG,&ex);CHKERRQ(ierr);\
1528d851a50bSGlenn Hammond   pc->data = ex;
1529d851a50bSGlenn Hammond 
1530d851a50bSGlenn Hammond   ex->its            = 1;
1531d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
1532d851a50bSGlenn Hammond   ex->relax_type     = 1;
1533d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
1534d851a50bSGlenn Hammond   ex->num_post_relax = 1;
1535d851a50bSGlenn Hammond 
1536d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
1537d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
1538d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
1539d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
1540d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
1541d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
1542d851a50bSGlenn Hammond   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(ex->hcomm));CHKERRQ(ierr);
1543d851a50bSGlenn Hammond   ierr = HYPRE_SStructSysPFMGCreate(ex->hcomm,&ex->ss_solver);CHKERRQ(ierr);
1544d851a50bSGlenn Hammond   PetscFunctionReturn(0);
1545d851a50bSGlenn Hammond }
1546d851a50bSGlenn Hammond EXTERN_C_END
1547