xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision e1ded4072bd11a97a078276d9035bf9425384c0a)
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;
219371c9d4SSatish Balay static const char hypreCitation[] = "@manual{hypre-web-page,\n  title  = {{\\sl hypre}: High Performance Preconditioners},\n  organization = {Lawrence Livermore National Laboratory},\n  note  = "
22bd87328aSJed Brown                                     "{\\url{https://www.llnl.gov/casc/hypre}}\n}\n";
231f817a21SBarry Smith 
2416d9e3a6SLisandro Dalcin /*
2516d9e3a6SLisandro Dalcin    Private context (data structure) for the  preconditioner.
2616d9e3a6SLisandro Dalcin */
2716d9e3a6SLisandro Dalcin typedef struct {
2816d9e3a6SLisandro Dalcin   HYPRE_Solver hsolver;
2949a781f5SStefano Zampini   Mat          hpmat; /* MatHYPRE */
3016d9e3a6SLisandro Dalcin 
314ddd07fcSJed Brown   HYPRE_Int (*destroy)(HYPRE_Solver);
324ddd07fcSJed Brown   HYPRE_Int (*solve)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
334ddd07fcSJed Brown   HYPRE_Int (*setup)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
3416d9e3a6SLisandro Dalcin 
3516d9e3a6SLisandro Dalcin   MPI_Comm comm_hypre;
3616d9e3a6SLisandro Dalcin   char    *hypre_type;
3716d9e3a6SLisandro Dalcin 
3816d9e3a6SLisandro Dalcin   /* options for Pilut and BoomerAMG*/
394ddd07fcSJed Brown   PetscInt  maxiter;
4039accc25SStefano Zampini   PetscReal tol;
4116d9e3a6SLisandro Dalcin 
4216d9e3a6SLisandro Dalcin   /* options for Pilut */
434ddd07fcSJed Brown   PetscInt factorrowsize;
4416d9e3a6SLisandro Dalcin 
4516d9e3a6SLisandro Dalcin   /* options for ParaSails */
464ddd07fcSJed Brown   PetscInt  nlevels;
478966356dSPierre Jolivet   PetscReal threshold;
4839accc25SStefano Zampini   PetscReal filter;
4939accc25SStefano Zampini   PetscReal loadbal;
504ddd07fcSJed Brown   PetscInt  logging;
514ddd07fcSJed Brown   PetscInt  ruse;
524ddd07fcSJed Brown   PetscInt  symt;
5316d9e3a6SLisandro Dalcin 
5422b6d1caSBarry Smith   /* options for BoomerAMG */
55ace3abfcSBarry Smith   PetscBool printstatistics;
5616d9e3a6SLisandro Dalcin 
5716d9e3a6SLisandro Dalcin   /* options for BoomerAMG */
584ddd07fcSJed Brown   PetscInt  cycletype;
594ddd07fcSJed Brown   PetscInt  maxlevels;
6039accc25SStefano Zampini   PetscReal strongthreshold;
6139accc25SStefano Zampini   PetscReal maxrowsum;
624ddd07fcSJed Brown   PetscInt  gridsweeps[3];
634ddd07fcSJed Brown   PetscInt  coarsentype;
644ddd07fcSJed Brown   PetscInt  measuretype;
656a251517SEike Mueller   PetscInt  smoothtype;
668131ecf7SEike Mueller   PetscInt  smoothnumlevels;
67ec64516dSEike Mueller   PetscInt  eu_level;         /* Number of levels for ILU(k) in Euclid */
6839accc25SStefano Zampini   PetscReal eu_droptolerance; /* Drop tolerance for ILU(k) in Euclid */
69ec64516dSEike Mueller   PetscInt  eu_bj;            /* Defines use of Block Jacobi ILU in Euclid */
704ddd07fcSJed Brown   PetscInt  relaxtype[3];
7139accc25SStefano Zampini   PetscReal relaxweight;
7239accc25SStefano Zampini   PetscReal outerrelaxweight;
734ddd07fcSJed Brown   PetscInt  relaxorder;
7439accc25SStefano Zampini   PetscReal truncfactor;
75ace3abfcSBarry Smith   PetscBool applyrichardson;
764ddd07fcSJed Brown   PetscInt  pmax;
774ddd07fcSJed Brown   PetscInt  interptype;
78589dcaf0SStefano Zampini   PetscInt  maxc;
79589dcaf0SStefano Zampini   PetscInt  minc;
80db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
81db6f9c32SMark Adams   char *spgemm_type; // this is a global hypre parameter but is closely associated with BoomerAMG
82db6f9c32SMark Adams #endif
836ea7df73SStefano Zampini   /* GPU */
846ea7df73SStefano Zampini   PetscBool keeptranspose;
856ea7df73SStefano Zampini   PetscInt  rap2;
866ea7df73SStefano Zampini   PetscInt  mod_rap2;
876ea7df73SStefano Zampini 
88589dcaf0SStefano Zampini   /* AIR */
89589dcaf0SStefano Zampini   PetscInt  Rtype;
90589dcaf0SStefano Zampini   PetscReal Rstrongthreshold;
91589dcaf0SStefano Zampini   PetscReal Rfilterthreshold;
92589dcaf0SStefano Zampini   PetscInt  Adroptype;
93589dcaf0SStefano Zampini   PetscReal Adroptol;
94589dcaf0SStefano Zampini 
954ddd07fcSJed Brown   PetscInt  agg_nl;
966ea7df73SStefano Zampini   PetscInt  agg_interptype;
974ddd07fcSJed Brown   PetscInt  agg_num_paths;
98ace3abfcSBarry Smith   PetscBool nodal_relax;
994ddd07fcSJed Brown   PetscInt  nodal_relax_levels;
1004cb006feSStefano Zampini 
1015272c319SBarry Smith   PetscInt  nodal_coarsening;
10222e51d31SStefano Zampini   PetscInt  nodal_coarsening_diag;
1035272c319SBarry Smith   PetscInt  vec_interp_variant;
10422e51d31SStefano Zampini   PetscInt  vec_interp_qmax;
10522e51d31SStefano Zampini   PetscBool vec_interp_smooth;
10622e51d31SStefano Zampini   PetscInt  interp_refine;
10722e51d31SStefano Zampini 
1086ea7df73SStefano Zampini   /* NearNullSpace support */
1096ea7df73SStefano Zampini   VecHYPRE_IJVector *hmnull;
1106ea7df73SStefano Zampini   HYPRE_ParVector   *phmnull;
1115272c319SBarry Smith   PetscInt           n_hmnull;
1125272c319SBarry Smith   Vec                hmnull_constant;
1135272c319SBarry Smith 
114863406b8SStefano Zampini   /* options for AS (Auxiliary Space preconditioners) */
115863406b8SStefano Zampini   PetscInt  as_print;
116863406b8SStefano Zampini   PetscInt  as_max_iter;
117863406b8SStefano Zampini   PetscReal as_tol;
118863406b8SStefano Zampini   PetscInt  as_relax_type;
119863406b8SStefano Zampini   PetscInt  as_relax_times;
120863406b8SStefano Zampini   PetscReal as_relax_weight;
121863406b8SStefano Zampini   PetscReal as_omega;
122863406b8SStefano 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) */
123863406b8SStefano Zampini   PetscReal as_amg_alpha_theta;   /* AMG strength for vector Poisson (AMS) or Curl problem (ADS) */
124863406b8SStefano 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) */
125863406b8SStefano Zampini   PetscReal as_amg_beta_theta;    /* AMG strength for scalar Poisson (AMS) or vector Poisson (ADS)  */
1264cb006feSStefano Zampini   PetscInt  ams_cycle_type;
127863406b8SStefano Zampini   PetscInt  ads_cycle_type;
1284cb006feSStefano Zampini 
1294cb006feSStefano Zampini   /* additional data */
1305ac14e1cSStefano Zampini   Mat G;             /* MatHYPRE */
1315ac14e1cSStefano Zampini   Mat C;             /* MatHYPRE */
1325ac14e1cSStefano Zampini   Mat alpha_Poisson; /* MatHYPRE */
1335ac14e1cSStefano Zampini   Mat beta_Poisson;  /* MatHYPRE */
1345ac14e1cSStefano Zampini 
1355ac14e1cSStefano Zampini   /* extra information for AMS */
1365ac14e1cSStefano Zampini   PetscInt          dim; /* geometrical dimension */
1376ea7df73SStefano Zampini   VecHYPRE_IJVector coords[3];
1386ea7df73SStefano Zampini   VecHYPRE_IJVector constants[3];
139be14dc20SKerry Key   VecHYPRE_IJVector interior;
1406bf688a0SCe Qin   Mat               RT_PiFull, RT_Pi[3];
1416bf688a0SCe Qin   Mat               ND_PiFull, ND_Pi[3];
1424cb006feSStefano Zampini   PetscBool         ams_beta_is_zero;
14323df4f25SStefano Zampini   PetscBool         ams_beta_is_zero_part;
14423df4f25SStefano Zampini   PetscInt          ams_proj_freq;
14516d9e3a6SLisandro Dalcin } PC_HYPRE;
14616d9e3a6SLisandro Dalcin 
147d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetSolver(PC pc, HYPRE_Solver *hsolver)
148d71ae5a4SJacob Faibussowitsch {
149d2128fa2SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
150d2128fa2SBarry Smith 
151d2128fa2SBarry Smith   PetscFunctionBegin;
152d2128fa2SBarry Smith   *hsolver = jac->hsolver;
1533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
154d2128fa2SBarry Smith }
15516d9e3a6SLisandro Dalcin 
156fd2dd295SFande Kong /*
1578a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1588a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1598a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
160fd2dd295SFande Kong */
161d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[])
162d71ae5a4SJacob Faibussowitsch {
1638a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1648a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1658a2c336bSFande Kong   PetscInt             num_levels, l;
1668a2c336bSFande Kong   Mat                 *mattmp;
1678a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1688a2c336bSFande Kong 
1698a2c336bSFande Kong   PetscFunctionBegin;
1709566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1715f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1728a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1748a2c336bSFande Kong   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)(jac->hsolver));
1758a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1769566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[num_levels - 1 - l])));
1778a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1788a2c336bSFande Kong     A_array[l] = NULL;
1798a2c336bSFande Kong   }
1808a2c336bSFande Kong   *nlevels   = num_levels;
1818a2c336bSFande Kong   *operators = mattmp;
1823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1838a2c336bSFande Kong }
1848a2c336bSFande Kong 
185fd2dd295SFande Kong /*
1868a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1878a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1888a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
189fd2dd295SFande Kong */
190d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[])
191d71ae5a4SJacob Faibussowitsch {
1928a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1938a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1948a2c336bSFande Kong   PetscInt             num_levels, l;
1958a2c336bSFande Kong   Mat                 *mattmp;
1968a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1978a2c336bSFande Kong 
1988a2c336bSFande Kong   PetscFunctionBegin;
1999566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
2005f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
2018a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
2029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
2038a2c336bSFande Kong   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)(jac->hsolver));
2048a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
2059566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[l - 1])));
2068a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
2078a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
2088a2c336bSFande Kong   }
2098a2c336bSFande Kong   *nlevels        = num_levels;
2108a2c336bSFande Kong   *interpolations = mattmp;
2113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2128a2c336bSFande Kong }
2138a2c336bSFande Kong 
214ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
215d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
216d71ae5a4SJacob Faibussowitsch {
217ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
218ce6a8a0dSJed Brown   PetscInt  i;
219ce6a8a0dSJed Brown 
2209d678128SJed Brown   PetscFunctionBegin;
22148a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2229566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2259d678128SJed Brown   jac->n_hmnull = 0;
2263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227ce6a8a0dSJed Brown }
228ce6a8a0dSJed Brown 
229d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
230d71ae5a4SJacob Faibussowitsch {
23116d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
23249a781f5SStefano Zampini   Mat_HYPRE         *hjac;
23316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
23416d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
23549a781f5SStefano Zampini   PetscBool          ishypre;
23616d9e3a6SLisandro Dalcin 
23716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23848a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2395f5c5b43SBarry Smith 
2409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
24149a781f5SStefano Zampini   if (!ishypre) {
2429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
2439566063dSJacob Faibussowitsch     PetscCall(MatConvert(pc->pmat, MATHYPRE, MAT_INITIAL_MATRIX, &jac->hpmat));
24449a781f5SStefano Zampini   } else {
2459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
24749a781f5SStefano Zampini     jac->hpmat = pc->pmat;
24816d9e3a6SLisandro Dalcin   }
2496ea7df73SStefano Zampini   /* allow debug */
2509566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
25149a781f5SStefano Zampini   hjac = (Mat_HYPRE *)(jac->hpmat->data);
2525f5c5b43SBarry Smith 
25316d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25416d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2555272c319SBarry Smith     MatNullSpace mnull;
2565272c319SBarry Smith     PetscBool    has_const;
25749a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2585272c319SBarry Smith     const Vec   *vecs;
2595272c319SBarry Smith 
2609566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
261792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2629566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2635272c319SBarry Smith     if (mnull) {
2649566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2659566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2685272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2699566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2709566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
271792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2725272c319SBarry Smith       }
2735272c319SBarry Smith       if (has_const) {
2749566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2759566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2769566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2779566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2789566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
279792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2805272c319SBarry Smith         nvec++;
2815272c319SBarry Smith       }
282792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2835272c319SBarry Smith       jac->n_hmnull = nvec;
2845272c319SBarry Smith     }
2854cb006feSStefano Zampini   }
286863406b8SStefano Zampini 
2874cb006feSStefano Zampini   /* special case for AMS */
2884cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2895ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
2905ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2916bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
292f1580f4eSBarry Smith       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()");
2936bf688a0SCe Qin     }
29448a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
2955ac14e1cSStefano Zampini     if (jac->constants[0]) {
2965ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
297792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
298792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
29948a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
300792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
3015ac14e1cSStefano Zampini     }
3025ac14e1cSStefano Zampini     if (jac->coords[0]) {
3035ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3045ac14e1cSStefano Zampini       coords[0] = NULL;
3055ac14e1cSStefano Zampini       coords[1] = NULL;
3065ac14e1cSStefano Zampini       coords[2] = NULL;
307792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
308792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
309792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
310792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3115ac14e1cSStefano Zampini     }
3125f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3135ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
314792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
315792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3165ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3175ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->alpha_Poisson->data);
318792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
319792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3205ac14e1cSStefano Zampini     }
3215ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3235ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3245ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->beta_Poisson->data);
325792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
326792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
327be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
328be14dc20SKerry Key       if (jac->interior) {
329be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
330be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
331be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
332be14dc20SKerry Key       } else {
333be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
334be14dc20SKerry Key       }
3355ac14e1cSStefano Zampini     }
3366bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3376bf688a0SCe Qin       PetscInt           i;
3386bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3396bf688a0SCe Qin       if (jac->ND_PiFull) {
3406bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
341792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3426bf688a0SCe Qin       } else {
3436bf688a0SCe Qin         nd_parcsrfull = NULL;
3446bf688a0SCe Qin       }
3456bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3466bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3476bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
348792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3496bf688a0SCe Qin         } else {
3506bf688a0SCe Qin           nd_parcsr[i] = NULL;
3516bf688a0SCe Qin         }
3526bf688a0SCe Qin       }
353792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3546bf688a0SCe Qin     }
3554cb006feSStefano Zampini   }
356863406b8SStefano Zampini   /* special case for ADS */
357863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3585ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3595ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3606bf688a0SCe 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])))) {
3616bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3629371c9d4SSatish Balay     } 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");
3635f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3645f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3655ac14e1cSStefano Zampini     if (jac->coords[0]) {
3665ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3675ac14e1cSStefano Zampini       coords[0] = NULL;
3685ac14e1cSStefano Zampini       coords[1] = NULL;
3695ac14e1cSStefano Zampini       coords[2] = NULL;
370792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
371792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
372792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
373792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3745ac14e1cSStefano Zampini     }
3755ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
376792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
377792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
3785ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->C->data);
379792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
380792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3816bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3826bf688a0SCe Qin       PetscInt           i;
3836bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3846bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3856bf688a0SCe Qin       if (jac->RT_PiFull) {
3866bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->RT_PiFull->data);
387792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
3886bf688a0SCe Qin       } else {
3896bf688a0SCe Qin         rt_parcsrfull = NULL;
3906bf688a0SCe Qin       }
3916bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3926bf688a0SCe Qin         if (jac->RT_Pi[i]) {
3936bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->RT_Pi[i]->data);
394792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
3956bf688a0SCe Qin         } else {
3966bf688a0SCe Qin           rt_parcsr[i] = NULL;
3976bf688a0SCe Qin         }
3986bf688a0SCe Qin       }
3996bf688a0SCe Qin       if (jac->ND_PiFull) {
4006bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
401792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4026bf688a0SCe Qin       } else {
4036bf688a0SCe Qin         nd_parcsrfull = NULL;
4046bf688a0SCe Qin       }
4056bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4066bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4076bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
408792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4096bf688a0SCe Qin         } else {
4106bf688a0SCe Qin           nd_parcsr[i] = NULL;
4116bf688a0SCe Qin         }
4126bf688a0SCe Qin       }
413792fecdfSBarry 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]);
4146bf688a0SCe Qin     }
415863406b8SStefano Zampini   }
416792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
417792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
418792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
41997c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
420792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
42197c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
4223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42316d9e3a6SLisandro Dalcin }
42416d9e3a6SLisandro Dalcin 
425d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
426d71ae5a4SJacob Faibussowitsch {
42716d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
42849a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
42916d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
43016d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
43116d9e3a6SLisandro Dalcin 
43216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4339566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4349566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4359566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4369566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4379566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
438792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
439792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
440792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4419371c9d4SSatish Balay   PetscStackCallExternalVoid(
4429371c9d4SSatish Balay     "Hypre solve", do {
4435f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4445f80ce2aSJacob Faibussowitsch       if (hierr) {
4455f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
4465f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
4475f80ce2aSJacob Faibussowitsch       }
4485f80ce2aSJacob Faibussowitsch     } while (0));
44916d9e3a6SLisandro Dalcin 
45048a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4519566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4529566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
4533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45416d9e3a6SLisandro Dalcin }
45516d9e3a6SLisandro Dalcin 
456d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
457d71ae5a4SJacob Faibussowitsch {
4588695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
4598695de01SBarry Smith 
4608695de01SBarry Smith   PetscFunctionBegin;
4619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
4629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
4639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
4649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
4659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
4669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
4679566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
4689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
4699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
4709566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
4719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
4729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
4739566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
4749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
4759566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
4769566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
4779566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
4789566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
4799566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
480be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
4819566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
4825ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
483be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
4845ac14e1cSStefano Zampini   jac->dim                   = 0;
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4868695de01SBarry Smith }
4878695de01SBarry Smith 
488d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
489d71ae5a4SJacob Faibussowitsch {
49016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
49116d9e3a6SLisandro Dalcin 
49216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4939566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
494792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
4959566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
496db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
4979566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
498db6f9c32SMark Adams #endif
4999566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
5009566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
50116d9e3a6SLisandro Dalcin 
5029566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5102e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
511be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5162e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
5173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51816d9e3a6SLisandro Dalcin }
51916d9e3a6SLisandro Dalcin 
520d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
521d71ae5a4SJacob Faibussowitsch {
52216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
523ace3abfcSBarry Smith   PetscBool flag;
52416d9e3a6SLisandro Dalcin 
52516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
526d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
528792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
530792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
532792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
533d0609cedSBarry Smith   PetscOptionsHeadEnd();
5343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53516d9e3a6SLisandro Dalcin }
53616d9e3a6SLisandro Dalcin 
537d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
538d71ae5a4SJacob Faibussowitsch {
53916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
540ace3abfcSBarry Smith   PetscBool iascii;
54116d9e3a6SLisandro Dalcin 
54216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
54416d9e3a6SLisandro Dalcin   if (iascii) {
5459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
54616d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
54763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
54816d9e3a6SLisandro Dalcin     } else {
5499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
55016d9e3a6SLisandro Dalcin     }
55116d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
5529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
55316d9e3a6SLisandro Dalcin     } else {
5549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
55516d9e3a6SLisandro Dalcin     }
55616d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
55763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
55816d9e3a6SLisandro Dalcin     } else {
5599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
56016d9e3a6SLisandro Dalcin     }
56116d9e3a6SLisandro Dalcin   }
5623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56316d9e3a6SLisandro Dalcin }
56416d9e3a6SLisandro Dalcin 
565d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
566d71ae5a4SJacob Faibussowitsch {
567db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5688bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
569db966c6cSHong Zhang 
570db966c6cSHong Zhang   PetscFunctionBegin;
571d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
5729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
573792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
5748bf83915SBarry Smith 
5759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
5768bf83915SBarry Smith   if (flag) {
5778bf83915SBarry Smith     PetscMPIInt size;
5788bf83915SBarry Smith 
5799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
5807827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
581792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
5828bf83915SBarry Smith   }
5838bf83915SBarry Smith 
5849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
5858bf83915SBarry Smith   if (flag) {
5868bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
587792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
5888bf83915SBarry Smith   }
589d0609cedSBarry Smith   PetscOptionsHeadEnd();
5903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
591db966c6cSHong Zhang }
592db966c6cSHong Zhang 
593d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
594d71ae5a4SJacob Faibussowitsch {
595db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
596db966c6cSHong Zhang   PetscBool iascii;
597db966c6cSHong Zhang 
598db966c6cSHong Zhang   PetscFunctionBegin;
5999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
600db966c6cSHong Zhang   if (iascii) {
6019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
602db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
60363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
604db966c6cSHong Zhang     } else {
6059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
606db966c6cSHong Zhang     }
6079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
60863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
609db966c6cSHong Zhang   }
6103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
611db966c6cSHong Zhang }
612db966c6cSHong Zhang 
613d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
614d71ae5a4SJacob Faibussowitsch {
61516d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
61649a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
61716d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
61816d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
61916d9e3a6SLisandro Dalcin 
62016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6219566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6229566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6239566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6249566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
62516d9e3a6SLisandro Dalcin 
626792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
627792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
628792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
62916d9e3a6SLisandro Dalcin 
6309371c9d4SSatish Balay   PetscStackCallExternalVoid(
6319371c9d4SSatish Balay     "Hypre Transpose solve", do {
6325f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6335f80ce2aSJacob Faibussowitsch       if (hierr) {
63416d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6355f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
6365f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
6375f80ce2aSJacob Faibussowitsch       }
6385f80ce2aSJacob Faibussowitsch     } while (0));
63916d9e3a6SLisandro Dalcin 
6409566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6419566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64316d9e3a6SLisandro Dalcin }
64416d9e3a6SLisandro Dalcin 
645d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
646d71ae5a4SJacob Faibussowitsch {
647db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
648db6f9c32SMark Adams   PetscBool flag;
649db6f9c32SMark Adams 
650db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
651db6f9c32SMark Adams   PetscFunctionBegin;
652db6f9c32SMark Adams   if (jac->spgemm_type) {
6539566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
65428b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
6553ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
656db6f9c32SMark Adams   } else {
6579566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
658db6f9c32SMark Adams   }
6599566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
660db6f9c32SMark Adams   if (flag) {
661792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
6623ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
663db6f9c32SMark Adams   }
6649566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
665db6f9c32SMark Adams   if (flag) {
666792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
6673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
668db6f9c32SMark Adams   }
669db6f9c32SMark Adams   jac->spgemm_type = NULL;
67098921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEM type %s; Choices are cusparse, hypre", name);
671db6f9c32SMark Adams #endif
672db6f9c32SMark Adams }
673db6f9c32SMark Adams 
674d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
675d71ae5a4SJacob Faibussowitsch {
676db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
677db6f9c32SMark Adams 
678db6f9c32SMark Adams   PetscFunctionBegin;
679db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
680db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
681db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
682db6f9c32SMark Adams #endif
6833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
684db6f9c32SMark Adams }
685db6f9c32SMark Adams 
68616d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
6870f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
68816d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
68965de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
6906a251517SEike Mueller static const char *HYPREBoomerAMGSmoothType[] = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
6919371c9d4SSatish Balay static const char *HYPREBoomerAMGRelaxType[] = {"Jacobi", "sequential-Gauss-Seidel", "seqboundary-Gauss-Seidel", "SOR/Jacobi", "backward-SOR/Jacobi", "" /* [5] hybrid chaotic Gauss-Seidel (works only with OpenMP) */, "symmetric-SOR/Jacobi", "" /* 7 */, "l1scaled-SOR/Jacobi", "Gaussian-elimination", "" /* 10 */, "" /* 11 */, "" /* 12 */, "l1-Gauss-Seidel" /* nonsymmetric */, "backward-l1-Gauss-Seidel" /* nonsymmetric */, "CG" /* non-stationary */, "Chebyshev", "FCF-Jacobi", "l1scaled-Jacobi"};
6929371c9d4SSatish Balay static const char    *HYPREBoomerAMGInterpType[] = {"classical", "", "", "direct", "multipass", "multipass-wts", "ext+i", "ext+i-cc", "standard", "standard-wts", "block", "block-wtd", "FF", "FF1", "ext", "ad-wts", "ext-mm", "ext+i-mm", "ext+e-mm"};
693d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
694d71ae5a4SJacob Faibussowitsch {
69516d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
69622e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
697ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
69816d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
699589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
700db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
70116d9e3a6SLisandro Dalcin 
70216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
703d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
7049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
70516d9e3a6SLisandro Dalcin   if (flg) {
7064336a9eeSBarry Smith     jac->cycletype = indx + 1;
707792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
70816d9e3a6SLisandro Dalcin   }
7099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
71016d9e3a6SLisandro Dalcin   if (flg) {
71163a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
712792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
71316d9e3a6SLisandro Dalcin   }
7149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
71516d9e3a6SLisandro Dalcin   if (flg) {
71663a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
717792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
71816d9e3a6SLisandro Dalcin   }
7199566063dSJacob 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));
72016d9e3a6SLisandro Dalcin   if (flg) {
72108401ef6SPierre 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);
722792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
72316d9e3a6SLisandro Dalcin   }
72422e51d31SStefano Zampini   bs = 1;
72548a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
72748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
72816d9e3a6SLisandro Dalcin 
7299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
73016d9e3a6SLisandro Dalcin   if (flg) {
73108401ef6SPierre 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);
732792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
73316d9e3a6SLisandro Dalcin   }
73416d9e3a6SLisandro Dalcin 
7359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7360f1074feSSatish Balay   if (flg) {
73763a3b9bcSJacob 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);
738792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7390f1074feSSatish Balay   }
7400f1074feSSatish Balay 
7419566063dSJacob 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));
742792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7430f1074feSSatish Balay 
7449566063dSJacob 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));
7450f1074feSSatish Balay   if (flg) {
74663a3b9bcSJacob 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);
747792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
7480f1074feSSatish Balay   }
7490f1074feSSatish Balay 
7509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
75116d9e3a6SLisandro Dalcin   if (flg) {
75208401ef6SPierre 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);
753792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
75416d9e3a6SLisandro Dalcin   }
7559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
75616d9e3a6SLisandro Dalcin   if (flg) {
75708401ef6SPierre 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);
75808401ef6SPierre 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);
759792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
76016d9e3a6SLisandro Dalcin   }
76116d9e3a6SLisandro Dalcin 
76216d9e3a6SLisandro Dalcin   /* Grid sweeps */
7639566063dSJacob 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));
76416d9e3a6SLisandro Dalcin   if (flg) {
765792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
76616d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
76716d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
7680f1074feSSatish Balay     jac->gridsweeps[1] = indx;
7690f1074feSSatish Balay     /*defaults coarse to 1 */
7700f1074feSSatish Balay     jac->gridsweeps[2] = 1;
77116d9e3a6SLisandro Dalcin   }
7729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
77348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
7749566063dSJacob 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));
77548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
7769566063dSJacob 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));
77748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
7789566063dSJacob 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));
77948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
7809566063dSJacob 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));
78148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
7829566063dSJacob 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));
78348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
7849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
78516d9e3a6SLisandro Dalcin   if (flg) {
786792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
7870f1074feSSatish Balay     jac->gridsweeps[0] = indx;
78816d9e3a6SLisandro Dalcin   }
7899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
79016d9e3a6SLisandro Dalcin   if (flg) {
791792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
7920f1074feSSatish Balay     jac->gridsweeps[1] = indx;
79316d9e3a6SLisandro Dalcin   }
7949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
79516d9e3a6SLisandro Dalcin   if (flg) {
796792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
7970f1074feSSatish Balay     jac->gridsweeps[2] = indx;
79816d9e3a6SLisandro Dalcin   }
79916d9e3a6SLisandro Dalcin 
8006a251517SEike Mueller   /* Smooth type */
801dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
8026a251517SEike Mueller   if (flg) {
8036a251517SEike Mueller     jac->smoothtype = indx;
804792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
8058131ecf7SEike Mueller     jac->smoothnumlevels = 25;
806792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
8078131ecf7SEike Mueller   }
8088131ecf7SEike Mueller 
8098131ecf7SEike Mueller   /* Number of smoothing levels */
8109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
8118131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8128131ecf7SEike Mueller     jac->smoothnumlevels = indx;
813792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8146a251517SEike Mueller   }
8156a251517SEike Mueller 
8161810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8181810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8191810e44eSEike Mueller     jac->eu_level = indx;
820792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8211810e44eSEike Mueller   }
8221810e44eSEike Mueller 
8231810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8241810e44eSEike Mueller   double droptolerance;
8259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8261810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8271810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
828792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8291810e44eSEike Mueller   }
8301810e44eSEike Mueller 
8311810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8331810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8341810e44eSEike Mueller     jac->eu_bj = tmp_truth;
835792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8361810e44eSEike Mueller   }
8371810e44eSEike Mueller 
83816d9e3a6SLisandro Dalcin   /* Relax type */
839dd39110bSPierre 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));
84016d9e3a6SLisandro Dalcin   if (flg) {
8410f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
842792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8430f1074feSSatish Balay     /* by default, coarse type set to 9 */
8440f1074feSSatish Balay     jac->relaxtype[2] = 9;
845792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
84616d9e3a6SLisandro Dalcin   }
847dd39110bSPierre 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));
84816d9e3a6SLisandro Dalcin   if (flg) {
84916d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
850792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
85116d9e3a6SLisandro Dalcin   }
852dd39110bSPierre 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));
85316d9e3a6SLisandro Dalcin   if (flg) {
8540f1074feSSatish Balay     jac->relaxtype[1] = indx;
855792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
85616d9e3a6SLisandro Dalcin   }
857dd39110bSPierre 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));
85816d9e3a6SLisandro Dalcin   if (flg) {
8590f1074feSSatish Balay     jac->relaxtype[2] = indx;
860792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
86116d9e3a6SLisandro Dalcin   }
86216d9e3a6SLisandro Dalcin 
86316d9e3a6SLisandro Dalcin   /* Relaxation Weight */
8649566063dSJacob 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));
86516d9e3a6SLisandro Dalcin   if (flg) {
866792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
86716d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
86816d9e3a6SLisandro Dalcin   }
86916d9e3a6SLisandro Dalcin 
87016d9e3a6SLisandro Dalcin   n         = 2;
87116d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
87316d9e3a6SLisandro Dalcin   if (flg) {
8740fdf79fbSJacob Faibussowitsch     PetscCheck(n == 2, 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);
87516d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
876792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
87716d9e3a6SLisandro Dalcin   }
87816d9e3a6SLisandro Dalcin 
87916d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
8809566063dSJacob 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));
88116d9e3a6SLisandro Dalcin   if (flg) {
882792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
88316d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
88416d9e3a6SLisandro Dalcin   }
88516d9e3a6SLisandro Dalcin 
88616d9e3a6SLisandro Dalcin   n         = 2;
88716d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8889566063dSJacob 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));
88916d9e3a6SLisandro Dalcin   if (flg) {
8900fdf79fbSJacob Faibussowitsch     PetscCheck(n == 2, 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);
89116d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
892792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
89316d9e3a6SLisandro Dalcin   }
89416d9e3a6SLisandro Dalcin 
89516d9e3a6SLisandro Dalcin   /* the Relax Order */
8969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
89716d9e3a6SLisandro Dalcin 
8988afaa268SBarry Smith   if (flg && tmp_truth) {
89916d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
900792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
90116d9e3a6SLisandro Dalcin   }
902dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
90316d9e3a6SLisandro Dalcin   if (flg) {
90416d9e3a6SLisandro Dalcin     jac->measuretype = indx;
905792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
90616d9e3a6SLisandro Dalcin   }
9070f1074feSSatish Balay   /* update list length 3/07 */
908dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
90916d9e3a6SLisandro Dalcin   if (flg) {
91016d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
911792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
91216d9e3a6SLisandro Dalcin   }
9130f1074feSSatish Balay 
9149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
91548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
91748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
918db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
919db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
920dd39110bSPierre 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));
921db6f9c32SMark Adams   if (!flg) indx = 0;
9229566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
923db6f9c32SMark Adams #endif
924589dcaf0SStefano Zampini   /* AIR */
925589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9269566063dSJacob 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));
927792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
928589dcaf0SStefano Zampini   if (jac->Rtype) {
929589dcaf0SStefano 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 */
930589dcaf0SStefano Zampini 
9319566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
932792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
933589dcaf0SStefano Zampini 
9349566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
935792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
936589dcaf0SStefano Zampini 
9379566063dSJacob 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));
938792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
939589dcaf0SStefano Zampini 
9409566063dSJacob 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));
941792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
942589dcaf0SStefano Zampini   }
943589dcaf0SStefano Zampini #endif
944589dcaf0SStefano Zampini 
945ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
94663a3b9bcSJacob 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);
947ecae95adSPierre Jolivet #endif
948ecae95adSPierre Jolivet 
9490f1074feSSatish Balay   /* new 3/07 */
950dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
951589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
952589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
953792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
9540f1074feSSatish Balay   }
9550f1074feSSatish Balay 
9569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
95716d9e3a6SLisandro Dalcin   if (flg) {
958b96a4a96SBarry Smith     level = 3;
9599566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
9602fa5cd67SKarl Rupp 
961b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
962792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
9632ae77aedSBarry Smith   }
9642ae77aedSBarry Smith 
9659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
9662ae77aedSBarry Smith   if (flg) {
967b96a4a96SBarry Smith     level = 3;
9689566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
9692fa5cd67SKarl Rupp 
970b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
971792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
97216d9e3a6SLisandro Dalcin   }
9738f87f92bSBarry Smith 
9749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
9758f87f92bSBarry Smith   if (flg && tmp_truth) {
9768f87f92bSBarry Smith     PetscInt tmp_int;
9779566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
9788f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
979792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
980792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
981792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
982792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
9838f87f92bSBarry Smith   }
9848f87f92bSBarry Smith 
9859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
986792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
987589dcaf0SStefano Zampini 
988589dcaf0SStefano Zampini   /* options for ParaSails solvers */
989dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
990589dcaf0SStefano Zampini   if (flg) {
991589dcaf0SStefano Zampini     jac->symt = indx;
992792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
993589dcaf0SStefano Zampini   }
994589dcaf0SStefano Zampini 
995d0609cedSBarry Smith   PetscOptionsHeadEnd();
9963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99716d9e3a6SLisandro Dalcin }
99816d9e3a6SLisandro Dalcin 
999d71ae5a4SJacob Faibussowitsch 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)
1000d71ae5a4SJacob Faibussowitsch {
100116d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
10022cf14000SStefano Zampini   HYPRE_Int oits;
100316d9e3a6SLisandro Dalcin 
100416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10059566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1006792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1007792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
100816d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
10099566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
101016d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1011792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
10124d0a8057SBarry Smith   *outits = oits;
10134d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10144d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1015792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1016792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
10173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101816d9e3a6SLisandro Dalcin }
101916d9e3a6SLisandro Dalcin 
1020d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1021d71ae5a4SJacob Faibussowitsch {
102216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1023ace3abfcSBarry Smith   PetscBool iascii;
102416d9e3a6SLisandro Dalcin 
102516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
102716d9e3a6SLisandro Dalcin   if (iascii) {
10289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
10299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
103063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
103163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
10329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
10339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
10349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
103563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
103648a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
103763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
103863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
10390f1074feSSatish Balay 
10409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
104116d9e3a6SLisandro Dalcin 
104263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
104363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
104463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
104516d9e3a6SLisandro Dalcin 
10469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
10479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
10489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
104916d9e3a6SLisandro Dalcin 
10509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
10519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
105216d9e3a6SLisandro Dalcin 
105316d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
10549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
105516d9e3a6SLisandro Dalcin     } else {
10569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
105716d9e3a6SLisandro Dalcin     }
10586a251517SEike Mueller     if (jac->smoothtype != -1) {
10599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
106063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
10617e352d70SEike Mueller     } else {
10629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
10631810e44eSEike Mueller     }
10641810e44eSEike Mueller     if (jac->smoothtype == 3) {
106563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
10669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
106763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
10686a251517SEike Mueller     }
10699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
10709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
10719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
107248a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
10735272c319SBarry Smith     if (jac->vec_interp_variant) {
107463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
107563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
10769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
10778f87f92bSBarry Smith     }
107848a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1079db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
10809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
1081db6f9c32SMark Adams #endif
1082589dcaf0SStefano Zampini     /* AIR */
1083589dcaf0SStefano Zampini     if (jac->Rtype) {
108463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
10859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
10869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
10879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
108863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1089589dcaf0SStefano Zampini     }
109016d9e3a6SLisandro Dalcin   }
10913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109216d9e3a6SLisandro Dalcin }
109316d9e3a6SLisandro Dalcin 
1094d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1095d71ae5a4SJacob Faibussowitsch {
109616d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
10974ddd07fcSJed Brown   PetscInt    indx;
1098ace3abfcSBarry Smith   PetscBool   flag;
109916d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
110016d9e3a6SLisandro Dalcin 
110116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1102d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
11039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
11049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1105792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
110616d9e3a6SLisandro Dalcin 
11079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1108792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
110916d9e3a6SLisandro Dalcin 
11109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1111792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
111216d9e3a6SLisandro Dalcin 
11139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1114792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
111516d9e3a6SLisandro Dalcin 
11169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1117792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
111816d9e3a6SLisandro Dalcin 
1119dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
112016d9e3a6SLisandro Dalcin   if (flag) {
112116d9e3a6SLisandro Dalcin     jac->symt = indx;
1122792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
112316d9e3a6SLisandro Dalcin   }
112416d9e3a6SLisandro Dalcin 
1125d0609cedSBarry Smith   PetscOptionsHeadEnd();
11263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
112716d9e3a6SLisandro Dalcin }
112816d9e3a6SLisandro Dalcin 
1129d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1130d71ae5a4SJacob Faibussowitsch {
113116d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1132ace3abfcSBarry Smith   PetscBool   iascii;
1133feb237baSPierre Jolivet   const char *symt = 0;
113416d9e3a6SLisandro Dalcin 
113516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
113716d9e3a6SLisandro Dalcin   if (iascii) {
11389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
113963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
11409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
11419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
11429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
11439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
11449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
11452fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
11462fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
11472fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
114863a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
11499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
115016d9e3a6SLisandro Dalcin   }
11513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
115216d9e3a6SLisandro Dalcin }
1153f1580f4eSBarry Smith 
1154d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1155d71ae5a4SJacob Faibussowitsch {
11564cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11574cb006feSStefano Zampini   PetscInt  n;
11584cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
11594cb006feSStefano Zampini 
11604cb006feSStefano Zampini   PetscFunctionBegin;
1161d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
11629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1163792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
11649566063dSJacob 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));
1165792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
11669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1167792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
11689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1169792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
11709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
11719566063dSJacob 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));
11729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
11739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
117448a46eb9SPierre Jolivet   if (flag || flag2 || flag3 || flag4) PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
11759566063dSJacob 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));
11764cb006feSStefano Zampini   n = 5;
11779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
11784cb006feSStefano Zampini   if (flag || flag2) {
1179792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1180863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1181863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
11829371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1183a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
11844cb006feSStefano Zampini   }
11859566063dSJacob 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));
11864cb006feSStefano Zampini   n = 5;
11879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
11884cb006feSStefano Zampini   if (flag || flag2) {
1189792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1190863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1191863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
11929371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1193a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
11944cb006feSStefano Zampini   }
11959566063dSJacob 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));
119623df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1197792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
119823df4f25SStefano Zampini   }
1199d0609cedSBarry Smith   PetscOptionsHeadEnd();
12003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12014cb006feSStefano Zampini }
12024cb006feSStefano Zampini 
1203d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1204d71ae5a4SJacob Faibussowitsch {
12054cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12064cb006feSStefano Zampini   PetscBool iascii;
12074cb006feSStefano Zampini 
12084cb006feSStefano Zampini   PetscFunctionBegin;
12099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
12104cb006feSStefano Zampini   if (iascii) {
12119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
121263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
121363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
121463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
121563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
121663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
121763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
121863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12194cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
12214cb006feSStefano Zampini     } else {
12229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
12234cb006feSStefano Zampini     }
122463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
122563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
122663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
122763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
122863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
122963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12304cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12314cb006feSStefano Zampini       if (jac->beta_Poisson) {
12329566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
12334cb006feSStefano Zampini       } else {
12349566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
12354cb006feSStefano Zampini       }
123663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
123763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
123863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
123963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
124063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
124163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
124248a46eb9SPierre Jolivet       if (jac->ams_beta_is_zero_part) PetscCall(PetscViewerASCIIPrintf(viewer, "        compatible subspace projection frequency %" PetscInt_FMT " (-1 HYPRE uses default)\n", jac->ams_proj_freq));
124323df4f25SStefano Zampini     } else {
12449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
12454cb006feSStefano Zampini     }
12464cb006feSStefano Zampini   }
12473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12484cb006feSStefano Zampini }
12494cb006feSStefano Zampini 
1250d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1251d71ae5a4SJacob Faibussowitsch {
1252863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1253863406b8SStefano Zampini   PetscInt  n;
1254863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1255863406b8SStefano Zampini 
1256863406b8SStefano Zampini   PetscFunctionBegin;
1257d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
12589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1259792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
12609566063dSJacob 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));
1261792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
12629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1263792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
12649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1265792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
12669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12679566063dSJacob 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));
12689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
127048a46eb9SPierre Jolivet   if (flag || flag2 || flag3 || flag4) PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
12719566063dSJacob 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));
1272863406b8SStefano Zampini   n = 5;
12739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
12749566063dSJacob 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));
1275863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1276792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1277863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1278863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1279863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
12809371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1281a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1282863406b8SStefano Zampini   }
12839566063dSJacob 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));
1284863406b8SStefano Zampini   n = 5;
12859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1286863406b8SStefano Zampini   if (flag || flag2) {
1287792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1288863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1289863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
12909371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1291a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1292863406b8SStefano Zampini   }
1293d0609cedSBarry Smith   PetscOptionsHeadEnd();
12943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1295863406b8SStefano Zampini }
1296863406b8SStefano Zampini 
1297d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1298d71ae5a4SJacob Faibussowitsch {
1299863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1300863406b8SStefano Zampini   PetscBool iascii;
1301863406b8SStefano Zampini 
1302863406b8SStefano Zampini   PetscFunctionBegin;
13039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1304863406b8SStefano Zampini   if (iascii) {
13059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
130663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
130763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
130863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
130963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
131063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
131163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
131263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
131463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
131563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
131663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
131763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
131863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
131963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
132063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
132263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
132363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
132463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
132563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
132663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
132763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1328863406b8SStefano Zampini   }
13293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1330863406b8SStefano Zampini }
1331863406b8SStefano Zampini 
1332d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1333d71ae5a4SJacob Faibussowitsch {
13344cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13355ac14e1cSStefano Zampini   PetscBool ishypre;
13364cb006feSStefano Zampini 
13374cb006feSStefano Zampini   PetscFunctionBegin;
13389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
13395ac14e1cSStefano Zampini   if (ishypre) {
13409566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
13419566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13425ac14e1cSStefano Zampini     jac->G = G;
13435ac14e1cSStefano Zampini   } else {
13449566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13459566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
13465ac14e1cSStefano Zampini   }
13473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13484cb006feSStefano Zampini }
13494cb006feSStefano Zampini 
13504cb006feSStefano Zampini /*@
1351f1580f4eSBarry Smith    PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
13524cb006feSStefano Zampini 
1353c3339decSBarry Smith    Collective
13544cb006feSStefano Zampini 
13554cb006feSStefano Zampini    Input Parameters:
13564cb006feSStefano Zampini +  pc - the preconditioning context
13574cb006feSStefano Zampini -  G - the discrete gradient
13584cb006feSStefano Zampini 
13594cb006feSStefano Zampini    Level: intermediate
13604cb006feSStefano Zampini 
136195452b02SPatrick Sanan    Notes:
136295452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1363147403d9SBarry Smith 
1364863406b8SStefano 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
13654cb006feSStefano Zampini 
1366f1580f4eSBarry Smith    Developer Note:
1367f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1368f1580f4eSBarry Smith 
1369f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
13704cb006feSStefano Zampini @*/
1371d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1372d71ae5a4SJacob Faibussowitsch {
13734cb006feSStefano Zampini   PetscFunctionBegin;
13744cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
13754cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
13764cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1377cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
13783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13794cb006feSStefano Zampini }
13804cb006feSStefano Zampini 
1381d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1382d71ae5a4SJacob Faibussowitsch {
1383863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13845ac14e1cSStefano Zampini   PetscBool ishypre;
1385863406b8SStefano Zampini 
1386863406b8SStefano Zampini   PetscFunctionBegin;
13879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
13885ac14e1cSStefano Zampini   if (ishypre) {
13899566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
13909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13915ac14e1cSStefano Zampini     jac->C = C;
13925ac14e1cSStefano Zampini   } else {
13939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13949566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
13955ac14e1cSStefano Zampini   }
13963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1397863406b8SStefano Zampini }
1398863406b8SStefano Zampini 
1399863406b8SStefano Zampini /*@
1400f1580f4eSBarry Smith    PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1401863406b8SStefano Zampini 
1402c3339decSBarry Smith    Collective
1403863406b8SStefano Zampini 
1404863406b8SStefano Zampini    Input Parameters:
1405863406b8SStefano Zampini +  pc - the preconditioning context
1406863406b8SStefano Zampini -  C - the discrete curl
1407863406b8SStefano Zampini 
1408863406b8SStefano Zampini    Level: intermediate
1409863406b8SStefano Zampini 
141095452b02SPatrick Sanan    Notes:
141195452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1412147403d9SBarry Smith 
1413863406b8SStefano 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
1414863406b8SStefano Zampini 
1415f1580f4eSBarry Smith    Developer Note:
1416f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1417f1580f4eSBarry Smith 
1418f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1419f1580f4eSBarry Smith 
1420f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1421863406b8SStefano Zampini @*/
1422d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1423d71ae5a4SJacob Faibussowitsch {
1424863406b8SStefano Zampini   PetscFunctionBegin;
1425863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1426863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1427863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1428cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
14293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1430863406b8SStefano Zampini }
1431863406b8SStefano Zampini 
1432d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1433d71ae5a4SJacob Faibussowitsch {
14346bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14356bf688a0SCe Qin   PetscBool ishypre;
14366bf688a0SCe Qin   PetscInt  i;
14376bf688a0SCe Qin   PetscFunctionBegin;
14386bf688a0SCe Qin 
14399566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
14409566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
14416bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
14429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
14439566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
14446bf688a0SCe Qin   }
14456bf688a0SCe Qin 
14466bf688a0SCe Qin   jac->dim = dim;
14476bf688a0SCe Qin   if (RT_PiFull) {
14489566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
14496bf688a0SCe Qin     if (ishypre) {
14509566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
14516bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
14526bf688a0SCe Qin     } else {
14539566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
14546bf688a0SCe Qin     }
14556bf688a0SCe Qin   }
14566bf688a0SCe Qin   if (RT_Pi) {
14576bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14586bf688a0SCe Qin       if (RT_Pi[i]) {
14599566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
14606bf688a0SCe Qin         if (ishypre) {
14619566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
14626bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
14636bf688a0SCe Qin         } else {
14649566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
14656bf688a0SCe Qin         }
14666bf688a0SCe Qin       }
14676bf688a0SCe Qin     }
14686bf688a0SCe Qin   }
14696bf688a0SCe Qin   if (ND_PiFull) {
14709566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
14716bf688a0SCe Qin     if (ishypre) {
14729566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
14736bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
14746bf688a0SCe Qin     } else {
14759566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
14766bf688a0SCe Qin     }
14776bf688a0SCe Qin   }
14786bf688a0SCe Qin   if (ND_Pi) {
14796bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14806bf688a0SCe Qin       if (ND_Pi[i]) {
14819566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
14826bf688a0SCe Qin         if (ishypre) {
14839566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
14846bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
14856bf688a0SCe Qin         } else {
14869566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
14876bf688a0SCe Qin         }
14886bf688a0SCe Qin       }
14896bf688a0SCe Qin     }
14906bf688a0SCe Qin   }
14916bf688a0SCe Qin 
14923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14936bf688a0SCe Qin }
14946bf688a0SCe Qin 
14956bf688a0SCe Qin /*@
1496f1580f4eSBarry Smith    PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
14976bf688a0SCe Qin 
1498c3339decSBarry Smith    Collective
14996bf688a0SCe Qin 
15006bf688a0SCe Qin    Input Parameters:
15016bf688a0SCe Qin +  pc - the preconditioning context
15022fe279fdSBarry Smith .  dim - the dimension of the problem, only used in AMS
15032fe279fdSBarry Smith .  RT_PiFull - Raviart-Thomas interpolation matrix
15042fe279fdSBarry Smith .  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
15052fe279fdSBarry Smith .  ND_PiFull - Nedelec interpolation matrix
15066bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
15076bf688a0SCe Qin 
1508f1580f4eSBarry Smith    Level: intermediate
1509f1580f4eSBarry Smith 
151095452b02SPatrick Sanan    Notes:
151195452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1512147403d9SBarry Smith 
15136bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1514147403d9SBarry Smith 
1515f1580f4eSBarry Smith    Developer Note:
1516f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
15176bf688a0SCe Qin 
1518f1580f4eSBarry Smith .seealso: `PCHYPRE`
15196bf688a0SCe Qin @*/
1520d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1521d71ae5a4SJacob Faibussowitsch {
15226bf688a0SCe Qin   PetscInt i;
15236bf688a0SCe Qin 
15246bf688a0SCe Qin   PetscFunctionBegin;
15256bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15266bf688a0SCe Qin   if (RT_PiFull) {
15276bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
15286bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
15296bf688a0SCe Qin   }
15306bf688a0SCe Qin   if (RT_Pi) {
15316bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
15326bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15336bf688a0SCe Qin       if (RT_Pi[i]) {
15346bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
15356bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
15366bf688a0SCe Qin       }
15376bf688a0SCe Qin     }
15386bf688a0SCe Qin   }
15396bf688a0SCe Qin   if (ND_PiFull) {
15406bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
15416bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
15426bf688a0SCe Qin   }
15436bf688a0SCe Qin   if (ND_Pi) {
15446bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
15456bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15466bf688a0SCe Qin       if (ND_Pi[i]) {
15476bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
15486bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
15496bf688a0SCe Qin       }
15506bf688a0SCe Qin     }
15516bf688a0SCe Qin   }
1552cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
15533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15546bf688a0SCe Qin }
15556bf688a0SCe Qin 
1556d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1557d71ae5a4SJacob Faibussowitsch {
15584cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15595ac14e1cSStefano Zampini   PetscBool ishypre;
15604cb006feSStefano Zampini 
15614cb006feSStefano Zampini   PetscFunctionBegin;
15629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
15635ac14e1cSStefano Zampini   if (ishypre) {
15645ac14e1cSStefano Zampini     if (isalpha) {
15659566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
15669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15675ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
15685ac14e1cSStefano Zampini     } else {
15695ac14e1cSStefano Zampini       if (A) {
15709566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
15715ac14e1cSStefano Zampini       } else {
15725ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15735ac14e1cSStefano Zampini       }
15749566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
15755ac14e1cSStefano Zampini       jac->beta_Poisson = A;
15765ac14e1cSStefano Zampini     }
15775ac14e1cSStefano Zampini   } else {
15785ac14e1cSStefano Zampini     if (isalpha) {
15799566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15809566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
15815ac14e1cSStefano Zampini     } else {
15825ac14e1cSStefano Zampini       if (A) {
15839566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15849566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
15855ac14e1cSStefano Zampini       } else {
15869566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15875ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15885ac14e1cSStefano Zampini       }
15895ac14e1cSStefano Zampini     }
15905ac14e1cSStefano Zampini   }
15913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15924cb006feSStefano Zampini }
15934cb006feSStefano Zampini 
15944cb006feSStefano Zampini /*@
1595f1580f4eSBarry Smith    PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
15964cb006feSStefano Zampini 
1597c3339decSBarry Smith    Collective
15984cb006feSStefano Zampini 
15994cb006feSStefano Zampini    Input Parameters:
16004cb006feSStefano Zampini +  pc - the preconditioning context
16014cb006feSStefano Zampini -  A - the matrix
16024cb006feSStefano Zampini 
16034cb006feSStefano Zampini    Level: intermediate
16044cb006feSStefano Zampini 
1605f1580f4eSBarry Smith    Note:
160695452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
16074cb006feSStefano Zampini 
1608f1580f4eSBarry Smith    Developer Note:
1609f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1610f1580f4eSBarry Smith 
1611f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1612f1580f4eSBarry Smith 
1613f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
16144cb006feSStefano Zampini @*/
1615d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1616d71ae5a4SJacob Faibussowitsch {
16174cb006feSStefano Zampini   PetscFunctionBegin;
16184cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16194cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16204cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1621cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
16223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16234cb006feSStefano Zampini }
16244cb006feSStefano Zampini 
16254cb006feSStefano Zampini /*@
1626f1580f4eSBarry Smith    PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
16274cb006feSStefano Zampini 
1628c3339decSBarry Smith    Collective
16294cb006feSStefano Zampini 
16304cb006feSStefano Zampini    Input Parameters:
16314cb006feSStefano Zampini +  pc - the preconditioning context
1632f1580f4eSBarry Smith -  A - the matrix, or NULL to turn it off
16334cb006feSStefano Zampini 
16344cb006feSStefano Zampini    Level: intermediate
16354cb006feSStefano Zampini 
1636f1580f4eSBarry Smith    Note:
163795452b02SPatrick Sanan    A should be obtained by discretizing the Poisson problem with linear finite elements.
16384cb006feSStefano Zampini 
1639f1580f4eSBarry Smith    Developer Note:
1640f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1641f1580f4eSBarry Smith 
1642f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1643f1580f4eSBarry Smith 
1644f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16454cb006feSStefano Zampini @*/
1646d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1647d71ae5a4SJacob Faibussowitsch {
16484cb006feSStefano Zampini   PetscFunctionBegin;
16494cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16504cb006feSStefano Zampini   if (A) {
16514cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16524cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
16534cb006feSStefano Zampini   }
1654cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
16553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16564cb006feSStefano Zampini }
16574cb006feSStefano Zampini 
1658d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1659d71ae5a4SJacob Faibussowitsch {
16604cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16614cb006feSStefano Zampini 
16624cb006feSStefano Zampini   PetscFunctionBegin;
16634cb006feSStefano Zampini   /* throw away any vector if already set */
16649566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
16659566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
16669566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
16679566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
16689566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
16699566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
16709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
16715ac14e1cSStefano Zampini   jac->dim = 2;
16724cb006feSStefano Zampini   if (zzo) {
16739566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
16749566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
16755ac14e1cSStefano Zampini     jac->dim++;
16764cb006feSStefano Zampini   }
16773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16784cb006feSStefano Zampini }
16794cb006feSStefano Zampini 
16804cb006feSStefano Zampini /*@
1681f1580f4eSBarry Smith    PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
16824cb006feSStefano Zampini 
1683c3339decSBarry Smith    Collective
16844cb006feSStefano Zampini 
16854cb006feSStefano Zampini    Input Parameters:
16864cb006feSStefano Zampini +  pc - the preconditioning context
16872fe279fdSBarry Smith .  ozz - vector representing (1,0,0) (or (1,0) in 2D)
16882fe279fdSBarry Smith .  zoz - vector representing (0,1,0) (or (0,1) in 2D)
16894cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
16904cb006feSStefano Zampini 
16914cb006feSStefano Zampini    Level: intermediate
16924cb006feSStefano Zampini 
1693f1580f4eSBarry Smith    Developer Note:
1694f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1695f1580f4eSBarry Smith 
1696f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16974cb006feSStefano Zampini @*/
1698d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1699d71ae5a4SJacob Faibussowitsch {
17004cb006feSStefano Zampini   PetscFunctionBegin;
17014cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17024cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
17034cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
17044cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
17054cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
17064cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
17074cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1708cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
17093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17104cb006feSStefano Zampini }
17114cb006feSStefano Zampini 
1712d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1713d71ae5a4SJacob Faibussowitsch {
1714be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1715be14dc20SKerry Key 
1716be14dc20SKerry Key   PetscFunctionBegin;
1717be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1718be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1719be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1720be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
17213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1722be14dc20SKerry Key }
1723be14dc20SKerry Key 
1724be14dc20SKerry Key /*@
1725f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1726be14dc20SKerry Key 
1727c3339decSBarry Smith    Collective
1728be14dc20SKerry Key 
1729be14dc20SKerry Key    Input Parameters:
1730be14dc20SKerry Key +  pc - the preconditioning context
1731be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1732be14dc20SKerry Key 
1733be14dc20SKerry Key    Level: intermediate
1734be14dc20SKerry Key 
1735be14dc20SKerry Key    Note:
1736f1580f4eSBarry Smith    This calls `HYPRE_AMSSetInteriorNodes()`
1737f1580f4eSBarry Smith 
1738f1580f4eSBarry Smith    Developer Note:
1739f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1740f1580f4eSBarry Smith 
1741f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1742be14dc20SKerry Key @*/
1743d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1744d71ae5a4SJacob Faibussowitsch {
1745be14dc20SKerry Key   PetscFunctionBegin;
1746be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1747be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1748be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1749be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
17503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1751be14dc20SKerry Key }
1752be14dc20SKerry Key 
1753d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1754d71ae5a4SJacob Faibussowitsch {
17554cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17564cb006feSStefano Zampini   Vec       tv;
17574cb006feSStefano Zampini   PetscInt  i;
17584cb006feSStefano Zampini 
17594cb006feSStefano Zampini   PetscFunctionBegin;
17604cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
17619566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
17629566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
17639566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
17645ac14e1cSStefano Zampini   jac->dim = dim;
17655ac14e1cSStefano Zampini 
17664cb006feSStefano Zampini   /* compute IJ vector for coordinates */
17679566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
17689566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
17699566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
17704cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
17714cb006feSStefano Zampini     PetscScalar *array;
17724cb006feSStefano Zampini     PetscInt     j;
17734cb006feSStefano Zampini 
17749566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
17759566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
17766ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
17779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
17789566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
17794cb006feSStefano Zampini   }
17809566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
17813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17824cb006feSStefano Zampini }
17834cb006feSStefano Zampini 
1784d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1785d71ae5a4SJacob Faibussowitsch {
178616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
178716d9e3a6SLisandro Dalcin 
178816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
178916d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
17903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
179116d9e3a6SLisandro Dalcin }
179216d9e3a6SLisandro Dalcin 
1793d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1794d71ae5a4SJacob Faibussowitsch {
179516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1796ace3abfcSBarry Smith   PetscBool flag;
179716d9e3a6SLisandro Dalcin 
179816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
179916d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
18009566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
18015f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
18023ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
180316d9e3a6SLisandro Dalcin   } else {
18049566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
180516d9e3a6SLisandro Dalcin   }
180616d9e3a6SLisandro Dalcin 
180716d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
180816d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
180916d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
181016d9e3a6SLisandro Dalcin 
18119566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
181216d9e3a6SLisandro Dalcin   if (flag) {
18139566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1814792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
181516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
181616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
181716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
181816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
181916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
182016d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
18213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
182216d9e3a6SLisandro Dalcin   }
18239566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1824db966c6cSHong Zhang   if (flag) {
18254e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
18267de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
18278bf83915SBarry Smith #endif
18289566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1829792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1830db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1831db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1832db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1833db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1834db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1835db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1836db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
18373ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1838db966c6cSHong Zhang   }
18399566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
184016d9e3a6SLisandro Dalcin   if (flag) {
18419566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1842792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
184316d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
184416d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
184516d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
184616d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
184716d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
184816d9e3a6SLisandro Dalcin     /* initialize */
184916d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
18508966356dSPierre Jolivet     jac->threshold = .1;
185116d9e3a6SLisandro Dalcin     jac->filter    = .1;
185216d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
18532fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
18542fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
18552fa5cd67SKarl Rupp 
185616d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
185716d9e3a6SLisandro Dalcin     jac->symt = 0;
1858792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1859792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1860792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1861792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1862792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1863792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
18643ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
186516d9e3a6SLisandro Dalcin   }
18669566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
186716d9e3a6SLisandro Dalcin   if (flag) {
1868792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
186916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
187016d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
187116d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
187216d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
18739566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
18749566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
187516d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
187616d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
187716d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
187816d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
187916d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
188016d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
188116d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
188216d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
18838f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
188416d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
188516d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
188616d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
188716d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
188816d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
18890f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
18906a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1891b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
18921810e44eSEike Mueller     jac->eu_level                                                = 0;
18931810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
18941810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1895589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
18960f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
189716d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
189816d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
189916d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
19000f1074feSSatish Balay     jac->interptype                       = 0;
1901589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1902589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1903589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1904589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1905589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
19060f1074feSSatish Balay     jac->agg_nl                           = 0;
19076ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
19080f1074feSSatish Balay     jac->pmax                             = 0;
19090f1074feSSatish Balay     jac->truncfactor                      = 0.0;
19100f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1911589dcaf0SStefano Zampini     jac->maxc                             = 9;
1912589dcaf0SStefano Zampini     jac->minc                             = 1;
191322e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
191422e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
191522e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
191622e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
191722e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
191822e51d31SStefano Zampini     jac->interp_refine                    = 0;
19198f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
19208f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
19216ea7df73SStefano Zampini     jac->rap2                             = 0;
19226ea7df73SStefano Zampini 
19236ea7df73SStefano Zampini     /* GPU defaults
19246ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
19256ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
19266ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
19276ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
19286ea7df73SStefano Zampini     jac->mod_rap2       = 1;
19296ea7df73SStefano Zampini     jac->coarsentype    = 8;
19306ea7df73SStefano Zampini     jac->relaxorder     = 0;
19316ea7df73SStefano Zampini     jac->interptype     = 6;
19326ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
19336ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
19346ea7df73SStefano Zampini     jac->agg_interptype = 7;
19356ea7df73SStefano Zampini #else
19366ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
19376ea7df73SStefano Zampini     jac->mod_rap2      = 0;
19386ea7df73SStefano Zampini #endif
1939792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
1940792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
1941792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
1942792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1943792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
1944792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
1945792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
1946792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
1947792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
1948792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
1949792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
1950792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
1951792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
1952792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
1953792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
1954792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
1955792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
1956792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
1957792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
19586ea7df73SStefano Zampini     /* GPU */
19596ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1960792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1961792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
1962792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
19636ea7df73SStefano Zampini #endif
19646ea7df73SStefano Zampini 
1965589dcaf0SStefano Zampini     /* AIR */
19666ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1967792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1968792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1969792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1970792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1971792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
19726ea7df73SStefano Zampini #endif
19733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
197416d9e3a6SLisandro Dalcin   }
19759566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
19764cb006feSStefano Zampini   if (flag) {
19773ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
19784cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
19794cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
19804cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
19814cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
19824cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
19834cb006feSStefano Zampini     jac->coords[0]          = NULL;
19844cb006feSStefano Zampini     jac->coords[1]          = NULL;
19854cb006feSStefano Zampini     jac->coords[2]          = NULL;
1986be14dc20SKerry Key     jac->interior           = NULL;
19874cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
1988863406b8SStefano Zampini     jac->as_print       = 0;
1989863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
1990863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
19914cb006feSStefano Zampini     jac->ams_cycle_type = 13;
19924cb006feSStefano Zampini     /* Smoothing options */
1993863406b8SStefano Zampini     jac->as_relax_type   = 2;
1994863406b8SStefano Zampini     jac->as_relax_times  = 1;
1995863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
1996863406b8SStefano Zampini     jac->as_omega        = 1.0;
19974cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1998863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
1999863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
20000bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2001863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2002863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2003863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
20044cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2005863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2006863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
20070bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2008863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2009863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2010863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2011792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2012792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2013792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2014792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
20159371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2016792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2017863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2018863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
20199371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2020a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2021792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2022863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2023863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
20249371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2025a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
202623df4f25SStefano Zampini     /* Zero conductivity */
202723df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
202823df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
20293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
20304cb006feSStefano Zampini   }
20319566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2032863406b8SStefano Zampini   if (flag) {
20333ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2034863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2035863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2036863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2037863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2038863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2039863406b8SStefano Zampini     jac->coords[0]          = NULL;
2040863406b8SStefano Zampini     jac->coords[1]          = NULL;
2041863406b8SStefano Zampini     jac->coords[2]          = NULL;
2042863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2043863406b8SStefano Zampini     jac->as_print       = 0;
2044863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2045863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2046863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2047863406b8SStefano Zampini     /* Smoothing options */
2048863406b8SStefano Zampini     jac->as_relax_type   = 2;
2049863406b8SStefano Zampini     jac->as_relax_times  = 1;
2050863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2051863406b8SStefano Zampini     jac->as_omega        = 1.0;
2052863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2053863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2054863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2055863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2056863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2057863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2058863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2059863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2060863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2061863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2062863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2063863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2064863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2065863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2066863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2067792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2068792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2069792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2070792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
20719371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2072792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2073863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2074863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2075863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
20769371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2077a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2078792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2079863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2080863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
20819371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2082a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
20833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2084863406b8SStefano Zampini   }
20859566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
20862fa5cd67SKarl Rupp 
20870298fd71SBarry Smith   jac->hypre_type = NULL;
208898921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
208916d9e3a6SLisandro Dalcin }
209016d9e3a6SLisandro Dalcin 
209116d9e3a6SLisandro Dalcin /*
209216d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
209316d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
209416d9e3a6SLisandro Dalcin */
2095d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2096d71ae5a4SJacob Faibussowitsch {
20974ddd07fcSJed Brown   PetscInt    indx;
2098db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2099ace3abfcSBarry Smith   PetscBool   flg;
210016d9e3a6SLisandro Dalcin 
210116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2102d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2103dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
210416d9e3a6SLisandro Dalcin   if (flg) {
21059566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
210602a17cd4SBarry Smith   } else {
21079566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
210816d9e3a6SLisandro Dalcin   }
2109dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2110d0609cedSBarry Smith   PetscOptionsHeadEnd();
21113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211216d9e3a6SLisandro Dalcin }
211316d9e3a6SLisandro Dalcin 
211416d9e3a6SLisandro Dalcin /*@C
211516d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
211616d9e3a6SLisandro Dalcin 
211716d9e3a6SLisandro Dalcin    Input Parameters:
211816d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2119db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
212016d9e3a6SLisandro Dalcin 
2121f1580f4eSBarry Smith    Options Database Key:
2122db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
212316d9e3a6SLisandro Dalcin 
212416d9e3a6SLisandro Dalcin    Level: intermediate
212516d9e3a6SLisandro Dalcin 
2126f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
212716d9e3a6SLisandro Dalcin @*/
2128d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2129d71ae5a4SJacob Faibussowitsch {
213016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21310700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
213216d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2133cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
21343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213516d9e3a6SLisandro Dalcin }
213616d9e3a6SLisandro Dalcin 
213716d9e3a6SLisandro Dalcin /*@C
213816d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
213916d9e3a6SLisandro Dalcin 
214016d9e3a6SLisandro Dalcin    Input Parameter:
214116d9e3a6SLisandro Dalcin .     pc - the preconditioner context
214216d9e3a6SLisandro Dalcin 
214316d9e3a6SLisandro Dalcin    Output Parameter:
2144db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
214516d9e3a6SLisandro Dalcin 
214616d9e3a6SLisandro Dalcin    Level: intermediate
214716d9e3a6SLisandro Dalcin 
2148f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
214916d9e3a6SLisandro Dalcin @*/
2150d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2151d71ae5a4SJacob Faibussowitsch {
215216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21530700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
215416d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2155cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
21563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
215716d9e3a6SLisandro Dalcin }
215816d9e3a6SLisandro Dalcin 
2159db6f9c32SMark Adams /*@C
2160f1580f4eSBarry Smith    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2161db6f9c32SMark Adams 
2162c3339decSBarry Smith    Logically Collective
2163db6f9c32SMark Adams 
2164db6f9c32SMark Adams    Input Parameters:
2165db6f9c32SMark Adams +  pc - the hypre context
2166db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2167db6f9c32SMark Adams 
2168db6f9c32SMark Adams    Options Database Key:
216967b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2170db6f9c32SMark Adams 
2171db6f9c32SMark Adams    Level: intermediate
2172db6f9c32SMark Adams 
2173f1580f4eSBarry Smith    Developer Note:
2174f1580f4eSBarry Smith    How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2175db6f9c32SMark Adams 
2176f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2177db6f9c32SMark Adams @*/
2178d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2179d71ae5a4SJacob Faibussowitsch {
2180db6f9c32SMark Adams   PetscFunctionBegin;
2181db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2182cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
21833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2184db6f9c32SMark Adams }
2185db6f9c32SMark Adams 
2186db6f9c32SMark Adams /*@C
2187f1580f4eSBarry Smith    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2188db6f9c32SMark Adams 
2189db6f9c32SMark Adams    Not Collective
2190db6f9c32SMark Adams 
2191db6f9c32SMark Adams    Input Parameter:
2192db6f9c32SMark Adams .  pc - the multigrid context
2193db6f9c32SMark Adams 
2194db6f9c32SMark Adams    Output Parameter:
2195db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2196db6f9c32SMark Adams 
2197db6f9c32SMark Adams    Level: intermediate
2198db6f9c32SMark Adams 
2199f1580f4eSBarry Smith .seealso: `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2200db6f9c32SMark Adams @*/
2201d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2202d71ae5a4SJacob Faibussowitsch {
2203db6f9c32SMark Adams   PetscFunctionBegin;
2204db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2205cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
22063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2207db6f9c32SMark Adams }
2208db6f9c32SMark Adams 
220916d9e3a6SLisandro Dalcin /*MC
2210f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
221116d9e3a6SLisandro Dalcin 
221216d9e3a6SLisandro Dalcin    Options Database Keys:
2213*e1ded407SBarry Smith +   -pc_hypre_type - One of `euclid`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2214f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2215f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2216*e1ded407SBarry Smith -   Many others, run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
221716d9e3a6SLisandro Dalcin 
221816d9e3a6SLisandro Dalcin    Level: intermediate
221916d9e3a6SLisandro Dalcin 
222095452b02SPatrick Sanan    Notes:
2221*e1ded407SBarry Smith     Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
222216d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
222349567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
222416d9e3a6SLisandro Dalcin 
2225*e1ded407SBarry Smith           The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2226*e1ded407SBarry Smith           (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2227*e1ded407SBarry Smith           `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2228*e1ded407SBarry Smith           (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2229*e1ded407SBarry Smith           iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2230*e1ded407SBarry Smith           and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2231*e1ded407SBarry Smith           then AT MOST twenty V-cycles of boomeramg will be used.
223216d9e3a6SLisandro Dalcin 
2233*e1ded407SBarry Smith            Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
22340f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2235*e1ded407SBarry Smith            Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
223616d9e3a6SLisandro Dalcin 
2237f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2238*e1ded407SBarry Smith           the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
22390b1a5bd9SEric Chamberland 
2240f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2241f1580f4eSBarry Smith 
2242*e1ded407SBarry Smith           For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2243f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
224449567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2245f1580f4eSBarry Smith 
2246*e1ded407SBarry Smith   Sometimes people want to try algebraic multigrid as a "standalone" solver, that is not accelerating it with a Krylov method. Though we generally do not recommend this
2247*e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2248*e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2249*e1ded407SBarry Smith 
2250f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
22519e5bc791SBarry Smith 
2252ead8c081SBarry Smith    GPU Notes:
2253ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2254f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2255ead8c081SBarry Smith 
2256ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2257f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2258ead8c081SBarry Smith 
2259f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2260f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2261f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
226216d9e3a6SLisandro Dalcin M*/
226316d9e3a6SLisandro Dalcin 
2264d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2265d71ae5a4SJacob Faibussowitsch {
226616d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
226716d9e3a6SLisandro Dalcin 
226816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22694dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
22702fa5cd67SKarl Rupp 
227116d9e3a6SLisandro Dalcin   pc->data                = jac;
22728695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
227316d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
227416d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
227516d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
227616d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
227716d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
22789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
22799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
22809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
22819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
22829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
22839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
22849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2285be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
22869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
22879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
22889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
22896ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22906ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
22919566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
22926ea7df73SStefano Zampini   #endif
22936ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
22949566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
22956ea7df73SStefano Zampini   #endif
22966ea7df73SStefano Zampini #endif
22973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
229816d9e3a6SLisandro Dalcin }
2299ebc551c0SBarry Smith 
2300ebc551c0SBarry Smith typedef struct {
230168326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2302f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
23039e5bc791SBarry Smith 
23049e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
23054ddd07fcSJed Brown   PetscInt  its;
23069e5bc791SBarry Smith   double    tol;
23074ddd07fcSJed Brown   PetscInt  relax_type;
23084ddd07fcSJed Brown   PetscInt  rap_type;
23094ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
23104ddd07fcSJed Brown   PetscInt  max_levels;
23110be8cd64Sftrigaux   PetscInt  skip_relax;
23120be8cd64Sftrigaux   PetscBool print_statistics;
2313ebc551c0SBarry Smith } PC_PFMG;
2314ebc551c0SBarry Smith 
2315d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_PFMG(PC pc)
2316d71ae5a4SJacob Faibussowitsch {
2317f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2318ebc551c0SBarry Smith 
2319ebc551c0SBarry Smith   PetscFunctionBegin;
2320792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
23219566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
23229566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
23233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2324ebc551c0SBarry Smith }
2325ebc551c0SBarry Smith 
23269e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
23279e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
23289e5bc791SBarry Smith 
2329d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2330d71ae5a4SJacob Faibussowitsch {
2331ace3abfcSBarry Smith   PetscBool iascii;
2332f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2333ebc551c0SBarry Smith 
2334ebc551c0SBarry Smith   PetscFunctionBegin;
23359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
23369e5bc791SBarry Smith   if (iascii) {
23379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
233863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
23399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
23409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
23419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
234263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
234363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
23440be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
23459e5bc791SBarry Smith   }
23463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2347ebc551c0SBarry Smith }
2348ebc551c0SBarry Smith 
2349d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2350d71ae5a4SJacob Faibussowitsch {
2351f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2352ebc551c0SBarry Smith 
2353ebc551c0SBarry Smith   PetscFunctionBegin;
2354d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
23550be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
23569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2357792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
23589566063dSJacob 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));
2359792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
23609566063dSJacob 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));
2361792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
23629e5bc791SBarry Smith 
23639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2364792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
23653b46a515SGlenn Hammond 
23669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2367792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2368dd39110bSPierre 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));
2369792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2370dd39110bSPierre 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));
2371792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
23720be8cd64Sftrigaux   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));
23730be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2374d0609cedSBarry Smith   PetscOptionsHeadEnd();
23753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2376ebc551c0SBarry Smith }
2377ebc551c0SBarry Smith 
2378d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2379d71ae5a4SJacob Faibussowitsch {
2380f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2381d9ca1df4SBarry Smith   PetscScalar       *yy;
2382d9ca1df4SBarry Smith   const PetscScalar *xx;
23834ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
23842cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
238568326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2386f91d8e95SBarry Smith 
2387f91d8e95SBarry Smith   PetscFunctionBegin;
23889566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
23899566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
23902cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2391f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2392f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2393f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
23942cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
23952cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
23962cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
23972cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
23982cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
23992cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2400f91d8e95SBarry Smith 
2401f91d8e95SBarry Smith   /* copy x values over to hypre */
2402792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
24039566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2404792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
24059566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2406792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2407792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2408f91d8e95SBarry Smith 
2409f91d8e95SBarry Smith   /* copy solution values back to PETSc */
24109566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2411792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
24129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
24133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2414f91d8e95SBarry Smith }
2415f91d8e95SBarry Smith 
2416d71ae5a4SJacob Faibussowitsch 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)
2417d71ae5a4SJacob Faibussowitsch {
24189e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
24192cf14000SStefano Zampini   HYPRE_Int oits;
24209e5bc791SBarry Smith 
24219e5bc791SBarry Smith   PetscFunctionBegin;
24229566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2423792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2424792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
24259e5bc791SBarry Smith 
24269566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2427792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
24289e5bc791SBarry Smith   *outits = oits;
24299e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
24309e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2431792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2432792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
24333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24349e5bc791SBarry Smith }
24359e5bc791SBarry Smith 
2436d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_PFMG(PC pc)
2437d71ae5a4SJacob Faibussowitsch {
24383a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
24393a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2440ace3abfcSBarry Smith   PetscBool        flg;
24413a32d3dbSGlenn Hammond 
24423a32d3dbSGlenn Hammond   PetscFunctionBegin;
24439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
244428b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
24453a32d3dbSGlenn Hammond 
24463a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2447792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2448792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
24490be8cd64Sftrigaux 
24500be8cd64Sftrigaux   // Print Hypre statistics about the solve process
24510be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
24520be8cd64Sftrigaux 
24530be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
24540be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24550be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24560be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24570be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24580be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
24590be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
24600be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24610be8cd64Sftrigaux 
2462792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2463792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
24643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24653a32d3dbSGlenn Hammond }
24663a32d3dbSGlenn Hammond 
2467ebc551c0SBarry Smith /*MC
2468ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2469ebc551c0SBarry Smith 
2470f1580f4eSBarry Smith    Options Database Keys:
247167b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
247267b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
247367b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
247467b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
24759e5bc791SBarry 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
24760be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2477f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2478f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2479f1580f4eSBarry Smith 
2480f1580f4eSBarry Smith    Level: advanced
2481f91d8e95SBarry Smith 
248295452b02SPatrick Sanan    Notes:
248395452b02SPatrick Sanan    This is for CELL-centered descretizations
24849e5bc791SBarry Smith 
2485f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
24869e5bc791SBarry Smith 
2487f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2488f1580f4eSBarry Smith 
2489f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2490f1580f4eSBarry Smith 
2491f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2492f1580f4eSBarry Smith 
2493f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2494ebc551c0SBarry Smith M*/
2495ebc551c0SBarry Smith 
2496d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2497d71ae5a4SJacob Faibussowitsch {
2498ebc551c0SBarry Smith   PC_PFMG *ex;
2499ebc551c0SBarry Smith 
2500ebc551c0SBarry Smith   PetscFunctionBegin;
25019371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
250268326731SBarry Smith   pc->data = ex;
2503ebc551c0SBarry Smith 
25049e5bc791SBarry Smith   ex->its              = 1;
25059e5bc791SBarry Smith   ex->tol              = 1.e-8;
25069e5bc791SBarry Smith   ex->relax_type       = 1;
25079e5bc791SBarry Smith   ex->rap_type         = 0;
25089e5bc791SBarry Smith   ex->num_pre_relax    = 1;
25099e5bc791SBarry Smith   ex->num_post_relax   = 1;
25103b46a515SGlenn Hammond   ex->max_levels       = 0;
25110be8cd64Sftrigaux   ex->skip_relax       = 0;
25120be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
25139e5bc791SBarry Smith 
2514ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2515ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2516ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2517f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
25189e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
251968326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
25202fa5cd67SKarl Rupp 
25219566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2522792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2524ebc551c0SBarry Smith }
2525d851a50bSGlenn Hammond 
2526d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2527d851a50bSGlenn Hammond typedef struct {
2528d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2529d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2530d851a50bSGlenn Hammond 
2531d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
25324ddd07fcSJed Brown   PetscInt its;
2533d851a50bSGlenn Hammond   double   tol;
25344ddd07fcSJed Brown   PetscInt relax_type;
25354ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2536d851a50bSGlenn Hammond } PC_SysPFMG;
2537d851a50bSGlenn Hammond 
2538d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SysPFMG(PC pc)
2539d71ae5a4SJacob Faibussowitsch {
2540d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2541d851a50bSGlenn Hammond 
2542d851a50bSGlenn Hammond   PetscFunctionBegin;
2543792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
25449566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
25459566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
25463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2547d851a50bSGlenn Hammond }
2548d851a50bSGlenn Hammond 
2549d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2550d851a50bSGlenn Hammond 
2551d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2552d71ae5a4SJacob Faibussowitsch {
2553ace3abfcSBarry Smith   PetscBool   iascii;
2554d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2555d851a50bSGlenn Hammond 
2556d851a50bSGlenn Hammond   PetscFunctionBegin;
25579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2558d851a50bSGlenn Hammond   if (iascii) {
25599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
256063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
25619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
25629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
256363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2564d851a50bSGlenn Hammond   }
25653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2566d851a50bSGlenn Hammond }
2567d851a50bSGlenn Hammond 
2568d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2569d71ae5a4SJacob Faibussowitsch {
2570d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2571ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2572d851a50bSGlenn Hammond 
2573d851a50bSGlenn Hammond   PetscFunctionBegin;
2574d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
25759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
257648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
25779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2578792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
25799566063dSJacob 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));
2580792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
25819566063dSJacob 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));
2582792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2583d851a50bSGlenn Hammond 
25849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2585792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2586dd39110bSPierre 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));
2587792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2588d0609cedSBarry Smith   PetscOptionsHeadEnd();
25893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2590d851a50bSGlenn Hammond }
2591d851a50bSGlenn Hammond 
2592d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2593d71ae5a4SJacob Faibussowitsch {
2594d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2595d9ca1df4SBarry Smith   PetscScalar       *yy;
2596d9ca1df4SBarry Smith   const PetscScalar *xx;
25974ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
25982cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2599d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
26004ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
26014ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
26024ddd07fcSJed Brown   PetscInt           part     = 0;
26034ddd07fcSJed Brown   PetscInt           size;
26044ddd07fcSJed Brown   PetscInt           i;
2605d851a50bSGlenn Hammond 
2606d851a50bSGlenn Hammond   PetscFunctionBegin;
26079566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
26089566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
26092cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2610d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2611d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2612d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
26132cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
26142cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
26152cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
26162cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
26172cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
26182cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2619d851a50bSGlenn Hammond 
2620d851a50bSGlenn Hammond   size = 1;
26212fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
26222fa5cd67SKarl Rupp 
2623d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2624d851a50bSGlenn Hammond   if (ordering) {
2625792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26269566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2627792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
26289566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2629792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2630792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2631792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2632d851a50bSGlenn Hammond 
2633d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26349566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2635792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
26369566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2637a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2638d851a50bSGlenn Hammond     PetscScalar *z;
26394ddd07fcSJed Brown     PetscInt     j, k;
2640d851a50bSGlenn Hammond 
26419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2642792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26439566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2644d851a50bSGlenn Hammond 
2645d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2646d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2647d851a50bSGlenn Hammond       k = i * nvars;
26482fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2649d851a50bSGlenn Hammond     }
2650792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
26519566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2652792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2653792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2654d851a50bSGlenn Hammond 
2655d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26569566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2657792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2658d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2659d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2660d851a50bSGlenn Hammond       k = i * nvars;
26612fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2662d851a50bSGlenn Hammond     }
26639566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
26649566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2665d851a50bSGlenn Hammond   }
26663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2667d851a50bSGlenn Hammond }
2668d851a50bSGlenn Hammond 
2669d71ae5a4SJacob Faibussowitsch 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)
2670d71ae5a4SJacob Faibussowitsch {
2671d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
26722cf14000SStefano Zampini   HYPRE_Int   oits;
2673d851a50bSGlenn Hammond 
2674d851a50bSGlenn Hammond   PetscFunctionBegin;
26759566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2676792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2677792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
26789566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2679792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2680d851a50bSGlenn Hammond   *outits = oits;
2681d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2682d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2683792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2684792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
26853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2686d851a50bSGlenn Hammond }
2687d851a50bSGlenn Hammond 
2688d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SysPFMG(PC pc)
2689d71ae5a4SJacob Faibussowitsch {
2690d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2691d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2692ace3abfcSBarry Smith   PetscBool         flg;
2693d851a50bSGlenn Hammond 
2694d851a50bSGlenn Hammond   PetscFunctionBegin;
26959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
269628b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2697d851a50bSGlenn Hammond 
2698d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2699792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2700792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2701792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2702792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
27033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2704d851a50bSGlenn Hammond }
2705d851a50bSGlenn Hammond 
2706d851a50bSGlenn Hammond /*MC
2707f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2708d851a50bSGlenn Hammond 
2709d851a50bSGlenn Hammond    Level: advanced
2710d851a50bSGlenn Hammond 
2711f1580f4eSBarry Smith    Options Database Keys:
271267b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
271367b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
271467b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
271567b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
271667b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2717d851a50bSGlenn Hammond 
271895452b02SPatrick Sanan    Notes:
2719f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2720f1580f4eSBarry Smith 
2721f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2722f1580f4eSBarry Smith 
272395452b02SPatrick Sanan    This is for CELL-centered descretizations
2724d851a50bSGlenn Hammond 
2725f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2726d851a50bSGlenn Hammond 
2727f1580f4eSBarry Smith    This does not give access to all the functionality of hypres SysPFMG, it supports only one part, and one block per process defined by a PETSc `DMDA`.
2728f1580f4eSBarry Smith 
2729f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2730d851a50bSGlenn Hammond M*/
2731d851a50bSGlenn Hammond 
2732d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2733d71ae5a4SJacob Faibussowitsch {
2734d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2735d851a50bSGlenn Hammond 
2736d851a50bSGlenn Hammond   PetscFunctionBegin;
27379371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2738d851a50bSGlenn Hammond   pc->data = ex;
2739d851a50bSGlenn Hammond 
2740d851a50bSGlenn Hammond   ex->its            = 1;
2741d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2742d851a50bSGlenn Hammond   ex->relax_type     = 1;
2743d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2744d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2745d851a50bSGlenn Hammond 
2746d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2747d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2748d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2749d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2750d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2751d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
27522fa5cd67SKarl Rupp 
27539566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2754792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
27553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2756d851a50bSGlenn Hammond }
27571c188c59Sftrigaux 
2758f1580f4eSBarry Smith /* PC SMG */
27591c188c59Sftrigaux typedef struct {
27601c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
27611c188c59Sftrigaux   HYPRE_StructSolver hsolver;
27621c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
27631c188c59Sftrigaux   double             tol;
27641c188c59Sftrigaux   PetscBool          print_statistics;
27651c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
27661c188c59Sftrigaux } PC_SMG;
27671c188c59Sftrigaux 
2768d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SMG(PC pc)
2769d71ae5a4SJacob Faibussowitsch {
27701c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
27711c188c59Sftrigaux 
27721c188c59Sftrigaux   PetscFunctionBegin;
27731c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
27741c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
27751c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
27763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27771c188c59Sftrigaux }
27781c188c59Sftrigaux 
2779d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2780d71ae5a4SJacob Faibussowitsch {
27811c188c59Sftrigaux   PetscBool iascii;
27821c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
27831c188c59Sftrigaux 
27841c188c59Sftrigaux   PetscFunctionBegin;
27851c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
27861c188c59Sftrigaux   if (iascii) {
27871c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
27881c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27891c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27901c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
27911c188c59Sftrigaux   }
27923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27931c188c59Sftrigaux }
27941c188c59Sftrigaux 
2795d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2796d71ae5a4SJacob Faibussowitsch {
27971c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
27981c188c59Sftrigaux 
27991c188c59Sftrigaux   PetscFunctionBegin;
28001c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
28011c188c59Sftrigaux 
28021c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
28031c188c59Sftrigaux   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));
28041c188c59Sftrigaux   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));
28051c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
28061c188c59Sftrigaux 
28071c188c59Sftrigaux   PetscOptionsHeadEnd();
28083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28091c188c59Sftrigaux }
28101c188c59Sftrigaux 
2811d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2812d71ae5a4SJacob Faibussowitsch {
28131c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
28141c188c59Sftrigaux   PetscScalar       *yy;
28151c188c59Sftrigaux   const PetscScalar *xx;
28161c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
28171c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
28181c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28191c188c59Sftrigaux 
28201c188c59Sftrigaux   PetscFunctionBegin;
28211c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28221c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28231c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
28241c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
28251c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
28261c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
28271c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
28281c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
28291c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
28301c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
28311c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
28321c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
28331c188c59Sftrigaux 
28341c188c59Sftrigaux   /* copy x values over to hypre */
28351c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
28361c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
28371c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
28381c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
28391c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
28401c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
28411c188c59Sftrigaux 
28421c188c59Sftrigaux   /* copy solution values back to PETSc */
28431c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
28441c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
28451c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
28463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28471c188c59Sftrigaux }
28481c188c59Sftrigaux 
2849d71ae5a4SJacob Faibussowitsch 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)
2850d71ae5a4SJacob Faibussowitsch {
28511c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
28521c188c59Sftrigaux   HYPRE_Int oits;
28531c188c59Sftrigaux 
28541c188c59Sftrigaux   PetscFunctionBegin;
28551c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28561c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
28571c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
28581c188c59Sftrigaux 
28591c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
28601c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
28611c188c59Sftrigaux   *outits = oits;
28621c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
28631c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
28641c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
28651c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
28663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28671c188c59Sftrigaux }
28681c188c59Sftrigaux 
2869d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SMG(PC pc)
2870d71ae5a4SJacob Faibussowitsch {
28711c188c59Sftrigaux   PetscInt         i, dim;
28721c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
28731c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28741c188c59Sftrigaux   PetscBool        flg;
28751c188c59Sftrigaux   DMBoundaryType   p[3];
28761c188c59Sftrigaux   PetscInt         M[3];
28771c188c59Sftrigaux 
28781c188c59Sftrigaux   PetscFunctionBegin;
28791c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
28801c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
28811c188c59Sftrigaux 
28821c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
28831c188c59Sftrigaux   // Check if power of 2 in periodic directions
28841c188c59Sftrigaux   for (i = 0; i < dim; i++) {
28851c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
28861c188c59Sftrigaux       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]);
28871c188c59Sftrigaux     }
28881c188c59Sftrigaux   }
28891c188c59Sftrigaux 
28901c188c59Sftrigaux   /* create the hypre solver object and set its information */
28911c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
28921c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
28931c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
28941c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
28951c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28961c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28971c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
28981c188c59Sftrigaux 
28991c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29001c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
29013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29021c188c59Sftrigaux }
29031c188c59Sftrigaux 
29041c188c59Sftrigaux /*MC
29055cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
29061c188c59Sftrigaux 
29071c188c59Sftrigaux    Level: advanced
29081c188c59Sftrigaux 
2909f1580f4eSBarry Smith    Options Database Keys:
29105cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
29115cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
29125cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
29135cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
29141c188c59Sftrigaux 
29151c188c59Sftrigaux    Notes:
29161c188c59Sftrigaux    This is for CELL-centered descretizations
29171c188c59Sftrigaux 
29185cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
29191c188c59Sftrigaux 
2920f1580f4eSBarry Smith    This does not provide all the functionality of  hypre's SMG solver, it supports only one block per process defined by a PETSc `DMDA`.
2921f1580f4eSBarry Smith 
2922f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
2923f1580f4eSBarry Smith 
2924f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
29251c188c59Sftrigaux M*/
29261c188c59Sftrigaux 
2927d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
2928d71ae5a4SJacob Faibussowitsch {
29291c188c59Sftrigaux   PC_SMG *ex;
29301c188c59Sftrigaux 
29311c188c59Sftrigaux   PetscFunctionBegin;
29329371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
29331c188c59Sftrigaux   pc->data = ex;
29341c188c59Sftrigaux 
29351c188c59Sftrigaux   ex->its            = 1;
29361c188c59Sftrigaux   ex->tol            = 1.e-8;
29371c188c59Sftrigaux   ex->num_pre_relax  = 1;
29381c188c59Sftrigaux   ex->num_post_relax = 1;
29391c188c59Sftrigaux 
29401c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
29411c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
29421c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
29431c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
29441c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
29451c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
29461c188c59Sftrigaux 
29471c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
29481c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
29493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29501c188c59Sftrigaux }
2951