xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 5cb80ecd61fc93edbe681011dc160a66bbda2b5d)
116d9e3a6SLisandro Dalcin /*
216d9e3a6SLisandro Dalcin    Provides an interface to the LLNL package hypre
316d9e3a6SLisandro Dalcin */
40f1074feSSatish Balay 
5589dcaf0SStefano Zampini #include <petscpkg_version.h>
6af0996ceSBarry Smith #include <petsc/private/pcimpl.h>          /*I "petscpc.h" I*/
749a781f5SStefano Zampini /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */
849a781f5SStefano Zampini #include <petsc/private/matimpl.h>
96ea7df73SStefano Zampini #include <petsc/private/vecimpl.h>
1058968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1149a781f5SStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
12c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
134cb006feSStefano Zampini #include <_hypre_parcsr_ls.h>
148a2c336bSFande Kong #include <petscmathypre.h>
1516d9e3a6SLisandro Dalcin 
16a4af0ceeSJacob Faibussowitsch #if defined(PETSC_HAVE_HYPRE_DEVICE)
17a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
18a4af0ceeSJacob Faibussowitsch #endif
19a4af0ceeSJacob Faibussowitsch 
20dff31646SBarry Smith static PetscBool cite = PETSC_FALSE;
21a8d69d7bSBarry Smith static const char hypreCitation[] = "@manual{hypre-web-page,\n  title  = {{\\sl hypre}: High Performance Preconditioners},\n  organization = {Lawrence Livermore National Laboratory},\n  note  = {\\url{https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods}}\n}\n";
221f817a21SBarry Smith 
2316d9e3a6SLisandro Dalcin /*
2416d9e3a6SLisandro Dalcin    Private context (data structure) for the  preconditioner.
2516d9e3a6SLisandro Dalcin */
2616d9e3a6SLisandro Dalcin typedef struct {
2716d9e3a6SLisandro Dalcin   HYPRE_Solver   hsolver;
2849a781f5SStefano Zampini   Mat            hpmat; /* MatHYPRE */
2916d9e3a6SLisandro Dalcin 
304ddd07fcSJed Brown   HYPRE_Int (*destroy)(HYPRE_Solver);
314ddd07fcSJed Brown   HYPRE_Int (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
324ddd07fcSJed Brown   HYPRE_Int (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
3316d9e3a6SLisandro Dalcin 
3416d9e3a6SLisandro Dalcin   MPI_Comm comm_hypre;
3516d9e3a6SLisandro Dalcin   char     *hypre_type;
3616d9e3a6SLisandro Dalcin 
3716d9e3a6SLisandro Dalcin   /* options for Pilut and BoomerAMG*/
384ddd07fcSJed Brown   PetscInt  maxiter;
3939accc25SStefano Zampini   PetscReal tol;
4016d9e3a6SLisandro Dalcin 
4116d9e3a6SLisandro Dalcin   /* options for Pilut */
424ddd07fcSJed Brown   PetscInt factorrowsize;
4316d9e3a6SLisandro Dalcin 
4416d9e3a6SLisandro Dalcin   /* options for ParaSails */
454ddd07fcSJed Brown   PetscInt  nlevels;
468966356dSPierre Jolivet   PetscReal threshold;
4739accc25SStefano Zampini   PetscReal filter;
4839accc25SStefano Zampini   PetscReal loadbal;
494ddd07fcSJed Brown   PetscInt  logging;
504ddd07fcSJed Brown   PetscInt  ruse;
514ddd07fcSJed Brown   PetscInt  symt;
5216d9e3a6SLisandro Dalcin 
5322b6d1caSBarry Smith   /* options for BoomerAMG */
54ace3abfcSBarry Smith   PetscBool printstatistics;
5516d9e3a6SLisandro Dalcin 
5616d9e3a6SLisandro Dalcin   /* options for BoomerAMG */
574ddd07fcSJed Brown   PetscInt  cycletype;
584ddd07fcSJed Brown   PetscInt  maxlevels;
5939accc25SStefano Zampini   PetscReal strongthreshold;
6039accc25SStefano Zampini   PetscReal maxrowsum;
614ddd07fcSJed Brown   PetscInt  gridsweeps[3];
624ddd07fcSJed Brown   PetscInt  coarsentype;
634ddd07fcSJed Brown   PetscInt  measuretype;
646a251517SEike Mueller   PetscInt  smoothtype;
658131ecf7SEike Mueller   PetscInt  smoothnumlevels;
66ec64516dSEike Mueller   PetscInt  eu_level;   /* Number of levels for ILU(k) in Euclid */
6739accc25SStefano Zampini   PetscReal eu_droptolerance; /* Drop tolerance for ILU(k) in Euclid */
68ec64516dSEike Mueller   PetscInt  eu_bj;      /* Defines use of Block Jacobi ILU in Euclid */
694ddd07fcSJed Brown   PetscInt  relaxtype[3];
7039accc25SStefano Zampini   PetscReal relaxweight;
7139accc25SStefano Zampini   PetscReal outerrelaxweight;
724ddd07fcSJed Brown   PetscInt  relaxorder;
7339accc25SStefano Zampini   PetscReal truncfactor;
74ace3abfcSBarry Smith   PetscBool applyrichardson;
754ddd07fcSJed Brown   PetscInt  pmax;
764ddd07fcSJed Brown   PetscInt  interptype;
77589dcaf0SStefano Zampini   PetscInt  maxc;
78589dcaf0SStefano Zampini   PetscInt  minc;
79db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2,23,0)
80db6f9c32SMark Adams   char      *spgemm_type; // this is a global hypre parameter but is closely associated with BoomerAMG
81db6f9c32SMark Adams #endif
826ea7df73SStefano Zampini   /* GPU */
836ea7df73SStefano Zampini   PetscBool keeptranspose;
846ea7df73SStefano Zampini   PetscInt  rap2;
856ea7df73SStefano Zampini   PetscInt  mod_rap2;
866ea7df73SStefano Zampini 
87589dcaf0SStefano Zampini   /* AIR */
88589dcaf0SStefano Zampini   PetscInt  Rtype;
89589dcaf0SStefano Zampini   PetscReal Rstrongthreshold;
90589dcaf0SStefano Zampini   PetscReal Rfilterthreshold;
91589dcaf0SStefano Zampini   PetscInt  Adroptype;
92589dcaf0SStefano Zampini   PetscReal Adroptol;
93589dcaf0SStefano Zampini 
944ddd07fcSJed Brown   PetscInt  agg_nl;
956ea7df73SStefano Zampini   PetscInt  agg_interptype;
964ddd07fcSJed Brown   PetscInt  agg_num_paths;
97ace3abfcSBarry Smith   PetscBool nodal_relax;
984ddd07fcSJed Brown   PetscInt  nodal_relax_levels;
994cb006feSStefano Zampini 
1005272c319SBarry Smith   PetscInt  nodal_coarsening;
10122e51d31SStefano Zampini   PetscInt  nodal_coarsening_diag;
1025272c319SBarry Smith   PetscInt  vec_interp_variant;
10322e51d31SStefano Zampini   PetscInt  vec_interp_qmax;
10422e51d31SStefano Zampini   PetscBool vec_interp_smooth;
10522e51d31SStefano Zampini   PetscInt  interp_refine;
10622e51d31SStefano Zampini 
1076ea7df73SStefano Zampini   /* NearNullSpace support */
1086ea7df73SStefano Zampini   VecHYPRE_IJVector *hmnull;
1096ea7df73SStefano Zampini   HYPRE_ParVector   *phmnull;
1105272c319SBarry Smith   PetscInt          n_hmnull;
1115272c319SBarry Smith   Vec               hmnull_constant;
1125272c319SBarry Smith 
113863406b8SStefano Zampini   /* options for AS (Auxiliary Space preconditioners) */
114863406b8SStefano Zampini   PetscInt  as_print;
115863406b8SStefano Zampini   PetscInt  as_max_iter;
116863406b8SStefano Zampini   PetscReal as_tol;
117863406b8SStefano Zampini   PetscInt  as_relax_type;
118863406b8SStefano Zampini   PetscInt  as_relax_times;
119863406b8SStefano Zampini   PetscReal as_relax_weight;
120863406b8SStefano Zampini   PetscReal as_omega;
121863406b8SStefano Zampini   PetscInt  as_amg_alpha_opts[5]; /* AMG coarsen type, agg_levels, relax_type, interp_type, Pmax for vector Poisson (AMS) or Curl problem (ADS) */
122863406b8SStefano Zampini   PetscReal as_amg_alpha_theta;   /* AMG strength for vector Poisson (AMS) or Curl problem (ADS) */
123863406b8SStefano Zampini   PetscInt  as_amg_beta_opts[5];  /* AMG coarsen type, agg_levels, relax_type, interp_type, Pmax for scalar Poisson (AMS) or vector Poisson (ADS) */
124863406b8SStefano Zampini   PetscReal as_amg_beta_theta;    /* AMG strength for scalar Poisson (AMS) or vector Poisson (ADS)  */
1254cb006feSStefano Zampini   PetscInt  ams_cycle_type;
126863406b8SStefano Zampini   PetscInt  ads_cycle_type;
1274cb006feSStefano Zampini 
1284cb006feSStefano Zampini   /* additional data */
1295ac14e1cSStefano Zampini   Mat G;             /* MatHYPRE */
1305ac14e1cSStefano Zampini   Mat C;             /* MatHYPRE */
1315ac14e1cSStefano Zampini   Mat alpha_Poisson; /* MatHYPRE */
1325ac14e1cSStefano Zampini   Mat beta_Poisson;  /* MatHYPRE */
1335ac14e1cSStefano Zampini 
1345ac14e1cSStefano Zampini   /* extra information for AMS */
1355ac14e1cSStefano Zampini   PetscInt          dim; /* geometrical dimension */
1366ea7df73SStefano Zampini   VecHYPRE_IJVector coords[3];
1376ea7df73SStefano Zampini   VecHYPRE_IJVector constants[3];
138be14dc20SKerry Key   VecHYPRE_IJVector interior;
1396bf688a0SCe Qin   Mat               RT_PiFull, RT_Pi[3];
1406bf688a0SCe Qin   Mat               ND_PiFull, ND_Pi[3];
1414cb006feSStefano Zampini   PetscBool         ams_beta_is_zero;
14223df4f25SStefano Zampini   PetscBool         ams_beta_is_zero_part;
14323df4f25SStefano Zampini   PetscInt          ams_proj_freq;
14416d9e3a6SLisandro Dalcin } PC_HYPRE;
14516d9e3a6SLisandro Dalcin 
146d2128fa2SBarry Smith PetscErrorCode PCHYPREGetSolver(PC pc,HYPRE_Solver *hsolver)
147d2128fa2SBarry Smith {
148d2128fa2SBarry Smith   PC_HYPRE *jac = (PC_HYPRE*)pc->data;
149d2128fa2SBarry Smith 
150d2128fa2SBarry Smith   PetscFunctionBegin;
151d2128fa2SBarry Smith   *hsolver = jac->hsolver;
152d2128fa2SBarry Smith   PetscFunctionReturn(0);
153d2128fa2SBarry Smith }
15416d9e3a6SLisandro Dalcin 
155fd2dd295SFande Kong /*
1568a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1578a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1588a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
159fd2dd295SFande Kong */
160fd2dd295SFande Kong static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc,PetscInt *nlevels,Mat *operators[])
1618a2c336bSFande Kong {
1628a2c336bSFande Kong   PC_HYPRE             *jac  = (PC_HYPRE*)pc->data;
1638a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1648a2c336bSFande Kong   PetscInt             num_levels,l;
1658a2c336bSFande Kong   Mat                  *mattmp;
1668a2c336bSFande Kong   hypre_ParCSRMatrix   **A_array;
1678a2c336bSFande Kong 
1688a2c336bSFande Kong   PetscFunctionBegin;
1699566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type,"boomeramg",&same));
1705f80ce2aSJacob Faibussowitsch   PetscCheck(same,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_NOTSAMETYPE,"Hypre type is not BoomerAMG ");
1718a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData*) (jac->hsolver));
1729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels,&mattmp));
1738a2c336bSFande Kong   A_array    = hypre_ParAMGDataAArray((hypre_ParAMGData*) (jac->hsolver));
1748a2c336bSFande Kong   for (l=1; l<num_levels; l++) {
1759566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l],MATAIJ,PETSC_OWN_POINTER, &(mattmp[num_levels-1-l])));
1768a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1778a2c336bSFande Kong     A_array[l] = NULL;
1788a2c336bSFande Kong   }
1798a2c336bSFande Kong   *nlevels = num_levels;
1808a2c336bSFande Kong   *operators = mattmp;
1818a2c336bSFande Kong   PetscFunctionReturn(0);
1828a2c336bSFande Kong }
1838a2c336bSFande Kong 
184fd2dd295SFande Kong /*
1858a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1868a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1878a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
188fd2dd295SFande Kong */
189fd2dd295SFande Kong static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc,PetscInt *nlevels,Mat *interpolations[])
1908a2c336bSFande Kong {
1918a2c336bSFande Kong   PC_HYPRE             *jac  = (PC_HYPRE*)pc->data;
1928a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1938a2c336bSFande Kong   PetscInt             num_levels,l;
1948a2c336bSFande Kong   Mat                  *mattmp;
1958a2c336bSFande Kong   hypre_ParCSRMatrix   **P_array;
1968a2c336bSFande Kong 
1978a2c336bSFande Kong   PetscFunctionBegin;
1989566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type,"boomeramg",&same));
1995f80ce2aSJacob Faibussowitsch   PetscCheck(same,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_NOTSAMETYPE,"Hypre type is not BoomerAMG ");
2008a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData*) (jac->hsolver));
2019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels,&mattmp));
2028a2c336bSFande Kong   P_array  = hypre_ParAMGDataPArray((hypre_ParAMGData*) (jac->hsolver));
2038a2c336bSFande Kong   for (l=1; l<num_levels; l++) {
2049566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels-1-l],MATAIJ,PETSC_OWN_POINTER, &(mattmp[l-1])));
2058a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
2068a2c336bSFande Kong     P_array[num_levels-1-l] = NULL;
2078a2c336bSFande Kong   }
2088a2c336bSFande Kong   *nlevels = num_levels;
2098a2c336bSFande Kong   *interpolations = mattmp;
2108a2c336bSFande Kong   PetscFunctionReturn(0);
2118a2c336bSFande Kong }
2128a2c336bSFande Kong 
213ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
214ce6a8a0dSJed Brown static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
215ce6a8a0dSJed Brown {
216ce6a8a0dSJed Brown   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
217ce6a8a0dSJed Brown   PetscInt       i;
218ce6a8a0dSJed Brown 
2199d678128SJed Brown   PetscFunctionBegin;
220ce6a8a0dSJed Brown   for (i=0; i<jac->n_hmnull; i++) {
2219566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
222ce6a8a0dSJed Brown   }
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2249566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2269d678128SJed Brown   jac->n_hmnull = 0;
227ce6a8a0dSJed Brown   PetscFunctionReturn(0);
228ce6a8a0dSJed Brown }
229ce6a8a0dSJed Brown 
23016d9e3a6SLisandro Dalcin static PetscErrorCode PCSetUp_HYPRE(PC pc)
23116d9e3a6SLisandro Dalcin {
23216d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
23349a781f5SStefano Zampini   Mat_HYPRE          *hjac;
23416d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
23516d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv,xv;
23649a781f5SStefano Zampini   PetscBool          ishypre;
23716d9e3a6SLisandro Dalcin 
23816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23916d9e3a6SLisandro Dalcin   if (!jac->hypre_type) {
2409566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType(pc,"boomeramg"));
24116d9e3a6SLisandro Dalcin   }
2425f5c5b43SBarry Smith 
2439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRE,&ishypre));
24449a781f5SStefano Zampini   if (!ishypre) {
2459566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
2469566063dSJacob Faibussowitsch     PetscCall(MatConvert(pc->pmat,MATHYPRE,MAT_INITIAL_MATRIX,&jac->hpmat));
2479566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->hpmat));
24849a781f5SStefano Zampini   } else {
2499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2509566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
25149a781f5SStefano Zampini     jac->hpmat = pc->pmat;
25216d9e3a6SLisandro Dalcin   }
2536ea7df73SStefano Zampini   /* allow debug */
2549566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat,NULL,"-pc_hypre_mat_view"));
25549a781f5SStefano Zampini   hjac = (Mat_HYPRE*)(jac->hpmat->data);
2565f5c5b43SBarry Smith 
25716d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25816d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2595272c319SBarry Smith     MatNullSpace mnull;
2605272c319SBarry Smith     PetscBool    has_const;
26149a781f5SStefano Zampini     PetscInt     bs,nvec,i;
2625272c319SBarry Smith     const Vec    *vecs;
2635272c319SBarry Smith 
2649566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat,&bs));
265792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions,jac->hsolver,bs);
2669566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2675272c319SBarry Smith     if (mnull) {
2689566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2699566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec+1,&jac->hmnull));
2719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec+1,&jac->phmnull));
2725272c319SBarry Smith       for (i=0; i<nvec; i++) {
2739566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map,&jac->hmnull[i]));
2749566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i],jac->hmnull[i]));
275792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject,jac->hmnull[i]->ij,(void**)&jac->phmnull[i]);
2765272c319SBarry Smith       }
2775272c319SBarry Smith       if (has_const) {
2789566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat,&jac->hmnull_constant,NULL));
2799566063dSJacob Faibussowitsch         PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->hmnull_constant));
2809566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant,1));
2819566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant,NULL));
2829566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map,&jac->hmnull[nvec]));
2839566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant,jac->hmnull[nvec]));
284792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject,jac->hmnull[nvec]->ij,(void**)&jac->phmnull[nvec]);
2855272c319SBarry Smith         nvec++;
2865272c319SBarry Smith       }
287792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors,jac->hsolver,nvec,jac->phmnull);
2885272c319SBarry Smith       jac->n_hmnull = nvec;
2895272c319SBarry Smith     }
2904cb006feSStefano Zampini   }
291863406b8SStefano Zampini 
2924cb006feSStefano Zampini   /* special case for AMS */
2934cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2945ac14e1cSStefano Zampini     Mat_HYPRE          *hm;
2955ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2966bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
2976bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE AMS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the edge constant vectors via PCHYPRESetEdgeConstantVectors() or the interpolation matrix via PCHYPRESetInterpolations");
2986bf688a0SCe Qin     }
2995ac14e1cSStefano Zampini     if (jac->dim) {
300792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetDimension,jac->hsolver,jac->dim);
3015ac14e1cSStefano Zampini     }
3025ac14e1cSStefano Zampini     if (jac->constants[0]) {
3035ac14e1cSStefano Zampini       HYPRE_ParVector ozz,zoz,zzo = NULL;
304792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject,jac->constants[0]->ij,(void**)(&ozz));
305792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject,jac->constants[1]->ij,(void**)(&zoz));
3065ac14e1cSStefano Zampini       if (jac->constants[2]) {
307792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject,jac->constants[2]->ij,(void**)(&zzo));
3085ac14e1cSStefano Zampini       }
309792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors,jac->hsolver,ozz,zoz,zzo);
3105ac14e1cSStefano Zampini     }
3115ac14e1cSStefano Zampini     if (jac->coords[0]) {
3125ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3135ac14e1cSStefano Zampini       coords[0] = NULL;
3145ac14e1cSStefano Zampini       coords[1] = NULL;
3155ac14e1cSStefano Zampini       coords[2] = NULL;
316792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject,jac->coords[0]->ij,(void**)(&coords[0]));
317792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject,jac->coords[1]->ij,(void**)(&coords[1]));
318792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject,jac->coords[2]->ij,(void**)(&coords[2]));
319792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors,jac->hsolver,coords[0],coords[1],coords[2]);
3205ac14e1cSStefano Zampini     }
3215f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G,PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3225ac14e1cSStefano Zampini     hm = (Mat_HYPRE*)(jac->G->data);
323792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&parcsr));
324792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient,jac->hsolver,parcsr);
3255ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3265ac14e1cSStefano Zampini       hm = (Mat_HYPRE*)(jac->alpha_Poisson->data);
327792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&parcsr));
328792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix,jac->hsolver,parcsr);
3295ac14e1cSStefano Zampini     }
3305ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
331792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix,jac->hsolver,NULL);
3325ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3335ac14e1cSStefano Zampini       hm = (Mat_HYPRE*)(jac->beta_Poisson->data);
334792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&parcsr));
335792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix,jac->hsolver,parcsr);
336be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part)  {
337be14dc20SKerry Key       if (jac->interior) {
338be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
339be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject,jac->interior->ij,(void**)(&interior));
340be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes,jac->hsolver,interior);
341be14dc20SKerry Key       } else {
342be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
343be14dc20SKerry Key       }
3445ac14e1cSStefano Zampini     }
3456bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3466bf688a0SCe Qin       PetscInt           i;
3476bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3486bf688a0SCe Qin       if (jac->ND_PiFull) {
3496bf688a0SCe Qin         hm = (Mat_HYPRE*)(jac->ND_PiFull->data);
350792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&nd_parcsrfull));
3516bf688a0SCe Qin       } else {
3526bf688a0SCe Qin         nd_parcsrfull = NULL;
3536bf688a0SCe Qin       }
3546bf688a0SCe Qin       for (i=0;i<3;++i) {
3556bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3566bf688a0SCe Qin           hm = (Mat_HYPRE*)(jac->ND_Pi[i]->data);
357792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&nd_parcsr[i]));
3586bf688a0SCe Qin         } else {
3596bf688a0SCe Qin           nd_parcsr[i] = NULL;
3606bf688a0SCe Qin         }
3616bf688a0SCe Qin       }
362792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations,jac->hsolver,nd_parcsrfull,nd_parcsr[0],nd_parcsr[1],nd_parcsr[2]);
3636bf688a0SCe Qin     }
3644cb006feSStefano Zampini   }
365863406b8SStefano Zampini   /* special case for ADS */
366863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3675ac14e1cSStefano Zampini     Mat_HYPRE          *hm;
3685ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3696bf688a0SCe Qin     if (!jac->coords[0] && !((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])))) {
3706bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3716bf688a0SCe Qin     }
3727827d75bSBarry Smith     else PetscCheck(jac->coords[1] && jac->coords[2],PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner has been designed for three dimensional problems! For two dimensional problems, use HYPRE AMS instead");
3735f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G,PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3745f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C,PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3755ac14e1cSStefano Zampini     if (jac->coords[0]) {
3765ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3775ac14e1cSStefano Zampini       coords[0] = NULL;
3785ac14e1cSStefano Zampini       coords[1] = NULL;
3795ac14e1cSStefano Zampini       coords[2] = NULL;
380792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject,jac->coords[0]->ij,(void**)(&coords[0]));
381792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject,jac->coords[1]->ij,(void**)(&coords[1]));
382792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject,jac->coords[2]->ij,(void**)(&coords[2]));
383792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors,jac->hsolver,coords[0],coords[1],coords[2]);
3845ac14e1cSStefano Zampini     }
3855ac14e1cSStefano Zampini     hm = (Mat_HYPRE*)(jac->G->data);
386792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&parcsr));
387792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient,jac->hsolver,parcsr);
3885ac14e1cSStefano Zampini     hm = (Mat_HYPRE*)(jac->C->data);
389792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&parcsr));
390792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl,jac->hsolver,parcsr);
3916bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3926bf688a0SCe Qin       PetscInt           i;
3936bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3946bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3956bf688a0SCe Qin       if (jac->RT_PiFull) {
3966bf688a0SCe Qin         hm = (Mat_HYPRE*)(jac->RT_PiFull->data);
397792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&rt_parcsrfull));
3986bf688a0SCe Qin       } else {
3996bf688a0SCe Qin         rt_parcsrfull = NULL;
4006bf688a0SCe Qin       }
4016bf688a0SCe Qin       for (i=0;i<3;++i) {
4026bf688a0SCe Qin         if (jac->RT_Pi[i]) {
4036bf688a0SCe Qin           hm = (Mat_HYPRE*)(jac->RT_Pi[i]->data);
404792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&rt_parcsr[i]));
4056bf688a0SCe Qin         } else {
4066bf688a0SCe Qin           rt_parcsr[i] = NULL;
4076bf688a0SCe Qin         }
4086bf688a0SCe Qin       }
4096bf688a0SCe Qin       if (jac->ND_PiFull) {
4106bf688a0SCe Qin         hm = (Mat_HYPRE*)(jac->ND_PiFull->data);
411792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&nd_parcsrfull));
4126bf688a0SCe Qin       } else {
4136bf688a0SCe Qin         nd_parcsrfull = NULL;
4146bf688a0SCe Qin       }
4156bf688a0SCe Qin       for (i=0;i<3;++i) {
4166bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4176bf688a0SCe Qin           hm = (Mat_HYPRE*)(jac->ND_Pi[i]->data);
418792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject,hm->ij,(void**)(&nd_parcsr[i]));
4196bf688a0SCe Qin         } else {
4206bf688a0SCe Qin           nd_parcsr[i] = NULL;
4216bf688a0SCe Qin         }
4226bf688a0SCe Qin       }
423792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetInterpolations,jac->hsolver,rt_parcsrfull,rt_parcsr[0],rt_parcsr[1],rt_parcsr[2],nd_parcsrfull,nd_parcsr[0],nd_parcsr[1],nd_parcsr[2]);
4246bf688a0SCe Qin     }
425863406b8SStefano Zampini   }
426792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject,hjac->ij,(void**)&hmat);
427792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject,hjac->b->ij,(void**)&bv);
428792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject,hjac->x->ij,(void**)&xv);
429792fecdfSBarry Smith   PetscCallExternal(jac->setup,jac->hsolver,hmat,bv,xv);
43016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
43116d9e3a6SLisandro Dalcin }
43216d9e3a6SLisandro Dalcin 
43316d9e3a6SLisandro Dalcin static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x)
43416d9e3a6SLisandro Dalcin {
43516d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
43649a781f5SStefano Zampini   Mat_HYPRE          *hjac = (Mat_HYPRE*)(jac->hpmat->data);
43716d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
43816d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv,jxv;
43916d9e3a6SLisandro Dalcin 
44016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4419566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
4429566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x,0.0));
4439566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b,b));
4449566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x,x));
4459566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x,x));
446792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject,hjac->ij,(void**)&hmat);
447792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject,hjac->b->ij,(void**)&jbv);
448792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject,hjac->x->ij,(void**)&jxv);
449e77caa6dSBarry Smith   PetscStackCallExternalVoid("Hypre solve",do {
4505f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv);
4515f80ce2aSJacob Faibussowitsch       if (hierr) {
4525f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",(int)hierr);
4535f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
4545f80ce2aSJacob Faibussowitsch       }
4555f80ce2aSJacob Faibussowitsch     } while (0));
45616d9e3a6SLisandro Dalcin 
45723df4f25SStefano Zampini   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) {
458792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSProjectOutGradients,jac->hsolver,jxv);
45921df291bSStefano Zampini   }
4609566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4619566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
46216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
46316d9e3a6SLisandro Dalcin }
46416d9e3a6SLisandro Dalcin 
4658695de01SBarry Smith static PetscErrorCode PCReset_HYPRE(PC pc)
4668695de01SBarry Smith {
4678695de01SBarry Smith   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
4688695de01SBarry Smith 
4698695de01SBarry Smith   PetscFunctionBegin;
4709566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
4719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
4729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
4739566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
4749566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
4759566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
4769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
4779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
4789566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
4799566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
4809566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
4819566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
4829566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
4839566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
4849566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
4859566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
4869566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
4879566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
4889566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
489be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
4909566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
4915ac14e1cSStefano Zampini   jac->ams_beta_is_zero = PETSC_FALSE;
492be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
4935ac14e1cSStefano Zampini   jac->dim = 0;
4948695de01SBarry Smith   PetscFunctionReturn(0);
4958695de01SBarry Smith }
4968695de01SBarry Smith 
49716d9e3a6SLisandro Dalcin static PetscErrorCode PCDestroy_HYPRE(PC pc)
49816d9e3a6SLisandro Dalcin {
49916d9e3a6SLisandro Dalcin   PC_HYPRE                 *jac = (PC_HYPRE*)pc->data;
50016d9e3a6SLisandro Dalcin 
50116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5029566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
503792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy,jac->hsolver);
5049566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
505db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2,23,0)
5069566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
507db6f9c32SMark Adams #endif
5089566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc),&jac->comm_hypre));
5099566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
51016d9e3a6SLisandro Dalcin 
5119566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc,0));
5129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetType_C",NULL));
5139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPREGetType_C",NULL));
5149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteGradient_C",NULL));
5159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteCurl_C",NULL));
5169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetInterpolations_C",NULL));
5179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetConstantEdgeVectors_C",NULL));
5189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetPoissonMatrix_C",NULL));
5192e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetEdgeConstantVectors_C",NULL));
520be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPREAMSSetInteriorNodes_C",NULL));
5219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",NULL));
5229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",NULL));
5239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGalerkinSetMatProductAlgorithm_C",NULL));
5249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGalerkinGetMatProductAlgorithm_C",NULL));
5252e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL));
52616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
52716d9e3a6SLisandro Dalcin }
52816d9e3a6SLisandro Dalcin 
52916d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
5304416b707SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PetscOptionItems *PetscOptionsObject,PC pc)
53116d9e3a6SLisandro Dalcin {
53216d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
533ace3abfcSBarry Smith   PetscBool      flag;
53416d9e3a6SLisandro Dalcin 
53516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
536d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"HYPRE Pilut Options");
5379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag));
538792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter,jac->hsolver,jac->maxiter);
5399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag));
540792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance,jac->hsolver,jac->tol);
5419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag));
542792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize,jac->hsolver,jac->factorrowsize);
543d0609cedSBarry Smith   PetscOptionsHeadEnd();
54416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
54516d9e3a6SLisandro Dalcin }
54616d9e3a6SLisandro Dalcin 
54716d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)
54816d9e3a6SLisandro Dalcin {
54916d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
550ace3abfcSBarry Smith   PetscBool      iascii;
55116d9e3a6SLisandro Dalcin 
55216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
55416d9e3a6SLisandro Dalcin   if (iascii) {
5559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut preconditioning\n"));
55616d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
55763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    maximum number of iterations %" PetscInt_FMT "\n",jac->maxiter));
55816d9e3a6SLisandro Dalcin     } else {
5599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    default maximum number of iterations \n"));
56016d9e3a6SLisandro Dalcin     }
56116d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
5629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    drop tolerance %g\n",(double)jac->tol));
56316d9e3a6SLisandro Dalcin     } else {
5649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    default drop tolerance \n"));
56516d9e3a6SLisandro Dalcin     }
56616d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
56763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    factor row size %" PetscInt_FMT "\n",jac->factorrowsize));
56816d9e3a6SLisandro Dalcin     } else {
5699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    default factor row size \n"));
57016d9e3a6SLisandro Dalcin     }
57116d9e3a6SLisandro Dalcin   }
57216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
57316d9e3a6SLisandro Dalcin }
57416d9e3a6SLisandro Dalcin 
57516d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
576db966c6cSHong Zhang static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PetscOptionItems *PetscOptionsObject,PC pc)
577db966c6cSHong Zhang {
578db966c6cSHong Zhang   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
5798bf83915SBarry Smith   PetscBool      flag,eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
580db966c6cSHong Zhang 
581db966c6cSHong Zhang   PetscFunctionBegin;
582d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"HYPRE Euclid Options");
5839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level","Factorization levels","None",jac->eu_level,&jac->eu_level,&flag));
584792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel,jac->hsolver,jac->eu_level);
5858bf83915SBarry Smith 
5869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance","Drop tolerance for ILU(k) in Euclid","None",jac->eu_droptolerance,&jac->eu_droptolerance,&flag));
5878bf83915SBarry Smith   if (flag) {
5888bf83915SBarry Smith     PetscMPIInt size;
5898bf83915SBarry Smith 
5909566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
5917827d75bSBarry Smith     PetscCheck(size == 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"hypre's Euclid does not support a parallel drop tolerance");
592792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT,jac->hsolver,jac->eu_droptolerance);
5938bf83915SBarry Smith   }
5948bf83915SBarry Smith 
5959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj,&eu_bj,&flag));
5968bf83915SBarry Smith   if (flag) {
5978bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
598792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ,jac->hsolver,jac->eu_bj);
5998bf83915SBarry Smith   }
600d0609cedSBarry Smith   PetscOptionsHeadEnd();
601db966c6cSHong Zhang   PetscFunctionReturn(0);
602db966c6cSHong Zhang }
603db966c6cSHong Zhang 
604db966c6cSHong Zhang static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)
605db966c6cSHong Zhang {
606db966c6cSHong Zhang   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
607db966c6cSHong Zhang   PetscBool      iascii;
608db966c6cSHong Zhang 
609db966c6cSHong Zhang   PetscFunctionBegin;
6109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
611db966c6cSHong Zhang   if (iascii) {
6129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid preconditioning\n"));
613db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
61463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    factorization levels %" PetscInt_FMT "\n",jac->eu_level));
615db966c6cSHong Zhang     } else {
6169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    default factorization levels \n"));
617db966c6cSHong Zhang     }
6189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    drop tolerance %g\n",(double)jac->eu_droptolerance));
61963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    use Block-Jacobi? %" PetscInt_FMT "\n",jac->eu_bj));
620db966c6cSHong Zhang   }
621db966c6cSHong Zhang   PetscFunctionReturn(0);
622db966c6cSHong Zhang }
623db966c6cSHong Zhang 
624db966c6cSHong Zhang /* --------------------------------------------------------------------------------------------*/
62516d9e3a6SLisandro Dalcin 
62616d9e3a6SLisandro Dalcin static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x)
62716d9e3a6SLisandro Dalcin {
62816d9e3a6SLisandro Dalcin   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
62949a781f5SStefano Zampini   Mat_HYPRE          *hjac = (Mat_HYPRE*)(jac->hpmat->data);
63016d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
63116d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv,jxv;
63216d9e3a6SLisandro Dalcin 
63316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6349566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
6359566063dSJacob Faibussowitsch   PetscCall(VecSet(x,0.0));
6369566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x,b));
6379566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b,x));
63816d9e3a6SLisandro Dalcin 
639792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject,hjac->ij,(void**)&hmat);
640792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject,hjac->b->ij,(void**)&jbv);
641792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject,hjac->x->ij,(void**)&jxv);
64216d9e3a6SLisandro Dalcin 
643e77caa6dSBarry Smith   PetscStackCallExternalVoid("Hypre Transpose solve",do {
6445f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jbv,jxv);
6455f80ce2aSJacob Faibussowitsch       if (hierr) {
64616d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6475f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",(int)hierr);
6485f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
6495f80ce2aSJacob Faibussowitsch       }
6505f80ce2aSJacob Faibussowitsch     } while (0));
65116d9e3a6SLisandro Dalcin 
6529566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6539566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
65416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
65516d9e3a6SLisandro Dalcin }
65616d9e3a6SLisandro Dalcin 
657db6f9c32SMark Adams static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc,const char name[])
658db6f9c32SMark Adams {
659db6f9c32SMark Adams   PC_HYPRE *jac  = (PC_HYPRE*)pc->data;
660db6f9c32SMark Adams   PetscBool      flag;
661db6f9c32SMark Adams 
662db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2,23,0)
663db6f9c32SMark Adams   PetscFunctionBegin;
664db6f9c32SMark Adams   if (jac->spgemm_type) {
6659566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type,name,&flag));
66628b400f6SJacob Faibussowitsch     PetscCheck(flag,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Cannot reset the HYPRE SpGEMM (really we can)");
667db6f9c32SMark Adams     PetscFunctionReturn(0);
668db6f9c32SMark Adams   } else {
6699566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
670db6f9c32SMark Adams   }
6719566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse",jac->spgemm_type,&flag));
672db6f9c32SMark Adams   if (flag) {
673792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse,1);
674db6f9c32SMark Adams     PetscFunctionReturn(0);
675db6f9c32SMark Adams   }
6769566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre",jac->spgemm_type,&flag));
677db6f9c32SMark Adams   if (flag) {
678792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse,0);
679db6f9c32SMark Adams     PetscFunctionReturn(0);
680db6f9c32SMark Adams   }
681db6f9c32SMark Adams   jac->spgemm_type = NULL;
68298921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE SpGEM type %s; Choices are cusparse, hypre",name);
683db6f9c32SMark Adams #endif
684db6f9c32SMark Adams }
685db6f9c32SMark Adams 
686db6f9c32SMark Adams static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
687db6f9c32SMark Adams {
688db6f9c32SMark Adams   PC_HYPRE *jac  = (PC_HYPRE*)pc->data;
689db6f9c32SMark Adams 
690db6f9c32SMark Adams   PetscFunctionBegin;
691db6f9c32SMark Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
692db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2,23,0)
693db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
694db6f9c32SMark Adams #endif
695db6f9c32SMark Adams   PetscFunctionReturn(0);
696db6f9c32SMark Adams }
697db6f9c32SMark Adams 
69816d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"","V","W"};
6990f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout", "", "PMIS", "", "HMIS"};
70016d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local","global"};
70165de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
7026a251517SEike Mueller static const char *HYPREBoomerAMGSmoothType[]  = {"Schwarz-smoothers","Pilut","ParaSails","Euclid"};
70365de4495SJed Brown static const char *HYPREBoomerAMGRelaxType[]   = {"Jacobi","sequential-Gauss-Seidel","seqboundary-Gauss-Seidel","SOR/Jacobi","backward-SOR/Jacobi",
70465de4495SJed Brown                                                   "" /* [5] hybrid chaotic Gauss-Seidel (works only with OpenMP) */,"symmetric-SOR/Jacobi",
70565de4495SJed Brown                                                   "" /* 7 */,"l1scaled-SOR/Jacobi","Gaussian-elimination",
7067b7fa87dSPierre Jolivet                                                   "" /* 10 */, "" /* 11 */, "" /* 12 */, "l1-Gauss-Seidel" /* nonsymmetric */, "backward-l1-Gauss-Seidel" /* nonsymmetric */,
70765de4495SJed Brown                                                   "CG" /* non-stationary */,"Chebyshev","FCF-Jacobi","l1scaled-Jacobi"};
7080f1074feSSatish Balay static const char *HYPREBoomerAMGInterpType[]  = {"classical", "", "", "direct", "multipass", "multipass-wts", "ext+i",
709589dcaf0SStefano Zampini                                                   "ext+i-cc", "standard", "standard-wts", "block", "block-wtd", "FF", "FF1",
710589dcaf0SStefano Zampini                                                   "ext", "ad-wts", "ext-mm", "ext+i-mm", "ext+e-mm"};
7114416b707SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PetscOptionItems *PetscOptionsObject,PC pc)
71216d9e3a6SLisandro Dalcin {
71316d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
71422e51d31SStefano Zampini   PetscInt       bs,n,indx,level;
715ace3abfcSBarry Smith   PetscBool      flg, tmp_truth;
71616d9e3a6SLisandro Dalcin   double         tmpdbl, twodbl[2];
717589dcaf0SStefano Zampini   const char     *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
718db6f9c32SMark Adams   const char     *PCHYPRESpgemmTypes[] = {"cusparse","hypre"};
71916d9e3a6SLisandro Dalcin 
72016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
721d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"HYPRE BoomerAMG Options");
7229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType+1,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg));
72316d9e3a6SLisandro Dalcin   if (flg) {
7244336a9eeSBarry Smith     jac->cycletype = indx+1;
725792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType,jac->hsolver,jac->cycletype);
72616d9e3a6SLisandro Dalcin   }
7279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg));
72816d9e3a6SLisandro Dalcin   if (flg) {
72963a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %" PetscInt_FMT " must be at least two",jac->maxlevels);
730792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels,jac->hsolver,jac->maxlevels);
73116d9e3a6SLisandro Dalcin   }
7329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg));
73316d9e3a6SLisandro Dalcin   if (flg) {
73463a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %" PetscInt_FMT " must be at least one",jac->maxiter);
735792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter,jac->hsolver,jac->maxiter);
73616d9e3a6SLisandro Dalcin   }
7379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_tol","Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)","None",jac->tol,&jac->tol,&flg));
73816d9e3a6SLisandro Dalcin   if (flg) {
73908401ef6SPierre Jolivet     PetscCheck(jac->tol >= 0.0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Tolerance %g must be greater than or equal to zero",(double)jac->tol);
740792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol,jac->hsolver,jac->tol);
74116d9e3a6SLisandro Dalcin   }
74222e51d31SStefano Zampini   bs = 1;
74322e51d31SStefano Zampini   if (pc->pmat) {
7449566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat,&bs));
74522e51d31SStefano Zampini   }
7469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions","Number of functions","HYPRE_BoomerAMGSetNumFunctions",bs,&bs,&flg));
74722e51d31SStefano Zampini   if (flg) {
748792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions,jac->hsolver,bs);
74922e51d31SStefano Zampini   }
75016d9e3a6SLisandro Dalcin 
7519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor","Truncation factor for interpolation (0=no truncation)","None",jac->truncfactor,&jac->truncfactor,&flg));
75216d9e3a6SLisandro Dalcin   if (flg) {
75308401ef6SPierre Jolivet     PetscCheck(jac->truncfactor >= 0.0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Truncation factor %g must be great than or equal zero",(double)jac->truncfactor);
754792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor,jac->hsolver,jac->truncfactor);
75516d9e3a6SLisandro Dalcin   }
75616d9e3a6SLisandro Dalcin 
7579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max","Max elements per row for interpolation operator (0=unlimited)","None",jac->pmax,&jac->pmax,&flg));
7580f1074feSSatish Balay   if (flg) {
75963a3b9bcSJacob Faibussowitsch     PetscCheck(jac->pmax >= 0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"P_max %" PetscInt_FMT " must be greater than or equal to zero",jac->pmax);
760792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts,jac->hsolver,jac->pmax);
7610f1074feSSatish Balay   }
7620f1074feSSatish Balay 
7639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRangeInt("-pc_hypre_boomeramg_agg_nl","Number of levels of aggressive coarsening","None",jac->agg_nl,&jac->agg_nl,&flg,0,jac->maxlevels));
764792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels,jac->hsolver,jac->agg_nl);
7650f1074feSSatish Balay 
7669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_agg_num_paths","Number of paths for aggressive coarsening","None",jac->agg_num_paths,&jac->agg_num_paths,&flg));
7670f1074feSSatish Balay   if (flg) {
76863a3b9bcSJacob Faibussowitsch     PetscCheck(jac->agg_num_paths >= 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of paths %" PetscInt_FMT " must be greater than or equal to 1",jac->agg_num_paths);
769792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths,jac->hsolver,jac->agg_num_paths);
7700f1074feSSatish Balay   }
7710f1074feSSatish Balay 
7729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg));
77316d9e3a6SLisandro Dalcin   if (flg) {
77408401ef6SPierre Jolivet     PetscCheck(jac->strongthreshold >= 0.0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Strong threshold %g must be great than or equal zero",(double)jac->strongthreshold);
775792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold,jac->hsolver,jac->strongthreshold);
77616d9e3a6SLisandro Dalcin   }
7779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg));
77816d9e3a6SLisandro Dalcin   if (flg) {
77908401ef6SPierre Jolivet     PetscCheck(jac->maxrowsum >= 0.0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %g must be greater than zero",(double)jac->maxrowsum);
78008401ef6SPierre Jolivet     PetscCheck(jac->maxrowsum <= 1.0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %g must be less than or equal one",(double)jac->maxrowsum);
781792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum,jac->hsolver,jac->maxrowsum);
78216d9e3a6SLisandro Dalcin   }
78316d9e3a6SLisandro Dalcin 
78416d9e3a6SLisandro Dalcin   /* Grid sweeps */
7859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_all","Number of sweeps for the up and down grid levels","None",jac->gridsweeps[0],&indx,&flg));
78616d9e3a6SLisandro Dalcin   if (flg) {
787792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps,jac->hsolver,indx);
78816d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
78916d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
7900f1074feSSatish Balay     jac->gridsweeps[1] = indx;
7910f1074feSSatish Balay     /*defaults coarse to 1 */
7920f1074feSSatish Balay     jac->gridsweeps[2] = 1;
79316d9e3a6SLisandro Dalcin   }
7949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen","Use a nodal based coarsening 1-6","HYPRE_BoomerAMGSetNodal",jac->nodal_coarsening,&jac->nodal_coarsening,&flg));
7955272c319SBarry Smith   if (flg) {
796792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNodal,jac->hsolver,jac->nodal_coarsening);
7975272c319SBarry Smith   }
7989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen_diag","Diagonal in strength matrix for nodal based coarsening 0-2","HYPRE_BoomerAMGSetNodalDiag",jac->nodal_coarsening_diag,&jac->nodal_coarsening_diag,&flg));
79922e51d31SStefano Zampini   if (flg) {
800792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag,jac->hsolver,jac->nodal_coarsening_diag);
80122e51d31SStefano Zampini   }
8029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_vec_interp_variant","Variant of algorithm 1-3","HYPRE_BoomerAMGSetInterpVecVariant",jac->vec_interp_variant, &jac->vec_interp_variant,&flg));
8035272c319SBarry Smith   if (flg) {
804792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant,jac->hsolver,jac->vec_interp_variant);
8055272c319SBarry Smith   }
8069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_vec_interp_qmax","Max elements per row for each Q","HYPRE_BoomerAMGSetInterpVecQMax",jac->vec_interp_qmax, &jac->vec_interp_qmax,&flg));
80722e51d31SStefano Zampini   if (flg) {
808792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax,jac->hsolver,jac->vec_interp_qmax);
80922e51d31SStefano Zampini   }
8109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_vec_interp_smooth","Whether to smooth the interpolation vectors","HYPRE_BoomerAMGSetSmoothInterpVectors",jac->vec_interp_smooth, &jac->vec_interp_smooth,&flg));
81122e51d31SStefano Zampini   if (flg) {
812792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors,jac->hsolver,jac->vec_interp_smooth);
81322e51d31SStefano Zampini   }
8149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_interp_refine","Preprocess the interpolation matrix through iterative weight refinement","HYPRE_BoomerAMGSetInterpRefine",jac->interp_refine, &jac->interp_refine,&flg));
81522e51d31SStefano Zampini   if (flg) {
816792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine,jac->hsolver,jac->interp_refine);
81722e51d31SStefano Zampini   }
8189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[0], &indx,&flg));
81916d9e3a6SLisandro Dalcin   if (flg) {
820792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps,jac->hsolver,indx, 1);
8210f1074feSSatish Balay     jac->gridsweeps[0] = indx;
82216d9e3a6SLisandro Dalcin   }
8239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg));
82416d9e3a6SLisandro Dalcin   if (flg) {
825792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps,jac->hsolver,indx, 2);
8260f1074feSSatish Balay     jac->gridsweeps[1] = indx;
82716d9e3a6SLisandro Dalcin   }
8289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[2],&indx,&flg));
82916d9e3a6SLisandro Dalcin   if (flg) {
830792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps,jac->hsolver,indx, 3);
8310f1074feSSatish Balay     jac->gridsweeps[2] = indx;
83216d9e3a6SLisandro Dalcin   }
83316d9e3a6SLisandro Dalcin 
8346a251517SEike Mueller   /* Smooth type */
835dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type","Enable more complex smoothers","None",HYPREBoomerAMGSmoothType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType),HYPREBoomerAMGSmoothType[0],&indx,&flg));
8366a251517SEike Mueller   if (flg) {
8376a251517SEike Mueller     jac->smoothtype = indx;
838792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType,jac->hsolver,indx+6);
8398131ecf7SEike Mueller     jac->smoothnumlevels = 25;
840792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels,jac->hsolver,25);
8418131ecf7SEike Mueller   }
8428131ecf7SEike Mueller 
8438131ecf7SEike Mueller   /* Number of smoothing levels */
8449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels","Number of levels on which more complex smoothers are used","None",25,&indx,&flg));
8458131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8468131ecf7SEike Mueller     jac->smoothnumlevels = indx;
847792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels,jac->hsolver,indx);
8486a251517SEike Mueller   }
8496a251517SEike Mueller 
8501810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level","Number of levels for ILU(k) in Euclid smoother","None",0,&indx,&flg));
8521810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8531810e44eSEike Mueller     jac->eu_level = indx;
854792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel,jac->hsolver,indx);
8551810e44eSEike Mueller   }
8561810e44eSEike Mueller 
8571810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8581810e44eSEike Mueller   double droptolerance;
8599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance","Drop tolerance for ILU(k) in Euclid smoother","None",0,&droptolerance,&flg));
8601810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8611810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
862792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel,jac->hsolver,droptolerance);
8631810e44eSEike Mueller   }
8641810e44eSEike Mueller 
8651810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8671810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8681810e44eSEike Mueller     jac->eu_bj = tmp_truth;
869792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ,jac->hsolver,jac->eu_bj);
8701810e44eSEike Mueller   }
8711810e44eSEike Mueller 
87216d9e3a6SLisandro Dalcin   /* Relax type */
873dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all","Relax type for the up and down cycles","None",HYPREBoomerAMGRelaxType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg));
87416d9e3a6SLisandro Dalcin   if (flg) {
8750f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1]  = indx;
876792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType,jac->hsolver, indx);
8770f1074feSSatish Balay     /* by default, coarse type set to 9 */
8780f1074feSSatish Balay     jac->relaxtype[2] = 9;
879792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType,jac->hsolver, 9, 3);
88016d9e3a6SLisandro Dalcin   }
881dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg));
88216d9e3a6SLisandro Dalcin   if (flg) {
88316d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
884792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType,jac->hsolver, indx, 1);
88516d9e3a6SLisandro Dalcin   }
886dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg));
88716d9e3a6SLisandro Dalcin   if (flg) {
8880f1074feSSatish Balay     jac->relaxtype[1] = indx;
889792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType,jac->hsolver, indx, 2);
89016d9e3a6SLisandro Dalcin   }
891dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[9],&indx,&flg));
89216d9e3a6SLisandro Dalcin   if (flg) {
8930f1074feSSatish Balay     jac->relaxtype[2] = indx;
894792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType,jac->hsolver, indx, 3);
89516d9e3a6SLisandro Dalcin   }
89616d9e3a6SLisandro Dalcin 
89716d9e3a6SLisandro Dalcin   /* Relaxation Weight */
8989566063dSJacob Faibussowitsch   PetscCall(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));
89916d9e3a6SLisandro Dalcin   if (flg) {
900792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt,jac->hsolver,tmpdbl);
90116d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
90216d9e3a6SLisandro Dalcin   }
90316d9e3a6SLisandro Dalcin 
90416d9e3a6SLisandro Dalcin   n         = 2;
90516d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level","Set the relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg));
90716d9e3a6SLisandro Dalcin   if (flg) {
90816d9e3a6SLisandro Dalcin     if (n == 2) {
90916d9e3a6SLisandro Dalcin       indx =  (int)PetscAbsReal(twodbl[1]);
910792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt,jac->hsolver,twodbl[0],indx);
91163a3b9bcSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT,n);
91216d9e3a6SLisandro Dalcin   }
91316d9e3a6SLisandro Dalcin 
91416d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
9159566063dSJacob Faibussowitsch   PetscCall(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));
91616d9e3a6SLisandro Dalcin   if (flg) {
917792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt,jac->hsolver, tmpdbl);
91816d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
91916d9e3a6SLisandro Dalcin   }
92016d9e3a6SLisandro Dalcin 
92116d9e3a6SLisandro Dalcin   n         = 2;
92216d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_outer_relax_weight_level","Set the outer relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg));
92416d9e3a6SLisandro Dalcin   if (flg) {
92516d9e3a6SLisandro Dalcin     if (n == 2) {
92616d9e3a6SLisandro Dalcin       indx =  (int)PetscAbsReal(twodbl[1]);
927792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt,jac->hsolver, twodbl[0], indx);
92863a3b9bcSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT,n);
92916d9e3a6SLisandro Dalcin   }
93016d9e3a6SLisandro Dalcin 
93116d9e3a6SLisandro Dalcin   /* the Relax Order */
9329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
93316d9e3a6SLisandro Dalcin 
9348afaa268SBarry Smith   if (flg && tmp_truth) {
93516d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
936792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder,jac->hsolver, jac->relaxorder);
93716d9e3a6SLisandro Dalcin   }
938dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType),HYPREBoomerAMGMeasureType[0],&indx,&flg));
93916d9e3a6SLisandro Dalcin   if (flg) {
94016d9e3a6SLisandro Dalcin     jac->measuretype = indx;
941792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType,jac->hsolver,jac->measuretype);
94216d9e3a6SLisandro Dalcin   }
9430f1074feSSatish Balay   /* update list length 3/07 */
944dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType),HYPREBoomerAMGCoarsenType[6],&indx,&flg));
94516d9e3a6SLisandro Dalcin   if (flg) {
94616d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
947792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType,jac->hsolver,jac->coarsentype);
94816d9e3a6SLisandro Dalcin   }
9490f1074feSSatish Balay 
9509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
951589dcaf0SStefano Zampini   if (flg) {
952792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize,jac->hsolver, jac->maxc);
953589dcaf0SStefano Zampini   }
9549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
955589dcaf0SStefano Zampini   if (flg) {
956792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize,jac->hsolver, jac->minc);
957589dcaf0SStefano Zampini   }
958db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2,23,0)
959db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
960dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_mg_galerkin_mat_product_algorithm","Type of SpGEMM to use in hypre (only for now)","PCMGGalerkinSetMatProductAlgorithm",PCHYPRESpgemmTypes,PETSC_STATIC_ARRAY_LENGTH(PCHYPRESpgemmTypes),PCHYPRESpgemmTypes[0],&indx,&flg));
961db6f9c32SMark Adams   if (!flg) indx = 0;
9629566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc,PCHYPRESpgemmTypes[indx]));
963db6f9c32SMark Adams #endif
964589dcaf0SStefano Zampini   /* AIR */
965589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,18,0)
9669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_restriction_type", "Type of AIR method (distance 1 or 2, 0 means no AIR)", "None", jac->Rtype, &jac->Rtype, NULL));
967792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction,jac->hsolver,jac->Rtype);
968589dcaf0SStefano Zampini   if (jac->Rtype) {
969589dcaf0SStefano Zampini     jac->interptype = 100; /* no way we can pass this with strings... Set it as default as in MFEM, then users can still customize it back to a different one */
970589dcaf0SStefano Zampini 
9719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR","Threshold for R","None",jac->Rstrongthreshold,&jac->Rstrongthreshold,NULL));
972792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR,jac->hsolver,jac->Rstrongthreshold);
973589dcaf0SStefano Zampini 
9749566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR","Filter threshold for R","None",jac->Rfilterthreshold,&jac->Rfilterthreshold,NULL));
975792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR,jac->hsolver,jac->Rfilterthreshold);
976589dcaf0SStefano Zampini 
9779566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_Adroptol","Defines the drop tolerance for the A-matrices from the 2nd level of AMG","None",jac->Adroptol,&jac->Adroptol,NULL));
978792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol,jac->hsolver,jac->Adroptol);
979589dcaf0SStefano Zampini 
9809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_Adroptype","Drops the entries that are not on the diagonal and smaller than its row norm: type 1: 1-norm, 2: 2-norm, -1: infinity norm","None",jac->Adroptype,&jac->Adroptype,NULL));
981792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType,jac->hsolver,jac->Adroptype);
982589dcaf0SStefano Zampini   }
983589dcaf0SStefano Zampini #endif
984589dcaf0SStefano Zampini 
985ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9,9,9)
98663a3b9bcSJacob Faibussowitsch   PetscCheck(!jac->Rtype || !jac->agg_nl,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"-pc_hypre_boomeramg_restriction_type (%" PetscInt_FMT ") and -pc_hypre_boomeramg_agg_nl (%" PetscInt_FMT ")",jac->Rtype,jac->agg_nl);
987ecae95adSPierre Jolivet #endif
988ecae95adSPierre Jolivet 
9890f1074feSSatish Balay   /* new 3/07 */
990dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type","Interpolation type","None",HYPREBoomerAMGInterpType,PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType),HYPREBoomerAMGInterpType[0],&indx,&flg));
991589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
992589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
993792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType,jac->hsolver,jac->interptype);
9940f1074feSSatish Balay   }
9950f1074feSSatish Balay 
9969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg));
99716d9e3a6SLisandro Dalcin   if (flg) {
998b96a4a96SBarry Smith     level = 3;
9999566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,NULL));
10002fa5cd67SKarl Rupp 
1001b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1002792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel,jac->hsolver,level);
10032ae77aedSBarry Smith   }
10042ae77aedSBarry Smith 
10059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug","Print debug information","None",&flg));
10062ae77aedSBarry Smith   if (flg) {
1007b96a4a96SBarry Smith     level = 3;
10089566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug","Print debug information","None",level,&level,NULL));
10092fa5cd67SKarl Rupp 
1010b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1011792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag,jac->hsolver,level);
101216d9e3a6SLisandro Dalcin   }
10138f87f92bSBarry Smith 
10149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
10158f87f92bSBarry Smith   if (flg && tmp_truth) {
10168f87f92bSBarry Smith     PetscInt tmp_int;
10179566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None",jac->nodal_relax_levels,&tmp_int,&flg));
10188f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1019792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType,jac->hsolver,6);
1020792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType,jac->hsolver,1);
1021792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap,jac->hsolver,0);
1022792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels,jac->hsolver,jac->nodal_relax_levels);
10238f87f92bSBarry Smith   }
10248f87f92bSBarry Smith 
10259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1026792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose,jac->hsolver,jac->keeptranspose ? 1 : 0);
1027589dcaf0SStefano Zampini 
1028589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1029dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,PETSC_STATIC_ARRAY_LENGTH(symtlist),symtlist[0],&indx,&flg));
1030589dcaf0SStefano Zampini   if (flg) {
1031589dcaf0SStefano Zampini     jac->symt = indx;
1032792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym,jac->hsolver,jac->symt);
1033589dcaf0SStefano Zampini   }
1034589dcaf0SStefano Zampini 
1035d0609cedSBarry Smith   PetscOptionsHeadEnd();
103616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
103716d9e3a6SLisandro Dalcin }
103816d9e3a6SLisandro Dalcin 
1039ace3abfcSBarry Smith static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
104016d9e3a6SLisandro Dalcin {
104116d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
10422cf14000SStefano Zampini   HYPRE_Int      oits;
104316d9e3a6SLisandro Dalcin 
104416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10459566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
1046792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter,jac->hsolver,its*jac->maxiter);
1047792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol,jac->hsolver,rtol);
104816d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
10499566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc,b,y));
105016d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1051792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations,jac->hsolver,&oits);
10524d0a8057SBarry Smith   *outits = oits;
10534d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10544d0a8057SBarry Smith   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
1055792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol,jac->hsolver,jac->tol);
1056792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter,jac->hsolver,jac->maxiter);
105716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
105816d9e3a6SLisandro Dalcin }
105916d9e3a6SLisandro Dalcin 
106016d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
106116d9e3a6SLisandro Dalcin {
106216d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1063ace3abfcSBarry Smith   PetscBool      iascii;
106416d9e3a6SLisandro Dalcin 
106516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
106716d9e3a6SLisandro Dalcin   if (iascii) {
10689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG preconditioning\n"));
10699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]));
107063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Maximum number of levels %" PetscInt_FMT "\n",jac->maxlevels));
107163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n",jac->maxiter));
10729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Convergence tolerance PER hypre call %g\n",(double)jac->tol));
10739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Threshold for strong coupling %g\n",(double)jac->strongthreshold));
10749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Interpolation truncation factor %g\n",(double)jac->truncfactor));
107563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Interpolation: max elements per row %" PetscInt_FMT "\n",jac->pmax));
107622e51d31SStefano Zampini     if (jac->interp_refine) {
107763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n",jac->interp_refine));
107822e51d31SStefano Zampini     }
107963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Number of levels of aggressive coarsening %" PetscInt_FMT "\n",jac->agg_nl));
108063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Number of paths for aggressive coarsening %" PetscInt_FMT "\n",jac->agg_num_paths));
10810f1074feSSatish Balay 
10829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Maximum row sums %g\n",(double)jac->maxrowsum));
108316d9e3a6SLisandro Dalcin 
108463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Sweeps down         %" PetscInt_FMT "\n",jac->gridsweeps[0]));
108563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Sweeps up           %" PetscInt_FMT "\n",jac->gridsweeps[1]));
108663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Sweeps on coarse    %" PetscInt_FMT "\n",jac->gridsweeps[2]));
108716d9e3a6SLisandro Dalcin 
10889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Relax down          %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
10899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Relax up            %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
10909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Relax on coarse     %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
109116d9e3a6SLisandro Dalcin 
10929566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Relax weight  (all)      %g\n",(double)jac->relaxweight));
10939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Outer relax weight (all) %g\n",(double)jac->outerrelaxweight));
109416d9e3a6SLisandro Dalcin 
109516d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
10969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using CF-relaxation\n"));
109716d9e3a6SLisandro Dalcin     } else {
10989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Not using CF-relaxation\n"));
109916d9e3a6SLisandro Dalcin     }
11006a251517SEike Mueller     if (jac->smoothtype!=-1) {
11019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Smooth type          %s\n",HYPREBoomerAMGSmoothType[jac->smoothtype]));
110263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Smooth num levels    %" PetscInt_FMT "\n",jac->smoothnumlevels));
11037e352d70SEike Mueller     } else {
11049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Not using more complex smoothers.\n"));
11051810e44eSEike Mueller     }
11061810e44eSEike Mueller     if (jac->smoothtype==3) {
110763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Euclid ILU(k) levels %" PetscInt_FMT "\n",jac->eu_level));
11089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Euclid ILU(k) drop tolerance %g\n",(double)jac->eu_droptolerance));
110963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n",jac->eu_bj));
11106a251517SEike Mueller     }
11119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Measure type        %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]));
11129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Coarsen type        %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]));
11139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    Interpolation type  %s\n",jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
11145272c319SBarry Smith     if (jac->nodal_coarsening) {
111563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n",jac->nodal_coarsening));
11165272c319SBarry Smith     }
11175272c319SBarry Smith     if (jac->vec_interp_variant) {
111863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n",jac->vec_interp_variant));
111963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n",jac->vec_interp_qmax));
11209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n",jac->vec_interp_smooth));
11218f87f92bSBarry Smith     }
11228f87f92bSBarry Smith     if (jac->nodal_relax) {
112363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n",jac->nodal_relax_levels));
11248f87f92bSBarry Smith     }
1125db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2,23,0)
11269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    SpGEMM type         %s\n",jac->spgemm_type));
1127db6f9c32SMark Adams #endif
1128589dcaf0SStefano Zampini     /* AIR */
1129589dcaf0SStefano Zampini     if (jac->Rtype) {
113063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using approximate ideal restriction type %" PetscInt_FMT "\n",jac->Rtype));
11319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"      Threshold for R %g\n",(double)jac->Rstrongthreshold));
11329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"      Filter for R %g\n",(double)jac->Rfilterthreshold));
11339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"      A drop tolerance %g\n",(double)jac->Adroptol));
113463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"      A drop type %" PetscInt_FMT "\n",jac->Adroptype));
1135589dcaf0SStefano Zampini     }
113616d9e3a6SLisandro Dalcin   }
113716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
113816d9e3a6SLisandro Dalcin }
113916d9e3a6SLisandro Dalcin 
114016d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
11414416b707SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PetscOptionItems *PetscOptionsObject,PC pc)
114216d9e3a6SLisandro Dalcin {
114316d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
11444ddd07fcSJed Brown   PetscInt       indx;
1145ace3abfcSBarry Smith   PetscBool      flag;
114616d9e3a6SLisandro Dalcin   const char     *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
114716d9e3a6SLisandro Dalcin 
114816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1149d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"HYPRE ParaSails Options");
11509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0));
11519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshold,&jac->threshold,&flag));
1152792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams,jac->hsolver,jac->threshold,jac->nlevels);
115316d9e3a6SLisandro Dalcin 
11549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag));
1155792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter,jac->hsolver,jac->filter);
115616d9e3a6SLisandro Dalcin 
11579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag));
1158792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal,jac->hsolver,jac->loadbal);
115916d9e3a6SLisandro Dalcin 
11609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging","Print info to screen","None",(PetscBool)jac->logging,(PetscBool*)&jac->logging,&flag));
1161792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging,jac->hsolver,jac->logging);
116216d9e3a6SLisandro Dalcin 
11639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscBool)jac->ruse,(PetscBool*)&jac->ruse,&flag));
1164792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse,jac->hsolver,jac->ruse);
116516d9e3a6SLisandro Dalcin 
1166dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,PETSC_STATIC_ARRAY_LENGTH(symtlist),symtlist[0],&indx,&flag));
116716d9e3a6SLisandro Dalcin   if (flag) {
116816d9e3a6SLisandro Dalcin     jac->symt = indx;
1169792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym,jac->hsolver,jac->symt);
117016d9e3a6SLisandro Dalcin   }
117116d9e3a6SLisandro Dalcin 
1172d0609cedSBarry Smith   PetscOptionsHeadEnd();
117316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
117416d9e3a6SLisandro Dalcin }
117516d9e3a6SLisandro Dalcin 
117616d9e3a6SLisandro Dalcin static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
117716d9e3a6SLisandro Dalcin {
117816d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1179ace3abfcSBarry Smith   PetscBool      iascii;
1180feb237baSPierre Jolivet   const char     *symt = 0;
118116d9e3a6SLisandro Dalcin 
118216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
118416d9e3a6SLisandro Dalcin   if (iascii) {
11859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails preconditioning\n"));
118663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    nlevels %" PetscInt_FMT "\n",jac->nlevels));
11879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    threshold %g\n",(double)jac->threshold));
11889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    filter %g\n",(double)jac->filter));
11899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    load balance %g\n",(double)jac->loadbal));
11909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    reuse nonzero structure %s\n",PetscBools[jac->ruse]));
11919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    print info to screen %s\n",PetscBools[jac->logging]));
11922fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
11932fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
11942fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
119563a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT,jac->symt);
11969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    %s\n",symt));
119716d9e3a6SLisandro Dalcin   }
119816d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
119916d9e3a6SLisandro Dalcin }
12004cb006feSStefano Zampini /* --------------------------------------------------------------------------------------------*/
12014416b707SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PetscOptionItems *PetscOptionsObject,PC pc)
12024cb006feSStefano Zampini {
12034cb006feSStefano Zampini   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
12044cb006feSStefano Zampini   PetscInt       n;
12054cb006feSStefano Zampini   PetscBool      flag,flag2,flag3,flag4;
12064cb006feSStefano Zampini 
12074cb006feSStefano Zampini   PetscFunctionBegin;
1208d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"HYPRE AMS Options");
12099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level","Debugging output level for AMS","None",jac->as_print,&jac->as_print,&flag));
1210792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel,jac->hsolver,jac->as_print);
12119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_max_iter","Maximum number of AMS multigrid iterations within PCApply","None",jac->as_max_iter,&jac->as_max_iter,&flag));
1212792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter,jac->hsolver,jac->as_max_iter);
12139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type","Cycle type for AMS multigrid","None",jac->ams_cycle_type,&jac->ams_cycle_type,&flag));
1214792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType,jac->hsolver,jac->ams_cycle_type);
12159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol","Error tolerance for AMS multigrid","None",jac->as_tol,&jac->as_tol,&flag));
1216792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol,jac->hsolver,jac->as_tol);
12179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type","Relaxation type for AMS smoother","None",jac->as_relax_type,&jac->as_relax_type,&flag));
12189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_times","Number of relaxation steps for AMS smoother","None",jac->as_relax_times,&jac->as_relax_times,&flag2));
12199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight","Relaxation weight for AMS smoother","None",jac->as_relax_weight,&jac->as_relax_weight,&flag3));
12209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega","SSOR coefficient for AMS smoother","None",jac->as_omega,&jac->as_omega,&flag4));
12214cb006feSStefano Zampini   if (flag || flag2 || flag3 || flag4) {
1222792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetSmoothingOptions,jac->hsolver,jac->as_relax_type,
1223863406b8SStefano Zampini                                                                       jac->as_relax_times,
1224863406b8SStefano Zampini                                                                       jac->as_relax_weight,
1225a74df02fSJacob Faibussowitsch                                                                       jac->as_omega);
12264cb006feSStefano Zampini   }
12279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_amg_alpha_theta","Threshold for strong coupling of vector Poisson AMG solver","None",jac->as_amg_alpha_theta,&jac->as_amg_alpha_theta,&flag));
12284cb006feSStefano Zampini   n = 5;
12299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options","AMG options for vector Poisson","None",jac->as_amg_alpha_opts,&n,&flag2));
12304cb006feSStefano Zampini   if (flag || flag2) {
1231792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions,jac->hsolver,jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
1232863406b8SStefano Zampini                                                                      jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
1233863406b8SStefano Zampini                                                                      jac->as_amg_alpha_opts[2],       /* AMG relax_type */
1234863406b8SStefano Zampini                                                                      jac->as_amg_alpha_theta,
1235863406b8SStefano Zampini                                                                      jac->as_amg_alpha_opts[3],       /* AMG interp_type */
1236a74df02fSJacob Faibussowitsch                                                                      jac->as_amg_alpha_opts[4]);     /* AMG Pmax */
12374cb006feSStefano Zampini   }
12389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_amg_beta_theta","Threshold for strong coupling of scalar Poisson AMG solver","None",jac->as_amg_beta_theta,&jac->as_amg_beta_theta,&flag));
12394cb006feSStefano Zampini   n = 5;
12409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options","AMG options for scalar Poisson solver","None",jac->as_amg_beta_opts,&n,&flag2));
12414cb006feSStefano Zampini   if (flag || flag2) {
1242792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions,jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
1243863406b8SStefano Zampini                                                                     jac->as_amg_beta_opts[1],       /* AMG agg_levels */
1244863406b8SStefano Zampini                                                                     jac->as_amg_beta_opts[2],       /* AMG relax_type */
1245863406b8SStefano Zampini                                                                     jac->as_amg_beta_theta,
1246863406b8SStefano Zampini                                                                     jac->as_amg_beta_opts[3],       /* AMG interp_type */
1247a74df02fSJacob Faibussowitsch                                                                     jac->as_amg_beta_opts[4]);     /* AMG Pmax */
12484cb006feSStefano Zampini   }
12499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_projection_frequency","Frequency at which a projection onto the compatible subspace for problems with zero conductivity regions is performed","None",jac->ams_proj_freq,&jac->ams_proj_freq,&flag));
125023df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1251792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency,jac->hsolver,jac->ams_proj_freq);
125223df4f25SStefano Zampini   }
1253d0609cedSBarry Smith   PetscOptionsHeadEnd();
12544cb006feSStefano Zampini   PetscFunctionReturn(0);
12554cb006feSStefano Zampini }
12564cb006feSStefano Zampini 
12574cb006feSStefano Zampini static PetscErrorCode PCView_HYPRE_AMS(PC pc,PetscViewer viewer)
12584cb006feSStefano Zampini {
12594cb006feSStefano Zampini   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
12604cb006feSStefano Zampini   PetscBool      iascii;
12614cb006feSStefano Zampini 
12624cb006feSStefano Zampini   PetscFunctionBegin;
12639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
12644cb006feSStefano Zampini   if (iascii) {
12659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE AMS preconditioning\n"));
126663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    subspace iterations per application %" PetscInt_FMT "\n",jac->as_max_iter));
126763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    subspace cycle type %" PetscInt_FMT "\n",jac->ams_cycle_type));
126863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    subspace iteration tolerance %g\n",(double)jac->as_tol));
126963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    smoother type %" PetscInt_FMT "\n",jac->as_relax_type));
127063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    number of smoothing steps %" PetscInt_FMT "\n",jac->as_relax_times));
127163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    smoother weight %g\n",(double)jac->as_relax_weight));
127263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    smoother omega %g\n",(double)jac->as_omega));
12734cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    vector Poisson solver (passed in by user)\n"));
12754cb006feSStefano Zampini     } else {
12769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    vector Poisson solver (computed) \n"));
12774cb006feSStefano Zampini     }
127863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG coarsening type %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[0]));
127963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[1]));
128063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG relaxation type %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[2]));
128163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG interpolation type %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[3]));
128263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[4]));
128363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG strength threshold %g\n",(double)jac->as_amg_alpha_theta));
12844cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12854cb006feSStefano Zampini       if (jac->beta_Poisson) {
12869566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"    scalar Poisson solver (passed in by user)\n"));
12874cb006feSStefano Zampini       } else {
12889566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"    scalar Poisson solver (computed) \n"));
12894cb006feSStefano Zampini       }
129063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG coarsening type %" PetscInt_FMT "\n",jac->as_amg_beta_opts[0]));
129163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n",jac->as_amg_beta_opts[1]));
129263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG relaxation type %" PetscInt_FMT "\n",jac->as_amg_beta_opts[2]));
129363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG interpolation type %" PetscInt_FMT "\n",jac->as_amg_beta_opts[3]));
129463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n",jac->as_amg_beta_opts[4]));
129563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"        boomerAMG strength threshold %g\n",(double)jac->as_amg_beta_theta));
129623df4f25SStefano Zampini       if (jac->ams_beta_is_zero_part) {
129763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"        compatible subspace projection frequency %" PetscInt_FMT " (-1 HYPRE uses default)\n",jac->ams_proj_freq));
129823df4f25SStefano Zampini       }
129923df4f25SStefano Zampini     } else {
13009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
13014cb006feSStefano Zampini     }
13024cb006feSStefano Zampini   }
13034cb006feSStefano Zampini   PetscFunctionReturn(0);
13044cb006feSStefano Zampini }
13054cb006feSStefano Zampini 
13064416b707SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PetscOptionItems *PetscOptionsObject,PC pc)
1307863406b8SStefano Zampini {
1308863406b8SStefano Zampini   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1309863406b8SStefano Zampini   PetscInt       n;
1310863406b8SStefano Zampini   PetscBool      flag,flag2,flag3,flag4;
1311863406b8SStefano Zampini 
1312863406b8SStefano Zampini   PetscFunctionBegin;
1313d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"HYPRE ADS Options");
13149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level","Debugging output level for ADS","None",jac->as_print,&jac->as_print,&flag));
1315792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel,jac->hsolver,jac->as_print);
13169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_max_iter","Maximum number of ADS multigrid iterations within PCApply","None",jac->as_max_iter,&jac->as_max_iter,&flag));
1317792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter,jac->hsolver,jac->as_max_iter);
13189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type","Cycle type for ADS multigrid","None",jac->ads_cycle_type,&jac->ads_cycle_type,&flag));
1319792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType,jac->hsolver,jac->ads_cycle_type);
13209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol","Error tolerance for ADS multigrid","None",jac->as_tol,&jac->as_tol,&flag));
1321792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol,jac->hsolver,jac->as_tol);
13229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type","Relaxation type for ADS smoother","None",jac->as_relax_type,&jac->as_relax_type,&flag));
13239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_times","Number of relaxation steps for ADS smoother","None",jac->as_relax_times,&jac->as_relax_times,&flag2));
13249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight","Relaxation weight for ADS smoother","None",jac->as_relax_weight,&jac->as_relax_weight,&flag3));
13259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega","SSOR coefficient for ADS smoother","None",jac->as_omega,&jac->as_omega,&flag4));
1326863406b8SStefano Zampini   if (flag || flag2 || flag3 || flag4) {
1327792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetSmoothingOptions,jac->hsolver,jac->as_relax_type,
1328863406b8SStefano Zampini                                                                       jac->as_relax_times,
1329863406b8SStefano Zampini                                                                       jac->as_relax_weight,
1330a74df02fSJacob Faibussowitsch                                                                       jac->as_omega);
1331863406b8SStefano Zampini   }
13329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_ams_theta","Threshold for strong coupling of AMS solver inside ADS","None",jac->as_amg_alpha_theta,&jac->as_amg_alpha_theta,&flag));
1333863406b8SStefano Zampini   n = 5;
13349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options","AMG options for AMS solver inside ADS","None",jac->as_amg_alpha_opts,&n,&flag2));
13359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_ams_cycle_type","Cycle type for AMS solver inside ADS","None",jac->ams_cycle_type,&jac->ams_cycle_type,&flag3));
1336863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1337792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions,jac->hsolver,jac->ams_cycle_type,             /* AMS cycle type */
1338863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
1339863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
1340863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[2],       /* AMG relax_type */
1341863406b8SStefano Zampini                                                                 jac->as_amg_alpha_theta,
1342863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[3],       /* AMG interp_type */
1343a74df02fSJacob Faibussowitsch                                                                 jac->as_amg_alpha_opts[4]);     /* AMG Pmax */
1344863406b8SStefano Zampini   }
13459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_amg_theta","Threshold for strong coupling of vector AMG solver inside ADS","None",jac->as_amg_beta_theta,&jac->as_amg_beta_theta,&flag));
1346863406b8SStefano Zampini   n = 5;
13479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options","AMG options for vector AMG solver inside ADS","None",jac->as_amg_beta_opts,&n,&flag2));
1348863406b8SStefano Zampini   if (flag || flag2) {
1349792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions,jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
1350863406b8SStefano Zampini                                                                 jac->as_amg_beta_opts[1],       /* AMG agg_levels */
1351863406b8SStefano Zampini                                                                 jac->as_amg_beta_opts[2],       /* AMG relax_type */
1352863406b8SStefano Zampini                                                                 jac->as_amg_beta_theta,
1353863406b8SStefano Zampini                                                                 jac->as_amg_beta_opts[3],       /* AMG interp_type */
1354a74df02fSJacob Faibussowitsch                                                                 jac->as_amg_beta_opts[4]);     /* AMG Pmax */
1355863406b8SStefano Zampini   }
1356d0609cedSBarry Smith   PetscOptionsHeadEnd();
1357863406b8SStefano Zampini   PetscFunctionReturn(0);
1358863406b8SStefano Zampini }
1359863406b8SStefano Zampini 
1360863406b8SStefano Zampini static PetscErrorCode PCView_HYPRE_ADS(PC pc,PetscViewer viewer)
1361863406b8SStefano Zampini {
1362863406b8SStefano Zampini   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1363863406b8SStefano Zampini   PetscBool      iascii;
1364863406b8SStefano Zampini 
1365863406b8SStefano Zampini   PetscFunctionBegin;
13669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
1367863406b8SStefano Zampini   if (iascii) {
13689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE ADS preconditioning\n"));
136963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    subspace iterations per application %" PetscInt_FMT "\n",jac->as_max_iter));
137063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    subspace cycle type %" PetscInt_FMT "\n",jac->ads_cycle_type));
137163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    subspace iteration tolerance %g\n",(double)jac->as_tol));
137263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    smoother type %" PetscInt_FMT "\n",jac->as_relax_type));
137363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    number of smoothing steps %" PetscInt_FMT "\n",jac->as_relax_times));
137463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    smoother weight %g\n",(double)jac->as_relax_weight));
137563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    smoother omega %g\n",(double)jac->as_omega));
13769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    AMS solver using boomerAMG\n"));
137763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        subspace cycle type %" PetscInt_FMT "\n",jac->ams_cycle_type));
137863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        coarsening type %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[0]));
137963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        levels of aggressive coarsening %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[1]));
138063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        relaxation type %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[2]));
138163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        interpolation type %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[3]));
138263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        max nonzero elements in interpolation rows %" PetscInt_FMT "\n",jac->as_amg_alpha_opts[4]));
138363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        strength threshold %g\n",(double)jac->as_amg_alpha_theta));
13849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    vector Poisson solver using boomerAMG\n"));
138563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        coarsening type %" PetscInt_FMT "\n",jac->as_amg_beta_opts[0]));
138663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        levels of aggressive coarsening %" PetscInt_FMT "\n",jac->as_amg_beta_opts[1]));
138763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        relaxation type %" PetscInt_FMT "\n",jac->as_amg_beta_opts[2]));
138863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        interpolation type %" PetscInt_FMT "\n",jac->as_amg_beta_opts[3]));
138963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        max nonzero elements in interpolation rows %" PetscInt_FMT "\n",jac->as_amg_beta_opts[4]));
139063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"        strength threshold %g\n",(double)jac->as_amg_beta_theta));
1391863406b8SStefano Zampini   }
1392863406b8SStefano Zampini   PetscFunctionReturn(0);
1393863406b8SStefano Zampini }
1394863406b8SStefano Zampini 
1395863406b8SStefano Zampini static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
13964cb006feSStefano Zampini {
13974cb006feSStefano Zampini   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
13985ac14e1cSStefano Zampini   PetscBool      ishypre;
13994cb006feSStefano Zampini 
14004cb006feSStefano Zampini   PetscFunctionBegin;
14019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G,MATHYPRE,&ishypre));
14025ac14e1cSStefano Zampini   if (ishypre) {
14039566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
14049566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14055ac14e1cSStefano Zampini     jac->G = G;
14065ac14e1cSStefano Zampini   } else {
14079566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14089566063dSJacob Faibussowitsch     PetscCall(MatConvert(G,MATHYPRE,MAT_INITIAL_MATRIX,&jac->G));
14095ac14e1cSStefano Zampini   }
14104cb006feSStefano Zampini   PetscFunctionReturn(0);
14114cb006feSStefano Zampini }
14124cb006feSStefano Zampini 
14134cb006feSStefano Zampini /*@
14144cb006feSStefano Zampini  PCHYPRESetDiscreteGradient - Set discrete gradient matrix
14154cb006feSStefano Zampini 
14164cb006feSStefano Zampini    Collective on PC
14174cb006feSStefano Zampini 
14184cb006feSStefano Zampini    Input Parameters:
14194cb006feSStefano Zampini +  pc - the preconditioning context
14204cb006feSStefano Zampini -  G - the discrete gradient
14214cb006feSStefano Zampini 
14224cb006feSStefano Zampini    Level: intermediate
14234cb006feSStefano Zampini 
142495452b02SPatrick Sanan    Notes:
142595452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1426147403d9SBarry Smith 
1427863406b8SStefano Zampini     Each row of G has 2 nonzeros, with column indexes being the global indexes of edge's endpoints: matrix entries are +1 and -1 depending on edge orientation
14284cb006feSStefano Zampini 
1429db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteCurl()`
14304cb006feSStefano Zampini @*/
14314cb006feSStefano Zampini PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
14324cb006feSStefano Zampini {
14334cb006feSStefano Zampini   PetscFunctionBegin;
14344cb006feSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
14354cb006feSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
14364cb006feSStefano Zampini   PetscCheckSameComm(pc,1,G,2);
1437cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPRESetDiscreteGradient_C",(PC,Mat),(pc,G));
14384cb006feSStefano Zampini   PetscFunctionReturn(0);
14394cb006feSStefano Zampini }
14404cb006feSStefano Zampini 
1441863406b8SStefano Zampini static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1442863406b8SStefano Zampini {
1443863406b8SStefano Zampini   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
14445ac14e1cSStefano Zampini   PetscBool      ishypre;
1445863406b8SStefano Zampini 
1446863406b8SStefano Zampini   PetscFunctionBegin;
14479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C,MATHYPRE,&ishypre));
14485ac14e1cSStefano Zampini   if (ishypre) {
14499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
14509566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14515ac14e1cSStefano Zampini     jac->C = C;
14525ac14e1cSStefano Zampini   } else {
14539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14549566063dSJacob Faibussowitsch     PetscCall(MatConvert(C,MATHYPRE,MAT_INITIAL_MATRIX,&jac->C));
14555ac14e1cSStefano Zampini   }
1456863406b8SStefano Zampini   PetscFunctionReturn(0);
1457863406b8SStefano Zampini }
1458863406b8SStefano Zampini 
1459863406b8SStefano Zampini /*@
1460863406b8SStefano Zampini  PCHYPRESetDiscreteCurl - Set discrete curl matrix
1461863406b8SStefano Zampini 
1462863406b8SStefano Zampini    Collective on PC
1463863406b8SStefano Zampini 
1464863406b8SStefano Zampini    Input Parameters:
1465863406b8SStefano Zampini +  pc - the preconditioning context
1466863406b8SStefano Zampini -  C - the discrete curl
1467863406b8SStefano Zampini 
1468863406b8SStefano Zampini    Level: intermediate
1469863406b8SStefano Zampini 
147095452b02SPatrick Sanan    Notes:
147195452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1472147403d9SBarry Smith 
1473863406b8SStefano Zampini     Each row of G has as many nonzeros as the number of edges of a face, with column indexes being the global indexes of the corresponding edge: matrix entries are +1 and -1 depending on edge orientation with respect to the face orientation
1474863406b8SStefano Zampini 
1475db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteGradient()`
1476863406b8SStefano Zampini @*/
1477863406b8SStefano Zampini PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1478863406b8SStefano Zampini {
1479863406b8SStefano Zampini   PetscFunctionBegin;
1480863406b8SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1481863406b8SStefano Zampini   PetscValidHeaderSpecific(C,MAT_CLASSID,2);
1482863406b8SStefano Zampini   PetscCheckSameComm(pc,1,C,2);
1483cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPRESetDiscreteCurl_C",(PC,Mat),(pc,C));
1484863406b8SStefano Zampini   PetscFunctionReturn(0);
1485863406b8SStefano Zampini }
1486863406b8SStefano Zampini 
14876bf688a0SCe Qin static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
14886bf688a0SCe Qin {
14896bf688a0SCe Qin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
14906bf688a0SCe Qin   PetscBool      ishypre;
14916bf688a0SCe Qin   PetscInt       i;
14926bf688a0SCe Qin   PetscFunctionBegin;
14936bf688a0SCe Qin 
14949566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
14959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
14966bf688a0SCe Qin   for (i=0;i<3;++i) {
14979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
14989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
14996bf688a0SCe Qin   }
15006bf688a0SCe Qin 
15016bf688a0SCe Qin   jac->dim = dim;
15026bf688a0SCe Qin   if (RT_PiFull) {
15039566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull,MATHYPRE,&ishypre));
15046bf688a0SCe Qin     if (ishypre) {
15059566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
15066bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
15076bf688a0SCe Qin     } else {
15089566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull,MATHYPRE,MAT_INITIAL_MATRIX,&jac->RT_PiFull));
15096bf688a0SCe Qin     }
15106bf688a0SCe Qin   }
15116bf688a0SCe Qin   if (RT_Pi) {
15126bf688a0SCe Qin     for (i=0;i<dim;++i) {
15136bf688a0SCe Qin       if (RT_Pi[i]) {
15149566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i],MATHYPRE,&ishypre));
15156bf688a0SCe Qin         if (ishypre) {
15169566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
15176bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
15186bf688a0SCe Qin         } else {
15199566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i],MATHYPRE,MAT_INITIAL_MATRIX,&jac->RT_Pi[i]));
15206bf688a0SCe Qin         }
15216bf688a0SCe Qin       }
15226bf688a0SCe Qin     }
15236bf688a0SCe Qin   }
15246bf688a0SCe Qin   if (ND_PiFull) {
15259566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull,MATHYPRE,&ishypre));
15266bf688a0SCe Qin     if (ishypre) {
15279566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
15286bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
15296bf688a0SCe Qin     } else {
15309566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull,MATHYPRE,MAT_INITIAL_MATRIX,&jac->ND_PiFull));
15316bf688a0SCe Qin     }
15326bf688a0SCe Qin   }
15336bf688a0SCe Qin   if (ND_Pi) {
15346bf688a0SCe Qin     for (i=0;i<dim;++i) {
15356bf688a0SCe Qin       if (ND_Pi[i]) {
15369566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i],MATHYPRE,&ishypre));
15376bf688a0SCe Qin         if (ishypre) {
15389566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
15396bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
15406bf688a0SCe Qin         } else {
15419566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i],MATHYPRE,MAT_INITIAL_MATRIX,&jac->ND_Pi[i]));
15426bf688a0SCe Qin         }
15436bf688a0SCe Qin       }
15446bf688a0SCe Qin     }
15456bf688a0SCe Qin   }
15466bf688a0SCe Qin 
15476bf688a0SCe Qin   PetscFunctionReturn(0);
15486bf688a0SCe Qin }
15496bf688a0SCe Qin 
15506bf688a0SCe Qin /*@
15516bf688a0SCe Qin  PCHYPRESetInterpolations - Set interpolation matrices for AMS/ADS preconditioner
15526bf688a0SCe Qin 
15536bf688a0SCe Qin    Collective on PC
15546bf688a0SCe Qin 
15556bf688a0SCe Qin    Input Parameters:
15566bf688a0SCe Qin +  pc - the preconditioning context
15576bf688a0SCe Qin -  dim - the dimension of the problem, only used in AMS
15586bf688a0SCe Qin -  RT_PiFull - Raviart-Thomas interpolation matrix
15596bf688a0SCe Qin -  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
15606bf688a0SCe Qin -  ND_PiFull - Nedelec interpolation matrix
15616bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
15626bf688a0SCe Qin 
156395452b02SPatrick Sanan    Notes:
156495452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1565147403d9SBarry Smith 
15666bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1567147403d9SBarry Smith 
15686bf688a0SCe Qin    Level: intermediate
15696bf688a0SCe Qin 
15706bf688a0SCe Qin @*/
15716bf688a0SCe Qin PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
15726bf688a0SCe Qin {
15736bf688a0SCe Qin   PetscInt       i;
15746bf688a0SCe Qin 
15756bf688a0SCe Qin   PetscFunctionBegin;
15766bf688a0SCe Qin   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
15776bf688a0SCe Qin   if (RT_PiFull) {
15786bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull,MAT_CLASSID,3);
15796bf688a0SCe Qin     PetscCheckSameComm(pc,1,RT_PiFull,3);
15806bf688a0SCe Qin   }
15816bf688a0SCe Qin   if (RT_Pi) {
15826bf688a0SCe Qin     PetscValidPointer(RT_Pi,4);
15836bf688a0SCe Qin     for (i=0;i<dim;++i) {
15846bf688a0SCe Qin       if (RT_Pi[i]) {
15856bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i],MAT_CLASSID,4);
15866bf688a0SCe Qin         PetscCheckSameComm(pc,1,RT_Pi[i],4);
15876bf688a0SCe Qin       }
15886bf688a0SCe Qin     }
15896bf688a0SCe Qin   }
15906bf688a0SCe Qin   if (ND_PiFull) {
15916bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull,MAT_CLASSID,5);
15926bf688a0SCe Qin     PetscCheckSameComm(pc,1,ND_PiFull,5);
15936bf688a0SCe Qin   }
15946bf688a0SCe Qin   if (ND_Pi) {
15956bf688a0SCe Qin     PetscValidPointer(ND_Pi,6);
15966bf688a0SCe Qin     for (i=0;i<dim;++i) {
15976bf688a0SCe Qin       if (ND_Pi[i]) {
15986bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i],MAT_CLASSID,6);
15996bf688a0SCe Qin         PetscCheckSameComm(pc,1,ND_Pi[i],6);
16006bf688a0SCe Qin       }
16016bf688a0SCe Qin     }
16026bf688a0SCe Qin   }
1603cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPRESetInterpolations_C",(PC,PetscInt,Mat,Mat[],Mat,Mat[]),(pc,dim,RT_PiFull,RT_Pi,ND_PiFull,ND_Pi));
16046bf688a0SCe Qin   PetscFunctionReturn(0);
16056bf688a0SCe Qin }
16066bf688a0SCe Qin 
16075ac14e1cSStefano Zampini static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
16084cb006feSStefano Zampini {
16094cb006feSStefano Zampini   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
16105ac14e1cSStefano Zampini   PetscBool      ishypre;
16114cb006feSStefano Zampini 
16124cb006feSStefano Zampini   PetscFunctionBegin;
16139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre));
16145ac14e1cSStefano Zampini   if (ishypre) {
16155ac14e1cSStefano Zampini     if (isalpha) {
16169566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
16179566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16185ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
16195ac14e1cSStefano Zampini     } else {
16205ac14e1cSStefano Zampini       if (A) {
16219566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
16225ac14e1cSStefano Zampini       } else {
16235ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16245ac14e1cSStefano Zampini       }
16259566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
16265ac14e1cSStefano Zampini       jac->beta_Poisson = A;
16275ac14e1cSStefano Zampini     }
16285ac14e1cSStefano Zampini   } else {
16295ac14e1cSStefano Zampini     if (isalpha) {
16309566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16319566063dSJacob Faibussowitsch       PetscCall(MatConvert(A,MATHYPRE,MAT_INITIAL_MATRIX,&jac->alpha_Poisson));
16325ac14e1cSStefano Zampini     } else {
16335ac14e1cSStefano Zampini       if (A) {
16349566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16359566063dSJacob Faibussowitsch         PetscCall(MatConvert(A,MATHYPRE,MAT_INITIAL_MATRIX,&jac->beta_Poisson));
16365ac14e1cSStefano Zampini       } else {
16379566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16385ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16395ac14e1cSStefano Zampini       }
16405ac14e1cSStefano Zampini     }
16415ac14e1cSStefano Zampini   }
16424cb006feSStefano Zampini   PetscFunctionReturn(0);
16434cb006feSStefano Zampini }
16444cb006feSStefano Zampini 
16454cb006feSStefano Zampini /*@
16464cb006feSStefano Zampini  PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix
16474cb006feSStefano Zampini 
16484cb006feSStefano Zampini    Collective on PC
16494cb006feSStefano Zampini 
16504cb006feSStefano Zampini    Input Parameters:
16514cb006feSStefano Zampini +  pc - the preconditioning context
16524cb006feSStefano Zampini -  A - the matrix
16534cb006feSStefano Zampini 
16544cb006feSStefano Zampini    Level: intermediate
16554cb006feSStefano Zampini 
165695452b02SPatrick Sanan    Notes:
165795452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
16584cb006feSStefano Zampini 
1659db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
16604cb006feSStefano Zampini @*/
16614cb006feSStefano Zampini PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
16624cb006feSStefano Zampini {
16634cb006feSStefano Zampini   PetscFunctionBegin;
16644cb006feSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
16654cb006feSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,2);
16664cb006feSStefano Zampini   PetscCheckSameComm(pc,1,A,2);
1667cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPRESetPoissonMatrix_C",(PC,Mat,PetscBool),(pc,A,PETSC_TRUE));
16684cb006feSStefano Zampini   PetscFunctionReturn(0);
16694cb006feSStefano Zampini }
16704cb006feSStefano Zampini 
16714cb006feSStefano Zampini /*@
16724cb006feSStefano Zampini  PCHYPRESetBetaPoissonMatrix - Set Poisson matrix
16734cb006feSStefano Zampini 
16744cb006feSStefano Zampini    Collective on PC
16754cb006feSStefano Zampini 
16764cb006feSStefano Zampini    Input Parameters:
16774cb006feSStefano Zampini +  pc - the preconditioning context
16784cb006feSStefano Zampini -  A - the matrix
16794cb006feSStefano Zampini 
16804cb006feSStefano Zampini    Level: intermediate
16814cb006feSStefano Zampini 
168295452b02SPatrick Sanan    Notes:
168395452b02SPatrick Sanan     A should be obtained by discretizing the Poisson problem with linear finite elements.
16844cb006feSStefano Zampini           Following HYPRE convention, the scalar Poisson solver of AMS can be turned off by passing NULL.
16854cb006feSStefano Zampini 
1686db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16874cb006feSStefano Zampini @*/
16884cb006feSStefano Zampini PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
16894cb006feSStefano Zampini {
16904cb006feSStefano Zampini   PetscFunctionBegin;
16914cb006feSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
16924cb006feSStefano Zampini   if (A) {
16934cb006feSStefano Zampini     PetscValidHeaderSpecific(A,MAT_CLASSID,2);
16944cb006feSStefano Zampini     PetscCheckSameComm(pc,1,A,2);
16954cb006feSStefano Zampini   }
1696cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPRESetPoissonMatrix_C",(PC,Mat,PetscBool),(pc,A,PETSC_FALSE));
16974cb006feSStefano Zampini   PetscFunctionReturn(0);
16984cb006feSStefano Zampini }
16994cb006feSStefano Zampini 
17005ac14e1cSStefano Zampini static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc,Vec ozz, Vec zoz, Vec zzo)
17014cb006feSStefano Zampini {
17024cb006feSStefano Zampini   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
17034cb006feSStefano Zampini 
17044cb006feSStefano Zampini   PetscFunctionBegin;
17054cb006feSStefano Zampini   /* throw away any vector if already set */
17069566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
17079566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
17089566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
17099566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map,&jac->constants[0]));
17109566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz,jac->constants[0]));
17119566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map,&jac->constants[1]));
17129566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz,jac->constants[1]));
17135ac14e1cSStefano Zampini   jac->dim = 2;
17144cb006feSStefano Zampini   if (zzo) {
17159566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map,&jac->constants[2]));
17169566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo,jac->constants[2]));
17175ac14e1cSStefano Zampini     jac->dim++;
17184cb006feSStefano Zampini   }
17194cb006feSStefano Zampini   PetscFunctionReturn(0);
17204cb006feSStefano Zampini }
17214cb006feSStefano Zampini 
17224cb006feSStefano Zampini /*@
1723147403d9SBarry Smith  PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis
17244cb006feSStefano Zampini 
17254cb006feSStefano Zampini    Collective on PC
17264cb006feSStefano Zampini 
17274cb006feSStefano Zampini    Input Parameters:
17284cb006feSStefano Zampini +  pc - the preconditioning context
17294cb006feSStefano Zampini -  ozz - vector representing (1,0,0) (or (1,0) in 2D)
17304cb006feSStefano Zampini -  zoz - vector representing (0,1,0) (or (0,1) in 2D)
17314cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
17324cb006feSStefano Zampini 
17334cb006feSStefano Zampini    Level: intermediate
17344cb006feSStefano Zampini 
17354cb006feSStefano Zampini @*/
17364cb006feSStefano Zampini PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
17374cb006feSStefano Zampini {
17384cb006feSStefano Zampini   PetscFunctionBegin;
17394cb006feSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
17404cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz,VEC_CLASSID,2);
17414cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz,VEC_CLASSID,3);
17424cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo,VEC_CLASSID,4);
17434cb006feSStefano Zampini   PetscCheckSameComm(pc,1,ozz,2);
17444cb006feSStefano Zampini   PetscCheckSameComm(pc,1,zoz,3);
17454cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc,1,zzo,4);
1746cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPRESetEdgeConstantVectors_C",(PC,Vec,Vec,Vec),(pc,ozz,zoz,zzo));
17474cb006feSStefano Zampini   PetscFunctionReturn(0);
17484cb006feSStefano Zampini }
17494cb006feSStefano Zampini 
1750be14dc20SKerry Key static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc,Vec interior)
1751be14dc20SKerry Key {
1752be14dc20SKerry Key   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
1753be14dc20SKerry Key 
1754be14dc20SKerry Key   PetscFunctionBegin;
1755be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1756be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map,&jac->interior));
1757be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior,jac->interior));
1758be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
1759be14dc20SKerry Key   PetscFunctionReturn(0);
1760be14dc20SKerry Key }
1761be14dc20SKerry Key 
1762be14dc20SKerry Key /*@
1763be14dc20SKerry Key  PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region.
1764be14dc20SKerry Key 
1765be14dc20SKerry Key    Collective on PC
1766be14dc20SKerry Key 
1767be14dc20SKerry Key    Input Parameters:
1768be14dc20SKerry Key +  pc - the preconditioning context
1769be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1770be14dc20SKerry Key 
1771be14dc20SKerry Key    Level: intermediate
1772be14dc20SKerry Key 
1773be14dc20SKerry Key    Note:
1774be14dc20SKerry Key    This calls HYPRE_AMSSetInteriorNodes()
1775be14dc20SKerry Key .seealso:
1776be14dc20SKerry Key @*/
1777be14dc20SKerry Key PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1778be14dc20SKerry Key {
1779be14dc20SKerry Key   PetscFunctionBegin;
1780be14dc20SKerry Key   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1781be14dc20SKerry Key   PetscValidHeaderSpecific(interior,VEC_CLASSID,2);
1782be14dc20SKerry Key   PetscCheckSameComm(pc,1,interior,2);
1783be14dc20SKerry Key   PetscTryMethod(pc,"PCHYPREAMSSetInteriorNodes_C",(PC,Vec),(pc,interior));
1784be14dc20SKerry Key   PetscFunctionReturn(0);
1785be14dc20SKerry Key }
1786be14dc20SKerry Key 
1787863406b8SStefano Zampini static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
17884cb006feSStefano Zampini {
17894cb006feSStefano Zampini   PC_HYPRE        *jac = (PC_HYPRE*)pc->data;
17904cb006feSStefano Zampini   Vec             tv;
17914cb006feSStefano Zampini   PetscInt        i;
17924cb006feSStefano Zampini 
17934cb006feSStefano Zampini   PetscFunctionBegin;
17944cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
17959566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
17969566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
17979566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
17985ac14e1cSStefano Zampini   jac->dim = dim;
17995ac14e1cSStefano Zampini 
18004cb006feSStefano Zampini   /* compute IJ vector for coordinates */
18019566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc),&tv));
18029566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv,VECSTANDARD));
18039566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv,nloc,PETSC_DECIDE));
18044cb006feSStefano Zampini   for (i=0;i<dim;i++) {
18054cb006feSStefano Zampini     PetscScalar *array;
18064cb006feSStefano Zampini     PetscInt    j;
18074cb006feSStefano Zampini 
18089566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map,&jac->coords[i]));
18099566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv,&array));
18106ea7df73SStefano Zampini     for (j=0;j<nloc;j++) array[j] = coords[j*dim+i];
18119566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv,&array));
18129566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv,jac->coords[i]));
18134cb006feSStefano Zampini   }
18149566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
18154cb006feSStefano Zampini   PetscFunctionReturn(0);
18164cb006feSStefano Zampini }
18174cb006feSStefano Zampini 
181816d9e3a6SLisandro Dalcin /* ---------------------------------------------------------------------------------*/
181916d9e3a6SLisandro Dalcin 
1820f7a08781SBarry Smith static PetscErrorCode  PCHYPREGetType_HYPRE(PC pc,const char *name[])
182116d9e3a6SLisandro Dalcin {
182216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE*)pc->data;
182316d9e3a6SLisandro Dalcin 
182416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
182516d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
182616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
182716d9e3a6SLisandro Dalcin }
182816d9e3a6SLisandro Dalcin 
1829f7a08781SBarry Smith static PetscErrorCode  PCHYPRESetType_HYPRE(PC pc,const char name[])
183016d9e3a6SLisandro Dalcin {
183116d9e3a6SLisandro Dalcin   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1832ace3abfcSBarry Smith   PetscBool      flag;
183316d9e3a6SLisandro Dalcin 
183416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
183516d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
18369566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type,name,&flag));
18375f80ce2aSJacob Faibussowitsch     PetscCheck(flag,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set");
183816d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
183916d9e3a6SLisandro Dalcin   } else {
18409566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
184116d9e3a6SLisandro Dalcin   }
184216d9e3a6SLisandro Dalcin 
184316d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
184416d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
184516d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
184616d9e3a6SLisandro Dalcin 
18479566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut",jac->hypre_type,&flag));
184816d9e3a6SLisandro Dalcin   if (flag) {
18499566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc),&jac->comm_hypre));
1850792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate,jac->comm_hypre,&jac->hsolver);
185116d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
185216d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
185316d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
185416d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
185516d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
185616d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
185716d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
185816d9e3a6SLisandro Dalcin   }
18599566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid",jac->hypre_type,&flag));
1860db966c6cSHong Zhang   if (flag) {
18614e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
18624e3c431bSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Hypre Euclid does not support 64 bit indices");
18638bf83915SBarry Smith #endif
18649566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc),&jac->comm_hypre));
1865792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate,jac->comm_hypre,&jac->hsolver);
1866db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1867db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1868db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1869db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1870db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1871db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1872db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
1873db966c6cSHong Zhang     PetscFunctionReturn(0);
1874db966c6cSHong Zhang   }
18759566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails",jac->hypre_type,&flag));
187616d9e3a6SLisandro Dalcin   if (flag) {
18779566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc),&jac->comm_hypre));
1878792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate,jac->comm_hypre,&jac->hsolver);
187916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
188016d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
188116d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
188216d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
188316d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
188416d9e3a6SLisandro Dalcin     /* initialize */
188516d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
18868966356dSPierre Jolivet     jac->threshold = .1;
188716d9e3a6SLisandro Dalcin     jac->filter    = .1;
188816d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
18892fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int) PETSC_TRUE;
18902fa5cd67SKarl Rupp     else jac->logging = (int) PETSC_FALSE;
18912fa5cd67SKarl Rupp 
189216d9e3a6SLisandro Dalcin     jac->ruse = (int) PETSC_FALSE;
189316d9e3a6SLisandro Dalcin     jac->symt = 0;
1894792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams,jac->hsolver,jac->threshold,jac->nlevels);
1895792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter,jac->hsolver,jac->filter);
1896792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal,jac->hsolver,jac->loadbal);
1897792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging,jac->hsolver,jac->logging);
1898792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse,jac->hsolver,jac->ruse);
1899792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym,jac->hsolver,jac->symt);
190016d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
190116d9e3a6SLisandro Dalcin   }
19029566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg",jac->hypre_type,&flag));
190316d9e3a6SLisandro Dalcin   if (flag) {
1904792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate,&jac->hsolver);
190516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
190616d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
190716d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
190816d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
19099566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",PCGetInterpolations_BoomerAMG));
19109566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",PCGetCoarseOperators_BoomerAMG));
191116d9e3a6SLisandro Dalcin     jac->destroy             = HYPRE_BoomerAMGDestroy;
191216d9e3a6SLisandro Dalcin     jac->setup               = HYPRE_BoomerAMGSetup;
191316d9e3a6SLisandro Dalcin     jac->solve               = HYPRE_BoomerAMGSolve;
191416d9e3a6SLisandro Dalcin     jac->applyrichardson     = PETSC_FALSE;
191516d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
191616d9e3a6SLisandro Dalcin     jac->cycletype        = 1;
191716d9e3a6SLisandro Dalcin     jac->maxlevels        = 25;
191816d9e3a6SLisandro Dalcin     jac->maxiter          = 1;
19198f87f92bSBarry Smith     jac->tol              = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
192016d9e3a6SLisandro Dalcin     jac->truncfactor      = 0.0;
192116d9e3a6SLisandro Dalcin     jac->strongthreshold  = .25;
192216d9e3a6SLisandro Dalcin     jac->maxrowsum        = .9;
192316d9e3a6SLisandro Dalcin     jac->coarsentype      = 6;
192416d9e3a6SLisandro Dalcin     jac->measuretype      = 0;
19250f1074feSSatish Balay     jac->gridsweeps[0]    = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
19266a251517SEike Mueller     jac->smoothtype       = -1; /* Not set by default */
1927b9eb5777SEike Mueller     jac->smoothnumlevels  = 25;
19281810e44eSEike Mueller     jac->eu_level         = 0;
19291810e44eSEike Mueller     jac->eu_droptolerance = 0;
19301810e44eSEike Mueller     jac->eu_bj            = 0;
1931589dcaf0SStefano Zampini     jac->relaxtype[0]     = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
19320f1074feSSatish Balay     jac->relaxtype[2]     = 9; /*G.E. */
193316d9e3a6SLisandro Dalcin     jac->relaxweight      = 1.0;
193416d9e3a6SLisandro Dalcin     jac->outerrelaxweight = 1.0;
193516d9e3a6SLisandro Dalcin     jac->relaxorder       = 1;
19360f1074feSSatish Balay     jac->interptype       = 0;
1937589dcaf0SStefano Zampini     jac->Rtype            = 0;
1938589dcaf0SStefano Zampini     jac->Rstrongthreshold = 0.25;
1939589dcaf0SStefano Zampini     jac->Rfilterthreshold = 0.0;
1940589dcaf0SStefano Zampini     jac->Adroptype        = -1;
1941589dcaf0SStefano Zampini     jac->Adroptol         = 0.0;
19420f1074feSSatish Balay     jac->agg_nl           = 0;
19436ea7df73SStefano Zampini     jac->agg_interptype   = 4;
19440f1074feSSatish Balay     jac->pmax             = 0;
19450f1074feSSatish Balay     jac->truncfactor      = 0.0;
19460f1074feSSatish Balay     jac->agg_num_paths    = 1;
1947589dcaf0SStefano Zampini     jac->maxc             = 9;
1948589dcaf0SStefano Zampini     jac->minc             = 1;
194922e51d31SStefano Zampini     jac->nodal_coarsening      = 0;
195022e51d31SStefano Zampini     jac->nodal_coarsening_diag = 0;
195122e51d31SStefano Zampini     jac->vec_interp_variant    = 0;
195222e51d31SStefano Zampini     jac->vec_interp_qmax       = 0;
195322e51d31SStefano Zampini     jac->vec_interp_smooth     = PETSC_FALSE;
195422e51d31SStefano Zampini     jac->interp_refine         = 0;
19558f87f92bSBarry Smith     jac->nodal_relax           = PETSC_FALSE;
19568f87f92bSBarry Smith     jac->nodal_relax_levels    = 1;
19576ea7df73SStefano Zampini     jac->rap2                  = 0;
19586ea7df73SStefano Zampini 
19596ea7df73SStefano Zampini     /* GPU defaults
19606ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
19616ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
19626ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
19636ea7df73SStefano Zampini     jac->keeptranspose         = PETSC_TRUE;
19646ea7df73SStefano Zampini     jac->mod_rap2              = 1;
19656ea7df73SStefano Zampini     jac->coarsentype           = 8;
19666ea7df73SStefano Zampini     jac->relaxorder            = 0;
19676ea7df73SStefano Zampini     jac->interptype            = 6;
19686ea7df73SStefano Zampini     jac->relaxtype[0]          = 18;
19696ea7df73SStefano Zampini     jac->relaxtype[1]          = 18;
19706ea7df73SStefano Zampini     jac->agg_interptype        = 7;
19716ea7df73SStefano Zampini #else
19726ea7df73SStefano Zampini     jac->keeptranspose         = PETSC_FALSE;
19736ea7df73SStefano Zampini     jac->mod_rap2              = 0;
19746ea7df73SStefano Zampini #endif
1975792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType,jac->hsolver,jac->cycletype);
1976792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels,jac->hsolver,jac->maxlevels);
1977792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter,jac->hsolver,jac->maxiter);
1978792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol,jac->hsolver,jac->tol);
1979792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor,jac->hsolver,jac->truncfactor);
1980792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold,jac->hsolver,jac->strongthreshold);
1981792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum,jac->hsolver,jac->maxrowsum);
1982792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType,jac->hsolver,jac->coarsentype);
1983792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType,jac->hsolver,jac->measuretype);
1984792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder,jac->hsolver, jac->relaxorder);
1985792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType,jac->hsolver,jac->interptype);
1986792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels,jac->hsolver,jac->agg_nl);
1987792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType,jac->hsolver,jac->agg_interptype);
1988792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts,jac->hsolver,jac->pmax);
1989792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths,jac->hsolver,jac->agg_num_paths);
1990792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType,jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
1991792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps,jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
1992792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize,jac->hsolver, jac->maxc);
1993792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize,jac->hsolver, jac->minc);
19946ea7df73SStefano Zampini     /* GPU */
19956ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,18,0)
1996792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose,jac->hsolver,jac->keeptranspose ? 1 : 0);
1997792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2,jac->hsolver, jac->rap2);
1998792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2,jac->hsolver, jac->mod_rap2);
19996ea7df73SStefano Zampini #endif
20006ea7df73SStefano Zampini 
2001589dcaf0SStefano Zampini     /* AIR */
20026ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,18,0)
2003792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction,jac->hsolver,jac->Rtype);
2004792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR,jac->hsolver,jac->Rstrongthreshold);
2005792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR,jac->hsolver,jac->Rfilterthreshold);
2006792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol,jac->hsolver,jac->Adroptol);
2007792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType,jac->hsolver,jac->Adroptype);
20086ea7df73SStefano Zampini #endif
200916d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
201016d9e3a6SLisandro Dalcin   }
20119566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams",jac->hypre_type,&flag));
20124cb006feSStefano Zampini   if (flag) {
20139566063dSJacob Faibussowitsch     PetscCall(HYPRE_AMSCreate(&jac->hsolver));
20144cb006feSStefano Zampini     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_AMS;
20154cb006feSStefano Zampini     pc->ops->view            = PCView_HYPRE_AMS;
20164cb006feSStefano Zampini     jac->destroy             = HYPRE_AMSDestroy;
20174cb006feSStefano Zampini     jac->setup               = HYPRE_AMSSetup;
20184cb006feSStefano Zampini     jac->solve               = HYPRE_AMSSolve;
20194cb006feSStefano Zampini     jac->coords[0]           = NULL;
20204cb006feSStefano Zampini     jac->coords[1]           = NULL;
20214cb006feSStefano Zampini     jac->coords[2]           = NULL;
2022be14dc20SKerry Key     jac->interior            = NULL;
20234cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2024863406b8SStefano Zampini     jac->as_print           = 0;
2025863406b8SStefano Zampini     jac->as_max_iter        = 1; /* used as a preconditioner */
2026863406b8SStefano Zampini     jac->as_tol             = 0.; /* used as a preconditioner */
20274cb006feSStefano Zampini     jac->ams_cycle_type     = 13;
20284cb006feSStefano Zampini     /* Smoothing options */
2029863406b8SStefano Zampini     jac->as_relax_type      = 2;
2030863406b8SStefano Zampini     jac->as_relax_times     = 1;
2031863406b8SStefano Zampini     jac->as_relax_weight    = 1.0;
2032863406b8SStefano Zampini     jac->as_omega           = 1.0;
20334cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2034863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2035863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
20360bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2037863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2038863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2039863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
20404cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2041863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2042863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
20430bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2044863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2045863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2046863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2047792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel,jac->hsolver,jac->as_print);
2048792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter,jac->hsolver,jac->as_max_iter);
2049792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType,jac->hsolver,jac->ams_cycle_type);
2050792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol,jac->hsolver,jac->as_tol);
2051792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetSmoothingOptions,jac->hsolver,jac->as_relax_type,
2052863406b8SStefano Zampini                                                                       jac->as_relax_times,
2053863406b8SStefano Zampini                                                                       jac->as_relax_weight,
2054a74df02fSJacob Faibussowitsch                                                                       jac->as_omega);
2055792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions,jac->hsolver,jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
2056863406b8SStefano Zampini                                                                      jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
2057863406b8SStefano Zampini                                                                      jac->as_amg_alpha_opts[2],       /* AMG relax_type */
2058863406b8SStefano Zampini                                                                      jac->as_amg_alpha_theta,
2059863406b8SStefano Zampini                                                                      jac->as_amg_alpha_opts[3],       /* AMG interp_type */
2060a74df02fSJacob Faibussowitsch                                                                      jac->as_amg_alpha_opts[4]);     /* AMG Pmax */
2061792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions,jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
2062863406b8SStefano Zampini                                                                     jac->as_amg_beta_opts[1],       /* AMG agg_levels */
2063863406b8SStefano Zampini                                                                     jac->as_amg_beta_opts[2],       /* AMG relax_type */
2064863406b8SStefano Zampini                                                                     jac->as_amg_beta_theta,
2065863406b8SStefano Zampini                                                                     jac->as_amg_beta_opts[3],       /* AMG interp_type */
2066a74df02fSJacob Faibussowitsch                                                                     jac->as_amg_beta_opts[4]);     /* AMG Pmax */
206723df4f25SStefano Zampini     /* Zero conductivity */
206823df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
206923df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
20704cb006feSStefano Zampini     PetscFunctionReturn(0);
20714cb006feSStefano Zampini   }
20729566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads",jac->hypre_type,&flag));
2073863406b8SStefano Zampini   if (flag) {
20749566063dSJacob Faibussowitsch     PetscCall(HYPRE_ADSCreate(&jac->hsolver));
2075863406b8SStefano Zampini     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_ADS;
2076863406b8SStefano Zampini     pc->ops->view            = PCView_HYPRE_ADS;
2077863406b8SStefano Zampini     jac->destroy             = HYPRE_ADSDestroy;
2078863406b8SStefano Zampini     jac->setup               = HYPRE_ADSSetup;
2079863406b8SStefano Zampini     jac->solve               = HYPRE_ADSSolve;
2080863406b8SStefano Zampini     jac->coords[0]           = NULL;
2081863406b8SStefano Zampini     jac->coords[1]           = NULL;
2082863406b8SStefano Zampini     jac->coords[2]           = NULL;
2083863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2084863406b8SStefano Zampini     jac->as_print           = 0;
2085863406b8SStefano Zampini     jac->as_max_iter        = 1; /* used as a preconditioner */
2086863406b8SStefano Zampini     jac->as_tol             = 0.; /* used as a preconditioner */
2087863406b8SStefano Zampini     jac->ads_cycle_type     = 13;
2088863406b8SStefano Zampini     /* Smoothing options */
2089863406b8SStefano Zampini     jac->as_relax_type      = 2;
2090863406b8SStefano Zampini     jac->as_relax_times     = 1;
2091863406b8SStefano Zampini     jac->as_relax_weight    = 1.0;
2092863406b8SStefano Zampini     jac->as_omega           = 1.0;
2093863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2094863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2095863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2096863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2097863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2098863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2099863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2100863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2101863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2102863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2103863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2104863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2105863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2106863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2107863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2108792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel,jac->hsolver,jac->as_print);
2109792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter,jac->hsolver,jac->as_max_iter);
2110792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType,jac->hsolver,jac->ams_cycle_type);
2111792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol,jac->hsolver,jac->as_tol);
2112792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetSmoothingOptions,jac->hsolver,jac->as_relax_type,
2113863406b8SStefano Zampini                                                                       jac->as_relax_times,
2114863406b8SStefano Zampini                                                                       jac->as_relax_weight,
2115a74df02fSJacob Faibussowitsch                                                                       jac->as_omega);
2116792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions,jac->hsolver,jac->ams_cycle_type,             /* AMG coarsen type */
2117863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
2118863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
2119863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[2],       /* AMG relax_type */
2120863406b8SStefano Zampini                                                                 jac->as_amg_alpha_theta,
2121863406b8SStefano Zampini                                                                 jac->as_amg_alpha_opts[3],       /* AMG interp_type */
2122a74df02fSJacob Faibussowitsch                                                                 jac->as_amg_alpha_opts[4]);     /* AMG Pmax */
2123792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions,jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
2124863406b8SStefano Zampini                                                                 jac->as_amg_beta_opts[1],       /* AMG agg_levels */
2125863406b8SStefano Zampini                                                                 jac->as_amg_beta_opts[2],       /* AMG relax_type */
2126863406b8SStefano Zampini                                                                 jac->as_amg_beta_theta,
2127863406b8SStefano Zampini                                                                 jac->as_amg_beta_opts[3],       /* AMG interp_type */
2128a74df02fSJacob Faibussowitsch                                                                 jac->as_amg_beta_opts[4]);     /* AMG Pmax */
2129863406b8SStefano Zampini     PetscFunctionReturn(0);
2130863406b8SStefano Zampini   }
21319566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
21322fa5cd67SKarl Rupp 
21330298fd71SBarry Smith   jac->hypre_type = NULL;
213498921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams",name);
213516d9e3a6SLisandro Dalcin }
213616d9e3a6SLisandro Dalcin 
213716d9e3a6SLisandro Dalcin /*
213816d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
213916d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
214016d9e3a6SLisandro Dalcin */
2141360ee056SFande Kong PetscErrorCode PCSetFromOptions_HYPRE(PetscOptionItems *PetscOptionsObject,PC pc)
214216d9e3a6SLisandro Dalcin {
21434ddd07fcSJed Brown   PetscInt       indx;
2144db966c6cSHong Zhang   const char     *type[] = {"euclid","pilut","parasails","boomeramg","ams","ads"};
2145ace3abfcSBarry Smith   PetscBool      flg;
214616d9e3a6SLisandro Dalcin 
214716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2148d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"HYPRE preconditioner options");
2149dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,PETSC_STATIC_ARRAY_LENGTH(type),"boomeramg",&indx,&flg));
215016d9e3a6SLisandro Dalcin   if (flg) {
21519566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc,type[indx]));
215202a17cd4SBarry Smith   } else {
21539566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc,"boomeramg"));
215416d9e3a6SLisandro Dalcin   }
21551baa6e33SBarry Smith   if (pc->ops->setfromoptions) PetscCall(pc->ops->setfromoptions(PetscOptionsObject,pc));
2156d0609cedSBarry Smith   PetscOptionsHeadEnd();
215716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
215816d9e3a6SLisandro Dalcin }
215916d9e3a6SLisandro Dalcin 
216016d9e3a6SLisandro Dalcin /*@C
216116d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
216216d9e3a6SLisandro Dalcin 
216316d9e3a6SLisandro Dalcin    Input Parameters:
216416d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2165db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
216616d9e3a6SLisandro Dalcin 
216716d9e3a6SLisandro Dalcin    Options Database Keys:
2168db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
216916d9e3a6SLisandro Dalcin 
217016d9e3a6SLisandro Dalcin    Level: intermediate
217116d9e3a6SLisandro Dalcin 
2172db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
2173db781477SPatrick Sanan           `PCHYPRE`
217416d9e3a6SLisandro Dalcin 
217516d9e3a6SLisandro Dalcin @*/
21767087cfbeSBarry Smith PetscErrorCode  PCHYPRESetType(PC pc,const char name[])
217716d9e3a6SLisandro Dalcin {
217816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21790700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
218016d9e3a6SLisandro Dalcin   PetscValidCharPointer(name,2);
2181cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPRESetType_C",(PC,const char[]),(pc,name));
218216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
218316d9e3a6SLisandro Dalcin }
218416d9e3a6SLisandro Dalcin 
218516d9e3a6SLisandro Dalcin /*@C
218616d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
218716d9e3a6SLisandro Dalcin 
218816d9e3a6SLisandro Dalcin    Input Parameter:
218916d9e3a6SLisandro Dalcin .     pc - the preconditioner context
219016d9e3a6SLisandro Dalcin 
219116d9e3a6SLisandro Dalcin    Output Parameter:
2192db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
219316d9e3a6SLisandro Dalcin 
219416d9e3a6SLisandro Dalcin    Level: intermediate
219516d9e3a6SLisandro Dalcin 
2196db781477SPatrick Sanan .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`,
2197db781477SPatrick Sanan           `PCHYPRE`
219816d9e3a6SLisandro Dalcin 
219916d9e3a6SLisandro Dalcin @*/
22007087cfbeSBarry Smith PetscErrorCode  PCHYPREGetType(PC pc,const char *name[])
220116d9e3a6SLisandro Dalcin {
220216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22030700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
220416d9e3a6SLisandro Dalcin   PetscValidPointer(name,2);
2205cac4c232SBarry Smith   PetscTryMethod(pc,"PCHYPREGetType_C",(PC,const char*[]),(pc,name));
220616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
220716d9e3a6SLisandro Dalcin }
220816d9e3a6SLisandro Dalcin 
2209db6f9c32SMark Adams /*@C
2210db6f9c32SMark Adams    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use
2211db6f9c32SMark Adams 
2212db6f9c32SMark Adams    Logically Collective on PC
2213db6f9c32SMark Adams 
2214db6f9c32SMark Adams    Input Parameters:
2215db6f9c32SMark Adams +  pc - the hypre context
2216db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2217db6f9c32SMark Adams 
2218db6f9c32SMark Adams    Options Database Key:
221967b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2220db6f9c32SMark Adams 
2221db6f9c32SMark Adams    Level: intermediate
2222db6f9c32SMark Adams 
2223db781477SPatrick Sanan .seealso: `PCMGGalerkinGetMatProductAlgorithm()`
2224db6f9c32SMark Adams 
2225db6f9c32SMark Adams @*/
2226db6f9c32SMark Adams PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc,const char name[])
2227db6f9c32SMark Adams {
2228db6f9c32SMark Adams   PetscFunctionBegin;
2229db6f9c32SMark Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2230cac4c232SBarry Smith   PetscTryMethod(pc,"PCMGGalerkinSetMatProductAlgorithm_C",(PC,const char[]),(pc,name));
2231db6f9c32SMark Adams   PetscFunctionReturn(0);
2232db6f9c32SMark Adams }
2233db6f9c32SMark Adams 
2234db6f9c32SMark Adams /*@C
2235db6f9c32SMark Adams    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre
2236db6f9c32SMark Adams 
2237db6f9c32SMark Adams    Not Collective
2238db6f9c32SMark Adams 
2239db6f9c32SMark Adams    Input Parameter:
2240db6f9c32SMark Adams .  pc - the multigrid context
2241db6f9c32SMark Adams 
2242db6f9c32SMark Adams    Output Parameter:
2243db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2244db6f9c32SMark Adams 
2245db6f9c32SMark Adams    Level: intermediate
2246db6f9c32SMark Adams 
2247db781477SPatrick Sanan .seealso: `PCMGGalerkinSetMatProductAlgorithm()`
2248db6f9c32SMark Adams 
2249db6f9c32SMark Adams @*/
2250db6f9c32SMark Adams PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc,const char *name[])
2251db6f9c32SMark Adams {
2252db6f9c32SMark Adams   PetscFunctionBegin;
2253db6f9c32SMark Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2254cac4c232SBarry Smith   PetscTryMethod(pc,"PCMGGalerkinGetMatProductAlgorithm_C",(PC,const char*[]),(pc,name));
2255db6f9c32SMark Adams   PetscFunctionReturn(0);
2256db6f9c32SMark Adams }
2257db6f9c32SMark Adams 
225816d9e3a6SLisandro Dalcin /*MC
225916d9e3a6SLisandro Dalcin      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
226016d9e3a6SLisandro Dalcin 
226116d9e3a6SLisandro Dalcin    Options Database Keys:
2262db966c6cSHong Zhang +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2263ead8c081SBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see HYPRE_BOOMERAMGSetNodal())
2264ead8c081SBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see HYPRE_BoomerAMGSetInterpVecVariant())
2265ead8c081SBarry Smith -   Many others, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX preconditioner
226616d9e3a6SLisandro Dalcin 
226716d9e3a6SLisandro Dalcin    Level: intermediate
226816d9e3a6SLisandro Dalcin 
226995452b02SPatrick Sanan    Notes:
227095452b02SPatrick Sanan     Apart from pc_hypre_type (for which there is PCHYPRESetType()),
227116d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
227216d9e3a6SLisandro Dalcin           or with PetscOptionsSetValue(), there are no functions to set them)
227316d9e3a6SLisandro Dalcin 
2274c231f9e3SBarryFSmith           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
22750f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
22760f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2277c231f9e3SBarryFSmith           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
22788f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
22790f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
22800f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
228116d9e3a6SLisandro Dalcin 
22820f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
22830f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
22840f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
228516d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
228616d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
228716d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
228816d9e3a6SLisandro Dalcin 
228916d9e3a6SLisandro Dalcin           2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
229016d9e3a6SLisandro Dalcin           -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
229116d9e3a6SLisandro Dalcin 
22925272c319SBarry Smith           MatSetNearNullSpace() - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2293fdd15c9aSJunchao Zhang           the following two options:
22940b1a5bd9SEric Chamberland 
22959e5bc791SBarry Smith           See PCPFMG for access to the hypre Struct PFMG solver
22969e5bc791SBarry Smith 
2297ead8c081SBarry Smith    GPU Notes:
2298ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2299ead8c081SBarry Smith      Then pass VECCUDA vectors and MATAIJCUSPARSE matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2300ead8c081SBarry Smith 
2301ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2302ead8c081SBarry Smith      Then pass VECHIP vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2303ead8c081SBarry Smith 
2304db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
2305db781477SPatrick Sanan           `PCHYPRESetType()`, `PCPFMG`
230616d9e3a6SLisandro Dalcin 
230716d9e3a6SLisandro Dalcin M*/
230816d9e3a6SLisandro Dalcin 
23098cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
231016d9e3a6SLisandro Dalcin {
231116d9e3a6SLisandro Dalcin   PC_HYPRE       *jac;
231216d9e3a6SLisandro Dalcin 
231316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23149566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc,&jac));
23152fa5cd67SKarl Rupp 
231616d9e3a6SLisandro Dalcin   pc->data                = jac;
23178695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
231816d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
231916d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
232016d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
232116d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
232216d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
23239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetType_C",PCHYPRESetType_HYPRE));
23249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPREGetType_C",PCHYPREGetType_HYPRE));
23259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_HYPRE));
23269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteGradient_C",PCHYPRESetDiscreteGradient_HYPRE));
23279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteCurl_C",PCHYPRESetDiscreteCurl_HYPRE));
23289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetInterpolations_C",PCHYPRESetInterpolations_HYPRE));
23299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetEdgeConstantVectors_C",PCHYPRESetEdgeConstantVectors_HYPRE));
2330be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPREAMSSetInteriorNodes_C",PCHYPREAMSSetInteriorNodes_HYPRE));
23319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetPoissonMatrix_C",PCHYPRESetPoissonMatrix_HYPRE));
23329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGalerkinSetMatProductAlgorithm_C",PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
23339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGalerkinGetMatProductAlgorithm_C",PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
23346ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23356ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP)
23369566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
23376ea7df73SStefano Zampini #endif
23386ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA)
23399566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
23406ea7df73SStefano Zampini #endif
23416ea7df73SStefano Zampini #endif
234216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
234316d9e3a6SLisandro Dalcin }
2344ebc551c0SBarry Smith 
2345f91d8e95SBarry Smith /* ---------------------------------------------------------------------------------------------------------------------------------*/
2346f91d8e95SBarry Smith 
2347ebc551c0SBarry Smith typedef struct {
234868326731SBarry Smith   MPI_Comm           hcomm;        /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2349f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
23509e5bc791SBarry Smith 
23519e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
23524ddd07fcSJed Brown   PetscInt its;
23539e5bc791SBarry Smith   double   tol;
23544ddd07fcSJed Brown   PetscInt relax_type;
23554ddd07fcSJed Brown   PetscInt rap_type;
23564ddd07fcSJed Brown   PetscInt num_pre_relax,num_post_relax;
23574ddd07fcSJed Brown   PetscInt max_levels;
23580be8cd64Sftrigaux   PetscInt skip_relax;
23590be8cd64Sftrigaux   PetscBool print_statistics;
2360ebc551c0SBarry Smith } PC_PFMG;
2361ebc551c0SBarry Smith 
2362ebc551c0SBarry Smith PetscErrorCode PCDestroy_PFMG(PC pc)
2363ebc551c0SBarry Smith {
2364f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
2365ebc551c0SBarry Smith 
2366ebc551c0SBarry Smith   PetscFunctionBegin;
2367792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy,ex->hsolver);
23689566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc),&ex->hcomm));
23699566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2370ebc551c0SBarry Smith   PetscFunctionReturn(0);
2371ebc551c0SBarry Smith }
2372ebc551c0SBarry Smith 
23739e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi","Weighted-Jacobi","symmetric-Red/Black-Gauss-Seidel","Red/Black-Gauss-Seidel"};
23749e5bc791SBarry Smith static const char *PFMGRAPType[] = {"Galerkin","non-Galerkin"};
23759e5bc791SBarry Smith 
2376ebc551c0SBarry Smith PetscErrorCode PCView_PFMG(PC pc,PetscViewer viewer)
2377ebc551c0SBarry Smith {
2378ace3abfcSBarry Smith   PetscBool      iascii;
2379f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
2380ebc551c0SBarry Smith 
2381ebc551c0SBarry Smith   PetscFunctionBegin;
23829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
23839e5bc791SBarry Smith   if (iascii) {
23849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG preconditioning\n"));
238563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    max iterations %" PetscInt_FMT "\n",ex->its));
23869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    tolerance %g\n",ex->tol));
23879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    relax type %s\n",PFMGRelaxType[ex->relax_type]));
23889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    RAP type %s\n",PFMGRAPType[ex->rap_type]));
238963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n",ex->num_pre_relax,ex->num_post_relax));
239063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    max levels %" PetscInt_FMT "\n",ex->max_levels));
23910be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer,"    skip relax %" PetscInt_FMT "\n",ex->skip_relax));
23929e5bc791SBarry Smith   }
2393ebc551c0SBarry Smith   PetscFunctionReturn(0);
2394ebc551c0SBarry Smith }
2395ebc551c0SBarry Smith 
23964416b707SBarry Smith PetscErrorCode PCSetFromOptions_PFMG(PetscOptionItems *PetscOptionsObject,PC pc)
2397ebc551c0SBarry Smith {
2398f91d8e95SBarry Smith   PC_PFMG        *ex = (PC_PFMG*) pc->data;
2399ebc551c0SBarry Smith 
2400ebc551c0SBarry Smith   PetscFunctionBegin;
2401d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"PFMG options");
24020be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics","Print statistics","HYPRE_StructPFMGSetPrintLevel",ex->print_statistics,&ex->print_statistics,NULL));
24039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its","Number of iterations of PFMG to use as preconditioner","HYPRE_StructPFMGSetMaxIter",ex->its,&ex->its,NULL));
2404792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter,ex->hsolver,ex->its);
24059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_StructPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,NULL));
2406792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax,ex->hsolver,ex->num_pre_relax);
24079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_StructPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,NULL));
2408792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax,ex->hsolver,ex->num_post_relax);
24099e5bc791SBarry Smith 
24109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels","Max Levels for MG hierarchy","HYPRE_StructPFMGSetMaxLevels",ex->max_levels,&ex->max_levels,NULL));
2411792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels,ex->hsolver,ex->max_levels);
24123b46a515SGlenn Hammond 
24139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol","Tolerance of PFMG","HYPRE_StructPFMGSetTol",ex->tol,&ex->tol,NULL));
2414792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol,ex->hsolver,ex->tol);
2415dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_pfmg_relax_type","Relax type for the up and down cycles","HYPRE_StructPFMGSetRelaxType",PFMGRelaxType,PETSC_STATIC_ARRAY_LENGTH(PFMGRelaxType),PFMGRelaxType[ex->relax_type],&ex->relax_type,NULL));
2416792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType,ex->hsolver, ex->relax_type);
2417dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_pfmg_rap_type","RAP type","HYPRE_StructPFMGSetRAPType",PFMGRAPType,PETSC_STATIC_ARRAY_LENGTH(PFMGRAPType),PFMGRAPType[ex->rap_type],&ex->rap_type,NULL));
2418792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType,ex->hsolver, ex->rap_type);
24190be8cd64Sftrigaux   PetscCall(PetscOptionsInt("-pc_pfmg_skip_relax","Skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations when the underlying problem is isotropic","HYPRE_StructPFMGSetSkipRelax",ex->skip_relax,&ex->skip_relax,NULL));
24200be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax,ex->hsolver, ex->skip_relax);
2421d0609cedSBarry Smith   PetscOptionsHeadEnd();
2422ebc551c0SBarry Smith   PetscFunctionReturn(0);
2423ebc551c0SBarry Smith }
2424ebc551c0SBarry Smith 
2425f91d8e95SBarry Smith PetscErrorCode PCApply_PFMG(PC pc,Vec x,Vec y)
2426f91d8e95SBarry Smith {
2427f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG*) pc->data;
2428d9ca1df4SBarry Smith   PetscScalar       *yy;
2429d9ca1df4SBarry Smith   const PetscScalar *xx;
24304ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
24312cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
243268326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(pc->pmat->data);
2433f91d8e95SBarry Smith 
2434f91d8e95SBarry Smith   PetscFunctionBegin;
24359566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
24369566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
24372cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2438f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2439f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2440f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
24412cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
24422cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
24432cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
24442cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
24452cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
24462cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
2447f91d8e95SBarry Smith 
2448f91d8e95SBarry Smith   /* copy x values over to hypre */
2449792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues,mx->hb,0.0);
24509566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x,&xx));
2451792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues,mx->hb,hlower,hupper,(HYPRE_Complex*)xx);
24529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x,&xx));
2453792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble,mx->hb);
2454792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve,ex->hsolver,mx->hmat,mx->hb,mx->hx);
2455f91d8e95SBarry Smith 
2456f91d8e95SBarry Smith   /* copy solution values back to PETSc */
24579566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&yy));
2458792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues,mx->hx,hlower,hupper,(HYPRE_Complex*)yy);
24599566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&yy));
2460f91d8e95SBarry Smith   PetscFunctionReturn(0);
2461f91d8e95SBarry Smith }
2462f91d8e95SBarry Smith 
2463ace3abfcSBarry Smith static PetscErrorCode PCApplyRichardson_PFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
24649e5bc791SBarry Smith {
24659e5bc791SBarry Smith   PC_PFMG        *jac = (PC_PFMG*)pc->data;
24662cf14000SStefano Zampini   HYPRE_Int      oits;
24679e5bc791SBarry Smith 
24689e5bc791SBarry Smith   PetscFunctionBegin;
24699566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
2470792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter,jac->hsolver,its*jac->its);
2471792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol,jac->hsolver,rtol);
24729e5bc791SBarry Smith 
24739566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc,b,y));
2474792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations,jac->hsolver,&oits);
24759e5bc791SBarry Smith   *outits = oits;
24769e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
24779e5bc791SBarry Smith   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
2478792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol,jac->hsolver,jac->tol);
2479792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter,jac->hsolver,jac->its);
24809e5bc791SBarry Smith   PetscFunctionReturn(0);
24819e5bc791SBarry Smith }
24829e5bc791SBarry Smith 
24833a32d3dbSGlenn Hammond PetscErrorCode PCSetUp_PFMG(PC pc)
24843a32d3dbSGlenn Hammond {
24853a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG*) pc->data;
24863a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(pc->pmat->data);
2487ace3abfcSBarry Smith   PetscBool       flg;
24883a32d3dbSGlenn Hammond 
24893a32d3dbSGlenn Hammond   PetscFunctionBegin;
24909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg));
249128b400f6SJacob Faibussowitsch   PetscCheck(flg,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner");
24923a32d3dbSGlenn Hammond 
24933a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2494792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy,ex->hsolver);
2495792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate,ex->hcomm,&ex->hsolver);
24960be8cd64Sftrigaux 
24970be8cd64Sftrigaux   // Print Hypre statistics about the solve process
24980be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel,ex->hsolver,3);
24990be8cd64Sftrigaux 
25000be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
25010be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter     ,ex->hsolver, ex->its);
25020be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax ,ex->hsolver, ex->num_pre_relax);
25030be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax,ex->hsolver, ex->num_post_relax);
25040be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels   ,ex->hsolver, ex->max_levels);
25050be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol         ,ex->hsolver, ex->tol);
25060be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType   ,ex->hsolver, ex->relax_type);
25070be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType     ,ex->hsolver, ex->rap_type);
25080be8cd64Sftrigaux 
2509792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup,ex->hsolver,mx->hmat,mx->hb,mx->hx);
2510792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess,ex->hsolver);
25113a32d3dbSGlenn Hammond   PetscFunctionReturn(0);
25123a32d3dbSGlenn Hammond }
25133a32d3dbSGlenn Hammond 
2514ebc551c0SBarry Smith /*MC
2515ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2516ebc551c0SBarry Smith 
2517ebc551c0SBarry Smith    Level: advanced
2518ebc551c0SBarry Smith 
25199e5bc791SBarry Smith    Options Database:
252067b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
252167b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
252267b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
252367b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
25249e5bc791SBarry 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
25250be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
25260be8cd64Sftrigaux - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations when the underlying problem is isotropic, one of 0,1
2527f91d8e95SBarry Smith 
252895452b02SPatrick Sanan    Notes:
252995452b02SPatrick Sanan     This is for CELL-centered descretizations
25309e5bc791SBarry Smith 
25318e395302SJed Brown            This must be used with the MATHYPRESTRUCT matrix type.
2532aa219208SBarry Smith            This is less general than in hypre, it supports only one block per process defined by a PETSc DMDA.
25339e5bc791SBarry Smith 
2534db781477SPatrick Sanan .seealso: `PCMG`, `MATHYPRESTRUCT`
2535ebc551c0SBarry Smith M*/
2536ebc551c0SBarry Smith 
25378cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2538ebc551c0SBarry Smith {
2539ebc551c0SBarry Smith   PC_PFMG        *ex;
2540ebc551c0SBarry Smith 
2541ebc551c0SBarry Smith   PetscFunctionBegin;
25429566063dSJacob Faibussowitsch   PetscCall(PetscNew(&ex)); \
254368326731SBarry Smith   pc->data = ex;
2544ebc551c0SBarry Smith 
25459e5bc791SBarry Smith   ex->its            = 1;
25469e5bc791SBarry Smith   ex->tol            = 1.e-8;
25479e5bc791SBarry Smith   ex->relax_type     = 1;
25489e5bc791SBarry Smith   ex->rap_type       = 0;
25499e5bc791SBarry Smith   ex->num_pre_relax  = 1;
25509e5bc791SBarry Smith   ex->num_post_relax = 1;
25513b46a515SGlenn Hammond   ex->max_levels     = 0;
25520be8cd64Sftrigaux   ex->skip_relax     = 0;
25530be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
25549e5bc791SBarry Smith 
2555ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2556ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2557ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2558f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
25599e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
256068326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
25612fa5cd67SKarl Rupp 
25629566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc),&ex->hcomm));
2563792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate,ex->hcomm,&ex->hsolver);
2564ebc551c0SBarry Smith   PetscFunctionReturn(0);
2565ebc551c0SBarry Smith }
2566d851a50bSGlenn Hammond 
2567325fc9f4SBarry Smith /* ---------------------------------------------------------------------------------------------------------------------------------------------------*/
2568325fc9f4SBarry Smith 
2569d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2570d851a50bSGlenn Hammond typedef struct {
2571d851a50bSGlenn Hammond   MPI_Comm            hcomm;       /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2572d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2573d851a50bSGlenn Hammond 
2574d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
25754ddd07fcSJed Brown   PetscInt its;
2576d851a50bSGlenn Hammond   double   tol;
25774ddd07fcSJed Brown   PetscInt relax_type;
25784ddd07fcSJed Brown   PetscInt num_pre_relax,num_post_relax;
2579d851a50bSGlenn Hammond } PC_SysPFMG;
2580d851a50bSGlenn Hammond 
2581d851a50bSGlenn Hammond PetscErrorCode PCDestroy_SysPFMG(PC pc)
2582d851a50bSGlenn Hammond {
2583d851a50bSGlenn Hammond   PC_SysPFMG     *ex = (PC_SysPFMG*) pc->data;
2584d851a50bSGlenn Hammond 
2585d851a50bSGlenn Hammond   PetscFunctionBegin;
2586792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy,ex->ss_solver);
25879566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc),&ex->hcomm));
25889566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2589d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2590d851a50bSGlenn Hammond }
2591d851a50bSGlenn Hammond 
2592d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi","Red/Black-Gauss-Seidel"};
2593d851a50bSGlenn Hammond 
2594d851a50bSGlenn Hammond PetscErrorCode PCView_SysPFMG(PC pc,PetscViewer viewer)
2595d851a50bSGlenn Hammond {
2596ace3abfcSBarry Smith   PetscBool      iascii;
2597d851a50bSGlenn Hammond   PC_SysPFMG     *ex = (PC_SysPFMG*) pc->data;
2598d851a50bSGlenn Hammond 
2599d851a50bSGlenn Hammond   PetscFunctionBegin;
26009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
2601d851a50bSGlenn Hammond   if (iascii) {
26029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG preconditioning\n"));
260363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  max iterations %" PetscInt_FMT "\n",ex->its));
26049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  tolerance %g\n",ex->tol));
26059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  relax type %s\n",PFMGRelaxType[ex->relax_type]));
260663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n",ex->num_pre_relax,ex->num_post_relax));
2607d851a50bSGlenn Hammond   }
2608d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2609d851a50bSGlenn Hammond }
2610d851a50bSGlenn Hammond 
26114416b707SBarry Smith PetscErrorCode PCSetFromOptions_SysPFMG(PetscOptionItems *PetscOptionsObject,PC pc)
2612d851a50bSGlenn Hammond {
2613d851a50bSGlenn Hammond   PC_SysPFMG     *ex = (PC_SysPFMG*) pc->data;
2614ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
2615d851a50bSGlenn Hammond 
2616d851a50bSGlenn Hammond   PetscFunctionBegin;
2617d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"SysPFMG options");
26189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics","Print statistics","HYPRE_SStructSysPFMGSetPrintLevel",flg,&flg,NULL));
2619d851a50bSGlenn Hammond   if (flg) {
2620792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel,ex->ss_solver,3);
2621d851a50bSGlenn Hammond   }
26229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its","Number of iterations of SysPFMG to use as preconditioner","HYPRE_SStructSysPFMGSetMaxIter",ex->its,&ex->its,NULL));
2623792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter,ex->ss_solver,ex->its);
26249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_SStructSysPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,NULL));
2625792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax,ex->ss_solver,ex->num_pre_relax);
26269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_SStructSysPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,NULL));
2627792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax,ex->ss_solver,ex->num_post_relax);
2628d851a50bSGlenn Hammond 
26299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol","Tolerance of SysPFMG","HYPRE_SStructSysPFMGSetTol",ex->tol,&ex->tol,NULL));
2630792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol,ex->ss_solver,ex->tol);
2631dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_syspfmg_relax_type","Relax type for the up and down cycles","HYPRE_SStructSysPFMGSetRelaxType",SysPFMGRelaxType,PETSC_STATIC_ARRAY_LENGTH(SysPFMGRelaxType),SysPFMGRelaxType[ex->relax_type],&ex->relax_type,NULL));
2632792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType,ex->ss_solver, ex->relax_type);
2633d0609cedSBarry Smith   PetscOptionsHeadEnd();
2634d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2635d851a50bSGlenn Hammond }
2636d851a50bSGlenn Hammond 
2637d851a50bSGlenn Hammond PetscErrorCode PCApply_SysPFMG(PC pc,Vec x,Vec y)
2638d851a50bSGlenn Hammond {
2639d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG*) pc->data;
2640d9ca1df4SBarry Smith   PetscScalar       *yy;
2641d9ca1df4SBarry Smith   const PetscScalar *xx;
26424ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
26432cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
2644d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(pc->pmat->data);
26454ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
26464ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
26474ddd07fcSJed Brown   PetscInt          part    = 0;
26484ddd07fcSJed Brown   PetscInt          size;
26494ddd07fcSJed Brown   PetscInt          i;
2650d851a50bSGlenn Hammond 
2651d851a50bSGlenn Hammond   PetscFunctionBegin;
26529566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
26539566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
26542cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2655d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2656d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2657d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
26582cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
26592cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
26602cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
26612cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
26622cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
26632cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
2664d851a50bSGlenn Hammond 
2665d851a50bSGlenn Hammond   size = 1;
26662fa5cd67SKarl Rupp   for (i= 0; i< 3; i++) size *= (iupper[i]-ilower[i]+1);
26672fa5cd67SKarl Rupp 
2668d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2669d851a50bSGlenn Hammond   if (ordering) {
2670792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
26719566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
2672792fecdfSBarry Smith     for (i= 0; i< nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(xx+(size*i)));
26739566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
2674792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble,mx->ss_b);
2675792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec,1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
2676792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve,ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x);
2677d851a50bSGlenn Hammond 
2678d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26799566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
2680792fecdfSBarry Smith     for (i= 0; i< nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(yy+(size*i)));
26819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
2682a65764d7SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2683d851a50bSGlenn Hammond     PetscScalar *z;
26844ddd07fcSJed Brown     PetscInt    j, k;
2685d851a50bSGlenn Hammond 
26869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars*size,&z));
2687792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
26889566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
2689d851a50bSGlenn Hammond 
2690d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2691d851a50bSGlenn Hammond     for (i= 0; i< size; i++) {
2692d851a50bSGlenn Hammond       k= i*nvars;
26932fa5cd67SKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
2694d851a50bSGlenn Hammond     }
2695792fecdfSBarry Smith     for (i= 0; i< nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
26969566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
2697792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble,mx->ss_b);
2698792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve,ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x);
2699d851a50bSGlenn Hammond 
2700d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27019566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
2702792fecdfSBarry Smith     for (i= 0; i< nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
2703d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2704d851a50bSGlenn Hammond     for (i= 0; i< size; i++) {
2705d851a50bSGlenn Hammond       k= i*nvars;
27062fa5cd67SKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
2707d851a50bSGlenn Hammond     }
27089566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
27099566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2710d851a50bSGlenn Hammond   }
2711d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2712d851a50bSGlenn Hammond }
2713d851a50bSGlenn Hammond 
2714ace3abfcSBarry Smith static PetscErrorCode PCApplyRichardson_SysPFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
2715d851a50bSGlenn Hammond {
2716d851a50bSGlenn Hammond   PC_SysPFMG     *jac = (PC_SysPFMG*)pc->data;
27172cf14000SStefano Zampini   HYPRE_Int      oits;
2718d851a50bSGlenn Hammond 
2719d851a50bSGlenn Hammond   PetscFunctionBegin;
27209566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
2721792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter,jac->ss_solver,its*jac->its);
2722792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol,jac->ss_solver,rtol);
27239566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc,b,y));
2724792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations,jac->ss_solver,&oits);
2725d851a50bSGlenn Hammond   *outits = oits;
2726d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2727d851a50bSGlenn Hammond   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
2728792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol,jac->ss_solver,jac->tol);
2729792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter,jac->ss_solver,jac->its);
2730d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2731d851a50bSGlenn Hammond }
2732d851a50bSGlenn Hammond 
2733d851a50bSGlenn Hammond PetscErrorCode PCSetUp_SysPFMG(PC pc)
2734d851a50bSGlenn Hammond {
2735d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG*) pc->data;
2736d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct*)(pc->pmat->data);
2737ace3abfcSBarry Smith   PetscBool        flg;
2738d851a50bSGlenn Hammond 
2739d851a50bSGlenn Hammond   PetscFunctionBegin;
27409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESSTRUCT,&flg));
274128b400f6SJacob Faibussowitsch   PetscCheck(flg,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESSTRUCT with this preconditioner");
2742d851a50bSGlenn Hammond 
2743d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2744792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy,ex->ss_solver);
2745792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate,ex->hcomm,&ex->ss_solver);
2746792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess,ex->ss_solver);
2747792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup,ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x);
2748d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2749d851a50bSGlenn Hammond }
2750d851a50bSGlenn Hammond 
2751d851a50bSGlenn Hammond /*MC
2752d851a50bSGlenn Hammond      PCSysPFMG - the hypre SysPFMG multigrid solver
2753d851a50bSGlenn Hammond 
2754d851a50bSGlenn Hammond    Level: advanced
2755d851a50bSGlenn Hammond 
2756d851a50bSGlenn Hammond    Options Database:
275767b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
275867b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
275967b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
276067b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
276167b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2762d851a50bSGlenn Hammond 
276395452b02SPatrick Sanan    Notes:
276495452b02SPatrick Sanan     This is for CELL-centered descretizations
2765d851a50bSGlenn Hammond 
2766f6680f47SSatish Balay            This must be used with the MATHYPRESSTRUCT matrix type.
2767aa219208SBarry Smith            This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DMDA.
2768d851a50bSGlenn Hammond            Also, only cell-centered variables.
2769d851a50bSGlenn Hammond 
2770db781477SPatrick Sanan .seealso: `PCMG`, `MATHYPRESSTRUCT`
2771d851a50bSGlenn Hammond M*/
2772d851a50bSGlenn Hammond 
27738cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2774d851a50bSGlenn Hammond {
2775d851a50bSGlenn Hammond   PC_SysPFMG     *ex;
2776d851a50bSGlenn Hammond 
2777d851a50bSGlenn Hammond   PetscFunctionBegin;
27789566063dSJacob Faibussowitsch   PetscCall(PetscNew(&ex)); \
2779d851a50bSGlenn Hammond   pc->data = ex;
2780d851a50bSGlenn Hammond 
2781d851a50bSGlenn Hammond   ex->its            = 1;
2782d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2783d851a50bSGlenn Hammond   ex->relax_type     = 1;
2784d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2785d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2786d851a50bSGlenn Hammond 
2787d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2788d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2789d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2790d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2791d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2792d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
27932fa5cd67SKarl Rupp 
27949566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc),&ex->hcomm));
2795792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate,ex->hcomm,&ex->ss_solver);
2796d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2797d851a50bSGlenn Hammond }
27981c188c59Sftrigaux 
27991c188c59Sftrigaux /* ---------------------------------------------------------------------------------------------------------------------------------*/
28001c188c59Sftrigaux 
28011c188c59Sftrigaux // PC SMG
28021c188c59Sftrigaux typedef struct {
28031c188c59Sftrigaux   MPI_Comm           hcomm;        /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
28041c188c59Sftrigaux   HYPRE_StructSolver hsolver;
28051c188c59Sftrigaux   PetscInt           its;          /* keep copy of SMG options used so may view them */
28061c188c59Sftrigaux   double             tol;
28071c188c59Sftrigaux   PetscBool          print_statistics;
28081c188c59Sftrigaux   PetscInt           num_pre_relax,num_post_relax;
28091c188c59Sftrigaux } PC_SMG;
28101c188c59Sftrigaux 
28111c188c59Sftrigaux PetscErrorCode PCDestroy_SMG(PC pc)
28121c188c59Sftrigaux {
28131c188c59Sftrigaux   PC_SMG        *ex = (PC_SMG*) pc->data;
28141c188c59Sftrigaux 
28151c188c59Sftrigaux   PetscFunctionBegin;
28161c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy,ex->hsolver);
28171c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc),&ex->hcomm));
28181c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
28191c188c59Sftrigaux   PetscFunctionReturn(0);
28201c188c59Sftrigaux }
28211c188c59Sftrigaux 
28221c188c59Sftrigaux PetscErrorCode PCView_SMG(PC pc,PetscViewer viewer)
28231c188c59Sftrigaux {
28241c188c59Sftrigaux   PetscBool      iascii;
28251c188c59Sftrigaux   PC_SMG         *ex = (PC_SMG*) pc->data;
28261c188c59Sftrigaux 
28271c188c59Sftrigaux   PetscFunctionBegin;
28281c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
28291c188c59Sftrigaux   if (iascii) {
28301c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer,"  HYPRE SMG preconditioning\n"));
28311c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer,"    max iterations %" PetscInt_FMT "\n",ex->its));
28321c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer,"    tolerance %g\n",ex->tol));
28331c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer,"    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n",ex->num_pre_relax,ex->num_post_relax));
28341c188c59Sftrigaux   }
28351c188c59Sftrigaux   PetscFunctionReturn(0);
28361c188c59Sftrigaux }
28371c188c59Sftrigaux 
28381c188c59Sftrigaux PetscErrorCode PCSetFromOptions_SMG(PetscOptionItems *PetscOptionsObject,PC pc)
28391c188c59Sftrigaux {
28401c188c59Sftrigaux   PC_SMG        *ex = (PC_SMG*) pc->data;
28411c188c59Sftrigaux 
28421c188c59Sftrigaux   PetscFunctionBegin;
28431c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject,"SMG options");
28441c188c59Sftrigaux 
28451c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its","Number of iterations of SMG to use as preconditioner","HYPRE_StructSMGSetMaxIter",ex->its,&ex->its,NULL));
28461c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_StructSMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,NULL));
28471c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_StructSMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,NULL));
28481c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol","Tolerance of SMG","HYPRE_StructSMGSetTol",ex->tol,&ex->tol,NULL));
28491c188c59Sftrigaux 
28501c188c59Sftrigaux   PetscOptionsHeadEnd();
28511c188c59Sftrigaux   PetscFunctionReturn(0);
28521c188c59Sftrigaux }
28531c188c59Sftrigaux 
28541c188c59Sftrigaux PetscErrorCode PCApply_SMG(PC pc,Vec x,Vec y)
28551c188c59Sftrigaux {
28561c188c59Sftrigaux   PC_SMG           *ex = (PC_SMG*) pc->data;
28571c188c59Sftrigaux   PetscScalar       *yy;
28581c188c59Sftrigaux   const PetscScalar *xx;
28591c188c59Sftrigaux   PetscInt          ilower[3],iupper[3];
28601c188c59Sftrigaux   HYPRE_Int         hlower[3],hupper[3];
28611c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(pc->pmat->data);
28621c188c59Sftrigaux 
28631c188c59Sftrigaux   PetscFunctionBegin;
28641c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
28651c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
28661c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
28671c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
28681c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
28691c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
28701c188c59Sftrigaux   hlower[0]  = (HYPRE_Int)ilower[0];
28711c188c59Sftrigaux   hlower[1]  = (HYPRE_Int)ilower[1];
28721c188c59Sftrigaux   hlower[2]  = (HYPRE_Int)ilower[2];
28731c188c59Sftrigaux   hupper[0]  = (HYPRE_Int)iupper[0];
28741c188c59Sftrigaux   hupper[1]  = (HYPRE_Int)iupper[1];
28751c188c59Sftrigaux   hupper[2]  = (HYPRE_Int)iupper[2];
28761c188c59Sftrigaux 
28771c188c59Sftrigaux   /* copy x values over to hypre */
28781c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues,mx->hb,0.0);
28791c188c59Sftrigaux   PetscCall(VecGetArrayRead(x,&xx));
28801c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues,mx->hb,hlower,hupper,(HYPRE_Complex*)xx);
28811c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x,&xx));
28821c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble,mx->hb);
28831c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve,ex->hsolver,mx->hmat,mx->hb,mx->hx);
28841c188c59Sftrigaux 
28851c188c59Sftrigaux   /* copy solution values back to PETSc */
28861c188c59Sftrigaux   PetscCall(VecGetArray(y,&yy));
28871c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues,mx->hx,hlower,hupper,(HYPRE_Complex*)yy);
28881c188c59Sftrigaux   PetscCall(VecRestoreArray(y,&yy));
28891c188c59Sftrigaux   PetscFunctionReturn(0);
28901c188c59Sftrigaux }
28911c188c59Sftrigaux 
28921c188c59Sftrigaux static PetscErrorCode PCApplyRichardson_SMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
28931c188c59Sftrigaux {
28941c188c59Sftrigaux   PC_SMG        *jac = (PC_SMG*)pc->data;
28951c188c59Sftrigaux   HYPRE_Int      oits;
28961c188c59Sftrigaux 
28971c188c59Sftrigaux   PetscFunctionBegin;
28981c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation,&cite));
28991c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter,jac->hsolver,its*jac->its);
29001c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol,jac->hsolver,rtol);
29011c188c59Sftrigaux 
29021c188c59Sftrigaux   PetscCall(PCApply_SMG(pc,b,y));
29031c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations,jac->hsolver,&oits);
29041c188c59Sftrigaux   *outits = oits;
29051c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
29061c188c59Sftrigaux   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
29071c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol,jac->hsolver,jac->tol);
29081c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter,jac->hsolver,jac->its);
29091c188c59Sftrigaux   PetscFunctionReturn(0);
29101c188c59Sftrigaux }
29111c188c59Sftrigaux 
29121c188c59Sftrigaux PetscErrorCode PCSetUp_SMG(PC pc)
29131c188c59Sftrigaux {
29141c188c59Sftrigaux   PetscInt        i, dim;
29151c188c59Sftrigaux   PC_SMG         *ex = (PC_SMG*) pc->data;
29161c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(pc->pmat->data);
29171c188c59Sftrigaux   PetscBool       flg;
29181c188c59Sftrigaux   DMBoundaryType  p[3];
29191c188c59Sftrigaux   PetscInt        M[3];
29201c188c59Sftrigaux 
29211c188c59Sftrigaux   PetscFunctionBegin;
29221c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg));
29231c188c59Sftrigaux   PetscCheck(flg,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner");
29241c188c59Sftrigaux 
29251c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da,&dim,&M[0], &M[1], &M[2],0,0,0,0,0,&p[0],&p[1],&p[2],0));
29261c188c59Sftrigaux   // Check if power of 2 in periodic directions
29271c188c59Sftrigaux   for (i=0;i<dim;i++){
29281c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i]==DM_BOUNDARY_PERIODIC)) {
29291c188c59Sftrigaux       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"With SMG, the number of points in a periodic direction must be a power of 2, but is here %" PetscInt_FMT ".",M[i]);
29301c188c59Sftrigaux     }
29311c188c59Sftrigaux   }
29321c188c59Sftrigaux 
29331c188c59Sftrigaux   /* create the hypre solver object and set its information */
29341c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy,(ex->hsolver));
29351c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate,ex->hcomm,&ex->hsolver);
29361c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
29371c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter,ex->hsolver,ex->its);
29381c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax,ex->hsolver,ex->num_pre_relax);
29391c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax,ex->hsolver,ex->num_post_relax);
29401c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol,ex->hsolver,ex->tol);
29411c188c59Sftrigaux 
29421c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup,ex->hsolver,mx->hmat,mx->hb,mx->hx);
29431c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess,ex->hsolver);
29441c188c59Sftrigaux   PetscFunctionReturn(0);
29451c188c59Sftrigaux }
29461c188c59Sftrigaux 
29471c188c59Sftrigaux /*MC
2948*5cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
29491c188c59Sftrigaux 
29501c188c59Sftrigaux    Level: advanced
29511c188c59Sftrigaux 
29521c188c59Sftrigaux    Options Database:
2953*5cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
2954*5cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
2955*5cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
2956*5cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
29571c188c59Sftrigaux 
29581c188c59Sftrigaux    Notes:
29591c188c59Sftrigaux    This is for CELL-centered descretizations
29601c188c59Sftrigaux 
2961*5cb80ecdSBarry Smith   This must be used with the `MATHYPRESTRUCT` `MatType`.
2962*5cb80ecdSBarry Smith   This support is less general than in hypre, it supports only one block per process defined by a PETSc `DMDA`.
29631c188c59Sftrigaux 
29641c188c59Sftrigaux .seealso:  PCMG, MATHYPRESTRUCT, PCPFMG
29651c188c59Sftrigaux M*/
29661c188c59Sftrigaux 
29671c188c59Sftrigaux PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
29681c188c59Sftrigaux {
29691c188c59Sftrigaux   PC_SMG        *ex;
29701c188c59Sftrigaux 
29711c188c59Sftrigaux   PetscFunctionBegin;
29721c188c59Sftrigaux   PetscCall(PetscNew(&ex)); \
29731c188c59Sftrigaux   pc->data = ex;
29741c188c59Sftrigaux 
29751c188c59Sftrigaux   ex->its            = 1;
29761c188c59Sftrigaux   ex->tol            = 1.e-8;
29771c188c59Sftrigaux   ex->num_pre_relax  = 1;
29781c188c59Sftrigaux   ex->num_post_relax = 1;
29791c188c59Sftrigaux 
29801c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
29811c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
29821c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
29831c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
29841c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
29851c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
29861c188c59Sftrigaux 
29871c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc),&ex->hcomm));
29881c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate,ex->hcomm,&ex->hsolver);
29891c188c59Sftrigaux   PetscFunctionReturn(0);
29901c188c59Sftrigaux }
2991