xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 562efe2ef922487c6beae96ba39e19afd4eefbe6)
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 
147fd2dd295SFande Kong /*
1488a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1498a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1508a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
151fd2dd295SFande Kong */
152d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[])
153d71ae5a4SJacob Faibussowitsch {
1548a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1558a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1568a2c336bSFande Kong   PetscInt             num_levels, l;
1578a2c336bSFande Kong   Mat                 *mattmp;
1588a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1598a2c336bSFande Kong 
1608a2c336bSFande Kong   PetscFunctionBegin;
1619566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1625f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1638a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1658a2c336bSFande Kong   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)(jac->hsolver));
1668a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1679566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[num_levels - 1 - l])));
1688a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1698a2c336bSFande Kong     A_array[l] = NULL;
1708a2c336bSFande Kong   }
1718a2c336bSFande Kong   *nlevels   = num_levels;
1728a2c336bSFande Kong   *operators = mattmp;
1733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1748a2c336bSFande Kong }
1758a2c336bSFande Kong 
176fd2dd295SFande Kong /*
1778a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1788a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1798a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
180fd2dd295SFande Kong */
181d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[])
182d71ae5a4SJacob Faibussowitsch {
1838a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1848a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1858a2c336bSFande Kong   PetscInt             num_levels, l;
1868a2c336bSFande Kong   Mat                 *mattmp;
1878a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1888a2c336bSFande Kong 
1898a2c336bSFande Kong   PetscFunctionBegin;
1909566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1915f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1928a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1948a2c336bSFande Kong   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)(jac->hsolver));
1958a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1969566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[l - 1])));
1978a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1988a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
1998a2c336bSFande Kong   }
2008a2c336bSFande Kong   *nlevels        = num_levels;
2018a2c336bSFande Kong   *interpolations = mattmp;
2023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2038a2c336bSFande Kong }
2048a2c336bSFande Kong 
205ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
206d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
207d71ae5a4SJacob Faibussowitsch {
208ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
209ce6a8a0dSJed Brown   PetscInt  i;
210ce6a8a0dSJed Brown 
2119d678128SJed Brown   PetscFunctionBegin;
21248a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2139566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2149566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2169d678128SJed Brown   jac->n_hmnull = 0;
2173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218ce6a8a0dSJed Brown }
219ce6a8a0dSJed Brown 
220d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
221d71ae5a4SJacob Faibussowitsch {
22216d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
22349a781f5SStefano Zampini   Mat_HYPRE         *hjac;
22416d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
22516d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
22649a781f5SStefano Zampini   PetscBool          ishypre;
22716d9e3a6SLisandro Dalcin 
22816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2290df1829cSStefano Zampini   /* default type is boomerAMG */
23048a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2315f5c5b43SBarry Smith 
2320df1829cSStefano Zampini   /* get hypre matrix */
2330df1829cSStefano Zampini   if (pc->flag == DIFFERENT_NONZERO_PATTERN) PetscCall(MatDestroy(&jac->hpmat));
2349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
23549a781f5SStefano Zampini   if (!ishypre) {
2360df1829cSStefano Zampini     /* Temporary fix since we do not support MAT_REUSE_MATRIX with HYPRE device */
2370df1829cSStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
2380df1829cSStefano Zampini     PetscBool iscuda, iship, iskokkos;
2390df1829cSStefano Zampini 
2400df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
2410df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
2420df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iskokkos, MATSEQAIJKOKKOS, MATMPIAIJKOKKOS, ""));
2430df1829cSStefano Zampini     if (iscuda || iship || iskokkos) PetscCall(MatDestroy(&jac->hpmat));
2440df1829cSStefano Zampini #endif
2450df1829cSStefano Zampini     PetscCall(MatConvert(pc->pmat, MATHYPRE, jac->hpmat ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &jac->hpmat));
24649a781f5SStefano Zampini   } else {
2479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2489566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
24949a781f5SStefano Zampini     jac->hpmat = pc->pmat;
25016d9e3a6SLisandro Dalcin   }
2510df1829cSStefano Zampini 
2526ea7df73SStefano Zampini   /* allow debug */
2539566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
25449a781f5SStefano Zampini   hjac = (Mat_HYPRE *)(jac->hpmat->data);
2555f5c5b43SBarry Smith 
25616d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25716d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2585272c319SBarry Smith     MatNullSpace mnull;
2595272c319SBarry Smith     PetscBool    has_const;
26049a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2615272c319SBarry Smith     const Vec   *vecs;
2625272c319SBarry Smith 
2639566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
264792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2659566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2665272c319SBarry Smith     if (mnull) {
2679566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2689566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2699566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2715272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2729566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2739566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
274792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2755272c319SBarry Smith       }
2765272c319SBarry Smith       if (has_const) {
2779566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2789566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2799566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2809566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2819566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
282792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2835272c319SBarry Smith         nvec++;
2845272c319SBarry Smith       }
285792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2865272c319SBarry Smith       jac->n_hmnull = nvec;
2875272c319SBarry Smith     }
2884cb006feSStefano Zampini   }
289863406b8SStefano Zampini 
2904cb006feSStefano Zampini   /* special case for AMS */
2914cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2925ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
2935ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2946bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
295f1580f4eSBarry 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()");
2966bf688a0SCe Qin     }
29748a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
2985ac14e1cSStefano Zampini     if (jac->constants[0]) {
2995ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
300792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
301792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
30248a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
303792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
3045ac14e1cSStefano Zampini     }
3055ac14e1cSStefano Zampini     if (jac->coords[0]) {
3065ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3075ac14e1cSStefano Zampini       coords[0] = NULL;
3085ac14e1cSStefano Zampini       coords[1] = NULL;
3095ac14e1cSStefano Zampini       coords[2] = NULL;
310792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
311792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
312792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
313792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3145ac14e1cSStefano Zampini     }
3155f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3165ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
317792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
318792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3195ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3205ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->alpha_Poisson->data);
321792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3235ac14e1cSStefano Zampini     }
3245ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
325792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3265ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3275ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->beta_Poisson->data);
328792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
329792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
330be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
331be14dc20SKerry Key       if (jac->interior) {
332be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
333be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
334be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
335be14dc20SKerry Key       } else {
336be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
337be14dc20SKerry Key       }
3385ac14e1cSStefano Zampini     }
3396bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3406bf688a0SCe Qin       PetscInt           i;
3416bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3426bf688a0SCe Qin       if (jac->ND_PiFull) {
3436bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
344792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3456bf688a0SCe Qin       } else {
3466bf688a0SCe Qin         nd_parcsrfull = NULL;
3476bf688a0SCe Qin       }
3486bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3496bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3506bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
351792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3526bf688a0SCe Qin         } else {
3536bf688a0SCe Qin           nd_parcsr[i] = NULL;
3546bf688a0SCe Qin         }
3556bf688a0SCe Qin       }
356792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3576bf688a0SCe Qin     }
3584cb006feSStefano Zampini   }
359863406b8SStefano Zampini   /* special case for ADS */
360863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3615ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3625ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3636bf688a0SCe 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])))) {
3646bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3659371c9d4SSatish 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");
3665f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3675f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3685ac14e1cSStefano Zampini     if (jac->coords[0]) {
3695ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3705ac14e1cSStefano Zampini       coords[0] = NULL;
3715ac14e1cSStefano Zampini       coords[1] = NULL;
3725ac14e1cSStefano Zampini       coords[2] = NULL;
373792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
374792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
375792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
376792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3775ac14e1cSStefano Zampini     }
3785ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
379792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
380792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
3815ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->C->data);
382792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
383792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3846bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3856bf688a0SCe Qin       PetscInt           i;
3866bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3876bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3886bf688a0SCe Qin       if (jac->RT_PiFull) {
3896bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->RT_PiFull->data);
390792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
3916bf688a0SCe Qin       } else {
3926bf688a0SCe Qin         rt_parcsrfull = NULL;
3936bf688a0SCe Qin       }
3946bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3956bf688a0SCe Qin         if (jac->RT_Pi[i]) {
3966bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->RT_Pi[i]->data);
397792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
3986bf688a0SCe Qin         } else {
3996bf688a0SCe Qin           rt_parcsr[i] = NULL;
4006bf688a0SCe Qin         }
4016bf688a0SCe Qin       }
4026bf688a0SCe Qin       if (jac->ND_PiFull) {
4036bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
404792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4056bf688a0SCe Qin       } else {
4066bf688a0SCe Qin         nd_parcsrfull = NULL;
4076bf688a0SCe Qin       }
4086bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4096bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4106bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
411792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4126bf688a0SCe Qin         } else {
4136bf688a0SCe Qin           nd_parcsr[i] = NULL;
4146bf688a0SCe Qin         }
4156bf688a0SCe Qin       }
416792fecdfSBarry 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]);
4176bf688a0SCe Qin     }
418863406b8SStefano Zampini   }
419792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
420792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
421792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
42297c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
423792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
42497c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
4253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42616d9e3a6SLisandro Dalcin }
42716d9e3a6SLisandro Dalcin 
428d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
429d71ae5a4SJacob Faibussowitsch {
43016d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
43149a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
43216d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
43316d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
43416d9e3a6SLisandro Dalcin 
43516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4369566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4379566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4389566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4399566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4409566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
441792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
442792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
443792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4449371c9d4SSatish Balay   PetscStackCallExternalVoid(
4459371c9d4SSatish Balay     "Hypre solve", do {
4465f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4475f80ce2aSJacob Faibussowitsch       if (hierr) {
4485f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
44985245615SPierre Jolivet         HYPRE_ClearAllErrors();
4505f80ce2aSJacob Faibussowitsch       }
4515f80ce2aSJacob Faibussowitsch     } while (0));
45216d9e3a6SLisandro Dalcin 
45348a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4549566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4559566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
4563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45716d9e3a6SLisandro Dalcin }
45816d9e3a6SLisandro Dalcin 
45985245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
46085245615SPierre Jolivet {
46185245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
46285245615SPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)(jac->hpmat->data);
46385245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
46485245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
46585245615SPierre Jolivet   const PetscScalar  *b;
46685245615SPierre Jolivet   PetscScalar        *x;
46785245615SPierre Jolivet   PetscInt            m, N, lda;
46885245615SPierre Jolivet   hypre_Vector       *x_local;
46985245615SPierre Jolivet   PetscMemType        type;
47085245615SPierre Jolivet 
47185245615SPierre Jolivet   PetscFunctionBegin;
47285245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
47385245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
47485245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
47585245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
47685245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
47785245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
47885245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
47985245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
48085245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
48185245615SPierre Jolivet   PetscCheck(lda == m, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot use a LDA different than the number of local rows: % " PetscInt_FMT " != % " PetscInt_FMT, lda, m);
48285245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
48385245615SPierre Jolivet   PetscCheck(lda == m, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot use a LDA different than the number of local rows: % " PetscInt_FMT " != % " PetscInt_FMT, lda, m);
48485245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
48585245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
48685245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
48785245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
48885245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
48985245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
49085245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
49185245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
49285245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
49385245615SPierre Jolivet   PetscStackCallExternalVoid(
49485245615SPierre Jolivet     "Hypre solve", do {
49585245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
49685245615SPierre Jolivet       if (hierr) {
49785245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
49885245615SPierre Jolivet         HYPRE_ClearAllErrors();
49985245615SPierre Jolivet       }
50085245615SPierre Jolivet     } while (0));
50185245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
50285245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
50385245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
50485245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
50585245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
50685245615SPierre Jolivet }
50785245615SPierre Jolivet 
508d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
509d71ae5a4SJacob Faibussowitsch {
5108695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5118695de01SBarry Smith 
5128695de01SBarry Smith   PetscFunctionBegin;
5139566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
5149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
5159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
5169566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
5179566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
5189566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
5199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
5209566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
5219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
5229566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
5239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
5249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
5259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
5269566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
5279566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
5289566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
5299566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
5309566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
5319566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
532be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
5339566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
5345ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
535be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
5365ac14e1cSStefano Zampini   jac->dim                   = 0;
5373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5388695de01SBarry Smith }
5398695de01SBarry Smith 
540d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
541d71ae5a4SJacob Faibussowitsch {
54216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
54316d9e3a6SLisandro Dalcin 
54416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5459566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
546792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
5479566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
548db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
5499566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
550db6f9c32SMark Adams #endif
5519566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
5529566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
55316d9e3a6SLisandro Dalcin 
5549566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5622e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
563be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5682e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
5693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57016d9e3a6SLisandro Dalcin }
57116d9e3a6SLisandro Dalcin 
572d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
573d71ae5a4SJacob Faibussowitsch {
57416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
575ace3abfcSBarry Smith   PetscBool flag;
57616d9e3a6SLisandro Dalcin 
57716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
578d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
580792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
582792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
584792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
585d0609cedSBarry Smith   PetscOptionsHeadEnd();
5863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58716d9e3a6SLisandro Dalcin }
58816d9e3a6SLisandro Dalcin 
589d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
590d71ae5a4SJacob Faibussowitsch {
59116d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
592ace3abfcSBarry Smith   PetscBool iascii;
59316d9e3a6SLisandro Dalcin 
59416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
59616d9e3a6SLisandro Dalcin   if (iascii) {
5979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
59816d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
59963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
60016d9e3a6SLisandro Dalcin     } else {
6019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
60216d9e3a6SLisandro Dalcin     }
60316d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
6049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
60516d9e3a6SLisandro Dalcin     } else {
6069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
60716d9e3a6SLisandro Dalcin     }
60816d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
60963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
61016d9e3a6SLisandro Dalcin     } else {
6119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
61216d9e3a6SLisandro Dalcin     }
61316d9e3a6SLisandro Dalcin   }
6143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61516d9e3a6SLisandro Dalcin }
61616d9e3a6SLisandro Dalcin 
617d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
618d71ae5a4SJacob Faibussowitsch {
619db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6208bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
621db966c6cSHong Zhang 
622db966c6cSHong Zhang   PetscFunctionBegin;
623d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
6249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
625792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
6268bf83915SBarry Smith 
6279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
6288bf83915SBarry Smith   if (flag) {
6298bf83915SBarry Smith     PetscMPIInt size;
6308bf83915SBarry Smith 
6319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
6327827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
633792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
6348bf83915SBarry Smith   }
6358bf83915SBarry Smith 
6369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
6378bf83915SBarry Smith   if (flag) {
6388bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
639792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
6408bf83915SBarry Smith   }
641d0609cedSBarry Smith   PetscOptionsHeadEnd();
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
643db966c6cSHong Zhang }
644db966c6cSHong Zhang 
645d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
646d71ae5a4SJacob Faibussowitsch {
647db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
648db966c6cSHong Zhang   PetscBool iascii;
649db966c6cSHong Zhang 
650db966c6cSHong Zhang   PetscFunctionBegin;
6519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
652db966c6cSHong Zhang   if (iascii) {
6539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
654db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
65563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
656db966c6cSHong Zhang     } else {
6579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
658db966c6cSHong Zhang     }
6599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
66063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
661db966c6cSHong Zhang   }
6623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
663db966c6cSHong Zhang }
664db966c6cSHong Zhang 
665d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
666d71ae5a4SJacob Faibussowitsch {
66716d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
66849a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
66916d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
67016d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
67116d9e3a6SLisandro Dalcin 
67216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6739566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6749566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6759566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6769566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
67716d9e3a6SLisandro Dalcin 
678792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
679792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
680792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
68116d9e3a6SLisandro Dalcin 
6829371c9d4SSatish Balay   PetscStackCallExternalVoid(
6839371c9d4SSatish Balay     "Hypre Transpose solve", do {
6845f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6855f80ce2aSJacob Faibussowitsch       if (hierr) {
68616d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6875f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
68885245615SPierre Jolivet         HYPRE_ClearAllErrors();
6895f80ce2aSJacob Faibussowitsch       }
6905f80ce2aSJacob Faibussowitsch     } while (0));
69116d9e3a6SLisandro Dalcin 
6929566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6939566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
6943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69516d9e3a6SLisandro Dalcin }
69616d9e3a6SLisandro Dalcin 
697d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
698d71ae5a4SJacob Faibussowitsch {
699db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
700db6f9c32SMark Adams   PetscBool flag;
701db6f9c32SMark Adams 
702db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
703db6f9c32SMark Adams   PetscFunctionBegin;
704db6f9c32SMark Adams   if (jac->spgemm_type) {
7059566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
70628b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
7073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
708db6f9c32SMark Adams   } else {
7099566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
710db6f9c32SMark Adams   }
7119566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
712db6f9c32SMark Adams   if (flag) {
713792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
7143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
715db6f9c32SMark Adams   }
7169566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
717db6f9c32SMark Adams   if (flag) {
718792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
7193ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
720db6f9c32SMark Adams   }
721db6f9c32SMark Adams   jac->spgemm_type = NULL;
7222d6c3ceeSStefano Zampini   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEMM type %s; Choices are cusparse, hypre", name);
723db6f9c32SMark Adams #endif
724db6f9c32SMark Adams }
725db6f9c32SMark Adams 
726d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
727d71ae5a4SJacob Faibussowitsch {
728db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
729db6f9c32SMark Adams 
730db6f9c32SMark Adams   PetscFunctionBegin;
731db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
732db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
733db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
734db6f9c32SMark Adams #endif
7353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
736db6f9c32SMark Adams }
737db6f9c32SMark Adams 
73816d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
7390f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
74016d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
74165de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
7426a251517SEike Mueller static const char *HYPREBoomerAMGSmoothType[] = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
7439371c9d4SSatish 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"};
7449371c9d4SSatish 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"};
745d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
746d71ae5a4SJacob Faibussowitsch {
74716d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
74822e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
749ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
75016d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
751589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
752db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
75316d9e3a6SLisandro Dalcin 
75416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
755d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
7569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
75716d9e3a6SLisandro Dalcin   if (flg) {
7584336a9eeSBarry Smith     jac->cycletype = indx + 1;
759792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
76016d9e3a6SLisandro Dalcin   }
7619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
76216d9e3a6SLisandro Dalcin   if (flg) {
76363a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
764792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
76516d9e3a6SLisandro Dalcin   }
7669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
76716d9e3a6SLisandro Dalcin   if (flg) {
76863a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
769792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
77016d9e3a6SLisandro Dalcin   }
7719566063dSJacob 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));
77216d9e3a6SLisandro Dalcin   if (flg) {
77308401ef6SPierre 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);
774792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
77516d9e3a6SLisandro Dalcin   }
77622e51d31SStefano Zampini   bs = 1;
77748a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
77948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
78016d9e3a6SLisandro Dalcin 
7819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
78216d9e3a6SLisandro Dalcin   if (flg) {
78308401ef6SPierre 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);
784792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
78516d9e3a6SLisandro Dalcin   }
78616d9e3a6SLisandro Dalcin 
7879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7880f1074feSSatish Balay   if (flg) {
78963a3b9bcSJacob 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);
790792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7910f1074feSSatish Balay   }
7920f1074feSSatish Balay 
7939566063dSJacob 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));
794792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7950f1074feSSatish Balay 
7969566063dSJacob 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));
7970f1074feSSatish Balay   if (flg) {
79863a3b9bcSJacob 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);
799792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
8000f1074feSSatish Balay   }
8010f1074feSSatish Balay 
8029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
80316d9e3a6SLisandro Dalcin   if (flg) {
80408401ef6SPierre 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);
805792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
80616d9e3a6SLisandro Dalcin   }
8079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
80816d9e3a6SLisandro Dalcin   if (flg) {
80908401ef6SPierre 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);
81008401ef6SPierre 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);
811792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
81216d9e3a6SLisandro Dalcin   }
81316d9e3a6SLisandro Dalcin 
81416d9e3a6SLisandro Dalcin   /* Grid sweeps */
8159566063dSJacob 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));
81616d9e3a6SLisandro Dalcin   if (flg) {
817792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
81816d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
81916d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
8200f1074feSSatish Balay     jac->gridsweeps[1] = indx;
8210f1074feSSatish Balay     /*defaults coarse to 1 */
8220f1074feSSatish Balay     jac->gridsweeps[2] = 1;
82316d9e3a6SLisandro Dalcin   }
8249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
82548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
8269566063dSJacob 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));
82748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
8289566063dSJacob 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));
82948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
8309566063dSJacob 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));
83148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
8329566063dSJacob 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));
83348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
8349566063dSJacob 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));
83548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
8369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
83716d9e3a6SLisandro Dalcin   if (flg) {
838792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
8390f1074feSSatish Balay     jac->gridsweeps[0] = indx;
84016d9e3a6SLisandro Dalcin   }
8419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
84216d9e3a6SLisandro Dalcin   if (flg) {
843792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
8440f1074feSSatish Balay     jac->gridsweeps[1] = indx;
84516d9e3a6SLisandro Dalcin   }
8469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
84716d9e3a6SLisandro Dalcin   if (flg) {
848792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
8490f1074feSSatish Balay     jac->gridsweeps[2] = indx;
85016d9e3a6SLisandro Dalcin   }
85116d9e3a6SLisandro Dalcin 
8526a251517SEike Mueller   /* Smooth type */
853dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
8546a251517SEike Mueller   if (flg) {
8556a251517SEike Mueller     jac->smoothtype = indx;
856792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
8578131ecf7SEike Mueller     jac->smoothnumlevels = 25;
858792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
8598131ecf7SEike Mueller   }
8608131ecf7SEike Mueller 
8618131ecf7SEike Mueller   /* Number of smoothing levels */
8629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
8638131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8648131ecf7SEike Mueller     jac->smoothnumlevels = indx;
865792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8666a251517SEike Mueller   }
8676a251517SEike Mueller 
8681810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8701810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8711810e44eSEike Mueller     jac->eu_level = indx;
872792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8731810e44eSEike Mueller   }
8741810e44eSEike Mueller 
8751810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8761810e44eSEike Mueller   double droptolerance;
8779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8781810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8791810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
880792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8811810e44eSEike Mueller   }
8821810e44eSEike Mueller 
8831810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8851810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8861810e44eSEike Mueller     jac->eu_bj = tmp_truth;
887792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8881810e44eSEike Mueller   }
8891810e44eSEike Mueller 
89016d9e3a6SLisandro Dalcin   /* Relax type */
891dd39110bSPierre 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));
89216d9e3a6SLisandro Dalcin   if (flg) {
8930f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
894792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8950f1074feSSatish Balay     /* by default, coarse type set to 9 */
8960f1074feSSatish Balay     jac->relaxtype[2] = 9;
897792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
89816d9e3a6SLisandro Dalcin   }
899dd39110bSPierre 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));
90016d9e3a6SLisandro Dalcin   if (flg) {
90116d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
902792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
90316d9e3a6SLisandro Dalcin   }
904dd39110bSPierre 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));
90516d9e3a6SLisandro Dalcin   if (flg) {
9060f1074feSSatish Balay     jac->relaxtype[1] = indx;
907792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
90816d9e3a6SLisandro Dalcin   }
909dd39110bSPierre 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));
91016d9e3a6SLisandro Dalcin   if (flg) {
9110f1074feSSatish Balay     jac->relaxtype[2] = indx;
912792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
91316d9e3a6SLisandro Dalcin   }
91416d9e3a6SLisandro Dalcin 
91516d9e3a6SLisandro Dalcin   /* Relaxation Weight */
9169566063dSJacob 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));
91716d9e3a6SLisandro Dalcin   if (flg) {
918792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
91916d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
92016d9e3a6SLisandro Dalcin   }
92116d9e3a6SLisandro Dalcin 
92216d9e3a6SLisandro Dalcin   n         = 2;
92316d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
92516d9e3a6SLisandro Dalcin   if (flg) {
9260fdf79fbSJacob 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);
92716d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
928792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
92916d9e3a6SLisandro Dalcin   }
93016d9e3a6SLisandro Dalcin 
93116d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
9329566063dSJacob 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));
93316d9e3a6SLisandro Dalcin   if (flg) {
934792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
93516d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
93616d9e3a6SLisandro Dalcin   }
93716d9e3a6SLisandro Dalcin 
93816d9e3a6SLisandro Dalcin   n         = 2;
93916d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9409566063dSJacob 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));
94116d9e3a6SLisandro Dalcin   if (flg) {
9420fdf79fbSJacob 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);
94316d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
944792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
94516d9e3a6SLisandro Dalcin   }
94616d9e3a6SLisandro Dalcin 
94716d9e3a6SLisandro Dalcin   /* the Relax Order */
9489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
94916d9e3a6SLisandro Dalcin 
9508afaa268SBarry Smith   if (flg && tmp_truth) {
95116d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
952792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
95316d9e3a6SLisandro Dalcin   }
954dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
95516d9e3a6SLisandro Dalcin   if (flg) {
95616d9e3a6SLisandro Dalcin     jac->measuretype = indx;
957792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
95816d9e3a6SLisandro Dalcin   }
9590f1074feSSatish Balay   /* update list length 3/07 */
960dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
96116d9e3a6SLisandro Dalcin   if (flg) {
96216d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
963792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
96416d9e3a6SLisandro Dalcin   }
9650f1074feSSatish Balay 
9669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
96748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
96948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
970db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
971db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
972dd39110bSPierre 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));
9732d6c3ceeSStefano Zampini   #if defined(PETSC_HAVE_HYPRE_DEVICE)
974db6f9c32SMark Adams   if (!flg) indx = 0;
9759566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
9762d6c3ceeSStefano Zampini   #else
9772d6c3ceeSStefano Zampini   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, "hypre"));
9782d6c3ceeSStefano Zampini   #endif
979db6f9c32SMark Adams #endif
980589dcaf0SStefano Zampini   /* AIR */
981589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9829566063dSJacob 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));
983792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
984589dcaf0SStefano Zampini   if (jac->Rtype) {
98519be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
98619be502cSAlexander     char       *prerelax[256];
98719be502cSAlexander     char       *postrelax[256];
98819be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
98919be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
99019be502cSAlexander     PetscBool   matchF, matchC, matchA;
99119be502cSAlexander 
992589dcaf0SStefano 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 */
993589dcaf0SStefano Zampini 
9949566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
995792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
996589dcaf0SStefano Zampini 
9979566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
998792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
999589dcaf0SStefano Zampini 
10009566063dSJacob 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));
1001792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1002589dcaf0SStefano Zampini 
10039566063dSJacob 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));
1004792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
100519be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
100619be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
100719be502cSAlexander     PetscCheck(ns_down == jac->gridsweeps[0], PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_SIZ, "The number of arguments passed to -pc_hypre_boomeramg_prerelax must match the number passed to -pc_hypre_bomeramg_grid_sweeps_down");
100819be502cSAlexander     PetscCheck(ns_up == jac->gridsweeps[1], PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_SIZ, "The number of arguments passed to -pc_hypre_boomeramg_postrelax must match the number passed to -pc_hypre_bomeramg_grid_sweeps_up");
100919be502cSAlexander 
101019be502cSAlexander     grid_relax_points[0]    = NULL;
101119be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
101219be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
101319be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
101419be502cSAlexander     grid_relax_points[3][0] = 0;
101519be502cSAlexander 
101619be502cSAlexander     // set down relax scheme
101719be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
101819be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
101919be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
102019be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
102119be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
102219be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
102319be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
102419be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
102519be502cSAlexander     }
102619be502cSAlexander 
102719be502cSAlexander     // set up relax scheme
102819be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
102919be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
103019be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
103119be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
103219be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
103319be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
103419be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
103519be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
103619be502cSAlexander     }
103719be502cSAlexander 
103819be502cSAlexander     // set coarse relax scheme
103919be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
104019be502cSAlexander 
104119be502cSAlexander     // Pass relax schemes to hypre
104219be502cSAlexander     PetscCallExternal(HYPRE_BoomerAMGSetGridRelaxPoints, jac->hsolver, grid_relax_points);
104319be502cSAlexander 
104419be502cSAlexander     // cleanup memory
104519be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
104619be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1047589dcaf0SStefano Zampini   }
1048589dcaf0SStefano Zampini #endif
1049589dcaf0SStefano Zampini 
1050ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
105163a3b9bcSJacob 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);
1052ecae95adSPierre Jolivet #endif
1053ecae95adSPierre Jolivet 
10540f1074feSSatish Balay   /* new 3/07 */
1055dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1056589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1057589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1058792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
10590f1074feSSatish Balay   }
10600f1074feSSatish Balay 
10619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
106216d9e3a6SLisandro Dalcin   if (flg) {
1063b96a4a96SBarry Smith     level = 3;
10649566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
10652fa5cd67SKarl Rupp 
1066b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1067792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
10682ae77aedSBarry Smith   }
10692ae77aedSBarry Smith 
10709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
10712ae77aedSBarry Smith   if (flg) {
1072b96a4a96SBarry Smith     level = 3;
10739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
10742fa5cd67SKarl Rupp 
1075b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1076792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
107716d9e3a6SLisandro Dalcin   }
10788f87f92bSBarry Smith 
10799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
10808f87f92bSBarry Smith   if (flg && tmp_truth) {
10818f87f92bSBarry Smith     PetscInt tmp_int;
10829566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
10838f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1084792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1085792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1086792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1087792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
10888f87f92bSBarry Smith   }
10898f87f92bSBarry Smith 
10909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1091792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1092589dcaf0SStefano Zampini 
1093589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1094dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1095589dcaf0SStefano Zampini   if (flg) {
1096589dcaf0SStefano Zampini     jac->symt = indx;
1097792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1098589dcaf0SStefano Zampini   }
1099589dcaf0SStefano Zampini 
1100d0609cedSBarry Smith   PetscOptionsHeadEnd();
11013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
110216d9e3a6SLisandro Dalcin }
110316d9e3a6SLisandro Dalcin 
1104d71ae5a4SJacob 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)
1105d71ae5a4SJacob Faibussowitsch {
110616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11072cf14000SStefano Zampini   HYPRE_Int oits;
110816d9e3a6SLisandro Dalcin 
110916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11109566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1111792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1112792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
111316d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
11149566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
111516d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1116792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
11174d0a8057SBarry Smith   *outits = oits;
11184d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
11194d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1120792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1121792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
11223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
112316d9e3a6SLisandro Dalcin }
112416d9e3a6SLisandro Dalcin 
1125d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1126d71ae5a4SJacob Faibussowitsch {
112716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1128ace3abfcSBarry Smith   PetscBool iascii;
112916d9e3a6SLisandro Dalcin 
113016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
113216d9e3a6SLisandro Dalcin   if (iascii) {
11339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
11349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
113563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
113663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
11379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
11389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
11399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
114063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
114148a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
114263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
114363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
11440f1074feSSatish Balay 
11459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
114616d9e3a6SLisandro Dalcin 
114763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
114863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
114963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
115016d9e3a6SLisandro Dalcin 
11519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
11529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
11539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
115416d9e3a6SLisandro Dalcin 
11559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
11569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
115716d9e3a6SLisandro Dalcin 
115819be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
115919be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
116019be502cSAlexander 
116116d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
11629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
116316d9e3a6SLisandro Dalcin     } else {
11649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
116516d9e3a6SLisandro Dalcin     }
11666a251517SEike Mueller     if (jac->smoothtype != -1) {
11679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
116863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
11697e352d70SEike Mueller     } else {
11709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
11711810e44eSEike Mueller     }
11721810e44eSEike Mueller     if (jac->smoothtype == 3) {
117363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
11749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
117563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
11766a251517SEike Mueller     }
11779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
11789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
11799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
118048a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
11815272c319SBarry Smith     if (jac->vec_interp_variant) {
118263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
118363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
11849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
11858f87f92bSBarry Smith     }
118648a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1187db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
11889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
11892d6c3ceeSStefano Zampini #else
11902d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1191db6f9c32SMark Adams #endif
1192589dcaf0SStefano Zampini     /* AIR */
1193589dcaf0SStefano Zampini     if (jac->Rtype) {
119463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
11959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
11969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
11979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
119863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1199589dcaf0SStefano Zampini     }
120016d9e3a6SLisandro Dalcin   }
12013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120216d9e3a6SLisandro Dalcin }
120316d9e3a6SLisandro Dalcin 
1204d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1205d71ae5a4SJacob Faibussowitsch {
120616d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
12074ddd07fcSJed Brown   PetscInt    indx;
1208ace3abfcSBarry Smith   PetscBool   flag;
120916d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
121016d9e3a6SLisandro Dalcin 
121116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1212d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
12139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
12149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1215792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
121616d9e3a6SLisandro Dalcin 
12179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1218792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
121916d9e3a6SLisandro Dalcin 
12209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1221792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
122216d9e3a6SLisandro Dalcin 
12239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1224792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
122516d9e3a6SLisandro Dalcin 
12269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1227792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
122816d9e3a6SLisandro Dalcin 
1229dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
123016d9e3a6SLisandro Dalcin   if (flag) {
123116d9e3a6SLisandro Dalcin     jac->symt = indx;
1232792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
123316d9e3a6SLisandro Dalcin   }
123416d9e3a6SLisandro Dalcin 
1235d0609cedSBarry Smith   PetscOptionsHeadEnd();
12363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123716d9e3a6SLisandro Dalcin }
123816d9e3a6SLisandro Dalcin 
1239d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1240d71ae5a4SJacob Faibussowitsch {
124116d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1242ace3abfcSBarry Smith   PetscBool   iascii;
1243feb237baSPierre Jolivet   const char *symt = 0;
124416d9e3a6SLisandro Dalcin 
124516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
12469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
124716d9e3a6SLisandro Dalcin   if (iascii) {
12489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
124963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
12509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
12519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
12529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
12539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
12549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
12552fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
12562fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
12572fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
125863a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
12599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
126016d9e3a6SLisandro Dalcin   }
12613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
126216d9e3a6SLisandro Dalcin }
1263f1580f4eSBarry Smith 
1264d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1265d71ae5a4SJacob Faibussowitsch {
12664cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12674cb006feSStefano Zampini   PetscInt  n;
12684cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
12694cb006feSStefano Zampini 
12704cb006feSStefano Zampini   PetscFunctionBegin;
1271d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
12729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1273792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
12749566063dSJacob 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));
1275792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
12769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1277792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
12789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1279792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
12809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12819566063dSJacob 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));
12829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
128448a46eb9SPierre 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);
12859566063dSJacob 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));
12864cb006feSStefano Zampini   n = 5;
12879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
12884cb006feSStefano Zampini   if (flag || flag2) {
1289792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1290863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1291863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
12929371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1293a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
12944cb006feSStefano Zampini   }
12959566063dSJacob 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));
12964cb006feSStefano Zampini   n = 5;
12979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
12984cb006feSStefano Zampini   if (flag || flag2) {
1299792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1300863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1301863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
13029371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1303a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
13044cb006feSStefano Zampini   }
13059566063dSJacob 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));
130623df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1307792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
130823df4f25SStefano Zampini   }
1309d0609cedSBarry Smith   PetscOptionsHeadEnd();
13103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13114cb006feSStefano Zampini }
13124cb006feSStefano Zampini 
1313d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1314d71ae5a4SJacob Faibussowitsch {
13154cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13164cb006feSStefano Zampini   PetscBool iascii;
13174cb006feSStefano Zampini 
13184cb006feSStefano Zampini   PetscFunctionBegin;
13199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
13204cb006feSStefano Zampini   if (iascii) {
13219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
132263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
132363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
132463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
132563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
132663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
132763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
132863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13294cb006feSStefano Zampini     if (jac->alpha_Poisson) {
13309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
13314cb006feSStefano Zampini     } else {
13329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
13334cb006feSStefano Zampini     }
133463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
133563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
133663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
133763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
133863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
133963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13404cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
13414cb006feSStefano Zampini       if (jac->beta_Poisson) {
13429566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
13434cb006feSStefano Zampini       } else {
13449566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
13454cb006feSStefano Zampini       }
134663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
134763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
134863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
134963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
135063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
135163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
135248a46eb9SPierre 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));
135323df4f25SStefano Zampini     } else {
13549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
13554cb006feSStefano Zampini     }
13564cb006feSStefano Zampini   }
13573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13584cb006feSStefano Zampini }
13594cb006feSStefano Zampini 
1360d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1361d71ae5a4SJacob Faibussowitsch {
1362863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1363863406b8SStefano Zampini   PetscInt  n;
1364863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1365863406b8SStefano Zampini 
1366863406b8SStefano Zampini   PetscFunctionBegin;
1367d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
13689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1369792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
13709566063dSJacob 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));
1371792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
13729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1373792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
13749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1375792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
13769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
13779566063dSJacob 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));
13789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
13799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
138048a46eb9SPierre 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);
13819566063dSJacob 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));
1382863406b8SStefano Zampini   n = 5;
13839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
13849566063dSJacob 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));
1385863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1386792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1387863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1388863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1389863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
13909371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1391a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1392863406b8SStefano Zampini   }
13939566063dSJacob 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));
1394863406b8SStefano Zampini   n = 5;
13959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1396863406b8SStefano Zampini   if (flag || flag2) {
1397792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1398863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1399863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
14009371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1401a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1402863406b8SStefano Zampini   }
1403d0609cedSBarry Smith   PetscOptionsHeadEnd();
14043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1405863406b8SStefano Zampini }
1406863406b8SStefano Zampini 
1407d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1408d71ae5a4SJacob Faibussowitsch {
1409863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1410863406b8SStefano Zampini   PetscBool iascii;
1411863406b8SStefano Zampini 
1412863406b8SStefano Zampini   PetscFunctionBegin;
14139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1414863406b8SStefano Zampini   if (iascii) {
14159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
141663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
141763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
141863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
141963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
142063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
142163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
142263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
14239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
142463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
142563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
142663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
142763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
142863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
142963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
143063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
14319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
143263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
143363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
143463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
143563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
143663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
143763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1438863406b8SStefano Zampini   }
14393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1440863406b8SStefano Zampini }
1441863406b8SStefano Zampini 
1442d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1443d71ae5a4SJacob Faibussowitsch {
14444cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14455ac14e1cSStefano Zampini   PetscBool ishypre;
14464cb006feSStefano Zampini 
14474cb006feSStefano Zampini   PetscFunctionBegin;
14489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
14495ac14e1cSStefano Zampini   if (ishypre) {
14509566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
14519566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14525ac14e1cSStefano Zampini     jac->G = G;
14535ac14e1cSStefano Zampini   } else {
14549566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14559566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
14565ac14e1cSStefano Zampini   }
14573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14584cb006feSStefano Zampini }
14594cb006feSStefano Zampini 
14604cb006feSStefano Zampini /*@
1461f1580f4eSBarry Smith   PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
14624cb006feSStefano Zampini 
1463c3339decSBarry Smith   Collective
14644cb006feSStefano Zampini 
14654cb006feSStefano Zampini   Input Parameters:
14664cb006feSStefano Zampini + pc - the preconditioning context
14674cb006feSStefano Zampini - G  - the discrete gradient
14684cb006feSStefano Zampini 
14694cb006feSStefano Zampini   Level: intermediate
14704cb006feSStefano Zampini 
147195452b02SPatrick Sanan   Notes:
147295452b02SPatrick Sanan   G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1473147403d9SBarry Smith 
1474863406b8SStefano 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
14754cb006feSStefano Zampini 
1476feefa0e1SJacob Faibussowitsch   Developer Notes:
1477f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1478f1580f4eSBarry Smith 
1479*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
14804cb006feSStefano Zampini @*/
1481d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1482d71ae5a4SJacob Faibussowitsch {
14834cb006feSStefano Zampini   PetscFunctionBegin;
14844cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14854cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
14864cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1487cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
14883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14894cb006feSStefano Zampini }
14904cb006feSStefano Zampini 
1491d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1492d71ae5a4SJacob Faibussowitsch {
1493863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14945ac14e1cSStefano Zampini   PetscBool ishypre;
1495863406b8SStefano Zampini 
1496863406b8SStefano Zampini   PetscFunctionBegin;
14979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
14985ac14e1cSStefano Zampini   if (ishypre) {
14999566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
15009566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
15015ac14e1cSStefano Zampini     jac->C = C;
15025ac14e1cSStefano Zampini   } else {
15039566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
15049566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
15055ac14e1cSStefano Zampini   }
15063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1507863406b8SStefano Zampini }
1508863406b8SStefano Zampini 
1509863406b8SStefano Zampini /*@
1510f1580f4eSBarry Smith   PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1511863406b8SStefano Zampini 
1512c3339decSBarry Smith   Collective
1513863406b8SStefano Zampini 
1514863406b8SStefano Zampini   Input Parameters:
1515863406b8SStefano Zampini + pc - the preconditioning context
1516863406b8SStefano Zampini - C  - the discrete curl
1517863406b8SStefano Zampini 
1518863406b8SStefano Zampini   Level: intermediate
1519863406b8SStefano Zampini 
152095452b02SPatrick Sanan   Notes:
152195452b02SPatrick Sanan   C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1522147403d9SBarry Smith 
1523863406b8SStefano 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
1524863406b8SStefano Zampini 
1525feefa0e1SJacob Faibussowitsch   Developer Notes:
1526f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1527f1580f4eSBarry Smith 
1528f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1529f1580f4eSBarry Smith 
1530*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1531863406b8SStefano Zampini @*/
1532d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1533d71ae5a4SJacob Faibussowitsch {
1534863406b8SStefano Zampini   PetscFunctionBegin;
1535863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1536863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1537863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1538cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
15393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1540863406b8SStefano Zampini }
1541863406b8SStefano Zampini 
1542d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1543d71ae5a4SJacob Faibussowitsch {
15446bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15456bf688a0SCe Qin   PetscBool ishypre;
15466bf688a0SCe Qin   PetscInt  i;
15476bf688a0SCe Qin   PetscFunctionBegin;
15486bf688a0SCe Qin 
15499566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
15509566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
15516bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
15529566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
15539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
15546bf688a0SCe Qin   }
15556bf688a0SCe Qin 
15566bf688a0SCe Qin   jac->dim = dim;
15576bf688a0SCe Qin   if (RT_PiFull) {
15589566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
15596bf688a0SCe Qin     if (ishypre) {
15609566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
15616bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
15626bf688a0SCe Qin     } else {
15639566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
15646bf688a0SCe Qin     }
15656bf688a0SCe Qin   }
15666bf688a0SCe Qin   if (RT_Pi) {
15676bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15686bf688a0SCe Qin       if (RT_Pi[i]) {
15699566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
15706bf688a0SCe Qin         if (ishypre) {
15719566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
15726bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
15736bf688a0SCe Qin         } else {
15749566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
15756bf688a0SCe Qin         }
15766bf688a0SCe Qin       }
15776bf688a0SCe Qin     }
15786bf688a0SCe Qin   }
15796bf688a0SCe Qin   if (ND_PiFull) {
15809566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
15816bf688a0SCe Qin     if (ishypre) {
15829566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
15836bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
15846bf688a0SCe Qin     } else {
15859566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
15866bf688a0SCe Qin     }
15876bf688a0SCe Qin   }
15886bf688a0SCe Qin   if (ND_Pi) {
15896bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15906bf688a0SCe Qin       if (ND_Pi[i]) {
15919566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
15926bf688a0SCe Qin         if (ishypre) {
15939566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
15946bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
15956bf688a0SCe Qin         } else {
15969566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
15976bf688a0SCe Qin         }
15986bf688a0SCe Qin       }
15996bf688a0SCe Qin     }
16006bf688a0SCe Qin   }
16016bf688a0SCe Qin 
16023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16036bf688a0SCe Qin }
16046bf688a0SCe Qin 
16056bf688a0SCe Qin /*@
1606f1580f4eSBarry Smith   PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
16076bf688a0SCe Qin 
1608c3339decSBarry Smith   Collective
16096bf688a0SCe Qin 
16106bf688a0SCe Qin   Input Parameters:
16116bf688a0SCe Qin + pc        - the preconditioning context
16122fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
16132fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
16142fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
16152fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
16166bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
16176bf688a0SCe Qin 
1618f1580f4eSBarry Smith   Level: intermediate
1619f1580f4eSBarry Smith 
162095452b02SPatrick Sanan   Notes:
162195452b02SPatrick Sanan   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1622147403d9SBarry Smith 
16236bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1624147403d9SBarry Smith 
1625feefa0e1SJacob Faibussowitsch   Developer Notes:
1626f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
16276bf688a0SCe Qin 
1628*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`
16296bf688a0SCe Qin @*/
1630d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1631d71ae5a4SJacob Faibussowitsch {
16326bf688a0SCe Qin   PetscInt i;
16336bf688a0SCe Qin 
16346bf688a0SCe Qin   PetscFunctionBegin;
16356bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16366bf688a0SCe Qin   if (RT_PiFull) {
16376bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
16386bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
16396bf688a0SCe Qin   }
16406bf688a0SCe Qin   if (RT_Pi) {
16414f572ea9SToby Isaac     PetscAssertPointer(RT_Pi, 4);
16426bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16436bf688a0SCe Qin       if (RT_Pi[i]) {
16446bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
16456bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
16466bf688a0SCe Qin       }
16476bf688a0SCe Qin     }
16486bf688a0SCe Qin   }
16496bf688a0SCe Qin   if (ND_PiFull) {
16506bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
16516bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
16526bf688a0SCe Qin   }
16536bf688a0SCe Qin   if (ND_Pi) {
16544f572ea9SToby Isaac     PetscAssertPointer(ND_Pi, 6);
16556bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16566bf688a0SCe Qin       if (ND_Pi[i]) {
16576bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
16586bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
16596bf688a0SCe Qin       }
16606bf688a0SCe Qin     }
16616bf688a0SCe Qin   }
1662cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
16633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16646bf688a0SCe Qin }
16656bf688a0SCe Qin 
1666d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1667d71ae5a4SJacob Faibussowitsch {
16684cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16695ac14e1cSStefano Zampini   PetscBool ishypre;
16704cb006feSStefano Zampini 
16714cb006feSStefano Zampini   PetscFunctionBegin;
16729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
16735ac14e1cSStefano Zampini   if (ishypre) {
16745ac14e1cSStefano Zampini     if (isalpha) {
16759566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
16769566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16775ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
16785ac14e1cSStefano Zampini     } else {
16795ac14e1cSStefano Zampini       if (A) {
16809566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
16815ac14e1cSStefano Zampini       } else {
16825ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16835ac14e1cSStefano Zampini       }
16849566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
16855ac14e1cSStefano Zampini       jac->beta_Poisson = A;
16865ac14e1cSStefano Zampini     }
16875ac14e1cSStefano Zampini   } else {
16885ac14e1cSStefano Zampini     if (isalpha) {
16899566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16909566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
16915ac14e1cSStefano Zampini     } else {
16925ac14e1cSStefano Zampini       if (A) {
16939566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16949566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
16955ac14e1cSStefano Zampini       } else {
16969566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16975ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16985ac14e1cSStefano Zampini       }
16995ac14e1cSStefano Zampini     }
17005ac14e1cSStefano Zampini   }
17013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17024cb006feSStefano Zampini }
17034cb006feSStefano Zampini 
17044cb006feSStefano Zampini /*@
1705f1580f4eSBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
17064cb006feSStefano Zampini 
1707c3339decSBarry Smith   Collective
17084cb006feSStefano Zampini 
17094cb006feSStefano Zampini   Input Parameters:
17104cb006feSStefano Zampini + pc - the preconditioning context
17114cb006feSStefano Zampini - A  - the matrix
17124cb006feSStefano Zampini 
17134cb006feSStefano Zampini   Level: intermediate
17144cb006feSStefano Zampini 
1715f1580f4eSBarry Smith   Note:
171695452b02SPatrick Sanan   A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
17174cb006feSStefano Zampini 
1718feefa0e1SJacob Faibussowitsch   Developer Notes:
1719f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1720f1580f4eSBarry Smith 
1721f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1722f1580f4eSBarry Smith 
1723*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
17244cb006feSStefano Zampini @*/
1725d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1726d71ae5a4SJacob Faibussowitsch {
17274cb006feSStefano Zampini   PetscFunctionBegin;
17284cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17294cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17304cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1731cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
17323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17334cb006feSStefano Zampini }
17344cb006feSStefano Zampini 
17354cb006feSStefano Zampini /*@
1736f1580f4eSBarry Smith   PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
17374cb006feSStefano Zampini 
1738c3339decSBarry Smith   Collective
17394cb006feSStefano Zampini 
17404cb006feSStefano Zampini   Input Parameters:
17414cb006feSStefano Zampini + pc - the preconditioning context
1742f1580f4eSBarry Smith - A  - the matrix, or NULL to turn it off
17434cb006feSStefano Zampini 
17444cb006feSStefano Zampini   Level: intermediate
17454cb006feSStefano Zampini 
1746f1580f4eSBarry Smith   Note:
174795452b02SPatrick Sanan   A should be obtained by discretizing the Poisson problem with linear finite elements.
17484cb006feSStefano Zampini 
1749feefa0e1SJacob Faibussowitsch   Developer Notes:
1750f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1751f1580f4eSBarry Smith 
1752f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1753f1580f4eSBarry Smith 
1754*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17554cb006feSStefano Zampini @*/
1756d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1757d71ae5a4SJacob Faibussowitsch {
17584cb006feSStefano Zampini   PetscFunctionBegin;
17594cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17604cb006feSStefano Zampini   if (A) {
17614cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17624cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
17634cb006feSStefano Zampini   }
1764cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
17653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17664cb006feSStefano Zampini }
17674cb006feSStefano Zampini 
1768d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1769d71ae5a4SJacob Faibussowitsch {
17704cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17714cb006feSStefano Zampini 
17724cb006feSStefano Zampini   PetscFunctionBegin;
17734cb006feSStefano Zampini   /* throw away any vector if already set */
17749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
17759566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
17769566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
17779566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
17789566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
17799566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
17809566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
17815ac14e1cSStefano Zampini   jac->dim = 2;
17824cb006feSStefano Zampini   if (zzo) {
17839566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
17849566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
17855ac14e1cSStefano Zampini     jac->dim++;
17864cb006feSStefano Zampini   }
17873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17884cb006feSStefano Zampini }
17894cb006feSStefano Zampini 
17904cb006feSStefano Zampini /*@
1791f1580f4eSBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
17924cb006feSStefano Zampini 
1793c3339decSBarry Smith   Collective
17944cb006feSStefano Zampini 
17954cb006feSStefano Zampini   Input Parameters:
17964cb006feSStefano Zampini + pc  - the preconditioning context
17972fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
17982fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
17994cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
18004cb006feSStefano Zampini 
18014cb006feSStefano Zampini   Level: intermediate
18024cb006feSStefano Zampini 
1803feefa0e1SJacob Faibussowitsch   Developer Notes:
1804f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1805f1580f4eSBarry Smith 
1806*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
18074cb006feSStefano Zampini @*/
1808d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1809d71ae5a4SJacob Faibussowitsch {
18104cb006feSStefano Zampini   PetscFunctionBegin;
18114cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
18124cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
18134cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
18144cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
18154cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
18164cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
18174cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1818cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
18193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18204cb006feSStefano Zampini }
18214cb006feSStefano Zampini 
1822d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1823d71ae5a4SJacob Faibussowitsch {
1824be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1825be14dc20SKerry Key 
1826be14dc20SKerry Key   PetscFunctionBegin;
1827be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1828be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1829be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1830be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
18313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1832be14dc20SKerry Key }
1833be14dc20SKerry Key 
1834be14dc20SKerry Key /*@
1835f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1836be14dc20SKerry Key 
1837c3339decSBarry Smith   Collective
1838be14dc20SKerry Key 
1839be14dc20SKerry Key   Input Parameters:
1840be14dc20SKerry Key + pc       - the preconditioning context
1841be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
1842be14dc20SKerry Key 
1843be14dc20SKerry Key   Level: intermediate
1844be14dc20SKerry Key 
1845be14dc20SKerry Key   Note:
1846f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
1847f1580f4eSBarry Smith 
1848feefa0e1SJacob Faibussowitsch   Developer Notes:
1849f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1850f1580f4eSBarry Smith 
1851*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1852be14dc20SKerry Key @*/
1853d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1854d71ae5a4SJacob Faibussowitsch {
1855be14dc20SKerry Key   PetscFunctionBegin;
1856be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1857be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1858be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1859be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
18603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1861be14dc20SKerry Key }
1862be14dc20SKerry Key 
1863d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1864d71ae5a4SJacob Faibussowitsch {
18654cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18664cb006feSStefano Zampini   Vec       tv;
18674cb006feSStefano Zampini   PetscInt  i;
18684cb006feSStefano Zampini 
18694cb006feSStefano Zampini   PetscFunctionBegin;
18704cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
18719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
18729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
18739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
18745ac14e1cSStefano Zampini   jac->dim = dim;
18755ac14e1cSStefano Zampini 
18764cb006feSStefano Zampini   /* compute IJ vector for coordinates */
18779566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
18789566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
18799566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
18804cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
18814cb006feSStefano Zampini     PetscScalar *array;
18824cb006feSStefano Zampini     PetscInt     j;
18834cb006feSStefano Zampini 
18849566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
18859566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
18866ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
18879566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
18889566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
18894cb006feSStefano Zampini   }
18909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
18913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18924cb006feSStefano Zampini }
18934cb006feSStefano Zampini 
1894d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1895d71ae5a4SJacob Faibussowitsch {
189616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
189716d9e3a6SLisandro Dalcin 
189816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
189916d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
19003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
190116d9e3a6SLisandro Dalcin }
190216d9e3a6SLisandro Dalcin 
1903d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1904d71ae5a4SJacob Faibussowitsch {
190516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1906ace3abfcSBarry Smith   PetscBool flag;
190716d9e3a6SLisandro Dalcin 
190816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
190916d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
19109566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
19115f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
19123ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
191316d9e3a6SLisandro Dalcin   } else {
19149566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
191516d9e3a6SLisandro Dalcin   }
191616d9e3a6SLisandro Dalcin 
191716d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
191816d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
191916d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
192016d9e3a6SLisandro Dalcin 
19219566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
192216d9e3a6SLisandro Dalcin   if (flag) {
19239566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1924792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
192516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
192616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
192716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
192816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
192916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
193016d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
19313ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
193216d9e3a6SLisandro Dalcin   }
19339566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1934db966c6cSHong Zhang   if (flag) {
19354e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
19367de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
19378bf83915SBarry Smith #endif
19389566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1939792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1940db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1941db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1942db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1943db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1944db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1945db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1946db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
19473ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1948db966c6cSHong Zhang   }
19499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
195016d9e3a6SLisandro Dalcin   if (flag) {
19519566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1952792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
195316d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
195416d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
195516d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
195616d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
195716d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
195816d9e3a6SLisandro Dalcin     /* initialize */
195916d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
19608966356dSPierre Jolivet     jac->threshold = .1;
196116d9e3a6SLisandro Dalcin     jac->filter    = .1;
196216d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
19632fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
19642fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
19652fa5cd67SKarl Rupp 
196616d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
196716d9e3a6SLisandro Dalcin     jac->symt = 0;
1968792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1969792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1970792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1971792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1972792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1973792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
19743ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
197516d9e3a6SLisandro Dalcin   }
19769566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
197716d9e3a6SLisandro Dalcin   if (flag) {
1978792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
197916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
198016d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
198116d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
198216d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
198385245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
19849566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
19859566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
198616d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
198716d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
198816d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
198916d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
199016d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
199116d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
199216d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
199316d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
19948f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
199516d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
199616d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
199716d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
199816d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
199916d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
20000f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
20016a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
2002b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
20031810e44eSEike Mueller     jac->eu_level                                                = 0;
20041810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
20051810e44eSEike Mueller     jac->eu_bj                                                   = 0;
2006589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
20070f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
200816d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
200916d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
201016d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
20110f1074feSSatish Balay     jac->interptype                       = 0;
2012589dcaf0SStefano Zampini     jac->Rtype                            = 0;
2013589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
2014589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
2015589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
2016589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
20170f1074feSSatish Balay     jac->agg_nl                           = 0;
20186ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
20190f1074feSSatish Balay     jac->pmax                             = 0;
20200f1074feSSatish Balay     jac->truncfactor                      = 0.0;
20210f1074feSSatish Balay     jac->agg_num_paths                    = 1;
2022589dcaf0SStefano Zampini     jac->maxc                             = 9;
2023589dcaf0SStefano Zampini     jac->minc                             = 1;
202422e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
202522e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
202622e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
202722e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
202822e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
202922e51d31SStefano Zampini     jac->interp_refine                    = 0;
20308f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
20318f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
20326ea7df73SStefano Zampini     jac->rap2                             = 0;
20336ea7df73SStefano Zampini 
20346ea7df73SStefano Zampini     /* GPU defaults
20356ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
20366ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
20376ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
20386ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
20396ea7df73SStefano Zampini     jac->mod_rap2       = 1;
20406ea7df73SStefano Zampini     jac->coarsentype    = 8;
20416ea7df73SStefano Zampini     jac->relaxorder     = 0;
20426ea7df73SStefano Zampini     jac->interptype     = 6;
20436ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
20446ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
20456ea7df73SStefano Zampini     jac->agg_interptype = 7;
20466ea7df73SStefano Zampini #else
20476ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
20486ea7df73SStefano Zampini     jac->mod_rap2      = 0;
20496ea7df73SStefano Zampini #endif
2050792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
2051792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
2052792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
2053792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
2054792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
2055792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
2056792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
2057792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
2058792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
2059792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
2060792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
2061792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
2062792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2063792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2064792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2065792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2066792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2067792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2068792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
20696ea7df73SStefano Zampini     /* GPU */
20706ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2071792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2072792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2073792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
20746ea7df73SStefano Zampini #endif
20756ea7df73SStefano Zampini 
2076589dcaf0SStefano Zampini     /* AIR */
20776ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2078792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2079792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2080792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2081792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2082792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
20836ea7df73SStefano Zampini #endif
20843ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
208516d9e3a6SLisandro Dalcin   }
20869566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
20874cb006feSStefano Zampini   if (flag) {
20883ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
20894cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
20904cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
20914cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
20924cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
20934cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
20944cb006feSStefano Zampini     jac->coords[0]          = NULL;
20954cb006feSStefano Zampini     jac->coords[1]          = NULL;
20964cb006feSStefano Zampini     jac->coords[2]          = NULL;
2097be14dc20SKerry Key     jac->interior           = NULL;
20984cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2099863406b8SStefano Zampini     jac->as_print       = 0;
2100863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2101863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
21024cb006feSStefano Zampini     jac->ams_cycle_type = 13;
21034cb006feSStefano Zampini     /* Smoothing options */
2104863406b8SStefano Zampini     jac->as_relax_type   = 2;
2105863406b8SStefano Zampini     jac->as_relax_times  = 1;
2106863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2107863406b8SStefano Zampini     jac->as_omega        = 1.0;
21084cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2109863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2110863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
21110bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2112863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2113863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2114863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
21154cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2116863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2117863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
21180bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2119863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2120863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2121863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2122792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2123792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2124792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2125792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
21269371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2127792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2128863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2129863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
21309371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2131a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2132792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2133863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2134863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
21359371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2136a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
213723df4f25SStefano Zampini     /* Zero conductivity */
213823df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
213923df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
21403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
21414cb006feSStefano Zampini   }
21429566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2143863406b8SStefano Zampini   if (flag) {
21443ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2145863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2146863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2147863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2148863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2149863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2150863406b8SStefano Zampini     jac->coords[0]          = NULL;
2151863406b8SStefano Zampini     jac->coords[1]          = NULL;
2152863406b8SStefano Zampini     jac->coords[2]          = NULL;
2153863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2154863406b8SStefano Zampini     jac->as_print       = 0;
2155863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2156863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2157863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2158863406b8SStefano Zampini     /* Smoothing options */
2159863406b8SStefano Zampini     jac->as_relax_type   = 2;
2160863406b8SStefano Zampini     jac->as_relax_times  = 1;
2161863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2162863406b8SStefano Zampini     jac->as_omega        = 1.0;
2163863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2164863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2165863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2166863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2167863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2168863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2169863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2170863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2171863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2172863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2173863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2174863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2175863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2176863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2177863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2178792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2179792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2180792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2181792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
21829371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2183792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2184863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2185863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2186863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
21879371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2188a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2189792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2190863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2191863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
21929371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2193a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
21943ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2195863406b8SStefano Zampini   }
21969566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
21972fa5cd67SKarl Rupp 
21980298fd71SBarry Smith   jac->hypre_type = NULL;
219998921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
220016d9e3a6SLisandro Dalcin }
220116d9e3a6SLisandro Dalcin 
220216d9e3a6SLisandro Dalcin /*
220316d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
220416d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
220516d9e3a6SLisandro Dalcin */
2206ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2207d71ae5a4SJacob Faibussowitsch {
22084ddd07fcSJed Brown   PetscInt    indx;
2209db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2210ace3abfcSBarry Smith   PetscBool   flg;
221116d9e3a6SLisandro Dalcin 
221216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2213d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2214dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
221516d9e3a6SLisandro Dalcin   if (flg) {
22169566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
221702a17cd4SBarry Smith   } else {
22189566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
221916d9e3a6SLisandro Dalcin   }
2220dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2221d0609cedSBarry Smith   PetscOptionsHeadEnd();
22223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
222316d9e3a6SLisandro Dalcin }
222416d9e3a6SLisandro Dalcin 
222516d9e3a6SLisandro Dalcin /*@C
222616d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
222716d9e3a6SLisandro Dalcin 
222816d9e3a6SLisandro Dalcin   Input Parameters:
222916d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2230db966c6cSHong Zhang - name - either  euclid, pilut, parasails, boomeramg, ams, ads
223116d9e3a6SLisandro Dalcin 
2232f1580f4eSBarry Smith   Options Database Key:
2233feefa0e1SJacob Faibussowitsch . pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
223416d9e3a6SLisandro Dalcin 
223516d9e3a6SLisandro Dalcin   Level: intermediate
223616d9e3a6SLisandro Dalcin 
2237*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
223816d9e3a6SLisandro Dalcin @*/
2239d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2240d71ae5a4SJacob Faibussowitsch {
224116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22420700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
22434f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2244cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
22453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224616d9e3a6SLisandro Dalcin }
224716d9e3a6SLisandro Dalcin 
224816d9e3a6SLisandro Dalcin /*@C
224916d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
225016d9e3a6SLisandro Dalcin 
225116d9e3a6SLisandro Dalcin   Input Parameter:
225216d9e3a6SLisandro Dalcin . pc - the preconditioner context
225316d9e3a6SLisandro Dalcin 
225416d9e3a6SLisandro Dalcin   Output Parameter:
2255db966c6cSHong Zhang . name - either  euclid, pilut, parasails, boomeramg, ams, ads
225616d9e3a6SLisandro Dalcin 
225716d9e3a6SLisandro Dalcin   Level: intermediate
225816d9e3a6SLisandro Dalcin 
2259*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
226016d9e3a6SLisandro Dalcin @*/
2261d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2262d71ae5a4SJacob Faibussowitsch {
226316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22640700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
22654f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2266cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
22673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
226816d9e3a6SLisandro Dalcin }
226916d9e3a6SLisandro Dalcin 
2270db6f9c32SMark Adams /*@C
2271f1580f4eSBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2272db6f9c32SMark Adams 
2273c3339decSBarry Smith   Logically Collective
2274db6f9c32SMark Adams 
2275db6f9c32SMark Adams   Input Parameters:
2276db6f9c32SMark Adams + pc   - the hypre context
2277feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2278db6f9c32SMark Adams 
2279db6f9c32SMark Adams   Options Database Key:
228067b8a455SSatish Balay . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2281db6f9c32SMark Adams 
2282db6f9c32SMark Adams   Level: intermediate
2283db6f9c32SMark Adams 
2284feefa0e1SJacob Faibussowitsch   Developer Notes:
2285f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2286db6f9c32SMark Adams 
2287*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2288db6f9c32SMark Adams @*/
2289d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2290d71ae5a4SJacob Faibussowitsch {
2291db6f9c32SMark Adams   PetscFunctionBegin;
2292db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2293cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
22943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2295db6f9c32SMark Adams }
2296db6f9c32SMark Adams 
2297db6f9c32SMark Adams /*@C
2298f1580f4eSBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2299db6f9c32SMark Adams 
2300db6f9c32SMark Adams   Not Collective
2301db6f9c32SMark Adams 
2302db6f9c32SMark Adams   Input Parameter:
2303db6f9c32SMark Adams . pc - the multigrid context
2304db6f9c32SMark Adams 
2305db6f9c32SMark Adams   Output Parameter:
2306db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2307db6f9c32SMark Adams 
2308db6f9c32SMark Adams   Level: intermediate
2309db6f9c32SMark Adams 
2310*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2311db6f9c32SMark Adams @*/
2312d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2313d71ae5a4SJacob Faibussowitsch {
2314db6f9c32SMark Adams   PetscFunctionBegin;
2315db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2316cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
23173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2318db6f9c32SMark Adams }
2319db6f9c32SMark Adams 
232016d9e3a6SLisandro Dalcin /*MC
2321f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
232216d9e3a6SLisandro Dalcin 
232316d9e3a6SLisandro Dalcin    Options Database Keys:
2324e1ded407SBarry Smith +   -pc_hypre_type - One of `euclid`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2325f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2326f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2327e1ded407SBarry Smith -   Many others, run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
232816d9e3a6SLisandro Dalcin 
232916d9e3a6SLisandro Dalcin    Level: intermediate
233016d9e3a6SLisandro Dalcin 
233195452b02SPatrick Sanan    Notes:
2332e1ded407SBarry Smith     Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
233316d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
233449567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
233516d9e3a6SLisandro Dalcin 
2336e1ded407SBarry Smith           The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2337e1ded407SBarry Smith           (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2338e1ded407SBarry Smith           `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2339e1ded407SBarry Smith           (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2340e1ded407SBarry Smith           iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2341e1ded407SBarry Smith           and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2342e1ded407SBarry Smith           then AT MOST twenty V-cycles of boomeramg will be used.
234316d9e3a6SLisandro Dalcin 
2344e1ded407SBarry Smith            Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
23450f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2346e1ded407SBarry Smith            Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
234716d9e3a6SLisandro Dalcin 
2348f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2349e1ded407SBarry Smith           the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
23500b1a5bd9SEric Chamberland 
2351f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2352f1580f4eSBarry Smith 
2353e1ded407SBarry Smith           For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2354f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
235549567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2356f1580f4eSBarry Smith 
2357e1ded407SBarry 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
2358e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2359e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2360e1ded407SBarry Smith 
2361f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
23629e5bc791SBarry Smith 
2363ead8c081SBarry Smith    GPU Notes:
2364ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2365f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2366ead8c081SBarry Smith 
2367ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2368f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2369ead8c081SBarry Smith 
2370*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2371f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2372f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
237316d9e3a6SLisandro Dalcin M*/
237416d9e3a6SLisandro Dalcin 
2375d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2376d71ae5a4SJacob Faibussowitsch {
237716d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
237816d9e3a6SLisandro Dalcin 
237916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23804dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
23812fa5cd67SKarl Rupp 
238216d9e3a6SLisandro Dalcin   pc->data                = jac;
23838695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
238416d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
238516d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
238616d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
238716d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
238816d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
23899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
23909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
23919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
23929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
23939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
23949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
23959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2396be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
23979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
23989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
23999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
24006ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24016ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
24029566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24036ea7df73SStefano Zampini   #endif
24046ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
24059566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24066ea7df73SStefano Zampini   #endif
24076ea7df73SStefano Zampini #endif
2408ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
24093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
241016d9e3a6SLisandro Dalcin }
2411ebc551c0SBarry Smith 
2412ebc551c0SBarry Smith typedef struct {
241368326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2414f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
24159e5bc791SBarry Smith 
24169e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
24174ddd07fcSJed Brown   PetscInt  its;
24189e5bc791SBarry Smith   double    tol;
24194ddd07fcSJed Brown   PetscInt  relax_type;
24204ddd07fcSJed Brown   PetscInt  rap_type;
24214ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
24224ddd07fcSJed Brown   PetscInt  max_levels;
24230be8cd64Sftrigaux   PetscInt  skip_relax;
24240be8cd64Sftrigaux   PetscBool print_statistics;
2425ebc551c0SBarry Smith } PC_PFMG;
2426ebc551c0SBarry Smith 
2427ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_PFMG(PC pc)
2428d71ae5a4SJacob Faibussowitsch {
2429f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2430ebc551c0SBarry Smith 
2431ebc551c0SBarry Smith   PetscFunctionBegin;
2432792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
24339566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
24349566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
24353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2436ebc551c0SBarry Smith }
2437ebc551c0SBarry Smith 
24389e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
24399e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
24409e5bc791SBarry Smith 
2441ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2442d71ae5a4SJacob Faibussowitsch {
2443ace3abfcSBarry Smith   PetscBool iascii;
2444f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2445ebc551c0SBarry Smith 
2446ebc551c0SBarry Smith   PetscFunctionBegin;
24479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
24489e5bc791SBarry Smith   if (iascii) {
24499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
245063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
24519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
24529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
24539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
245463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
245563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
24560be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
24579e5bc791SBarry Smith   }
24583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2459ebc551c0SBarry Smith }
2460ebc551c0SBarry Smith 
2461ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2462d71ae5a4SJacob Faibussowitsch {
2463f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2464ebc551c0SBarry Smith 
2465ebc551c0SBarry Smith   PetscFunctionBegin;
2466d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
24670be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
24689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2469792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24709566063dSJacob 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));
2471792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24729566063dSJacob 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));
2473792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24749e5bc791SBarry Smith 
24759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2476792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24773b46a515SGlenn Hammond 
24789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2479792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2480dd39110bSPierre 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));
2481792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2482dd39110bSPierre 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));
2483792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24840be8cd64Sftrigaux   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));
24850be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2486d0609cedSBarry Smith   PetscOptionsHeadEnd();
24873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2488ebc551c0SBarry Smith }
2489ebc551c0SBarry Smith 
2490ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2491d71ae5a4SJacob Faibussowitsch {
2492f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2493d9ca1df4SBarry Smith   PetscScalar       *yy;
2494d9ca1df4SBarry Smith   const PetscScalar *xx;
24954ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
24962cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
249768326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2498f91d8e95SBarry Smith 
2499f91d8e95SBarry Smith   PetscFunctionBegin;
25009566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
25019566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
25022cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2503f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2504f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2505f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
25062cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
25072cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
25082cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
25092cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
25102cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
25112cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2512f91d8e95SBarry Smith 
2513f91d8e95SBarry Smith   /* copy x values over to hypre */
2514792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
25159566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2516792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
25179566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2518792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2519792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2520f91d8e95SBarry Smith 
2521f91d8e95SBarry Smith   /* copy solution values back to PETSc */
25229566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2523792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
25249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
25253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2526f91d8e95SBarry Smith }
2527f91d8e95SBarry Smith 
2528d71ae5a4SJacob 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)
2529d71ae5a4SJacob Faibussowitsch {
25309e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
25312cf14000SStefano Zampini   HYPRE_Int oits;
25329e5bc791SBarry Smith 
25339e5bc791SBarry Smith   PetscFunctionBegin;
25349566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2535792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2536792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
25379e5bc791SBarry Smith 
25389566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2539792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
25409e5bc791SBarry Smith   *outits = oits;
25419e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
25429e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2543792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2544792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
25453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25469e5bc791SBarry Smith }
25479e5bc791SBarry Smith 
2548ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_PFMG(PC pc)
2549d71ae5a4SJacob Faibussowitsch {
25503a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
25513a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2552ace3abfcSBarry Smith   PetscBool        flg;
25533a32d3dbSGlenn Hammond 
25543a32d3dbSGlenn Hammond   PetscFunctionBegin;
25559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
255628b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
25573a32d3dbSGlenn Hammond 
25583a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2559792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2560792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25610be8cd64Sftrigaux 
25620be8cd64Sftrigaux   // Print Hypre statistics about the solve process
25630be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
25640be8cd64Sftrigaux 
25650be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
25660be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
25670be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
25680be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
25690be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
25700be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
25710be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
25720be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
25730be8cd64Sftrigaux 
2574792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2575792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
25763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25773a32d3dbSGlenn Hammond }
25783a32d3dbSGlenn Hammond 
2579ebc551c0SBarry Smith /*MC
2580ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2581ebc551c0SBarry Smith 
2582f1580f4eSBarry Smith    Options Database Keys:
258367b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
258467b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
258567b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
258667b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
25879e5bc791SBarry 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
25880be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2589f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2590f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2591f1580f4eSBarry Smith 
2592f1580f4eSBarry Smith    Level: advanced
2593f91d8e95SBarry Smith 
259495452b02SPatrick Sanan    Notes:
259595452b02SPatrick Sanan    This is for CELL-centered descretizations
25969e5bc791SBarry Smith 
2597f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
25989e5bc791SBarry Smith 
2599f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2600f1580f4eSBarry Smith 
2601f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2602f1580f4eSBarry Smith 
2603f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2604f1580f4eSBarry Smith 
2605*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2606ebc551c0SBarry Smith M*/
2607ebc551c0SBarry Smith 
2608d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2609d71ae5a4SJacob Faibussowitsch {
2610ebc551c0SBarry Smith   PC_PFMG *ex;
2611ebc551c0SBarry Smith 
2612ebc551c0SBarry Smith   PetscFunctionBegin;
26139371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
261468326731SBarry Smith   pc->data = ex;
2615ebc551c0SBarry Smith 
26169e5bc791SBarry Smith   ex->its              = 1;
26179e5bc791SBarry Smith   ex->tol              = 1.e-8;
26189e5bc791SBarry Smith   ex->relax_type       = 1;
26199e5bc791SBarry Smith   ex->rap_type         = 0;
26209e5bc791SBarry Smith   ex->num_pre_relax    = 1;
26219e5bc791SBarry Smith   ex->num_post_relax   = 1;
26223b46a515SGlenn Hammond   ex->max_levels       = 0;
26230be8cd64Sftrigaux   ex->skip_relax       = 0;
26240be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
26259e5bc791SBarry Smith 
2626ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2627ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2628ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2629f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
26309e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
263168326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
26322fa5cd67SKarl Rupp 
26339566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2634ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2635792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
26363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2637ebc551c0SBarry Smith }
2638d851a50bSGlenn Hammond 
2639d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2640d851a50bSGlenn Hammond typedef struct {
2641d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2642d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2643d851a50bSGlenn Hammond 
2644d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
26454ddd07fcSJed Brown   PetscInt its;
2646d851a50bSGlenn Hammond   double   tol;
26474ddd07fcSJed Brown   PetscInt relax_type;
26484ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2649d851a50bSGlenn Hammond } PC_SysPFMG;
2650d851a50bSGlenn Hammond 
2651ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SysPFMG(PC pc)
2652d71ae5a4SJacob Faibussowitsch {
2653d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2654d851a50bSGlenn Hammond 
2655d851a50bSGlenn Hammond   PetscFunctionBegin;
2656792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
26579566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
26589566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
26593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2660d851a50bSGlenn Hammond }
2661d851a50bSGlenn Hammond 
2662d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2663d851a50bSGlenn Hammond 
2664ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2665d71ae5a4SJacob Faibussowitsch {
2666ace3abfcSBarry Smith   PetscBool   iascii;
2667d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2668d851a50bSGlenn Hammond 
2669d851a50bSGlenn Hammond   PetscFunctionBegin;
26709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2671d851a50bSGlenn Hammond   if (iascii) {
26729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
267363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
26749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
26759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
267663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2677d851a50bSGlenn Hammond   }
26783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2679d851a50bSGlenn Hammond }
2680d851a50bSGlenn Hammond 
2681ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2682d71ae5a4SJacob Faibussowitsch {
2683d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2684ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2685d851a50bSGlenn Hammond 
2686d851a50bSGlenn Hammond   PetscFunctionBegin;
2687d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
26889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
268948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
26909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2691792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
26929566063dSJacob 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));
2693792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
26949566063dSJacob 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));
2695792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2696d851a50bSGlenn Hammond 
26979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2698792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2699dd39110bSPierre 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));
2700792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2701d0609cedSBarry Smith   PetscOptionsHeadEnd();
27023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2703d851a50bSGlenn Hammond }
2704d851a50bSGlenn Hammond 
2705ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2706d71ae5a4SJacob Faibussowitsch {
2707d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2708d9ca1df4SBarry Smith   PetscScalar       *yy;
2709d9ca1df4SBarry Smith   const PetscScalar *xx;
27104ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
27112cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2712d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
27134ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
27144ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
27154ddd07fcSJed Brown   PetscInt           part     = 0;
27164ddd07fcSJed Brown   PetscInt           size;
27174ddd07fcSJed Brown   PetscInt           i;
2718d851a50bSGlenn Hammond 
2719d851a50bSGlenn Hammond   PetscFunctionBegin;
27209566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
27219566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
27222cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2723d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2724d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2725d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
27262cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
27272cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
27282cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
27292cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
27302cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
27312cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2732d851a50bSGlenn Hammond 
2733d851a50bSGlenn Hammond   size = 1;
27342fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
27352fa5cd67SKarl Rupp 
2736d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2737d851a50bSGlenn Hammond   if (ordering) {
2738792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27399566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2740792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
27419566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2742792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2743792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2744792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2745d851a50bSGlenn Hammond 
2746d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27479566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2748792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
27499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2750a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2751d851a50bSGlenn Hammond     PetscScalar *z;
27524ddd07fcSJed Brown     PetscInt     j, k;
2753d851a50bSGlenn Hammond 
27549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2755792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27569566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2757d851a50bSGlenn Hammond 
2758d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2759d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2760d851a50bSGlenn Hammond       k = i * nvars;
27612fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2762d851a50bSGlenn Hammond     }
2763792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
27649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2765792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2766792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2767d851a50bSGlenn Hammond 
2768d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27699566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2770792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2771d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2772d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2773d851a50bSGlenn Hammond       k = i * nvars;
27742fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2775d851a50bSGlenn Hammond     }
27769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
27779566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2778d851a50bSGlenn Hammond   }
27793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2780d851a50bSGlenn Hammond }
2781d851a50bSGlenn Hammond 
2782d71ae5a4SJacob 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)
2783d71ae5a4SJacob Faibussowitsch {
2784d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
27852cf14000SStefano Zampini   HYPRE_Int   oits;
2786d851a50bSGlenn Hammond 
2787d851a50bSGlenn Hammond   PetscFunctionBegin;
27889566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2789792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2790792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
27919566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2792792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2793d851a50bSGlenn Hammond   *outits = oits;
2794d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2795d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2796792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2797792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
27983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2799d851a50bSGlenn Hammond }
2800d851a50bSGlenn Hammond 
2801ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SysPFMG(PC pc)
2802d71ae5a4SJacob Faibussowitsch {
2803d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2804d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2805ace3abfcSBarry Smith   PetscBool         flg;
2806d851a50bSGlenn Hammond 
2807d851a50bSGlenn Hammond   PetscFunctionBegin;
28089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
280928b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2810d851a50bSGlenn Hammond 
2811d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2812792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2813792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2814792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2815792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
28163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2817d851a50bSGlenn Hammond }
2818d851a50bSGlenn Hammond 
2819d851a50bSGlenn Hammond /*MC
2820f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2821d851a50bSGlenn Hammond 
2822d851a50bSGlenn Hammond    Level: advanced
2823d851a50bSGlenn Hammond 
2824f1580f4eSBarry Smith    Options Database Keys:
282567b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
282667b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
282767b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
282867b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
282967b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2830d851a50bSGlenn Hammond 
283195452b02SPatrick Sanan    Notes:
2832f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2833f1580f4eSBarry Smith 
2834f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2835f1580f4eSBarry Smith 
283695452b02SPatrick Sanan    This is for CELL-centered descretizations
2837d851a50bSGlenn Hammond 
2838f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2839d851a50bSGlenn Hammond 
2840f1580f4eSBarry 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`.
2841f1580f4eSBarry Smith 
2842*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2843d851a50bSGlenn Hammond M*/
2844d851a50bSGlenn Hammond 
2845d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2846d71ae5a4SJacob Faibussowitsch {
2847d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2848d851a50bSGlenn Hammond 
2849d851a50bSGlenn Hammond   PetscFunctionBegin;
28509371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2851d851a50bSGlenn Hammond   pc->data = ex;
2852d851a50bSGlenn Hammond 
2853d851a50bSGlenn Hammond   ex->its            = 1;
2854d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2855d851a50bSGlenn Hammond   ex->relax_type     = 1;
2856d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2857d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2858d851a50bSGlenn Hammond 
2859d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2860d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2861d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2862d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2863d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2864d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
28652fa5cd67SKarl Rupp 
28669566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2867ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2868792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
28693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2870d851a50bSGlenn Hammond }
28711c188c59Sftrigaux 
2872f1580f4eSBarry Smith /* PC SMG */
28731c188c59Sftrigaux typedef struct {
28741c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
28751c188c59Sftrigaux   HYPRE_StructSolver hsolver;
28761c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
28771c188c59Sftrigaux   double             tol;
28781c188c59Sftrigaux   PetscBool          print_statistics;
28791c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
28801c188c59Sftrigaux } PC_SMG;
28811c188c59Sftrigaux 
2882ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SMG(PC pc)
2883d71ae5a4SJacob Faibussowitsch {
28841c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28851c188c59Sftrigaux 
28861c188c59Sftrigaux   PetscFunctionBegin;
28871c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
28881c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28891c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
28903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28911c188c59Sftrigaux }
28921c188c59Sftrigaux 
2893ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2894d71ae5a4SJacob Faibussowitsch {
28951c188c59Sftrigaux   PetscBool iascii;
28961c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
28971c188c59Sftrigaux 
28981c188c59Sftrigaux   PetscFunctionBegin;
28991c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
29001c188c59Sftrigaux   if (iascii) {
29011c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
29021c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
29031c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
29041c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
29051c188c59Sftrigaux   }
29063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29071c188c59Sftrigaux }
29081c188c59Sftrigaux 
2909ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2910d71ae5a4SJacob Faibussowitsch {
29111c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
29121c188c59Sftrigaux 
29131c188c59Sftrigaux   PetscFunctionBegin;
29141c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
29151c188c59Sftrigaux 
29161c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
29171c188c59Sftrigaux   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));
29181c188c59Sftrigaux   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));
29191c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
29201c188c59Sftrigaux 
29211c188c59Sftrigaux   PetscOptionsHeadEnd();
29223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29231c188c59Sftrigaux }
29241c188c59Sftrigaux 
2925ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2926d71ae5a4SJacob Faibussowitsch {
29271c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
29281c188c59Sftrigaux   PetscScalar       *yy;
29291c188c59Sftrigaux   const PetscScalar *xx;
29301c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
29311c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
29321c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
29331c188c59Sftrigaux 
29341c188c59Sftrigaux   PetscFunctionBegin;
29351c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29361c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
29371c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
29381c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
29391c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
29401c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
29411c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
29421c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
29431c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
29441c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
29451c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
29461c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
29471c188c59Sftrigaux 
29481c188c59Sftrigaux   /* copy x values over to hypre */
29491c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
29501c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
29511c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
29521c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
29531c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
29541c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29551c188c59Sftrigaux 
29561c188c59Sftrigaux   /* copy solution values back to PETSc */
29571c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
29581c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
29591c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
29603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29611c188c59Sftrigaux }
29621c188c59Sftrigaux 
2963d71ae5a4SJacob 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)
2964d71ae5a4SJacob Faibussowitsch {
29651c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
29661c188c59Sftrigaux   HYPRE_Int oits;
29671c188c59Sftrigaux 
29681c188c59Sftrigaux   PetscFunctionBegin;
29691c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29701c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
29711c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
29721c188c59Sftrigaux 
29731c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
29741c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
29751c188c59Sftrigaux   *outits = oits;
29761c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
29771c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
29781c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
29791c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
29803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29811c188c59Sftrigaux }
29821c188c59Sftrigaux 
2983ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SMG(PC pc)
2984d71ae5a4SJacob Faibussowitsch {
29851c188c59Sftrigaux   PetscInt         i, dim;
29861c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
29871c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
29881c188c59Sftrigaux   PetscBool        flg;
29891c188c59Sftrigaux   DMBoundaryType   p[3];
29901c188c59Sftrigaux   PetscInt         M[3];
29911c188c59Sftrigaux 
29921c188c59Sftrigaux   PetscFunctionBegin;
29931c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
29941c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
29951c188c59Sftrigaux 
29961c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
29971c188c59Sftrigaux   // Check if power of 2 in periodic directions
29981c188c59Sftrigaux   for (i = 0; i < dim; i++) {
29991c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
30001c188c59Sftrigaux       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]);
30011c188c59Sftrigaux     }
30021c188c59Sftrigaux   }
30031c188c59Sftrigaux 
30041c188c59Sftrigaux   /* create the hypre solver object and set its information */
30051c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
30061c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
30071c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
30081c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
30091c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
30101c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
30111c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
30121c188c59Sftrigaux 
30131c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
30141c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
30153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30161c188c59Sftrigaux }
30171c188c59Sftrigaux 
30181c188c59Sftrigaux /*MC
30195cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
30201c188c59Sftrigaux 
30211c188c59Sftrigaux    Level: advanced
30221c188c59Sftrigaux 
3023f1580f4eSBarry Smith    Options Database Keys:
30245cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
30255cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
30265cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
30275cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
30281c188c59Sftrigaux 
30291c188c59Sftrigaux    Notes:
30301c188c59Sftrigaux    This is for CELL-centered descretizations
30311c188c59Sftrigaux 
30325cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
30331c188c59Sftrigaux 
3034f1580f4eSBarry 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`.
3035f1580f4eSBarry Smith 
3036f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3037f1580f4eSBarry Smith 
3038f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
30391c188c59Sftrigaux M*/
30401c188c59Sftrigaux 
3041d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3042d71ae5a4SJacob Faibussowitsch {
30431c188c59Sftrigaux   PC_SMG *ex;
30441c188c59Sftrigaux 
30451c188c59Sftrigaux   PetscFunctionBegin;
30469371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
30471c188c59Sftrigaux   pc->data = ex;
30481c188c59Sftrigaux 
30491c188c59Sftrigaux   ex->its            = 1;
30501c188c59Sftrigaux   ex->tol            = 1.e-8;
30511c188c59Sftrigaux   ex->num_pre_relax  = 1;
30521c188c59Sftrigaux   ex->num_post_relax = 1;
30531c188c59Sftrigaux 
30541c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
30551c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
30561c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
30571c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
30581c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
30591c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
30601c188c59Sftrigaux 
30611c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3062ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
30631c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
30643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30651c188c59Sftrigaux }
3066