xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
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 ");
163*f4f49eeaSPierre Jolivet   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)jac->hsolver);
1649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
165*f4f49eeaSPierre Jolivet   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)jac->hsolver);
1668a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
167*f4f49eeaSPierre Jolivet     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 ");
192*f4f49eeaSPierre Jolivet   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)jac->hsolver);
1939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
194*f4f49eeaSPierre Jolivet   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)jac->hsolver);
1958a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
196*f4f49eeaSPierre Jolivet     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"));
254*f4f49eeaSPierre Jolivet   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");
316*f4f49eeaSPierre Jolivet     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) {
320*f4f49eeaSPierre Jolivet       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) {
327*f4f49eeaSPierre Jolivet       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) {
343*f4f49eeaSPierre Jolivet         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]) {
350*f4f49eeaSPierre Jolivet           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     }
378*f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
379792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
380792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
381*f4f49eeaSPierre Jolivet     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) {
389*f4f49eeaSPierre Jolivet         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]) {
396*f4f49eeaSPierre Jolivet           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) {
403*f4f49eeaSPierre Jolivet         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]) {
410*f4f49eeaSPierre Jolivet           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;
431*f4f49eeaSPierre Jolivet   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;
462*f4f49eeaSPierre 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;
668*f4f49eeaSPierre Jolivet   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   }
76152ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg, 2));
76252ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
76352ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg, 1));
76452ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
76552ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_tol", "Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)", "None", jac->tol, &jac->tol, &flg, 0.0));
76652ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
76722e51d31SStefano Zampini   bs = 1;
76848a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
77048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
77116d9e3a6SLisandro Dalcin 
77252ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg, 0.0));
77352ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
77416d9e3a6SLisandro Dalcin 
77552ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg, 0));
77652ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7770f1074feSSatish Balay 
7789566063dSJacob 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));
779792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7800f1074feSSatish Balay 
78152ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_agg_num_paths", "Number of paths for aggressive coarsening", "None", jac->agg_num_paths, &jac->agg_num_paths, &flg, 1));
78252ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
7830f1074feSSatish Balay 
78452ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg, 0.0));
78552ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
78652ce0ab5SPierre Jolivet   PetscCall(PetscOptionsRangeReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg, 0.0, 1.0));
78752ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
78816d9e3a6SLisandro Dalcin 
78916d9e3a6SLisandro Dalcin   /* Grid sweeps */
7909566063dSJacob 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));
79116d9e3a6SLisandro Dalcin   if (flg) {
792792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
79316d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
79416d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
7950f1074feSSatish Balay     jac->gridsweeps[1] = indx;
7960f1074feSSatish Balay     /*defaults coarse to 1 */
7970f1074feSSatish Balay     jac->gridsweeps[2] = 1;
79816d9e3a6SLisandro Dalcin   }
7999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
80048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
8019566063dSJacob 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));
80248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
8039566063dSJacob 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));
80448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
8059566063dSJacob 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));
80648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
8079566063dSJacob 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));
80848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
8099566063dSJacob 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));
81048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
8119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
81216d9e3a6SLisandro Dalcin   if (flg) {
813792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
8140f1074feSSatish Balay     jac->gridsweeps[0] = indx;
81516d9e3a6SLisandro Dalcin   }
8169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
81716d9e3a6SLisandro Dalcin   if (flg) {
818792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
8190f1074feSSatish Balay     jac->gridsweeps[1] = indx;
82016d9e3a6SLisandro Dalcin   }
8219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
82216d9e3a6SLisandro Dalcin   if (flg) {
823792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
8240f1074feSSatish Balay     jac->gridsweeps[2] = indx;
82516d9e3a6SLisandro Dalcin   }
82616d9e3a6SLisandro Dalcin 
8276a251517SEike Mueller   /* Smooth type */
828dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
8296a251517SEike Mueller   if (flg) {
8306a251517SEike Mueller     jac->smoothtype = indx;
831792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
8328131ecf7SEike Mueller     jac->smoothnumlevels = 25;
833792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
8348131ecf7SEike Mueller   }
8358131ecf7SEike Mueller 
8368131ecf7SEike Mueller   /* Number of smoothing levels */
8379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
8388131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8398131ecf7SEike Mueller     jac->smoothnumlevels = indx;
840792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8416a251517SEike Mueller   }
8426a251517SEike Mueller 
8431810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8451810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8461810e44eSEike Mueller     jac->eu_level = indx;
847792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8481810e44eSEike Mueller   }
8491810e44eSEike Mueller 
8501810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8511810e44eSEike Mueller   double droptolerance;
8529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8531810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8541810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
855792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8561810e44eSEike Mueller   }
8571810e44eSEike Mueller 
8581810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8601810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8611810e44eSEike Mueller     jac->eu_bj = tmp_truth;
862792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8631810e44eSEike Mueller   }
8641810e44eSEike Mueller 
86516d9e3a6SLisandro Dalcin   /* Relax type */
866dd39110bSPierre 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));
86716d9e3a6SLisandro Dalcin   if (flg) {
8680f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
869792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8700f1074feSSatish Balay     /* by default, coarse type set to 9 */
8710f1074feSSatish Balay     jac->relaxtype[2] = 9;
872792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
87316d9e3a6SLisandro Dalcin   }
874dd39110bSPierre 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));
87516d9e3a6SLisandro Dalcin   if (flg) {
87616d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
877792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
87816d9e3a6SLisandro Dalcin   }
879dd39110bSPierre 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));
88016d9e3a6SLisandro Dalcin   if (flg) {
8810f1074feSSatish Balay     jac->relaxtype[1] = indx;
882792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
88316d9e3a6SLisandro Dalcin   }
884dd39110bSPierre 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));
88516d9e3a6SLisandro Dalcin   if (flg) {
8860f1074feSSatish Balay     jac->relaxtype[2] = indx;
887792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
88816d9e3a6SLisandro Dalcin   }
88916d9e3a6SLisandro Dalcin 
89016d9e3a6SLisandro Dalcin   /* Relaxation Weight */
8919566063dSJacob 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));
89216d9e3a6SLisandro Dalcin   if (flg) {
893792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
89416d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
89516d9e3a6SLisandro Dalcin   }
89616d9e3a6SLisandro Dalcin 
89716d9e3a6SLisandro Dalcin   n         = 2;
89816d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
90016d9e3a6SLisandro Dalcin   if (flg) {
9010fdf79fbSJacob 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);
90216d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
903792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
90416d9e3a6SLisandro Dalcin   }
90516d9e3a6SLisandro Dalcin 
90616d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
9079566063dSJacob 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));
90816d9e3a6SLisandro Dalcin   if (flg) {
909792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
91016d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
91116d9e3a6SLisandro Dalcin   }
91216d9e3a6SLisandro Dalcin 
91316d9e3a6SLisandro Dalcin   n         = 2;
91416d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9159566063dSJacob 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));
91616d9e3a6SLisandro Dalcin   if (flg) {
9170fdf79fbSJacob 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);
91816d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
919792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
92016d9e3a6SLisandro Dalcin   }
92116d9e3a6SLisandro Dalcin 
92216d9e3a6SLisandro Dalcin   /* the Relax Order */
9239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
92416d9e3a6SLisandro Dalcin 
9258afaa268SBarry Smith   if (flg && tmp_truth) {
92616d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
927792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
92816d9e3a6SLisandro Dalcin   }
929dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
93016d9e3a6SLisandro Dalcin   if (flg) {
93116d9e3a6SLisandro Dalcin     jac->measuretype = indx;
932792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
93316d9e3a6SLisandro Dalcin   }
9340f1074feSSatish Balay   /* update list length 3/07 */
935dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
93616d9e3a6SLisandro Dalcin   if (flg) {
93716d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
938792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
93916d9e3a6SLisandro Dalcin   }
9400f1074feSSatish Balay 
9419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
94248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
94448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
945db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
946db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
947dd39110bSPierre 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));
9482d6c3ceeSStefano Zampini   #if defined(PETSC_HAVE_HYPRE_DEVICE)
949db6f9c32SMark Adams   if (!flg) indx = 0;
9509566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
9512d6c3ceeSStefano Zampini   #else
9522d6c3ceeSStefano Zampini   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, "hypre"));
9532d6c3ceeSStefano Zampini   #endif
954db6f9c32SMark Adams #endif
955589dcaf0SStefano Zampini   /* AIR */
956589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9579566063dSJacob 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));
958792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
959589dcaf0SStefano Zampini   if (jac->Rtype) {
96019be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
96119be502cSAlexander     char       *prerelax[256];
96219be502cSAlexander     char       *postrelax[256];
96319be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
96419be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
96519be502cSAlexander     PetscBool   matchF, matchC, matchA;
96619be502cSAlexander 
967589dcaf0SStefano 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 */
968589dcaf0SStefano Zampini 
9699566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
970792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
971589dcaf0SStefano Zampini 
9729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
973792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
974589dcaf0SStefano Zampini 
9759566063dSJacob 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));
976792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
977589dcaf0SStefano Zampini 
9789566063dSJacob 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));
979792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
98019be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
98119be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
98219be502cSAlexander     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");
98319be502cSAlexander     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");
98419be502cSAlexander 
98519be502cSAlexander     grid_relax_points[0]    = NULL;
98619be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
98719be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
98819be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
98919be502cSAlexander     grid_relax_points[3][0] = 0;
99019be502cSAlexander 
99119be502cSAlexander     // set down relax scheme
99219be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
99319be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
99419be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
99519be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
99619be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
99719be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
99819be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
99919be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
100019be502cSAlexander     }
100119be502cSAlexander 
100219be502cSAlexander     // set up relax scheme
100319be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
100419be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
100519be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
100619be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
100719be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
100819be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
100919be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
101019be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
101119be502cSAlexander     }
101219be502cSAlexander 
101319be502cSAlexander     // set coarse relax scheme
101419be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
101519be502cSAlexander 
101619be502cSAlexander     // Pass relax schemes to hypre
101719be502cSAlexander     PetscCallExternal(HYPRE_BoomerAMGSetGridRelaxPoints, jac->hsolver, grid_relax_points);
101819be502cSAlexander 
101919be502cSAlexander     // cleanup memory
102019be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
102119be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1022589dcaf0SStefano Zampini   }
1023589dcaf0SStefano Zampini #endif
1024589dcaf0SStefano Zampini 
1025ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
102663a3b9bcSJacob 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);
1027ecae95adSPierre Jolivet #endif
1028ecae95adSPierre Jolivet 
10290f1074feSSatish Balay   /* new 3/07 */
1030dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1031589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1032589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1033792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
10340f1074feSSatish Balay   }
10350f1074feSSatish Balay 
10369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
103716d9e3a6SLisandro Dalcin   if (flg) {
1038b96a4a96SBarry Smith     level = 3;
10399566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
10402fa5cd67SKarl Rupp 
1041b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1042792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
10432ae77aedSBarry Smith   }
10442ae77aedSBarry Smith 
10459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
10462ae77aedSBarry Smith   if (flg) {
1047b96a4a96SBarry Smith     level = 3;
10489566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
10492fa5cd67SKarl Rupp 
1050b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1051792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
105216d9e3a6SLisandro Dalcin   }
10538f87f92bSBarry Smith 
10549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
10558f87f92bSBarry Smith   if (flg && tmp_truth) {
10568f87f92bSBarry Smith     PetscInt tmp_int;
10579566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
10588f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1059792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1060792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1061792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1062792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
10638f87f92bSBarry Smith   }
10648f87f92bSBarry Smith 
10659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1066792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1067589dcaf0SStefano Zampini 
1068589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1069dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1070589dcaf0SStefano Zampini   if (flg) {
1071589dcaf0SStefano Zampini     jac->symt = indx;
1072792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1073589dcaf0SStefano Zampini   }
1074589dcaf0SStefano Zampini 
1075d0609cedSBarry Smith   PetscOptionsHeadEnd();
10763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
107716d9e3a6SLisandro Dalcin }
107816d9e3a6SLisandro Dalcin 
1079d71ae5a4SJacob 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)
1080d71ae5a4SJacob Faibussowitsch {
108116d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
10822cf14000SStefano Zampini   HYPRE_Int oits;
108316d9e3a6SLisandro Dalcin 
108416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10859566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1086792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1087792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
108816d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
10899566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
109016d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1091792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
10924d0a8057SBarry Smith   *outits = oits;
10934d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10944d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1095792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1096792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
10973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109816d9e3a6SLisandro Dalcin }
109916d9e3a6SLisandro Dalcin 
1100d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1101d71ae5a4SJacob Faibussowitsch {
110216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1103ace3abfcSBarry Smith   PetscBool iascii;
110416d9e3a6SLisandro Dalcin 
110516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
110716d9e3a6SLisandro Dalcin   if (iascii) {
11089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
11099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
111063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
111163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
11129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
11139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
11149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
111563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
111648a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
111763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
111863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
11190f1074feSSatish Balay 
11209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
112116d9e3a6SLisandro Dalcin 
112263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
112363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
112463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
112516d9e3a6SLisandro Dalcin 
11269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
11279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
11289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
112916d9e3a6SLisandro Dalcin 
11309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
11319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
113216d9e3a6SLisandro Dalcin 
113319be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
113419be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
113519be502cSAlexander 
113616d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
11379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
113816d9e3a6SLisandro Dalcin     } else {
11399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
114016d9e3a6SLisandro Dalcin     }
11416a251517SEike Mueller     if (jac->smoothtype != -1) {
11429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
114363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
11447e352d70SEike Mueller     } else {
11459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
11461810e44eSEike Mueller     }
11471810e44eSEike Mueller     if (jac->smoothtype == 3) {
114863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
11499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
115063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
11516a251517SEike Mueller     }
11529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
11539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
11549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
115548a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
11565272c319SBarry Smith     if (jac->vec_interp_variant) {
115763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
115863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
11599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
11608f87f92bSBarry Smith     }
116148a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1162db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
11639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
11642d6c3ceeSStefano Zampini #else
11652d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1166db6f9c32SMark Adams #endif
1167589dcaf0SStefano Zampini     /* AIR */
1168589dcaf0SStefano Zampini     if (jac->Rtype) {
116963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
11709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
11719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
11729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
117363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1174589dcaf0SStefano Zampini     }
117516d9e3a6SLisandro Dalcin   }
11763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
117716d9e3a6SLisandro Dalcin }
117816d9e3a6SLisandro Dalcin 
1179d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1180d71ae5a4SJacob Faibussowitsch {
118116d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
11824ddd07fcSJed Brown   PetscInt    indx;
1183ace3abfcSBarry Smith   PetscBool   flag;
118416d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
118516d9e3a6SLisandro Dalcin 
118616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1187d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
11889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
11899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1190792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
119116d9e3a6SLisandro Dalcin 
11929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1193792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
119416d9e3a6SLisandro Dalcin 
11959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1196792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
119716d9e3a6SLisandro Dalcin 
11989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1199792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
120016d9e3a6SLisandro Dalcin 
12019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1202792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
120316d9e3a6SLisandro Dalcin 
1204dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
120516d9e3a6SLisandro Dalcin   if (flag) {
120616d9e3a6SLisandro Dalcin     jac->symt = indx;
1207792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
120816d9e3a6SLisandro Dalcin   }
120916d9e3a6SLisandro Dalcin 
1210d0609cedSBarry Smith   PetscOptionsHeadEnd();
12113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121216d9e3a6SLisandro Dalcin }
121316d9e3a6SLisandro Dalcin 
1214d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1215d71ae5a4SJacob Faibussowitsch {
121616d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1217ace3abfcSBarry Smith   PetscBool   iascii;
1218feb237baSPierre Jolivet   const char *symt = 0;
121916d9e3a6SLisandro Dalcin 
122016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
12219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
122216d9e3a6SLisandro Dalcin   if (iascii) {
12239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
122463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
12259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
12269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
12279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
12289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
12299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
12302fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
12312fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
12322fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
123363a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
12349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
123516d9e3a6SLisandro Dalcin   }
12363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123716d9e3a6SLisandro Dalcin }
1238f1580f4eSBarry Smith 
1239d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1240d71ae5a4SJacob Faibussowitsch {
12414cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12424cb006feSStefano Zampini   PetscInt  n;
12434cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
12444cb006feSStefano Zampini 
12454cb006feSStefano Zampini   PetscFunctionBegin;
1246d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
12479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1248792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
12499566063dSJacob 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));
1250792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
12519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1252792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
12539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1254792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
12559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12569566063dSJacob 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));
12579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
125948a46eb9SPierre 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);
12609566063dSJacob 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));
12614cb006feSStefano Zampini   n = 5;
12629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
12634cb006feSStefano Zampini   if (flag || flag2) {
1264792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1265863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1266863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
12679371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1268a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
12694cb006feSStefano Zampini   }
12709566063dSJacob 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));
12714cb006feSStefano Zampini   n = 5;
12729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
12734cb006feSStefano Zampini   if (flag || flag2) {
1274792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1275863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1276863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
12779371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1278a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
12794cb006feSStefano Zampini   }
12809566063dSJacob 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));
128123df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1282792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
128323df4f25SStefano Zampini   }
1284d0609cedSBarry Smith   PetscOptionsHeadEnd();
12853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12864cb006feSStefano Zampini }
12874cb006feSStefano Zampini 
1288d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1289d71ae5a4SJacob Faibussowitsch {
12904cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12914cb006feSStefano Zampini   PetscBool iascii;
12924cb006feSStefano Zampini 
12934cb006feSStefano Zampini   PetscFunctionBegin;
12949566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
12954cb006feSStefano Zampini   if (iascii) {
12969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
129763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
129863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
129963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
130063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
130163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
130263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
130363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13044cb006feSStefano Zampini     if (jac->alpha_Poisson) {
13059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
13064cb006feSStefano Zampini     } else {
13079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
13084cb006feSStefano Zampini     }
130963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
131063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
131163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
131263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
131363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
131463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13154cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
13164cb006feSStefano Zampini       if (jac->beta_Poisson) {
13179566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
13184cb006feSStefano Zampini       } else {
13199566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
13204cb006feSStefano Zampini       }
132163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
132263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
132363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
132463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
132563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
132663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
132748a46eb9SPierre 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));
132823df4f25SStefano Zampini     } else {
13299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
13304cb006feSStefano Zampini     }
13314cb006feSStefano Zampini   }
13323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13334cb006feSStefano Zampini }
13344cb006feSStefano Zampini 
1335d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1336d71ae5a4SJacob Faibussowitsch {
1337863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1338863406b8SStefano Zampini   PetscInt  n;
1339863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1340863406b8SStefano Zampini 
1341863406b8SStefano Zampini   PetscFunctionBegin;
1342d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
13439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1344792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
13459566063dSJacob 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));
1346792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
13479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1348792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
13499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1350792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
13519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
13529566063dSJacob 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));
13539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
13549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
135548a46eb9SPierre 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);
13569566063dSJacob 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));
1357863406b8SStefano Zampini   n = 5;
13589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
13599566063dSJacob 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));
1360863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1361792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1362863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1363863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1364863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
13659371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1366a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1367863406b8SStefano Zampini   }
13689566063dSJacob 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));
1369863406b8SStefano Zampini   n = 5;
13709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1371863406b8SStefano Zampini   if (flag || flag2) {
1372792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1373863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1374863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
13759371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1376a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1377863406b8SStefano Zampini   }
1378d0609cedSBarry Smith   PetscOptionsHeadEnd();
13793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1380863406b8SStefano Zampini }
1381863406b8SStefano Zampini 
1382d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1383d71ae5a4SJacob Faibussowitsch {
1384863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1385863406b8SStefano Zampini   PetscBool iascii;
1386863406b8SStefano Zampini 
1387863406b8SStefano Zampini   PetscFunctionBegin;
13889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1389863406b8SStefano Zampini   if (iascii) {
13909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
139163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
139263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
139363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
139463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
139563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
139663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
139763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
139963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
140063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
140163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
140263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
140363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
140463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
140563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
14069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
140763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
140863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
140963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
141063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
141163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
141263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1413863406b8SStefano Zampini   }
14143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1415863406b8SStefano Zampini }
1416863406b8SStefano Zampini 
1417d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1418d71ae5a4SJacob Faibussowitsch {
14194cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14205ac14e1cSStefano Zampini   PetscBool ishypre;
14214cb006feSStefano Zampini 
14224cb006feSStefano Zampini   PetscFunctionBegin;
14239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
14245ac14e1cSStefano Zampini   if (ishypre) {
14259566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
14269566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14275ac14e1cSStefano Zampini     jac->G = G;
14285ac14e1cSStefano Zampini   } else {
14299566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14309566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
14315ac14e1cSStefano Zampini   }
14323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14334cb006feSStefano Zampini }
14344cb006feSStefano Zampini 
14354cb006feSStefano Zampini /*@
1436f1580f4eSBarry Smith   PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
14374cb006feSStefano Zampini 
1438c3339decSBarry Smith   Collective
14394cb006feSStefano Zampini 
14404cb006feSStefano Zampini   Input Parameters:
14414cb006feSStefano Zampini + pc - the preconditioning context
14424cb006feSStefano Zampini - G  - the discrete gradient
14434cb006feSStefano Zampini 
14444cb006feSStefano Zampini   Level: intermediate
14454cb006feSStefano Zampini 
144695452b02SPatrick Sanan   Notes:
144795452b02SPatrick Sanan   G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1448147403d9SBarry Smith 
1449863406b8SStefano 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
14504cb006feSStefano Zampini 
1451feefa0e1SJacob Faibussowitsch   Developer Notes:
1452f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1453f1580f4eSBarry Smith 
1454562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
14554cb006feSStefano Zampini @*/
1456d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1457d71ae5a4SJacob Faibussowitsch {
14584cb006feSStefano Zampini   PetscFunctionBegin;
14594cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14604cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
14614cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1462cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
14633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14644cb006feSStefano Zampini }
14654cb006feSStefano Zampini 
1466d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1467d71ae5a4SJacob Faibussowitsch {
1468863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14695ac14e1cSStefano Zampini   PetscBool ishypre;
1470863406b8SStefano Zampini 
1471863406b8SStefano Zampini   PetscFunctionBegin;
14729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
14735ac14e1cSStefano Zampini   if (ishypre) {
14749566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
14759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14765ac14e1cSStefano Zampini     jac->C = C;
14775ac14e1cSStefano Zampini   } else {
14789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14799566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
14805ac14e1cSStefano Zampini   }
14813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1482863406b8SStefano Zampini }
1483863406b8SStefano Zampini 
1484863406b8SStefano Zampini /*@
1485f1580f4eSBarry Smith   PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1486863406b8SStefano Zampini 
1487c3339decSBarry Smith   Collective
1488863406b8SStefano Zampini 
1489863406b8SStefano Zampini   Input Parameters:
1490863406b8SStefano Zampini + pc - the preconditioning context
1491863406b8SStefano Zampini - C  - the discrete curl
1492863406b8SStefano Zampini 
1493863406b8SStefano Zampini   Level: intermediate
1494863406b8SStefano Zampini 
149595452b02SPatrick Sanan   Notes:
149695452b02SPatrick Sanan   C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1497147403d9SBarry Smith 
1498863406b8SStefano 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
1499863406b8SStefano Zampini 
1500feefa0e1SJacob Faibussowitsch   Developer Notes:
1501f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1502f1580f4eSBarry Smith 
1503f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1504f1580f4eSBarry Smith 
1505562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1506863406b8SStefano Zampini @*/
1507d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1508d71ae5a4SJacob Faibussowitsch {
1509863406b8SStefano Zampini   PetscFunctionBegin;
1510863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1511863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1512863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1513cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
15143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1515863406b8SStefano Zampini }
1516863406b8SStefano Zampini 
1517d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1518d71ae5a4SJacob Faibussowitsch {
15196bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15206bf688a0SCe Qin   PetscBool ishypre;
15216bf688a0SCe Qin   PetscInt  i;
15226bf688a0SCe Qin 
15234d86920dSPierre Jolivet   PetscFunctionBegin;
15249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
15259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
15266bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
15279566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
15289566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
15296bf688a0SCe Qin   }
15306bf688a0SCe Qin 
15316bf688a0SCe Qin   jac->dim = dim;
15326bf688a0SCe Qin   if (RT_PiFull) {
15339566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
15346bf688a0SCe Qin     if (ishypre) {
15359566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
15366bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
15376bf688a0SCe Qin     } else {
15389566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
15396bf688a0SCe Qin     }
15406bf688a0SCe Qin   }
15416bf688a0SCe Qin   if (RT_Pi) {
15426bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15436bf688a0SCe Qin       if (RT_Pi[i]) {
15449566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
15456bf688a0SCe Qin         if (ishypre) {
15469566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
15476bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
15486bf688a0SCe Qin         } else {
15499566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
15506bf688a0SCe Qin         }
15516bf688a0SCe Qin       }
15526bf688a0SCe Qin     }
15536bf688a0SCe Qin   }
15546bf688a0SCe Qin   if (ND_PiFull) {
15559566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
15566bf688a0SCe Qin     if (ishypre) {
15579566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
15586bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
15596bf688a0SCe Qin     } else {
15609566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
15616bf688a0SCe Qin     }
15626bf688a0SCe Qin   }
15636bf688a0SCe Qin   if (ND_Pi) {
15646bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15656bf688a0SCe Qin       if (ND_Pi[i]) {
15669566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
15676bf688a0SCe Qin         if (ishypre) {
15689566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
15696bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
15706bf688a0SCe Qin         } else {
15719566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
15726bf688a0SCe Qin         }
15736bf688a0SCe Qin       }
15746bf688a0SCe Qin     }
15756bf688a0SCe Qin   }
15763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15776bf688a0SCe Qin }
15786bf688a0SCe Qin 
15796bf688a0SCe Qin /*@
1580f1580f4eSBarry Smith   PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
15816bf688a0SCe Qin 
1582c3339decSBarry Smith   Collective
15836bf688a0SCe Qin 
15846bf688a0SCe Qin   Input Parameters:
15856bf688a0SCe Qin + pc        - the preconditioning context
15862fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
15872fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
15882fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
15892fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
15906bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
15916bf688a0SCe Qin 
1592f1580f4eSBarry Smith   Level: intermediate
1593f1580f4eSBarry Smith 
159495452b02SPatrick Sanan   Notes:
159595452b02SPatrick Sanan   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1596147403d9SBarry Smith 
15976bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1598147403d9SBarry Smith 
1599feefa0e1SJacob Faibussowitsch   Developer Notes:
1600f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
16016bf688a0SCe Qin 
1602562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`
16036bf688a0SCe Qin @*/
1604d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1605d71ae5a4SJacob Faibussowitsch {
16066bf688a0SCe Qin   PetscInt i;
16076bf688a0SCe Qin 
16086bf688a0SCe Qin   PetscFunctionBegin;
16096bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16106bf688a0SCe Qin   if (RT_PiFull) {
16116bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
16126bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
16136bf688a0SCe Qin   }
16146bf688a0SCe Qin   if (RT_Pi) {
16154f572ea9SToby Isaac     PetscAssertPointer(RT_Pi, 4);
16166bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16176bf688a0SCe Qin       if (RT_Pi[i]) {
16186bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
16196bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
16206bf688a0SCe Qin       }
16216bf688a0SCe Qin     }
16226bf688a0SCe Qin   }
16236bf688a0SCe Qin   if (ND_PiFull) {
16246bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
16256bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
16266bf688a0SCe Qin   }
16276bf688a0SCe Qin   if (ND_Pi) {
16284f572ea9SToby Isaac     PetscAssertPointer(ND_Pi, 6);
16296bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16306bf688a0SCe Qin       if (ND_Pi[i]) {
16316bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
16326bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
16336bf688a0SCe Qin       }
16346bf688a0SCe Qin     }
16356bf688a0SCe Qin   }
1636cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
16373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16386bf688a0SCe Qin }
16396bf688a0SCe Qin 
1640d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1641d71ae5a4SJacob Faibussowitsch {
16424cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16435ac14e1cSStefano Zampini   PetscBool ishypre;
16444cb006feSStefano Zampini 
16454cb006feSStefano Zampini   PetscFunctionBegin;
16469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
16475ac14e1cSStefano Zampini   if (ishypre) {
16485ac14e1cSStefano Zampini     if (isalpha) {
16499566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
16509566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16515ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
16525ac14e1cSStefano Zampini     } else {
16535ac14e1cSStefano Zampini       if (A) {
16549566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
16555ac14e1cSStefano Zampini       } else {
16565ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16575ac14e1cSStefano Zampini       }
16589566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
16595ac14e1cSStefano Zampini       jac->beta_Poisson = A;
16605ac14e1cSStefano Zampini     }
16615ac14e1cSStefano Zampini   } else {
16625ac14e1cSStefano Zampini     if (isalpha) {
16639566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16649566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
16655ac14e1cSStefano Zampini     } else {
16665ac14e1cSStefano Zampini       if (A) {
16679566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16689566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
16695ac14e1cSStefano Zampini       } else {
16709566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16715ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16725ac14e1cSStefano Zampini       }
16735ac14e1cSStefano Zampini     }
16745ac14e1cSStefano Zampini   }
16753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16764cb006feSStefano Zampini }
16774cb006feSStefano Zampini 
16784cb006feSStefano Zampini /*@
1679f1580f4eSBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
16804cb006feSStefano Zampini 
1681c3339decSBarry Smith   Collective
16824cb006feSStefano Zampini 
16834cb006feSStefano Zampini   Input Parameters:
16844cb006feSStefano Zampini + pc - the preconditioning context
16854cb006feSStefano Zampini - A  - the matrix
16864cb006feSStefano Zampini 
16874cb006feSStefano Zampini   Level: intermediate
16884cb006feSStefano Zampini 
1689f1580f4eSBarry Smith   Note:
169095452b02SPatrick Sanan   A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
16914cb006feSStefano Zampini 
1692feefa0e1SJacob Faibussowitsch   Developer Notes:
1693f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1694f1580f4eSBarry Smith 
1695f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1696f1580f4eSBarry Smith 
1697562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
16984cb006feSStefano Zampini @*/
1699d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1700d71ae5a4SJacob Faibussowitsch {
17014cb006feSStefano Zampini   PetscFunctionBegin;
17024cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17034cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17044cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1705cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
17063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17074cb006feSStefano Zampini }
17084cb006feSStefano Zampini 
17094cb006feSStefano Zampini /*@
1710f1580f4eSBarry Smith   PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
17114cb006feSStefano Zampini 
1712c3339decSBarry Smith   Collective
17134cb006feSStefano Zampini 
17144cb006feSStefano Zampini   Input Parameters:
17154cb006feSStefano Zampini + pc - the preconditioning context
1716f1580f4eSBarry Smith - A  - the matrix, or NULL to turn it off
17174cb006feSStefano Zampini 
17184cb006feSStefano Zampini   Level: intermediate
17194cb006feSStefano Zampini 
1720f1580f4eSBarry Smith   Note:
172195452b02SPatrick Sanan   A should be obtained by discretizing the Poisson problem with linear finite elements.
17224cb006feSStefano Zampini 
1723feefa0e1SJacob Faibussowitsch   Developer Notes:
1724f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1725f1580f4eSBarry Smith 
1726f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1727f1580f4eSBarry Smith 
1728562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17294cb006feSStefano Zampini @*/
1730d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1731d71ae5a4SJacob Faibussowitsch {
17324cb006feSStefano Zampini   PetscFunctionBegin;
17334cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17344cb006feSStefano Zampini   if (A) {
17354cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17364cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
17374cb006feSStefano Zampini   }
1738cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
17393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17404cb006feSStefano Zampini }
17414cb006feSStefano Zampini 
1742d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1743d71ae5a4SJacob Faibussowitsch {
17444cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17454cb006feSStefano Zampini 
17464cb006feSStefano Zampini   PetscFunctionBegin;
17474cb006feSStefano Zampini   /* throw away any vector if already set */
17489566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
17499566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
17509566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
17519566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
17529566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
17539566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
17549566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
17555ac14e1cSStefano Zampini   jac->dim = 2;
17564cb006feSStefano Zampini   if (zzo) {
17579566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
17589566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
17595ac14e1cSStefano Zampini     jac->dim++;
17604cb006feSStefano Zampini   }
17613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17624cb006feSStefano Zampini }
17634cb006feSStefano Zampini 
17644cb006feSStefano Zampini /*@
1765f1580f4eSBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
17664cb006feSStefano Zampini 
1767c3339decSBarry Smith   Collective
17684cb006feSStefano Zampini 
17694cb006feSStefano Zampini   Input Parameters:
17704cb006feSStefano Zampini + pc  - the preconditioning context
17712fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
17722fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
17734cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
17744cb006feSStefano Zampini 
17754cb006feSStefano Zampini   Level: intermediate
17764cb006feSStefano Zampini 
1777feefa0e1SJacob Faibussowitsch   Developer Notes:
1778f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1779f1580f4eSBarry Smith 
1780562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17814cb006feSStefano Zampini @*/
1782d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1783d71ae5a4SJacob Faibussowitsch {
17844cb006feSStefano Zampini   PetscFunctionBegin;
17854cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17864cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
17874cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
17884cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
17894cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
17904cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
17914cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1792cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
17933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17944cb006feSStefano Zampini }
17954cb006feSStefano Zampini 
1796d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1797d71ae5a4SJacob Faibussowitsch {
1798be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1799be14dc20SKerry Key 
1800be14dc20SKerry Key   PetscFunctionBegin;
1801be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1802be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1803be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1804be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
18053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1806be14dc20SKerry Key }
1807be14dc20SKerry Key 
1808be14dc20SKerry Key /*@
1809f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1810be14dc20SKerry Key 
1811c3339decSBarry Smith   Collective
1812be14dc20SKerry Key 
1813be14dc20SKerry Key   Input Parameters:
1814be14dc20SKerry Key + pc       - the preconditioning context
1815be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
1816be14dc20SKerry Key 
1817be14dc20SKerry Key   Level: intermediate
1818be14dc20SKerry Key 
1819be14dc20SKerry Key   Note:
1820f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
1821f1580f4eSBarry Smith 
1822feefa0e1SJacob Faibussowitsch   Developer Notes:
1823f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1824f1580f4eSBarry Smith 
1825562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1826be14dc20SKerry Key @*/
1827d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1828d71ae5a4SJacob Faibussowitsch {
1829be14dc20SKerry Key   PetscFunctionBegin;
1830be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1831be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1832be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1833be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
18343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1835be14dc20SKerry Key }
1836be14dc20SKerry Key 
1837d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1838d71ae5a4SJacob Faibussowitsch {
18394cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18404cb006feSStefano Zampini   Vec       tv;
18414cb006feSStefano Zampini   PetscInt  i;
18424cb006feSStefano Zampini 
18434cb006feSStefano Zampini   PetscFunctionBegin;
18444cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
18459566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
18469566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
18479566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
18485ac14e1cSStefano Zampini   jac->dim = dim;
18495ac14e1cSStefano Zampini 
18504cb006feSStefano Zampini   /* compute IJ vector for coordinates */
18519566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
18529566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
18539566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
18544cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
18554cb006feSStefano Zampini     PetscScalar *array;
18564cb006feSStefano Zampini     PetscInt     j;
18574cb006feSStefano Zampini 
18589566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
18599566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
18606ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
18619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
18629566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
18634cb006feSStefano Zampini   }
18649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
18653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18664cb006feSStefano Zampini }
18674cb006feSStefano Zampini 
1868d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1869d71ae5a4SJacob Faibussowitsch {
187016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
187116d9e3a6SLisandro Dalcin 
187216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
187316d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
18743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
187516d9e3a6SLisandro Dalcin }
187616d9e3a6SLisandro Dalcin 
1877d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1878d71ae5a4SJacob Faibussowitsch {
187916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1880ace3abfcSBarry Smith   PetscBool flag;
188116d9e3a6SLisandro Dalcin 
188216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
188316d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
18849566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
18855f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
18863ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
188716d9e3a6SLisandro Dalcin   } else {
18889566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
188916d9e3a6SLisandro Dalcin   }
189016d9e3a6SLisandro Dalcin 
189116d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
189216d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
189316d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
189416d9e3a6SLisandro Dalcin 
18959566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
189616d9e3a6SLisandro Dalcin   if (flag) {
18979566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1898792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
189916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
190016d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
190116d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
190216d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
190316d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
190416d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
19053ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
190616d9e3a6SLisandro Dalcin   }
19079566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1908db966c6cSHong Zhang   if (flag) {
19094e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
19107de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
19118bf83915SBarry Smith #endif
19129566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1913792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1914db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1915db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1916db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1917db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1918db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1919db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1920db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
19213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1922db966c6cSHong Zhang   }
19239566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
192416d9e3a6SLisandro Dalcin   if (flag) {
19259566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1926792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
192716d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
192816d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
192916d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
193016d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
193116d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
193216d9e3a6SLisandro Dalcin     /* initialize */
193316d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
19348966356dSPierre Jolivet     jac->threshold = .1;
193516d9e3a6SLisandro Dalcin     jac->filter    = .1;
193616d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
19372fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
19382fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
19392fa5cd67SKarl Rupp 
194016d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
194116d9e3a6SLisandro Dalcin     jac->symt = 0;
1942792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1943792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1944792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1945792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1946792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1947792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
19483ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
194916d9e3a6SLisandro Dalcin   }
19509566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
195116d9e3a6SLisandro Dalcin   if (flag) {
1952792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
195316d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
195416d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
195516d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
195616d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
195785245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
19589566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
19599566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
196016d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
196116d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
196216d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
196316d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
196416d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
196516d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
196616d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
196716d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
19688f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
196916d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
197016d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
197116d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
197216d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
197316d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
19740f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
19756a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1976b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
19771810e44eSEike Mueller     jac->eu_level                                                = 0;
19781810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
19791810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1980589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
19810f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
198216d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
198316d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
198416d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
19850f1074feSSatish Balay     jac->interptype                       = 0;
1986589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1987589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1988589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1989589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1990589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
19910f1074feSSatish Balay     jac->agg_nl                           = 0;
19926ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
19930f1074feSSatish Balay     jac->pmax                             = 0;
19940f1074feSSatish Balay     jac->truncfactor                      = 0.0;
19950f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1996589dcaf0SStefano Zampini     jac->maxc                             = 9;
1997589dcaf0SStefano Zampini     jac->minc                             = 1;
199822e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
199922e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
200022e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
200122e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
200222e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
200322e51d31SStefano Zampini     jac->interp_refine                    = 0;
20048f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
20058f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
20066ea7df73SStefano Zampini     jac->rap2                             = 0;
20076ea7df73SStefano Zampini 
20086ea7df73SStefano Zampini     /* GPU defaults
20096ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
20106ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
20116ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
20126ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
20136ea7df73SStefano Zampini     jac->mod_rap2       = 1;
20146ea7df73SStefano Zampini     jac->coarsentype    = 8;
20156ea7df73SStefano Zampini     jac->relaxorder     = 0;
20166ea7df73SStefano Zampini     jac->interptype     = 6;
20176ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
20186ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
20196ea7df73SStefano Zampini     jac->agg_interptype = 7;
20206ea7df73SStefano Zampini #else
20216ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
20226ea7df73SStefano Zampini     jac->mod_rap2      = 0;
20236ea7df73SStefano Zampini #endif
2024792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
2025792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
2026792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
2027792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
2028792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
2029792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
2030792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
2031792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
2032792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
2033792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
2034792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
2035792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
2036792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2037792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2038792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2039792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2040792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2041792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2042792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
20436ea7df73SStefano Zampini     /* GPU */
20446ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2045792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2046792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2047792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
20486ea7df73SStefano Zampini #endif
20496ea7df73SStefano Zampini 
2050589dcaf0SStefano Zampini     /* AIR */
20516ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2052792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2053792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2054792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2055792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2056792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
20576ea7df73SStefano Zampini #endif
20583ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
205916d9e3a6SLisandro Dalcin   }
20609566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
20614cb006feSStefano Zampini   if (flag) {
20623ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
20634cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
20644cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
20654cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
20664cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
20674cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
20684cb006feSStefano Zampini     jac->coords[0]          = NULL;
20694cb006feSStefano Zampini     jac->coords[1]          = NULL;
20704cb006feSStefano Zampini     jac->coords[2]          = NULL;
2071be14dc20SKerry Key     jac->interior           = NULL;
20724cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2073863406b8SStefano Zampini     jac->as_print       = 0;
2074863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2075863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
20764cb006feSStefano Zampini     jac->ams_cycle_type = 13;
20774cb006feSStefano Zampini     /* Smoothing options */
2078863406b8SStefano Zampini     jac->as_relax_type   = 2;
2079863406b8SStefano Zampini     jac->as_relax_times  = 1;
2080863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2081863406b8SStefano Zampini     jac->as_omega        = 1.0;
20824cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2083863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2084863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
20850bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2086863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2087863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2088863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
20894cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2090863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2091863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
20920bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2093863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2094863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2095863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2096792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2097792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2098792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2099792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
21009371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2101792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2102863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2103863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
21049371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2105a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2106792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2107863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2108863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
21099371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2110a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
211123df4f25SStefano Zampini     /* Zero conductivity */
211223df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
211323df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
21143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
21154cb006feSStefano Zampini   }
21169566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2117863406b8SStefano Zampini   if (flag) {
21183ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2119863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2120863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2121863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2122863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2123863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2124863406b8SStefano Zampini     jac->coords[0]          = NULL;
2125863406b8SStefano Zampini     jac->coords[1]          = NULL;
2126863406b8SStefano Zampini     jac->coords[2]          = NULL;
2127863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2128863406b8SStefano Zampini     jac->as_print       = 0;
2129863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2130863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2131863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2132863406b8SStefano Zampini     /* Smoothing options */
2133863406b8SStefano Zampini     jac->as_relax_type   = 2;
2134863406b8SStefano Zampini     jac->as_relax_times  = 1;
2135863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2136863406b8SStefano Zampini     jac->as_omega        = 1.0;
2137863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2138863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2139863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2140863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2141863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2142863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2143863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2144863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2145863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2146863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2147863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2148863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2149863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2150863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2151863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2152792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2153792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2154792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2155792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
21569371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2157792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2158863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2159863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2160863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
21619371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2162a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2163792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2164863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2165863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
21669371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2167a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
21683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2169863406b8SStefano Zampini   }
21709566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
21712fa5cd67SKarl Rupp 
21720298fd71SBarry Smith   jac->hypre_type = NULL;
217398921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
217416d9e3a6SLisandro Dalcin }
217516d9e3a6SLisandro Dalcin 
217616d9e3a6SLisandro Dalcin /*
217716d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
217816d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
217916d9e3a6SLisandro Dalcin */
2180ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2181d71ae5a4SJacob Faibussowitsch {
21824ddd07fcSJed Brown   PetscInt    indx;
2183db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2184ace3abfcSBarry Smith   PetscBool   flg;
218516d9e3a6SLisandro Dalcin 
218616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2187d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2188dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
218916d9e3a6SLisandro Dalcin   if (flg) {
21909566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
219102a17cd4SBarry Smith   } else {
21929566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
219316d9e3a6SLisandro Dalcin   }
2194dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2195d0609cedSBarry Smith   PetscOptionsHeadEnd();
21963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219716d9e3a6SLisandro Dalcin }
219816d9e3a6SLisandro Dalcin 
219916d9e3a6SLisandro Dalcin /*@C
220016d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
220116d9e3a6SLisandro Dalcin 
220216d9e3a6SLisandro Dalcin   Input Parameters:
220316d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2204db966c6cSHong Zhang - name - either  euclid, pilut, parasails, boomeramg, ams, ads
220516d9e3a6SLisandro Dalcin 
2206f1580f4eSBarry Smith   Options Database Key:
2207feefa0e1SJacob Faibussowitsch . pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
220816d9e3a6SLisandro Dalcin 
220916d9e3a6SLisandro Dalcin   Level: intermediate
221016d9e3a6SLisandro Dalcin 
2211562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
221216d9e3a6SLisandro Dalcin @*/
2213d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2214d71ae5a4SJacob Faibussowitsch {
221516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22160700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
22174f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2218cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
22193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
222016d9e3a6SLisandro Dalcin }
222116d9e3a6SLisandro Dalcin 
222216d9e3a6SLisandro Dalcin /*@C
222316d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
222416d9e3a6SLisandro Dalcin 
222516d9e3a6SLisandro Dalcin   Input Parameter:
222616d9e3a6SLisandro Dalcin . pc - the preconditioner context
222716d9e3a6SLisandro Dalcin 
222816d9e3a6SLisandro Dalcin   Output Parameter:
2229db966c6cSHong Zhang . name - either  euclid, pilut, parasails, boomeramg, ams, ads
223016d9e3a6SLisandro Dalcin 
223116d9e3a6SLisandro Dalcin   Level: intermediate
223216d9e3a6SLisandro Dalcin 
2233562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
223416d9e3a6SLisandro Dalcin @*/
2235d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2236d71ae5a4SJacob Faibussowitsch {
223716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22380700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
22394f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2240cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
22413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224216d9e3a6SLisandro Dalcin }
224316d9e3a6SLisandro Dalcin 
2244db6f9c32SMark Adams /*@C
2245f1580f4eSBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2246db6f9c32SMark Adams 
2247c3339decSBarry Smith   Logically Collective
2248db6f9c32SMark Adams 
2249db6f9c32SMark Adams   Input Parameters:
2250db6f9c32SMark Adams + pc   - the hypre context
2251feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2252db6f9c32SMark Adams 
2253db6f9c32SMark Adams   Options Database Key:
225467b8a455SSatish Balay . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2255db6f9c32SMark Adams 
2256db6f9c32SMark Adams   Level: intermediate
2257db6f9c32SMark Adams 
2258feefa0e1SJacob Faibussowitsch   Developer Notes:
2259f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2260db6f9c32SMark Adams 
2261562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2262db6f9c32SMark Adams @*/
2263d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2264d71ae5a4SJacob Faibussowitsch {
2265db6f9c32SMark Adams   PetscFunctionBegin;
2266db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2267cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
22683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2269db6f9c32SMark Adams }
2270db6f9c32SMark Adams 
2271db6f9c32SMark Adams /*@C
2272f1580f4eSBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2273db6f9c32SMark Adams 
2274db6f9c32SMark Adams   Not Collective
2275db6f9c32SMark Adams 
2276db6f9c32SMark Adams   Input Parameter:
2277db6f9c32SMark Adams . pc - the multigrid context
2278db6f9c32SMark Adams 
2279db6f9c32SMark Adams   Output Parameter:
2280db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2281db6f9c32SMark Adams 
2282db6f9c32SMark Adams   Level: intermediate
2283db6f9c32SMark Adams 
2284562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2285db6f9c32SMark Adams @*/
2286d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2287d71ae5a4SJacob Faibussowitsch {
2288db6f9c32SMark Adams   PetscFunctionBegin;
2289db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2290cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
22913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2292db6f9c32SMark Adams }
2293db6f9c32SMark Adams 
229416d9e3a6SLisandro Dalcin /*MC
2295f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
229616d9e3a6SLisandro Dalcin 
229716d9e3a6SLisandro Dalcin    Options Database Keys:
2298e1ded407SBarry Smith +   -pc_hypre_type - One of `euclid`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2299f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2300f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2301e1ded407SBarry Smith -   Many others, run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
230216d9e3a6SLisandro Dalcin 
230316d9e3a6SLisandro Dalcin    Level: intermediate
230416d9e3a6SLisandro Dalcin 
230595452b02SPatrick Sanan    Notes:
2306e1ded407SBarry Smith     Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
230716d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
230849567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
230916d9e3a6SLisandro Dalcin 
2310e1ded407SBarry Smith           The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2311e1ded407SBarry Smith           (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2312e1ded407SBarry Smith           `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2313e1ded407SBarry Smith           (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2314e1ded407SBarry Smith           iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2315e1ded407SBarry Smith           and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2316e1ded407SBarry Smith           then AT MOST twenty V-cycles of boomeramg will be used.
231716d9e3a6SLisandro Dalcin 
2318e1ded407SBarry Smith            Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
23190f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2320e1ded407SBarry Smith            Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
232116d9e3a6SLisandro Dalcin 
2322f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2323e1ded407SBarry Smith           the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
23240b1a5bd9SEric Chamberland 
2325f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2326f1580f4eSBarry Smith 
2327e1ded407SBarry Smith           For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2328f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
232949567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2330f1580f4eSBarry Smith 
2331e1ded407SBarry 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
2332e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2333e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2334e1ded407SBarry Smith 
2335f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
23369e5bc791SBarry Smith 
2337ead8c081SBarry Smith    GPU Notes:
2338ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2339f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2340ead8c081SBarry Smith 
2341ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2342f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2343ead8c081SBarry Smith 
2344562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2345f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2346f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
234716d9e3a6SLisandro Dalcin M*/
234816d9e3a6SLisandro Dalcin 
2349d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2350d71ae5a4SJacob Faibussowitsch {
235116d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
235216d9e3a6SLisandro Dalcin 
235316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23544dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
23552fa5cd67SKarl Rupp 
235616d9e3a6SLisandro Dalcin   pc->data                = jac;
23578695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
235816d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
235916d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
236016d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
236116d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
236216d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
23639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
23649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
23659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
23669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
23679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
23689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
23699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2370be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
23719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
23729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
23739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
23746ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23756ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
23769566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
23776ea7df73SStefano Zampini   #endif
23786ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
23799566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
23806ea7df73SStefano Zampini   #endif
23816ea7df73SStefano Zampini #endif
2382ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
23833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
238416d9e3a6SLisandro Dalcin }
2385ebc551c0SBarry Smith 
2386ebc551c0SBarry Smith typedef struct {
238768326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2388f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
23899e5bc791SBarry Smith 
23909e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
23914ddd07fcSJed Brown   PetscInt  its;
23929e5bc791SBarry Smith   double    tol;
23934ddd07fcSJed Brown   PetscInt  relax_type;
23944ddd07fcSJed Brown   PetscInt  rap_type;
23954ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
23964ddd07fcSJed Brown   PetscInt  max_levels;
23970be8cd64Sftrigaux   PetscInt  skip_relax;
23980be8cd64Sftrigaux   PetscBool print_statistics;
2399ebc551c0SBarry Smith } PC_PFMG;
2400ebc551c0SBarry Smith 
2401ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_PFMG(PC pc)
2402d71ae5a4SJacob Faibussowitsch {
2403f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2404ebc551c0SBarry Smith 
2405ebc551c0SBarry Smith   PetscFunctionBegin;
2406792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
24079566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
24089566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
24093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2410ebc551c0SBarry Smith }
2411ebc551c0SBarry Smith 
24129e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
24139e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
24149e5bc791SBarry Smith 
2415ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2416d71ae5a4SJacob Faibussowitsch {
2417ace3abfcSBarry Smith   PetscBool iascii;
2418f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2419ebc551c0SBarry Smith 
2420ebc551c0SBarry Smith   PetscFunctionBegin;
24219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
24229e5bc791SBarry Smith   if (iascii) {
24239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
242463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
24259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
24269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
24279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
242863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
242963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
24300be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
24319e5bc791SBarry Smith   }
24323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2433ebc551c0SBarry Smith }
2434ebc551c0SBarry Smith 
2435ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2436d71ae5a4SJacob Faibussowitsch {
2437f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2438ebc551c0SBarry Smith 
2439ebc551c0SBarry Smith   PetscFunctionBegin;
2440d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
24410be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
24429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2443792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24449566063dSJacob 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));
2445792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24469566063dSJacob 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));
2447792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24489e5bc791SBarry Smith 
24499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2450792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24513b46a515SGlenn Hammond 
24529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2453792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2454dd39110bSPierre 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));
2455792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2456dd39110bSPierre 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));
2457792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24580be8cd64Sftrigaux   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));
24590be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2460d0609cedSBarry Smith   PetscOptionsHeadEnd();
24613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2462ebc551c0SBarry Smith }
2463ebc551c0SBarry Smith 
2464ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2465d71ae5a4SJacob Faibussowitsch {
2466f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2467d9ca1df4SBarry Smith   PetscScalar       *yy;
2468d9ca1df4SBarry Smith   const PetscScalar *xx;
24694ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
24702cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2471*f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
2472f91d8e95SBarry Smith 
2473f91d8e95SBarry Smith   PetscFunctionBegin;
24749566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
24759566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
24762cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2477f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2478f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2479f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
24802cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
24812cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
24822cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
24832cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
24842cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
24852cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2486f91d8e95SBarry Smith 
2487f91d8e95SBarry Smith   /* copy x values over to hypre */
2488792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
24899566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2490792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
24919566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2492792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2493792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2494f91d8e95SBarry Smith 
2495f91d8e95SBarry Smith   /* copy solution values back to PETSc */
24969566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2497792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
24989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
24993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2500f91d8e95SBarry Smith }
2501f91d8e95SBarry Smith 
2502d71ae5a4SJacob 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)
2503d71ae5a4SJacob Faibussowitsch {
25049e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
25052cf14000SStefano Zampini   HYPRE_Int oits;
25069e5bc791SBarry Smith 
25079e5bc791SBarry Smith   PetscFunctionBegin;
25089566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2509792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2510792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
25119e5bc791SBarry Smith 
25129566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2513792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
25149e5bc791SBarry Smith   *outits = oits;
25159e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
25169e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2517792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2518792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
25193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25209e5bc791SBarry Smith }
25219e5bc791SBarry Smith 
2522ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_PFMG(PC pc)
2523d71ae5a4SJacob Faibussowitsch {
25243a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
2525*f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
2526ace3abfcSBarry Smith   PetscBool        flg;
25273a32d3dbSGlenn Hammond 
25283a32d3dbSGlenn Hammond   PetscFunctionBegin;
25299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
253028b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
25313a32d3dbSGlenn Hammond 
25323a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2533792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2534792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25350be8cd64Sftrigaux 
25360be8cd64Sftrigaux   // Print Hypre statistics about the solve process
25370be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
25380be8cd64Sftrigaux 
25390be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
25400be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
25410be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
25420be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
25430be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
25440be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
25450be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
25460be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
25470be8cd64Sftrigaux 
2548792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2549792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
25503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25513a32d3dbSGlenn Hammond }
25523a32d3dbSGlenn Hammond 
2553ebc551c0SBarry Smith /*MC
2554ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2555ebc551c0SBarry Smith 
2556f1580f4eSBarry Smith    Options Database Keys:
255767b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
255867b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
255967b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
256067b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
25619e5bc791SBarry 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
25620be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2563f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2564f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2565f1580f4eSBarry Smith 
2566f1580f4eSBarry Smith    Level: advanced
2567f91d8e95SBarry Smith 
256895452b02SPatrick Sanan    Notes:
256995452b02SPatrick Sanan    This is for CELL-centered descretizations
25709e5bc791SBarry Smith 
2571f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
25729e5bc791SBarry Smith 
2573f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2574f1580f4eSBarry Smith 
2575f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2576f1580f4eSBarry Smith 
2577f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2578f1580f4eSBarry Smith 
2579562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2580ebc551c0SBarry Smith M*/
2581ebc551c0SBarry Smith 
2582d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2583d71ae5a4SJacob Faibussowitsch {
2584ebc551c0SBarry Smith   PC_PFMG *ex;
2585ebc551c0SBarry Smith 
2586ebc551c0SBarry Smith   PetscFunctionBegin;
25879371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
258868326731SBarry Smith   pc->data = ex;
2589ebc551c0SBarry Smith 
25909e5bc791SBarry Smith   ex->its              = 1;
25919e5bc791SBarry Smith   ex->tol              = 1.e-8;
25929e5bc791SBarry Smith   ex->relax_type       = 1;
25939e5bc791SBarry Smith   ex->rap_type         = 0;
25949e5bc791SBarry Smith   ex->num_pre_relax    = 1;
25959e5bc791SBarry Smith   ex->num_post_relax   = 1;
25963b46a515SGlenn Hammond   ex->max_levels       = 0;
25970be8cd64Sftrigaux   ex->skip_relax       = 0;
25980be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
25999e5bc791SBarry Smith 
2600ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2601ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2602ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2603f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
26049e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
260568326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
26062fa5cd67SKarl Rupp 
26079566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2608ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2609792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
26103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2611ebc551c0SBarry Smith }
2612d851a50bSGlenn Hammond 
2613d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2614d851a50bSGlenn Hammond typedef struct {
2615d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2616d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2617d851a50bSGlenn Hammond 
2618d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
26194ddd07fcSJed Brown   PetscInt its;
2620d851a50bSGlenn Hammond   double   tol;
26214ddd07fcSJed Brown   PetscInt relax_type;
26224ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2623d851a50bSGlenn Hammond } PC_SysPFMG;
2624d851a50bSGlenn Hammond 
2625ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SysPFMG(PC pc)
2626d71ae5a4SJacob Faibussowitsch {
2627d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2628d851a50bSGlenn Hammond 
2629d851a50bSGlenn Hammond   PetscFunctionBegin;
2630792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
26319566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
26329566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
26333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2634d851a50bSGlenn Hammond }
2635d851a50bSGlenn Hammond 
2636d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2637d851a50bSGlenn Hammond 
2638ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2639d71ae5a4SJacob Faibussowitsch {
2640ace3abfcSBarry Smith   PetscBool   iascii;
2641d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2642d851a50bSGlenn Hammond 
2643d851a50bSGlenn Hammond   PetscFunctionBegin;
26449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2645d851a50bSGlenn Hammond   if (iascii) {
26469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
264763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
26489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
26499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
265063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2651d851a50bSGlenn Hammond   }
26523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2653d851a50bSGlenn Hammond }
2654d851a50bSGlenn Hammond 
2655ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2656d71ae5a4SJacob Faibussowitsch {
2657d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2658ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2659d851a50bSGlenn Hammond 
2660d851a50bSGlenn Hammond   PetscFunctionBegin;
2661d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
26629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
266348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
26649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2665792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
26669566063dSJacob 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));
2667792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
26689566063dSJacob 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));
2669792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2670d851a50bSGlenn Hammond 
26719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2672792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2673dd39110bSPierre 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));
2674792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2675d0609cedSBarry Smith   PetscOptionsHeadEnd();
26763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2677d851a50bSGlenn Hammond }
2678d851a50bSGlenn Hammond 
2679ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2680d71ae5a4SJacob Faibussowitsch {
2681d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2682d9ca1df4SBarry Smith   PetscScalar       *yy;
2683d9ca1df4SBarry Smith   const PetscScalar *xx;
26844ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
26852cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2686*f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)pc->pmat->data;
26874ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
26884ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
26894ddd07fcSJed Brown   PetscInt           part     = 0;
26904ddd07fcSJed Brown   PetscInt           size;
26914ddd07fcSJed Brown   PetscInt           i;
2692d851a50bSGlenn Hammond 
2693d851a50bSGlenn Hammond   PetscFunctionBegin;
26949566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
26959566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
26962cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2697d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2698d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2699d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
27002cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
27012cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
27022cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
27032cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
27042cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
27052cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2706d851a50bSGlenn Hammond 
2707d851a50bSGlenn Hammond   size = 1;
27082fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
27092fa5cd67SKarl Rupp 
2710d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2711d851a50bSGlenn Hammond   if (ordering) {
2712792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27139566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2714792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
27159566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2716792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2717792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2718792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2719d851a50bSGlenn Hammond 
2720d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27219566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2722792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
27239566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2724a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2725d851a50bSGlenn Hammond     PetscScalar *z;
27264ddd07fcSJed Brown     PetscInt     j, k;
2727d851a50bSGlenn Hammond 
27289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2729792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27309566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2731d851a50bSGlenn Hammond 
2732d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2733d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2734d851a50bSGlenn Hammond       k = i * nvars;
27352fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2736d851a50bSGlenn Hammond     }
2737792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
27389566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2739792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2740792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2741d851a50bSGlenn Hammond 
2742d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27439566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2744792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2745d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2746d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2747d851a50bSGlenn Hammond       k = i * nvars;
27482fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2749d851a50bSGlenn Hammond     }
27509566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
27519566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2752d851a50bSGlenn Hammond   }
27533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2754d851a50bSGlenn Hammond }
2755d851a50bSGlenn Hammond 
2756d71ae5a4SJacob 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)
2757d71ae5a4SJacob Faibussowitsch {
2758d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
27592cf14000SStefano Zampini   HYPRE_Int   oits;
2760d851a50bSGlenn Hammond 
2761d851a50bSGlenn Hammond   PetscFunctionBegin;
27629566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2763792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2764792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
27659566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2766792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2767d851a50bSGlenn Hammond   *outits = oits;
2768d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2769d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2770792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2771792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
27723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2773d851a50bSGlenn Hammond }
2774d851a50bSGlenn Hammond 
2775ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SysPFMG(PC pc)
2776d71ae5a4SJacob Faibussowitsch {
2777d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2778*f4f49eeaSPierre Jolivet   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)pc->pmat->data;
2779ace3abfcSBarry Smith   PetscBool         flg;
2780d851a50bSGlenn Hammond 
2781d851a50bSGlenn Hammond   PetscFunctionBegin;
27829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
278328b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2784d851a50bSGlenn Hammond 
2785d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2786792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2787792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2788792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2789792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
27903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2791d851a50bSGlenn Hammond }
2792d851a50bSGlenn Hammond 
2793d851a50bSGlenn Hammond /*MC
2794f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2795d851a50bSGlenn Hammond 
2796d851a50bSGlenn Hammond    Level: advanced
2797d851a50bSGlenn Hammond 
2798f1580f4eSBarry Smith    Options Database Keys:
279967b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
280067b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
280167b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
280267b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
280367b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2804d851a50bSGlenn Hammond 
280595452b02SPatrick Sanan    Notes:
2806f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2807f1580f4eSBarry Smith 
2808f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2809f1580f4eSBarry Smith 
281095452b02SPatrick Sanan    This is for CELL-centered descretizations
2811d851a50bSGlenn Hammond 
2812f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2813d851a50bSGlenn Hammond 
2814f1580f4eSBarry 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`.
2815f1580f4eSBarry Smith 
2816562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2817d851a50bSGlenn Hammond M*/
2818d851a50bSGlenn Hammond 
2819d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2820d71ae5a4SJacob Faibussowitsch {
2821d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2822d851a50bSGlenn Hammond 
2823d851a50bSGlenn Hammond   PetscFunctionBegin;
28249371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2825d851a50bSGlenn Hammond   pc->data = ex;
2826d851a50bSGlenn Hammond 
2827d851a50bSGlenn Hammond   ex->its            = 1;
2828d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2829d851a50bSGlenn Hammond   ex->relax_type     = 1;
2830d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2831d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2832d851a50bSGlenn Hammond 
2833d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2834d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2835d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2836d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2837d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2838d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
28392fa5cd67SKarl Rupp 
28409566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2841ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2842792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
28433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2844d851a50bSGlenn Hammond }
28451c188c59Sftrigaux 
2846f1580f4eSBarry Smith /* PC SMG */
28471c188c59Sftrigaux typedef struct {
28481c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
28491c188c59Sftrigaux   HYPRE_StructSolver hsolver;
28501c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
28511c188c59Sftrigaux   double             tol;
28521c188c59Sftrigaux   PetscBool          print_statistics;
28531c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
28541c188c59Sftrigaux } PC_SMG;
28551c188c59Sftrigaux 
2856ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SMG(PC pc)
2857d71ae5a4SJacob Faibussowitsch {
28581c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28591c188c59Sftrigaux 
28601c188c59Sftrigaux   PetscFunctionBegin;
28611c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
28621c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28631c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
28643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28651c188c59Sftrigaux }
28661c188c59Sftrigaux 
2867ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2868d71ae5a4SJacob Faibussowitsch {
28691c188c59Sftrigaux   PetscBool iascii;
28701c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
28711c188c59Sftrigaux 
28721c188c59Sftrigaux   PetscFunctionBegin;
28731c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
28741c188c59Sftrigaux   if (iascii) {
28751c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
28761c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
28771c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
28781c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
28791c188c59Sftrigaux   }
28803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28811c188c59Sftrigaux }
28821c188c59Sftrigaux 
2883ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2884d71ae5a4SJacob Faibussowitsch {
28851c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28861c188c59Sftrigaux 
28871c188c59Sftrigaux   PetscFunctionBegin;
28881c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
28891c188c59Sftrigaux 
28901c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
28911c188c59Sftrigaux   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));
28921c188c59Sftrigaux   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));
28931c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
28941c188c59Sftrigaux 
28951c188c59Sftrigaux   PetscOptionsHeadEnd();
28963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28971c188c59Sftrigaux }
28981c188c59Sftrigaux 
2899ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2900d71ae5a4SJacob Faibussowitsch {
29011c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
29021c188c59Sftrigaux   PetscScalar       *yy;
29031c188c59Sftrigaux   const PetscScalar *xx;
29041c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
29051c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
2906*f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
29071c188c59Sftrigaux 
29081c188c59Sftrigaux   PetscFunctionBegin;
29091c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29101c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
29111c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
29121c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
29131c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
29141c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
29151c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
29161c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
29171c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
29181c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
29191c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
29201c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
29211c188c59Sftrigaux 
29221c188c59Sftrigaux   /* copy x values over to hypre */
29231c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
29241c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
29251c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
29261c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
29271c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
29281c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29291c188c59Sftrigaux 
29301c188c59Sftrigaux   /* copy solution values back to PETSc */
29311c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
29321c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
29331c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
29343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29351c188c59Sftrigaux }
29361c188c59Sftrigaux 
2937d71ae5a4SJacob 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)
2938d71ae5a4SJacob Faibussowitsch {
29391c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
29401c188c59Sftrigaux   HYPRE_Int oits;
29411c188c59Sftrigaux 
29421c188c59Sftrigaux   PetscFunctionBegin;
29431c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29441c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
29451c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
29461c188c59Sftrigaux 
29471c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
29481c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
29491c188c59Sftrigaux   *outits = oits;
29501c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
29511c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
29521c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
29531c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
29543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29551c188c59Sftrigaux }
29561c188c59Sftrigaux 
2957ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SMG(PC pc)
2958d71ae5a4SJacob Faibussowitsch {
29591c188c59Sftrigaux   PetscInt         i, dim;
29601c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
2961*f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
29621c188c59Sftrigaux   PetscBool        flg;
29631c188c59Sftrigaux   DMBoundaryType   p[3];
29641c188c59Sftrigaux   PetscInt         M[3];
29651c188c59Sftrigaux 
29661c188c59Sftrigaux   PetscFunctionBegin;
29671c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
29681c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
29691c188c59Sftrigaux 
29701c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
29711c188c59Sftrigaux   // Check if power of 2 in periodic directions
29721c188c59Sftrigaux   for (i = 0; i < dim; i++) {
29731c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
29741c188c59Sftrigaux       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]);
29751c188c59Sftrigaux     }
29761c188c59Sftrigaux   }
29771c188c59Sftrigaux 
29781c188c59Sftrigaux   /* create the hypre solver object and set its information */
29791c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
29801c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
29811c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
29821c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
29831c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
29841c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
29851c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
29861c188c59Sftrigaux 
29871c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29881c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
29893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29901c188c59Sftrigaux }
29911c188c59Sftrigaux 
29921c188c59Sftrigaux /*MC
29935cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
29941c188c59Sftrigaux 
29951c188c59Sftrigaux    Level: advanced
29961c188c59Sftrigaux 
2997f1580f4eSBarry Smith    Options Database Keys:
29985cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
29995cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
30005cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
30015cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
30021c188c59Sftrigaux 
30031c188c59Sftrigaux    Notes:
30041c188c59Sftrigaux    This is for CELL-centered descretizations
30051c188c59Sftrigaux 
30065cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
30071c188c59Sftrigaux 
3008f1580f4eSBarry 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`.
3009f1580f4eSBarry Smith 
3010f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3011f1580f4eSBarry Smith 
3012f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
30131c188c59Sftrigaux M*/
30141c188c59Sftrigaux 
3015d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3016d71ae5a4SJacob Faibussowitsch {
30171c188c59Sftrigaux   PC_SMG *ex;
30181c188c59Sftrigaux 
30191c188c59Sftrigaux   PetscFunctionBegin;
30209371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
30211c188c59Sftrigaux   pc->data = ex;
30221c188c59Sftrigaux 
30231c188c59Sftrigaux   ex->its            = 1;
30241c188c59Sftrigaux   ex->tol            = 1.e-8;
30251c188c59Sftrigaux   ex->num_pre_relax  = 1;
30261c188c59Sftrigaux   ex->num_post_relax = 1;
30271c188c59Sftrigaux 
30281c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
30291c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
30301c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
30311c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
30321c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
30331c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
30341c188c59Sftrigaux 
30351c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3036ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
30371c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
30383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30391c188c59Sftrigaux }
3040