xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision f1580f4e3ce5d5b2393648fd039d0d41b440385d)
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  = "
229371c9d4SSatish Balay                                     "{\\url{https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods}}\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 
1479371c9d4SSatish Balay PetscErrorCode PCHYPREGetSolver(PC pc, HYPRE_Solver *hsolver) {
148d2128fa2SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
149d2128fa2SBarry Smith 
150d2128fa2SBarry Smith   PetscFunctionBegin;
151d2128fa2SBarry Smith   *hsolver = jac->hsolver;
152d2128fa2SBarry Smith   PetscFunctionReturn(0);
153d2128fa2SBarry Smith }
15416d9e3a6SLisandro Dalcin 
155fd2dd295SFande Kong /*
1568a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1578a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1588a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
159fd2dd295SFande Kong */
1609371c9d4SSatish Balay static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[]) {
1618a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1628a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1638a2c336bSFande Kong   PetscInt             num_levels, l;
1648a2c336bSFande Kong   Mat                 *mattmp;
1658a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1668a2c336bSFande Kong 
1678a2c336bSFande Kong   PetscFunctionBegin;
1689566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1695f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1708a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1728a2c336bSFande Kong   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)(jac->hsolver));
1738a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1749566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[num_levels - 1 - l])));
1758a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1768a2c336bSFande Kong     A_array[l] = NULL;
1778a2c336bSFande Kong   }
1788a2c336bSFande Kong   *nlevels   = num_levels;
1798a2c336bSFande Kong   *operators = mattmp;
1808a2c336bSFande Kong   PetscFunctionReturn(0);
1818a2c336bSFande Kong }
1828a2c336bSFande Kong 
183fd2dd295SFande Kong /*
1848a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1858a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1868a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
187fd2dd295SFande Kong */
1889371c9d4SSatish Balay static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[]) {
1898a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1908a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1918a2c336bSFande Kong   PetscInt             num_levels, l;
1928a2c336bSFande Kong   Mat                 *mattmp;
1938a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1948a2c336bSFande Kong 
1958a2c336bSFande Kong   PetscFunctionBegin;
1969566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1975f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1988a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
2008a2c336bSFande Kong   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)(jac->hsolver));
2018a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
2029566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[l - 1])));
2038a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
2048a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
2058a2c336bSFande Kong   }
2068a2c336bSFande Kong   *nlevels        = num_levels;
2078a2c336bSFande Kong   *interpolations = mattmp;
2088a2c336bSFande Kong   PetscFunctionReturn(0);
2098a2c336bSFande Kong }
2108a2c336bSFande Kong 
211ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
2129371c9d4SSatish Balay static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc) {
213ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
214ce6a8a0dSJed Brown   PetscInt  i;
215ce6a8a0dSJed Brown 
2169d678128SJed Brown   PetscFunctionBegin;
21748a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2189566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2199566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2219d678128SJed Brown   jac->n_hmnull = 0;
222ce6a8a0dSJed Brown   PetscFunctionReturn(0);
223ce6a8a0dSJed Brown }
224ce6a8a0dSJed Brown 
2259371c9d4SSatish Balay static PetscErrorCode PCSetUp_HYPRE(PC pc) {
22616d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
22749a781f5SStefano Zampini   Mat_HYPRE         *hjac;
22816d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
22916d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
23049a781f5SStefano Zampini   PetscBool          ishypre;
23116d9e3a6SLisandro Dalcin 
23216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23348a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2345f5c5b43SBarry Smith 
2359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
23649a781f5SStefano Zampini   if (!ishypre) {
2379566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
2389566063dSJacob Faibussowitsch     PetscCall(MatConvert(pc->pmat, MATHYPRE, MAT_INITIAL_MATRIX, &jac->hpmat));
2399566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)jac->hpmat));
24049a781f5SStefano Zampini   } else {
2419566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
24349a781f5SStefano Zampini     jac->hpmat = pc->pmat;
24416d9e3a6SLisandro Dalcin   }
2456ea7df73SStefano Zampini   /* allow debug */
2469566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
24749a781f5SStefano Zampini   hjac = (Mat_HYPRE *)(jac->hpmat->data);
2485f5c5b43SBarry Smith 
24916d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25016d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2515272c319SBarry Smith     MatNullSpace mnull;
2525272c319SBarry Smith     PetscBool    has_const;
25349a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2545272c319SBarry Smith     const Vec   *vecs;
2555272c319SBarry Smith 
2569566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
257792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2589566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2595272c319SBarry Smith     if (mnull) {
2609566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2619566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2629566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2645272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2659566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2669566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
267792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2685272c319SBarry Smith       }
2695272c319SBarry Smith       if (has_const) {
2709566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2719566063dSJacob Faibussowitsch         PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)jac->hmnull_constant));
2729566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2739566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2749566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2759566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
276792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2775272c319SBarry Smith         nvec++;
2785272c319SBarry Smith       }
279792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2805272c319SBarry Smith       jac->n_hmnull = nvec;
2815272c319SBarry Smith     }
2824cb006feSStefano Zampini   }
283863406b8SStefano Zampini 
2844cb006feSStefano Zampini   /* special case for AMS */
2854cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2865ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
2875ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2886bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
289*f1580f4eSBarry 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()");
2906bf688a0SCe Qin     }
29148a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
2925ac14e1cSStefano Zampini     if (jac->constants[0]) {
2935ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
294792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
295792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
29648a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
297792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
2985ac14e1cSStefano Zampini     }
2995ac14e1cSStefano Zampini     if (jac->coords[0]) {
3005ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3015ac14e1cSStefano Zampini       coords[0] = NULL;
3025ac14e1cSStefano Zampini       coords[1] = NULL;
3035ac14e1cSStefano Zampini       coords[2] = NULL;
304792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
305792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
306792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
307792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3085ac14e1cSStefano Zampini     }
3095f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3105ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
311792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
312792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3135ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3145ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->alpha_Poisson->data);
315792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
316792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3175ac14e1cSStefano Zampini     }
3185ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
319792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3205ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3215ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->beta_Poisson->data);
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
323792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
324be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
325be14dc20SKerry Key       if (jac->interior) {
326be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
327be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
328be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
329be14dc20SKerry Key       } else {
330be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
331be14dc20SKerry Key       }
3325ac14e1cSStefano Zampini     }
3336bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3346bf688a0SCe Qin       PetscInt           i;
3356bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3366bf688a0SCe Qin       if (jac->ND_PiFull) {
3376bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
338792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3396bf688a0SCe Qin       } else {
3406bf688a0SCe Qin         nd_parcsrfull = NULL;
3416bf688a0SCe Qin       }
3426bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3436bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3446bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
345792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3466bf688a0SCe Qin         } else {
3476bf688a0SCe Qin           nd_parcsr[i] = NULL;
3486bf688a0SCe Qin         }
3496bf688a0SCe Qin       }
350792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3516bf688a0SCe Qin     }
3524cb006feSStefano Zampini   }
353863406b8SStefano Zampini   /* special case for ADS */
354863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3555ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3565ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3576bf688a0SCe 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])))) {
3586bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3599371c9d4SSatish 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");
3605f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3615f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3625ac14e1cSStefano Zampini     if (jac->coords[0]) {
3635ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3645ac14e1cSStefano Zampini       coords[0] = NULL;
3655ac14e1cSStefano Zampini       coords[1] = NULL;
3665ac14e1cSStefano Zampini       coords[2] = NULL;
367792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
368792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
369792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
370792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3715ac14e1cSStefano Zampini     }
3725ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
373792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
374792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
3755ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->C->data);
376792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
377792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3786bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3796bf688a0SCe Qin       PetscInt           i;
3806bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3816bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3826bf688a0SCe Qin       if (jac->RT_PiFull) {
3836bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->RT_PiFull->data);
384792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
3856bf688a0SCe Qin       } else {
3866bf688a0SCe Qin         rt_parcsrfull = NULL;
3876bf688a0SCe Qin       }
3886bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3896bf688a0SCe Qin         if (jac->RT_Pi[i]) {
3906bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->RT_Pi[i]->data);
391792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
3926bf688a0SCe Qin         } else {
3936bf688a0SCe Qin           rt_parcsr[i] = NULL;
3946bf688a0SCe Qin         }
3956bf688a0SCe Qin       }
3966bf688a0SCe Qin       if (jac->ND_PiFull) {
3976bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
398792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3996bf688a0SCe Qin       } else {
4006bf688a0SCe Qin         nd_parcsrfull = NULL;
4016bf688a0SCe Qin       }
4026bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4036bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4046bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
405792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4066bf688a0SCe Qin         } else {
4076bf688a0SCe Qin           nd_parcsr[i] = NULL;
4086bf688a0SCe Qin         }
4096bf688a0SCe Qin       }
410792fecdfSBarry 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]);
4116bf688a0SCe Qin     }
412863406b8SStefano Zampini   }
413792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
414792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
415792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
416792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
41716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
41816d9e3a6SLisandro Dalcin }
41916d9e3a6SLisandro Dalcin 
4209371c9d4SSatish Balay static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x) {
42116d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
42249a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
42316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
42416d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
42516d9e3a6SLisandro Dalcin 
42616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4279566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4289566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4299566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4309566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4319566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
432792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
433792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
434792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4359371c9d4SSatish Balay   PetscStackCallExternalVoid(
4369371c9d4SSatish Balay     "Hypre solve", do {
4375f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4385f80ce2aSJacob Faibussowitsch       if (hierr) {
4395f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
4405f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
4415f80ce2aSJacob Faibussowitsch       }
4425f80ce2aSJacob Faibussowitsch     } while (0));
44316d9e3a6SLisandro Dalcin 
44448a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4459566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4469566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
44716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
44816d9e3a6SLisandro Dalcin }
44916d9e3a6SLisandro Dalcin 
4509371c9d4SSatish Balay static PetscErrorCode PCReset_HYPRE(PC pc) {
4518695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
4528695de01SBarry Smith 
4538695de01SBarry Smith   PetscFunctionBegin;
4549566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
4559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
4569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
4579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
4589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
4599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
4609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
4619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
4629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
4639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
4649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
4659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
4669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
4679566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
4689566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
4699566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
4709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
4719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
4729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
473be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
4749566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
4755ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
476be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
4775ac14e1cSStefano Zampini   jac->dim                   = 0;
4788695de01SBarry Smith   PetscFunctionReturn(0);
4798695de01SBarry Smith }
4808695de01SBarry Smith 
4819371c9d4SSatish Balay static PetscErrorCode PCDestroy_HYPRE(PC pc) {
48216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
48316d9e3a6SLisandro Dalcin 
48416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4859566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
486792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
4879566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
488db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
4899566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
490db6f9c32SMark Adams #endif
4919566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
4929566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
49316d9e3a6SLisandro Dalcin 
4949566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
4959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
4969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
4979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
4989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
4999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5022e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
503be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5082e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
50916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
51016d9e3a6SLisandro Dalcin }
51116d9e3a6SLisandro Dalcin 
5129371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject) {
51316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
514ace3abfcSBarry Smith   PetscBool flag;
51516d9e3a6SLisandro Dalcin 
51616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
517d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
519792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
521792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
523792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
524d0609cedSBarry Smith   PetscOptionsHeadEnd();
52516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
52616d9e3a6SLisandro Dalcin }
52716d9e3a6SLisandro Dalcin 
5289371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer) {
52916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
530ace3abfcSBarry Smith   PetscBool iascii;
53116d9e3a6SLisandro Dalcin 
53216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
53416d9e3a6SLisandro Dalcin   if (iascii) {
5359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
53616d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
53763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
53816d9e3a6SLisandro Dalcin     } else {
5399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
54016d9e3a6SLisandro Dalcin     }
54116d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
5429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
54316d9e3a6SLisandro Dalcin     } else {
5449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
54516d9e3a6SLisandro Dalcin     }
54616d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
54763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
54816d9e3a6SLisandro Dalcin     } else {
5499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
55016d9e3a6SLisandro Dalcin     }
55116d9e3a6SLisandro Dalcin   }
55216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
55316d9e3a6SLisandro Dalcin }
55416d9e3a6SLisandro Dalcin 
5559371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject) {
556db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5578bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
558db966c6cSHong Zhang 
559db966c6cSHong Zhang   PetscFunctionBegin;
560d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
5619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
562792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
5638bf83915SBarry Smith 
5649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
5658bf83915SBarry Smith   if (flag) {
5668bf83915SBarry Smith     PetscMPIInt size;
5678bf83915SBarry Smith 
5689566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
5697827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
570792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
5718bf83915SBarry Smith   }
5728bf83915SBarry Smith 
5739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
5748bf83915SBarry Smith   if (flag) {
5758bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
576792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
5778bf83915SBarry Smith   }
578d0609cedSBarry Smith   PetscOptionsHeadEnd();
579db966c6cSHong Zhang   PetscFunctionReturn(0);
580db966c6cSHong Zhang }
581db966c6cSHong Zhang 
5829371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer) {
583db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
584db966c6cSHong Zhang   PetscBool iascii;
585db966c6cSHong Zhang 
586db966c6cSHong Zhang   PetscFunctionBegin;
5879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
588db966c6cSHong Zhang   if (iascii) {
5899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
590db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
59163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
592db966c6cSHong Zhang     } else {
5939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
594db966c6cSHong Zhang     }
5959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
59663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
597db966c6cSHong Zhang   }
598db966c6cSHong Zhang   PetscFunctionReturn(0);
599db966c6cSHong Zhang }
600db966c6cSHong Zhang 
6019371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x) {
60216d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
60349a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
60416d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
60516d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
60616d9e3a6SLisandro Dalcin 
60716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6089566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6099566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6109566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6119566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
61216d9e3a6SLisandro Dalcin 
613792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
614792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
615792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
61616d9e3a6SLisandro Dalcin 
6179371c9d4SSatish Balay   PetscStackCallExternalVoid(
6189371c9d4SSatish Balay     "Hypre Transpose solve", do {
6195f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6205f80ce2aSJacob Faibussowitsch       if (hierr) {
62116d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6225f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
6235f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
6245f80ce2aSJacob Faibussowitsch       }
6255f80ce2aSJacob Faibussowitsch     } while (0));
62616d9e3a6SLisandro Dalcin 
6279566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6289566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
62916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
63016d9e3a6SLisandro Dalcin }
63116d9e3a6SLisandro Dalcin 
6329371c9d4SSatish Balay static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[]) {
633db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
634db6f9c32SMark Adams   PetscBool flag;
635db6f9c32SMark Adams 
636db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
637db6f9c32SMark Adams   PetscFunctionBegin;
638db6f9c32SMark Adams   if (jac->spgemm_type) {
6399566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
64028b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
641db6f9c32SMark Adams     PetscFunctionReturn(0);
642db6f9c32SMark Adams   } else {
6439566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
644db6f9c32SMark Adams   }
6459566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
646db6f9c32SMark Adams   if (flag) {
647792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
648db6f9c32SMark Adams     PetscFunctionReturn(0);
649db6f9c32SMark Adams   }
6509566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
651db6f9c32SMark Adams   if (flag) {
652792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
653db6f9c32SMark Adams     PetscFunctionReturn(0);
654db6f9c32SMark Adams   }
655db6f9c32SMark Adams   jac->spgemm_type = NULL;
65698921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEM type %s; Choices are cusparse, hypre", name);
657db6f9c32SMark Adams #endif
658db6f9c32SMark Adams }
659db6f9c32SMark Adams 
6609371c9d4SSatish Balay static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[]) {
661db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
662db6f9c32SMark Adams 
663db6f9c32SMark Adams   PetscFunctionBegin;
664db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
665db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
666db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
667db6f9c32SMark Adams #endif
668db6f9c32SMark Adams   PetscFunctionReturn(0);
669db6f9c32SMark Adams }
670db6f9c32SMark Adams 
67116d9e3a6SLisandro Dalcin static const char    *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
6720f1074feSSatish Balay static const char    *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
67316d9e3a6SLisandro Dalcin static const char    *HYPREBoomerAMGMeasureType[] = {"local", "global"};
67465de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
6756a251517SEike Mueller static const char    *HYPREBoomerAMGSmoothType[]  = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
6769371c9d4SSatish 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"};
6779371c9d4SSatish 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"};
6789371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject) {
67916d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
68022e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
681ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
68216d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
683589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
684db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
68516d9e3a6SLisandro Dalcin 
68616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
687d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
6889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
68916d9e3a6SLisandro Dalcin   if (flg) {
6904336a9eeSBarry Smith     jac->cycletype = indx + 1;
691792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
69216d9e3a6SLisandro Dalcin   }
6939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
69416d9e3a6SLisandro Dalcin   if (flg) {
69563a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
696792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
69716d9e3a6SLisandro Dalcin   }
6989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
69916d9e3a6SLisandro Dalcin   if (flg) {
70063a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
701792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
70216d9e3a6SLisandro Dalcin   }
7039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_tol", "Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)", "None", jac->tol, &jac->tol, &flg));
70416d9e3a6SLisandro Dalcin   if (flg) {
70508401ef6SPierre Jolivet     PetscCheck(jac->tol >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Tolerance %g must be greater than or equal to zero", (double)jac->tol);
706792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
70716d9e3a6SLisandro Dalcin   }
70822e51d31SStefano Zampini   bs = 1;
70948a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
71148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
71216d9e3a6SLisandro Dalcin 
7139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
71416d9e3a6SLisandro Dalcin   if (flg) {
71508401ef6SPierre Jolivet     PetscCheck(jac->truncfactor >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Truncation factor %g must be great than or equal zero", (double)jac->truncfactor);
716792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
71716d9e3a6SLisandro Dalcin   }
71816d9e3a6SLisandro Dalcin 
7199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7200f1074feSSatish Balay   if (flg) {
72163a3b9bcSJacob Faibussowitsch     PetscCheck(jac->pmax >= 0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "P_max %" PetscInt_FMT " must be greater than or equal to zero", jac->pmax);
722792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7230f1074feSSatish Balay   }
7240f1074feSSatish Balay 
7259566063dSJacob 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));
726792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7270f1074feSSatish Balay 
7289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_agg_num_paths", "Number of paths for aggressive coarsening", "None", jac->agg_num_paths, &jac->agg_num_paths, &flg));
7290f1074feSSatish Balay   if (flg) {
73063a3b9bcSJacob Faibussowitsch     PetscCheck(jac->agg_num_paths >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of paths %" PetscInt_FMT " must be greater than or equal to 1", jac->agg_num_paths);
731792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
7320f1074feSSatish Balay   }
7330f1074feSSatish Balay 
7349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
73516d9e3a6SLisandro Dalcin   if (flg) {
73608401ef6SPierre Jolivet     PetscCheck(jac->strongthreshold >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Strong threshold %g must be great than or equal zero", (double)jac->strongthreshold);
737792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
73816d9e3a6SLisandro Dalcin   }
7399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
74016d9e3a6SLisandro Dalcin   if (flg) {
74108401ef6SPierre Jolivet     PetscCheck(jac->maxrowsum >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Maximum row sum %g must be greater than zero", (double)jac->maxrowsum);
74208401ef6SPierre Jolivet     PetscCheck(jac->maxrowsum <= 1.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Maximum row sum %g must be less than or equal one", (double)jac->maxrowsum);
743792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
74416d9e3a6SLisandro Dalcin   }
74516d9e3a6SLisandro Dalcin 
74616d9e3a6SLisandro Dalcin   /* Grid sweeps */
7479566063dSJacob 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));
74816d9e3a6SLisandro Dalcin   if (flg) {
749792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
75016d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
75116d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
7520f1074feSSatish Balay     jac->gridsweeps[1] = indx;
7530f1074feSSatish Balay     /*defaults coarse to 1 */
7540f1074feSSatish Balay     jac->gridsweeps[2] = 1;
75516d9e3a6SLisandro Dalcin   }
7569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
75748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
7589566063dSJacob 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));
75948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
7609566063dSJacob 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));
76148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
7629566063dSJacob 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));
76348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
7649566063dSJacob 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));
76548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
7669566063dSJacob 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));
76748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
7689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
76916d9e3a6SLisandro Dalcin   if (flg) {
770792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
7710f1074feSSatish Balay     jac->gridsweeps[0] = indx;
77216d9e3a6SLisandro Dalcin   }
7739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
77416d9e3a6SLisandro Dalcin   if (flg) {
775792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
7760f1074feSSatish Balay     jac->gridsweeps[1] = indx;
77716d9e3a6SLisandro Dalcin   }
7789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
77916d9e3a6SLisandro Dalcin   if (flg) {
780792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
7810f1074feSSatish Balay     jac->gridsweeps[2] = indx;
78216d9e3a6SLisandro Dalcin   }
78316d9e3a6SLisandro Dalcin 
7846a251517SEike Mueller   /* Smooth type */
785dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
7866a251517SEike Mueller   if (flg) {
7876a251517SEike Mueller     jac->smoothtype = indx;
788792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
7898131ecf7SEike Mueller     jac->smoothnumlevels = 25;
790792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
7918131ecf7SEike Mueller   }
7928131ecf7SEike Mueller 
7938131ecf7SEike Mueller   /* Number of smoothing levels */
7949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
7958131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
7968131ecf7SEike Mueller     jac->smoothnumlevels = indx;
797792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
7986a251517SEike Mueller   }
7996a251517SEike Mueller 
8001810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8021810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8031810e44eSEike Mueller     jac->eu_level = indx;
804792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8051810e44eSEike Mueller   }
8061810e44eSEike Mueller 
8071810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8081810e44eSEike Mueller   double droptolerance;
8099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8101810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8111810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
812792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8131810e44eSEike Mueller   }
8141810e44eSEike Mueller 
8151810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8171810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8181810e44eSEike Mueller     jac->eu_bj = tmp_truth;
819792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8201810e44eSEike Mueller   }
8211810e44eSEike Mueller 
82216d9e3a6SLisandro Dalcin   /* Relax type */
823dd39110bSPierre 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));
82416d9e3a6SLisandro Dalcin   if (flg) {
8250f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
826792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8270f1074feSSatish Balay     /* by default, coarse type set to 9 */
8280f1074feSSatish Balay     jac->relaxtype[2] = 9;
829792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
83016d9e3a6SLisandro Dalcin   }
831dd39110bSPierre 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));
83216d9e3a6SLisandro Dalcin   if (flg) {
83316d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
834792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
83516d9e3a6SLisandro Dalcin   }
836dd39110bSPierre 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));
83716d9e3a6SLisandro Dalcin   if (flg) {
8380f1074feSSatish Balay     jac->relaxtype[1] = indx;
839792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
84016d9e3a6SLisandro Dalcin   }
841dd39110bSPierre 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));
84216d9e3a6SLisandro Dalcin   if (flg) {
8430f1074feSSatish Balay     jac->relaxtype[2] = indx;
844792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
84516d9e3a6SLisandro Dalcin   }
84616d9e3a6SLisandro Dalcin 
84716d9e3a6SLisandro Dalcin   /* Relaxation Weight */
8489566063dSJacob 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));
84916d9e3a6SLisandro Dalcin   if (flg) {
850792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
85116d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
85216d9e3a6SLisandro Dalcin   }
85316d9e3a6SLisandro Dalcin 
85416d9e3a6SLisandro Dalcin   n         = 2;
85516d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
85716d9e3a6SLisandro Dalcin   if (flg) {
85816d9e3a6SLisandro Dalcin     if (n == 2) {
85916d9e3a6SLisandro Dalcin       indx = (int)PetscAbsReal(twodbl[1]);
860792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
86163a3b9bcSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT, n);
86216d9e3a6SLisandro Dalcin   }
86316d9e3a6SLisandro Dalcin 
86416d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
8659566063dSJacob 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));
86616d9e3a6SLisandro Dalcin   if (flg) {
867792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
86816d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
86916d9e3a6SLisandro Dalcin   }
87016d9e3a6SLisandro Dalcin 
87116d9e3a6SLisandro Dalcin   n         = 2;
87216d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8739566063dSJacob 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));
87416d9e3a6SLisandro Dalcin   if (flg) {
87516d9e3a6SLisandro Dalcin     if (n == 2) {
87616d9e3a6SLisandro Dalcin       indx = (int)PetscAbsReal(twodbl[1]);
877792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
87863a3b9bcSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT, n);
87916d9e3a6SLisandro Dalcin   }
88016d9e3a6SLisandro Dalcin 
88116d9e3a6SLisandro Dalcin   /* the Relax Order */
8829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
88316d9e3a6SLisandro Dalcin 
8848afaa268SBarry Smith   if (flg && tmp_truth) {
88516d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
886792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
88716d9e3a6SLisandro Dalcin   }
888dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
88916d9e3a6SLisandro Dalcin   if (flg) {
89016d9e3a6SLisandro Dalcin     jac->measuretype = indx;
891792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
89216d9e3a6SLisandro Dalcin   }
8930f1074feSSatish Balay   /* update list length 3/07 */
894dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
89516d9e3a6SLisandro Dalcin   if (flg) {
89616d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
897792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
89816d9e3a6SLisandro Dalcin   }
8990f1074feSSatish Balay 
9009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
90148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
90348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
904db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
905db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
906dd39110bSPierre 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));
907db6f9c32SMark Adams   if (!flg) indx = 0;
9089566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
909db6f9c32SMark Adams #endif
910589dcaf0SStefano Zampini   /* AIR */
911589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9129566063dSJacob 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));
913792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
914589dcaf0SStefano Zampini   if (jac->Rtype) {
915589dcaf0SStefano 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 */
916589dcaf0SStefano Zampini 
9179566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
918792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
919589dcaf0SStefano Zampini 
9209566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
921792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
922589dcaf0SStefano Zampini 
9239566063dSJacob 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));
924792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
925589dcaf0SStefano Zampini 
9269566063dSJacob 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));
927792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
928589dcaf0SStefano Zampini   }
929589dcaf0SStefano Zampini #endif
930589dcaf0SStefano Zampini 
931ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
93263a3b9bcSJacob 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);
933ecae95adSPierre Jolivet #endif
934ecae95adSPierre Jolivet 
9350f1074feSSatish Balay   /* new 3/07 */
936dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
937589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
938589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
939792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
9400f1074feSSatish Balay   }
9410f1074feSSatish Balay 
9429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
94316d9e3a6SLisandro Dalcin   if (flg) {
944b96a4a96SBarry Smith     level = 3;
9459566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
9462fa5cd67SKarl Rupp 
947b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
948792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
9492ae77aedSBarry Smith   }
9502ae77aedSBarry Smith 
9519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
9522ae77aedSBarry Smith   if (flg) {
953b96a4a96SBarry Smith     level = 3;
9549566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
9552fa5cd67SKarl Rupp 
956b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
957792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
95816d9e3a6SLisandro Dalcin   }
9598f87f92bSBarry Smith 
9609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
9618f87f92bSBarry Smith   if (flg && tmp_truth) {
9628f87f92bSBarry Smith     PetscInt tmp_int;
9639566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
9648f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
965792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
966792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
967792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
968792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
9698f87f92bSBarry Smith   }
9708f87f92bSBarry Smith 
9719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
972792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
973589dcaf0SStefano Zampini 
974589dcaf0SStefano Zampini   /* options for ParaSails solvers */
975dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
976589dcaf0SStefano Zampini   if (flg) {
977589dcaf0SStefano Zampini     jac->symt = indx;
978792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
979589dcaf0SStefano Zampini   }
980589dcaf0SStefano Zampini 
981d0609cedSBarry Smith   PetscOptionsHeadEnd();
98216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
98316d9e3a6SLisandro Dalcin }
98416d9e3a6SLisandro Dalcin 
9859371c9d4SSatish Balay 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) {
98616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
9872cf14000SStefano Zampini   HYPRE_Int oits;
98816d9e3a6SLisandro Dalcin 
98916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9909566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
991792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
992792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
99316d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
9949566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
99516d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
996792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
9974d0a8057SBarry Smith   *outits = oits;
9984d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
9994d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1000792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1001792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
100216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
100316d9e3a6SLisandro Dalcin }
100416d9e3a6SLisandro Dalcin 
10059371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer) {
100616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1007ace3abfcSBarry Smith   PetscBool iascii;
100816d9e3a6SLisandro Dalcin 
100916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
101116d9e3a6SLisandro Dalcin   if (iascii) {
10129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
10139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
101463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
101563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
10169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
10179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
10189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
101963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
102048a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
102163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
102263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
10230f1074feSSatish Balay 
10249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
102516d9e3a6SLisandro Dalcin 
102663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
102763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
102863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
102916d9e3a6SLisandro Dalcin 
10309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
10319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
10329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
103316d9e3a6SLisandro Dalcin 
10349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
10359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
103616d9e3a6SLisandro Dalcin 
103716d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
10389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
103916d9e3a6SLisandro Dalcin     } else {
10409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
104116d9e3a6SLisandro Dalcin     }
10426a251517SEike Mueller     if (jac->smoothtype != -1) {
10439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
104463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
10457e352d70SEike Mueller     } else {
10469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
10471810e44eSEike Mueller     }
10481810e44eSEike Mueller     if (jac->smoothtype == 3) {
104963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
10509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
105163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
10526a251517SEike Mueller     }
10539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
10549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
10559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
105648a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
10575272c319SBarry Smith     if (jac->vec_interp_variant) {
105863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
105963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
10609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
10618f87f92bSBarry Smith     }
106248a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1063db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
10649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
1065db6f9c32SMark Adams #endif
1066589dcaf0SStefano Zampini     /* AIR */
1067589dcaf0SStefano Zampini     if (jac->Rtype) {
106863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
10699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
10709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
10719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
107263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1073589dcaf0SStefano Zampini     }
107416d9e3a6SLisandro Dalcin   }
107516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
107616d9e3a6SLisandro Dalcin }
107716d9e3a6SLisandro Dalcin 
10789371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject) {
107916d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
10804ddd07fcSJed Brown   PetscInt    indx;
1081ace3abfcSBarry Smith   PetscBool   flag;
108216d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
108316d9e3a6SLisandro Dalcin 
108416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1085d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
10869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
10879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1088792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
108916d9e3a6SLisandro Dalcin 
10909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1091792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
109216d9e3a6SLisandro Dalcin 
10939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1094792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
109516d9e3a6SLisandro Dalcin 
10969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1097792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
109816d9e3a6SLisandro Dalcin 
10999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1100792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
110116d9e3a6SLisandro Dalcin 
1102dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
110316d9e3a6SLisandro Dalcin   if (flag) {
110416d9e3a6SLisandro Dalcin     jac->symt = indx;
1105792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
110616d9e3a6SLisandro Dalcin   }
110716d9e3a6SLisandro Dalcin 
1108d0609cedSBarry Smith   PetscOptionsHeadEnd();
110916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
111016d9e3a6SLisandro Dalcin }
111116d9e3a6SLisandro Dalcin 
11129371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer) {
111316d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1114ace3abfcSBarry Smith   PetscBool   iascii;
1115feb237baSPierre Jolivet   const char *symt = 0;
111616d9e3a6SLisandro Dalcin 
111716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
111916d9e3a6SLisandro Dalcin   if (iascii) {
11209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
112163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
11229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
11239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
11249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
11259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
11269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
11272fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
11282fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
11292fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
113063a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
11319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
113216d9e3a6SLisandro Dalcin   }
113316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
113416d9e3a6SLisandro Dalcin }
1135*f1580f4eSBarry Smith 
11369371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject) {
11374cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11384cb006feSStefano Zampini   PetscInt  n;
11394cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
11404cb006feSStefano Zampini 
11414cb006feSStefano Zampini   PetscFunctionBegin;
1142d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
11439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1144792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
11459566063dSJacob 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));
1146792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
11479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1148792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
11499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1150792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
11519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
11529566063dSJacob 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));
11539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
11549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
115548a46eb9SPierre 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);
11569566063dSJacob 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));
11574cb006feSStefano Zampini   n = 5;
11589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
11594cb006feSStefano Zampini   if (flag || flag2) {
1160792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1161863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1162863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
11639371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1164a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
11654cb006feSStefano Zampini   }
11669566063dSJacob 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));
11674cb006feSStefano Zampini   n = 5;
11689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
11694cb006feSStefano Zampini   if (flag || flag2) {
1170792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1171863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1172863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
11739371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1174a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
11754cb006feSStefano Zampini   }
11769566063dSJacob 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));
117723df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1178792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
117923df4f25SStefano Zampini   }
1180d0609cedSBarry Smith   PetscOptionsHeadEnd();
11814cb006feSStefano Zampini   PetscFunctionReturn(0);
11824cb006feSStefano Zampini }
11834cb006feSStefano Zampini 
11849371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer) {
11854cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11864cb006feSStefano Zampini   PetscBool iascii;
11874cb006feSStefano Zampini 
11884cb006feSStefano Zampini   PetscFunctionBegin;
11899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
11904cb006feSStefano Zampini   if (iascii) {
11919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
119263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
119363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
119463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
119563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
119663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
119763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
119863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
11994cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
12014cb006feSStefano Zampini     } else {
12029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
12034cb006feSStefano Zampini     }
120463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
120563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
120663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
120763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
120863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
120963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12104cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12114cb006feSStefano Zampini       if (jac->beta_Poisson) {
12129566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
12134cb006feSStefano Zampini       } else {
12149566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
12154cb006feSStefano Zampini       }
121663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
121763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
121863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
121963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
122063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
122163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
122248a46eb9SPierre 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));
122323df4f25SStefano Zampini     } else {
12249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
12254cb006feSStefano Zampini     }
12264cb006feSStefano Zampini   }
12274cb006feSStefano Zampini   PetscFunctionReturn(0);
12284cb006feSStefano Zampini }
12294cb006feSStefano Zampini 
12309371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject) {
1231863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1232863406b8SStefano Zampini   PetscInt  n;
1233863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1234863406b8SStefano Zampini 
1235863406b8SStefano Zampini   PetscFunctionBegin;
1236d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
12379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1238792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
12399566063dSJacob 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));
1240792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
12419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1242792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
12439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1244792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
12459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12469566063dSJacob 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));
12479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
124948a46eb9SPierre 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);
12509566063dSJacob 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));
1251863406b8SStefano Zampini   n = 5;
12529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
12539566063dSJacob 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));
1254863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1255792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1256863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1257863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1258863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
12599371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1260a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1261863406b8SStefano Zampini   }
12629566063dSJacob 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));
1263863406b8SStefano Zampini   n = 5;
12649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1265863406b8SStefano Zampini   if (flag || flag2) {
1266792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1267863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1268863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
12699371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1270a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1271863406b8SStefano Zampini   }
1272d0609cedSBarry Smith   PetscOptionsHeadEnd();
1273863406b8SStefano Zampini   PetscFunctionReturn(0);
1274863406b8SStefano Zampini }
1275863406b8SStefano Zampini 
12769371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer) {
1277863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1278863406b8SStefano Zampini   PetscBool iascii;
1279863406b8SStefano Zampini 
1280863406b8SStefano Zampini   PetscFunctionBegin;
12819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1282863406b8SStefano Zampini   if (iascii) {
12839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
128463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
128563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
128663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
128763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
128863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
128963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
129063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
129263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
129363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
129463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
129563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
129663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
129763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
129863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
130063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
130163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
130263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
130363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
130463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
130563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1306863406b8SStefano Zampini   }
1307863406b8SStefano Zampini   PetscFunctionReturn(0);
1308863406b8SStefano Zampini }
1309863406b8SStefano Zampini 
13109371c9d4SSatish Balay static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G) {
13114cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13125ac14e1cSStefano Zampini   PetscBool ishypre;
13134cb006feSStefano Zampini 
13144cb006feSStefano Zampini   PetscFunctionBegin;
13159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
13165ac14e1cSStefano Zampini   if (ishypre) {
13179566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
13189566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13195ac14e1cSStefano Zampini     jac->G = G;
13205ac14e1cSStefano Zampini   } else {
13219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13229566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
13235ac14e1cSStefano Zampini   }
13244cb006feSStefano Zampini   PetscFunctionReturn(0);
13254cb006feSStefano Zampini }
13264cb006feSStefano Zampini 
13274cb006feSStefano Zampini /*@
1328*f1580f4eSBarry Smith    PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
13294cb006feSStefano Zampini 
1330*f1580f4eSBarry Smith    Collective on pc
13314cb006feSStefano Zampini 
13324cb006feSStefano Zampini    Input Parameters:
13334cb006feSStefano Zampini +  pc - the preconditioning context
13344cb006feSStefano Zampini -  G - the discrete gradient
13354cb006feSStefano Zampini 
13364cb006feSStefano Zampini    Level: intermediate
13374cb006feSStefano Zampini 
133895452b02SPatrick Sanan    Notes:
133995452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1340147403d9SBarry Smith 
1341863406b8SStefano 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
13424cb006feSStefano Zampini 
1343*f1580f4eSBarry Smith    Developer Note:
1344*f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1345*f1580f4eSBarry Smith 
1346*f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
13474cb006feSStefano Zampini @*/
13489371c9d4SSatish Balay PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G) {
13494cb006feSStefano Zampini   PetscFunctionBegin;
13504cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
13514cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
13524cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1353cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
13544cb006feSStefano Zampini   PetscFunctionReturn(0);
13554cb006feSStefano Zampini }
13564cb006feSStefano Zampini 
13579371c9d4SSatish Balay static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C) {
1358863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13595ac14e1cSStefano Zampini   PetscBool ishypre;
1360863406b8SStefano Zampini 
1361863406b8SStefano Zampini   PetscFunctionBegin;
13629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
13635ac14e1cSStefano Zampini   if (ishypre) {
13649566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
13659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13665ac14e1cSStefano Zampini     jac->C = C;
13675ac14e1cSStefano Zampini   } else {
13689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13699566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
13705ac14e1cSStefano Zampini   }
1371863406b8SStefano Zampini   PetscFunctionReturn(0);
1372863406b8SStefano Zampini }
1373863406b8SStefano Zampini 
1374863406b8SStefano Zampini /*@
1375*f1580f4eSBarry Smith    PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1376863406b8SStefano Zampini 
1377*f1580f4eSBarry Smith    Collective on pc
1378863406b8SStefano Zampini 
1379863406b8SStefano Zampini    Input Parameters:
1380863406b8SStefano Zampini +  pc - the preconditioning context
1381863406b8SStefano Zampini -  C - the discrete curl
1382863406b8SStefano Zampini 
1383863406b8SStefano Zampini    Level: intermediate
1384863406b8SStefano Zampini 
138595452b02SPatrick Sanan    Notes:
138695452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1387147403d9SBarry Smith 
1388863406b8SStefano 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
1389863406b8SStefano Zampini 
1390*f1580f4eSBarry Smith    Developer Note:
1391*f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1392*f1580f4eSBarry Smith 
1393*f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1394*f1580f4eSBarry Smith 
1395*f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1396863406b8SStefano Zampini @*/
13979371c9d4SSatish Balay PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C) {
1398863406b8SStefano Zampini   PetscFunctionBegin;
1399863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1400863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1401863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1402cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
1403863406b8SStefano Zampini   PetscFunctionReturn(0);
1404863406b8SStefano Zampini }
1405863406b8SStefano Zampini 
14069371c9d4SSatish Balay static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[]) {
14076bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14086bf688a0SCe Qin   PetscBool ishypre;
14096bf688a0SCe Qin   PetscInt  i;
14106bf688a0SCe Qin   PetscFunctionBegin;
14116bf688a0SCe Qin 
14129566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
14139566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
14146bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
14159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
14169566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
14176bf688a0SCe Qin   }
14186bf688a0SCe Qin 
14196bf688a0SCe Qin   jac->dim = dim;
14206bf688a0SCe Qin   if (RT_PiFull) {
14219566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
14226bf688a0SCe Qin     if (ishypre) {
14239566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
14246bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
14256bf688a0SCe Qin     } else {
14269566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
14276bf688a0SCe Qin     }
14286bf688a0SCe Qin   }
14296bf688a0SCe Qin   if (RT_Pi) {
14306bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14316bf688a0SCe Qin       if (RT_Pi[i]) {
14329566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
14336bf688a0SCe Qin         if (ishypre) {
14349566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
14356bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
14366bf688a0SCe Qin         } else {
14379566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
14386bf688a0SCe Qin         }
14396bf688a0SCe Qin       }
14406bf688a0SCe Qin     }
14416bf688a0SCe Qin   }
14426bf688a0SCe Qin   if (ND_PiFull) {
14439566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
14446bf688a0SCe Qin     if (ishypre) {
14459566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
14466bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
14476bf688a0SCe Qin     } else {
14489566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
14496bf688a0SCe Qin     }
14506bf688a0SCe Qin   }
14516bf688a0SCe Qin   if (ND_Pi) {
14526bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14536bf688a0SCe Qin       if (ND_Pi[i]) {
14549566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
14556bf688a0SCe Qin         if (ishypre) {
14569566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
14576bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
14586bf688a0SCe Qin         } else {
14599566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
14606bf688a0SCe Qin         }
14616bf688a0SCe Qin       }
14626bf688a0SCe Qin     }
14636bf688a0SCe Qin   }
14646bf688a0SCe Qin 
14656bf688a0SCe Qin   PetscFunctionReturn(0);
14666bf688a0SCe Qin }
14676bf688a0SCe Qin 
14686bf688a0SCe Qin /*@
1469*f1580f4eSBarry Smith    PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
14706bf688a0SCe Qin 
1471*f1580f4eSBarry Smith    Collective on pc
14726bf688a0SCe Qin 
14736bf688a0SCe Qin    Input Parameters:
14746bf688a0SCe Qin +  pc - the preconditioning context
14756bf688a0SCe Qin -  dim - the dimension of the problem, only used in AMS
14766bf688a0SCe Qin -  RT_PiFull - Raviart-Thomas interpolation matrix
14776bf688a0SCe Qin -  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
14786bf688a0SCe Qin -  ND_PiFull - Nedelec interpolation matrix
14796bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
14806bf688a0SCe Qin 
1481*f1580f4eSBarry Smith    Level: intermediate
1482*f1580f4eSBarry Smith 
148395452b02SPatrick Sanan    Notes:
148495452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1485147403d9SBarry Smith 
14866bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1487147403d9SBarry Smith 
1488*f1580f4eSBarry Smith    Developer Note:
1489*f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
14906bf688a0SCe Qin 
1491*f1580f4eSBarry Smith .seealso: `PCHYPRE`
14926bf688a0SCe Qin @*/
14939371c9d4SSatish Balay PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[]) {
14946bf688a0SCe Qin   PetscInt i;
14956bf688a0SCe Qin 
14966bf688a0SCe Qin   PetscFunctionBegin;
14976bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14986bf688a0SCe Qin   if (RT_PiFull) {
14996bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
15006bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
15016bf688a0SCe Qin   }
15026bf688a0SCe Qin   if (RT_Pi) {
15036bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
15046bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15056bf688a0SCe Qin       if (RT_Pi[i]) {
15066bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
15076bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
15086bf688a0SCe Qin       }
15096bf688a0SCe Qin     }
15106bf688a0SCe Qin   }
15116bf688a0SCe Qin   if (ND_PiFull) {
15126bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
15136bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
15146bf688a0SCe Qin   }
15156bf688a0SCe Qin   if (ND_Pi) {
15166bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
15176bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15186bf688a0SCe Qin       if (ND_Pi[i]) {
15196bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
15206bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
15216bf688a0SCe Qin       }
15226bf688a0SCe Qin     }
15236bf688a0SCe Qin   }
1524cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
15256bf688a0SCe Qin   PetscFunctionReturn(0);
15266bf688a0SCe Qin }
15276bf688a0SCe Qin 
15289371c9d4SSatish Balay static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha) {
15294cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15305ac14e1cSStefano Zampini   PetscBool ishypre;
15314cb006feSStefano Zampini 
15324cb006feSStefano Zampini   PetscFunctionBegin;
15339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
15345ac14e1cSStefano Zampini   if (ishypre) {
15355ac14e1cSStefano Zampini     if (isalpha) {
15369566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
15379566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15385ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
15395ac14e1cSStefano Zampini     } else {
15405ac14e1cSStefano Zampini       if (A) {
15419566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
15425ac14e1cSStefano Zampini       } else {
15435ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15445ac14e1cSStefano Zampini       }
15459566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
15465ac14e1cSStefano Zampini       jac->beta_Poisson = A;
15475ac14e1cSStefano Zampini     }
15485ac14e1cSStefano Zampini   } else {
15495ac14e1cSStefano Zampini     if (isalpha) {
15509566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15519566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
15525ac14e1cSStefano Zampini     } else {
15535ac14e1cSStefano Zampini       if (A) {
15549566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15559566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
15565ac14e1cSStefano Zampini       } else {
15579566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15585ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15595ac14e1cSStefano Zampini       }
15605ac14e1cSStefano Zampini     }
15615ac14e1cSStefano Zampini   }
15624cb006feSStefano Zampini   PetscFunctionReturn(0);
15634cb006feSStefano Zampini }
15644cb006feSStefano Zampini 
15654cb006feSStefano Zampini /*@
1566*f1580f4eSBarry Smith    PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
15674cb006feSStefano Zampini 
1568*f1580f4eSBarry Smith    Collective on pc
15694cb006feSStefano Zampini 
15704cb006feSStefano Zampini    Input Parameters:
15714cb006feSStefano Zampini +  pc - the preconditioning context
15724cb006feSStefano Zampini -  A - the matrix
15734cb006feSStefano Zampini 
15744cb006feSStefano Zampini    Level: intermediate
15754cb006feSStefano Zampini 
1576*f1580f4eSBarry Smith    Note:
157795452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
15784cb006feSStefano Zampini 
1579*f1580f4eSBarry Smith    Developer Note:
1580*f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1581*f1580f4eSBarry Smith 
1582*f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1583*f1580f4eSBarry Smith 
1584*f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
15854cb006feSStefano Zampini @*/
15869371c9d4SSatish Balay PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A) {
15874cb006feSStefano Zampini   PetscFunctionBegin;
15884cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15894cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
15904cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1591cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
15924cb006feSStefano Zampini   PetscFunctionReturn(0);
15934cb006feSStefano Zampini }
15944cb006feSStefano Zampini 
15954cb006feSStefano Zampini /*@
1596*f1580f4eSBarry Smith    PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
15974cb006feSStefano Zampini 
1598*f1580f4eSBarry Smith    Collective on pc
15994cb006feSStefano Zampini 
16004cb006feSStefano Zampini    Input Parameters:
16014cb006feSStefano Zampini +  pc - the preconditioning context
1602*f1580f4eSBarry Smith -  A - the matrix, or NULL to turn it off
16034cb006feSStefano Zampini 
16044cb006feSStefano Zampini    Level: intermediate
16054cb006feSStefano Zampini 
1606*f1580f4eSBarry Smith    Note:
160795452b02SPatrick Sanan    A should be obtained by discretizing the Poisson problem with linear finite elements.
16084cb006feSStefano Zampini 
1609*f1580f4eSBarry Smith    Developer Note:
1610*f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1611*f1580f4eSBarry Smith 
1612*f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1613*f1580f4eSBarry Smith 
1614*f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16154cb006feSStefano Zampini @*/
16169371c9d4SSatish Balay PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A) {
16174cb006feSStefano Zampini   PetscFunctionBegin;
16184cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16194cb006feSStefano Zampini   if (A) {
16204cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16214cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
16224cb006feSStefano Zampini   }
1623cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
16244cb006feSStefano Zampini   PetscFunctionReturn(0);
16254cb006feSStefano Zampini }
16264cb006feSStefano Zampini 
16279371c9d4SSatish Balay static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo) {
16284cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16294cb006feSStefano Zampini 
16304cb006feSStefano Zampini   PetscFunctionBegin;
16314cb006feSStefano Zampini   /* throw away any vector if already set */
16329566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
16339566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
16349566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
16359566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
16369566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
16379566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
16389566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
16395ac14e1cSStefano Zampini   jac->dim = 2;
16404cb006feSStefano Zampini   if (zzo) {
16419566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
16429566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
16435ac14e1cSStefano Zampini     jac->dim++;
16444cb006feSStefano Zampini   }
16454cb006feSStefano Zampini   PetscFunctionReturn(0);
16464cb006feSStefano Zampini }
16474cb006feSStefano Zampini 
16484cb006feSStefano Zampini /*@
1649*f1580f4eSBarry Smith    PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
16504cb006feSStefano Zampini 
1651*f1580f4eSBarry Smith    Collective on pc
16524cb006feSStefano Zampini 
16534cb006feSStefano Zampini    Input Parameters:
16544cb006feSStefano Zampini +  pc - the preconditioning context
16554cb006feSStefano Zampini -  ozz - vector representing (1,0,0) (or (1,0) in 2D)
16564cb006feSStefano Zampini -  zoz - vector representing (0,1,0) (or (0,1) in 2D)
16574cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
16584cb006feSStefano Zampini 
16594cb006feSStefano Zampini    Level: intermediate
16604cb006feSStefano Zampini 
1661*f1580f4eSBarry Smith    Developer Note:
1662*f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1663*f1580f4eSBarry Smith 
1664*f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16654cb006feSStefano Zampini @*/
16669371c9d4SSatish Balay PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo) {
16674cb006feSStefano Zampini   PetscFunctionBegin;
16684cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16694cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
16704cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
16714cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
16724cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
16734cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
16744cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1675cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
16764cb006feSStefano Zampini   PetscFunctionReturn(0);
16774cb006feSStefano Zampini }
16784cb006feSStefano Zampini 
16799371c9d4SSatish Balay static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior) {
1680be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1681be14dc20SKerry Key 
1682be14dc20SKerry Key   PetscFunctionBegin;
1683be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1684be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1685be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1686be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
1687be14dc20SKerry Key   PetscFunctionReturn(0);
1688be14dc20SKerry Key }
1689be14dc20SKerry Key 
1690be14dc20SKerry Key /*@
1691*f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1692be14dc20SKerry Key 
1693*f1580f4eSBarry Smith    Collective on pc
1694be14dc20SKerry Key 
1695be14dc20SKerry Key    Input Parameters:
1696be14dc20SKerry Key +  pc - the preconditioning context
1697be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1698be14dc20SKerry Key 
1699be14dc20SKerry Key    Level: intermediate
1700be14dc20SKerry Key 
1701be14dc20SKerry Key    Note:
1702*f1580f4eSBarry Smith    This calls `HYPRE_AMSSetInteriorNodes()`
1703*f1580f4eSBarry Smith 
1704*f1580f4eSBarry Smith    Developer Note:
1705*f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1706*f1580f4eSBarry Smith 
1707*f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1708be14dc20SKerry Key @*/
17099371c9d4SSatish Balay PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior) {
1710be14dc20SKerry Key   PetscFunctionBegin;
1711be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1712be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1713be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1714be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
1715be14dc20SKerry Key   PetscFunctionReturn(0);
1716be14dc20SKerry Key }
1717be14dc20SKerry Key 
17189371c9d4SSatish Balay static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) {
17194cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17204cb006feSStefano Zampini   Vec       tv;
17214cb006feSStefano Zampini   PetscInt  i;
17224cb006feSStefano Zampini 
17234cb006feSStefano Zampini   PetscFunctionBegin;
17244cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
17259566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
17269566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
17279566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
17285ac14e1cSStefano Zampini   jac->dim = dim;
17295ac14e1cSStefano Zampini 
17304cb006feSStefano Zampini   /* compute IJ vector for coordinates */
17319566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
17329566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
17339566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
17344cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
17354cb006feSStefano Zampini     PetscScalar *array;
17364cb006feSStefano Zampini     PetscInt     j;
17374cb006feSStefano Zampini 
17389566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
17399566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
17406ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
17419566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
17429566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
17434cb006feSStefano Zampini   }
17449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
17454cb006feSStefano Zampini   PetscFunctionReturn(0);
17464cb006feSStefano Zampini }
17474cb006feSStefano Zampini 
17489371c9d4SSatish Balay static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[]) {
174916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
175016d9e3a6SLisandro Dalcin 
175116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
175216d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
175316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
175416d9e3a6SLisandro Dalcin }
175516d9e3a6SLisandro Dalcin 
17569371c9d4SSatish Balay static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[]) {
175716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1758ace3abfcSBarry Smith   PetscBool flag;
175916d9e3a6SLisandro Dalcin 
176016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
176116d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
17629566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
17635f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
176416d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
176516d9e3a6SLisandro Dalcin   } else {
17669566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
176716d9e3a6SLisandro Dalcin   }
176816d9e3a6SLisandro Dalcin 
176916d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
177016d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
177116d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
177216d9e3a6SLisandro Dalcin 
17739566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
177416d9e3a6SLisandro Dalcin   if (flag) {
17759566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1776792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
177716d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
177816d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
177916d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
178016d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
178116d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
178216d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
178316d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
178416d9e3a6SLisandro Dalcin   }
17859566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1786db966c6cSHong Zhang   if (flag) {
17874e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
17884e3c431bSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64 bit indices");
17898bf83915SBarry Smith #endif
17909566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1791792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1792db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1793db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1794db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1795db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1796db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1797db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1798db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
1799db966c6cSHong Zhang     PetscFunctionReturn(0);
1800db966c6cSHong Zhang   }
18019566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
180216d9e3a6SLisandro Dalcin   if (flag) {
18039566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1804792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
180516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
180616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
180716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
180816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
180916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
181016d9e3a6SLisandro Dalcin     /* initialize */
181116d9e3a6SLisandro Dalcin     jac->nlevels            = 1;
18128966356dSPierre Jolivet     jac->threshold          = .1;
181316d9e3a6SLisandro Dalcin     jac->filter             = .1;
181416d9e3a6SLisandro Dalcin     jac->loadbal            = 0;
18152fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
18162fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
18172fa5cd67SKarl Rupp 
181816d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
181916d9e3a6SLisandro Dalcin     jac->symt = 0;
1820792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1821792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1822792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1823792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1824792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1825792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
182616d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
182716d9e3a6SLisandro Dalcin   }
18289566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
182916d9e3a6SLisandro Dalcin   if (flag) {
1830792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
183116d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
183216d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
183316d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
183416d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
18359566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
18369566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
183716d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
183816d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
183916d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
184016d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
184116d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
184216d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
184316d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
184416d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
18458f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
184616d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
184716d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
184816d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
184916d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
185016d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
18510f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
18526a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1853b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
18541810e44eSEike Mueller     jac->eu_level                                                = 0;
18551810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
18561810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1857589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
18580f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
185916d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
186016d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
186116d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
18620f1074feSSatish Balay     jac->interptype                       = 0;
1863589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1864589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1865589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1866589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1867589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
18680f1074feSSatish Balay     jac->agg_nl                           = 0;
18696ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
18700f1074feSSatish Balay     jac->pmax                             = 0;
18710f1074feSSatish Balay     jac->truncfactor                      = 0.0;
18720f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1873589dcaf0SStefano Zampini     jac->maxc                             = 9;
1874589dcaf0SStefano Zampini     jac->minc                             = 1;
187522e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
187622e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
187722e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
187822e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
187922e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
188022e51d31SStefano Zampini     jac->interp_refine                    = 0;
18818f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
18828f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
18836ea7df73SStefano Zampini     jac->rap2                             = 0;
18846ea7df73SStefano Zampini 
18856ea7df73SStefano Zampini     /* GPU defaults
18866ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
18876ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
18886ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
18896ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
18906ea7df73SStefano Zampini     jac->mod_rap2       = 1;
18916ea7df73SStefano Zampini     jac->coarsentype    = 8;
18926ea7df73SStefano Zampini     jac->relaxorder     = 0;
18936ea7df73SStefano Zampini     jac->interptype     = 6;
18946ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
18956ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
18966ea7df73SStefano Zampini     jac->agg_interptype = 7;
18976ea7df73SStefano Zampini #else
18986ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
18996ea7df73SStefano Zampini     jac->mod_rap2      = 0;
19006ea7df73SStefano Zampini #endif
1901792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
1902792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
1903792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
1904792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1905792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
1906792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
1907792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
1908792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
1909792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
1910792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
1911792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
1912792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
1913792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
1914792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
1915792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
1916792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
1917792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
1918792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
1919792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
19206ea7df73SStefano Zampini     /* GPU */
19216ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1922792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1923792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
1924792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
19256ea7df73SStefano Zampini #endif
19266ea7df73SStefano Zampini 
1927589dcaf0SStefano Zampini     /* AIR */
19286ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1929792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1930792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1931792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1932792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1933792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
19346ea7df73SStefano Zampini #endif
193516d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
193616d9e3a6SLisandro Dalcin   }
19379566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
19384cb006feSStefano Zampini   if (flag) {
19399566063dSJacob Faibussowitsch     PetscCall(HYPRE_AMSCreate(&jac->hsolver));
19404cb006feSStefano Zampini     pc->ops->setfromoptions   = PCSetFromOptions_HYPRE_AMS;
19414cb006feSStefano Zampini     pc->ops->view             = PCView_HYPRE_AMS;
19424cb006feSStefano Zampini     jac->destroy              = HYPRE_AMSDestroy;
19434cb006feSStefano Zampini     jac->setup                = HYPRE_AMSSetup;
19444cb006feSStefano Zampini     jac->solve                = HYPRE_AMSSolve;
19454cb006feSStefano Zampini     jac->coords[0]            = NULL;
19464cb006feSStefano Zampini     jac->coords[1]            = NULL;
19474cb006feSStefano Zampini     jac->coords[2]            = NULL;
1948be14dc20SKerry Key     jac->interior             = NULL;
19494cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
1950863406b8SStefano Zampini     jac->as_print             = 0;
1951863406b8SStefano Zampini     jac->as_max_iter          = 1;  /* used as a preconditioner */
1952863406b8SStefano Zampini     jac->as_tol               = 0.; /* used as a preconditioner */
19534cb006feSStefano Zampini     jac->ams_cycle_type       = 13;
19544cb006feSStefano Zampini     /* Smoothing options */
1955863406b8SStefano Zampini     jac->as_relax_type        = 2;
1956863406b8SStefano Zampini     jac->as_relax_times       = 1;
1957863406b8SStefano Zampini     jac->as_relax_weight      = 1.0;
1958863406b8SStefano Zampini     jac->as_omega             = 1.0;
19594cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1960863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
1961863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
19620bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
1963863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
1964863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
1965863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
19664cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1967863406b8SStefano Zampini     jac->as_amg_beta_opts[0]  = 10;
1968863406b8SStefano Zampini     jac->as_amg_beta_opts[1]  = 1;
19690bdd8552SBarry Smith     jac->as_amg_beta_opts[2]  = 6;
1970863406b8SStefano Zampini     jac->as_amg_beta_opts[3]  = 6;
1971863406b8SStefano Zampini     jac->as_amg_beta_opts[4]  = 4;
1972863406b8SStefano Zampini     jac->as_amg_beta_theta    = 0.25;
1973792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
1974792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
1975792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
1976792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
19779371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
1978792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1979863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1980863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
19819371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1982a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
1983792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
1984863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
1985863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
19869371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
1987a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
198823df4f25SStefano Zampini     /* Zero conductivity */
198923df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
199023df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
19914cb006feSStefano Zampini     PetscFunctionReturn(0);
19924cb006feSStefano Zampini   }
19939566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
1994863406b8SStefano Zampini   if (flag) {
19959566063dSJacob Faibussowitsch     PetscCall(HYPRE_ADSCreate(&jac->hsolver));
1996863406b8SStefano Zampini     pc->ops->setfromoptions   = PCSetFromOptions_HYPRE_ADS;
1997863406b8SStefano Zampini     pc->ops->view             = PCView_HYPRE_ADS;
1998863406b8SStefano Zampini     jac->destroy              = HYPRE_ADSDestroy;
1999863406b8SStefano Zampini     jac->setup                = HYPRE_ADSSetup;
2000863406b8SStefano Zampini     jac->solve                = HYPRE_ADSSolve;
2001863406b8SStefano Zampini     jac->coords[0]            = NULL;
2002863406b8SStefano Zampini     jac->coords[1]            = NULL;
2003863406b8SStefano Zampini     jac->coords[2]            = NULL;
2004863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2005863406b8SStefano Zampini     jac->as_print             = 0;
2006863406b8SStefano Zampini     jac->as_max_iter          = 1;  /* used as a preconditioner */
2007863406b8SStefano Zampini     jac->as_tol               = 0.; /* used as a preconditioner */
2008863406b8SStefano Zampini     jac->ads_cycle_type       = 13;
2009863406b8SStefano Zampini     /* Smoothing options */
2010863406b8SStefano Zampini     jac->as_relax_type        = 2;
2011863406b8SStefano Zampini     jac->as_relax_times       = 1;
2012863406b8SStefano Zampini     jac->as_relax_weight      = 1.0;
2013863406b8SStefano Zampini     jac->as_omega             = 1.0;
2014863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2015863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2016863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2017863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2018863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2019863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2020863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2021863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2022863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2023863406b8SStefano Zampini     jac->as_amg_beta_opts[0]  = 10;
2024863406b8SStefano Zampini     jac->as_amg_beta_opts[1]  = 1;
2025863406b8SStefano Zampini     jac->as_amg_beta_opts[2]  = 6;
2026863406b8SStefano Zampini     jac->as_amg_beta_opts[3]  = 6;
2027863406b8SStefano Zampini     jac->as_amg_beta_opts[4]  = 4;
2028863406b8SStefano Zampini     jac->as_amg_beta_theta    = 0.25;
2029792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2030792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2031792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2032792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
20339371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2034792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2035863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2036863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2037863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
20389371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2039a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2040792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2041863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2042863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
20439371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2044a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
2045863406b8SStefano Zampini     PetscFunctionReturn(0);
2046863406b8SStefano Zampini   }
20479566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
20482fa5cd67SKarl Rupp 
20490298fd71SBarry Smith   jac->hypre_type = NULL;
205098921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
205116d9e3a6SLisandro Dalcin }
205216d9e3a6SLisandro Dalcin 
205316d9e3a6SLisandro Dalcin /*
205416d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
205516d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
205616d9e3a6SLisandro Dalcin */
20579371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject) {
20584ddd07fcSJed Brown   PetscInt    indx;
2059db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2060ace3abfcSBarry Smith   PetscBool   flg;
206116d9e3a6SLisandro Dalcin 
206216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2063d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2064dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
206516d9e3a6SLisandro Dalcin   if (flg) {
20669566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
206702a17cd4SBarry Smith   } else {
20689566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
206916d9e3a6SLisandro Dalcin   }
2070dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2071d0609cedSBarry Smith   PetscOptionsHeadEnd();
207216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
207316d9e3a6SLisandro Dalcin }
207416d9e3a6SLisandro Dalcin 
207516d9e3a6SLisandro Dalcin /*@C
207616d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
207716d9e3a6SLisandro Dalcin 
207816d9e3a6SLisandro Dalcin    Input Parameters:
207916d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2080db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
208116d9e3a6SLisandro Dalcin 
2082*f1580f4eSBarry Smith    Options Database Key:
2083db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
208416d9e3a6SLisandro Dalcin 
208516d9e3a6SLisandro Dalcin    Level: intermediate
208616d9e3a6SLisandro Dalcin 
2087*f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
208816d9e3a6SLisandro Dalcin @*/
20899371c9d4SSatish Balay PetscErrorCode PCHYPRESetType(PC pc, const char name[]) {
209016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
20910700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
209216d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2093cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
209416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
209516d9e3a6SLisandro Dalcin }
209616d9e3a6SLisandro Dalcin 
209716d9e3a6SLisandro Dalcin /*@C
209816d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
209916d9e3a6SLisandro Dalcin 
210016d9e3a6SLisandro Dalcin    Input Parameter:
210116d9e3a6SLisandro Dalcin .     pc - the preconditioner context
210216d9e3a6SLisandro Dalcin 
210316d9e3a6SLisandro Dalcin    Output Parameter:
2104db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
210516d9e3a6SLisandro Dalcin 
210616d9e3a6SLisandro Dalcin    Level: intermediate
210716d9e3a6SLisandro Dalcin 
2108*f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
210916d9e3a6SLisandro Dalcin @*/
21109371c9d4SSatish Balay PetscErrorCode PCHYPREGetType(PC pc, const char *name[]) {
211116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21120700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
211316d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2114cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
211516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
211616d9e3a6SLisandro Dalcin }
211716d9e3a6SLisandro Dalcin 
2118db6f9c32SMark Adams /*@C
2119*f1580f4eSBarry Smith    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2120db6f9c32SMark Adams 
2121*f1580f4eSBarry Smith    Logically Collective on pc
2122db6f9c32SMark Adams 
2123db6f9c32SMark Adams    Input Parameters:
2124db6f9c32SMark Adams +  pc - the hypre context
2125db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2126db6f9c32SMark Adams 
2127db6f9c32SMark Adams    Options Database Key:
212867b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2129db6f9c32SMark Adams 
2130db6f9c32SMark Adams    Level: intermediate
2131db6f9c32SMark Adams 
2132*f1580f4eSBarry Smith    Developer Note:
2133*f1580f4eSBarry Smith    How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2134db6f9c32SMark Adams 
2135*f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2136db6f9c32SMark Adams @*/
21379371c9d4SSatish Balay PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[]) {
2138db6f9c32SMark Adams   PetscFunctionBegin;
2139db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2140cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
2141db6f9c32SMark Adams   PetscFunctionReturn(0);
2142db6f9c32SMark Adams }
2143db6f9c32SMark Adams 
2144db6f9c32SMark Adams /*@C
2145*f1580f4eSBarry Smith    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2146db6f9c32SMark Adams 
2147db6f9c32SMark Adams    Not Collective
2148db6f9c32SMark Adams 
2149db6f9c32SMark Adams    Input Parameter:
2150db6f9c32SMark Adams .  pc - the multigrid context
2151db6f9c32SMark Adams 
2152db6f9c32SMark Adams    Output Parameter:
2153db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2154db6f9c32SMark Adams 
2155db6f9c32SMark Adams    Level: intermediate
2156db6f9c32SMark Adams 
2157*f1580f4eSBarry Smith .seealso: `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2158db6f9c32SMark Adams @*/
21599371c9d4SSatish Balay PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[]) {
2160db6f9c32SMark Adams   PetscFunctionBegin;
2161db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2162cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
2163db6f9c32SMark Adams   PetscFunctionReturn(0);
2164db6f9c32SMark Adams }
2165db6f9c32SMark Adams 
216616d9e3a6SLisandro Dalcin /*MC
2167*f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
216816d9e3a6SLisandro Dalcin 
216916d9e3a6SLisandro Dalcin    Options Database Keys:
2170db966c6cSHong Zhang +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2171*f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2172*f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2173ead8c081SBarry Smith -   Many others, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX preconditioner
217416d9e3a6SLisandro Dalcin 
217516d9e3a6SLisandro Dalcin    Level: intermediate
217616d9e3a6SLisandro Dalcin 
217795452b02SPatrick Sanan    Notes:
2178*f1580f4eSBarry Smith     Apart from pc_hypre_type (for which there is `PCHYPRESetType()`),
217916d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
218016d9e3a6SLisandro Dalcin           or with PetscOptionsSetValue(), there are no functions to set them)
218116d9e3a6SLisandro Dalcin 
2182c231f9e3SBarryFSmith           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
21830f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
21840f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2185c231f9e3SBarryFSmith           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
21868f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
21870f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
21880f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
218916d9e3a6SLisandro Dalcin 
21900f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
21910f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
21920f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
219316d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
219416d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
219516d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
219616d9e3a6SLisandro Dalcin 
219716d9e3a6SLisandro Dalcin           2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
219816d9e3a6SLisandro Dalcin           -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
219916d9e3a6SLisandro Dalcin 
2200*f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2201fdd15c9aSJunchao Zhang           the following two options:
22020b1a5bd9SEric Chamberland 
2203*f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2204*f1580f4eSBarry Smith 
2205*f1580f4eSBarry Smith           For `PCHYPRE` type of ams or ads auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2206*f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2207*f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
2208*f1580f4eSBarry Smith 
2209*f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
22109e5bc791SBarry Smith 
2211ead8c081SBarry Smith    GPU Notes:
2212ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2213*f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2214ead8c081SBarry Smith 
2215ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2216*f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2217ead8c081SBarry Smith 
2218*f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2219*f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2220*f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
222116d9e3a6SLisandro Dalcin M*/
222216d9e3a6SLisandro Dalcin 
22239371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc) {
222416d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
222516d9e3a6SLisandro Dalcin 
222616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22279566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &jac));
22282fa5cd67SKarl Rupp 
222916d9e3a6SLisandro Dalcin   pc->data                = jac;
22308695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
223116d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
223216d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
223316d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
223416d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
223516d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
22369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
22379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
22389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
22399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
22409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
22419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
22429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2243be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
22449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
22459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
22469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
22476ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22486ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP)
22499566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
22506ea7df73SStefano Zampini #endif
22516ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA)
22529566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
22536ea7df73SStefano Zampini #endif
22546ea7df73SStefano Zampini #endif
225516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
225616d9e3a6SLisandro Dalcin }
2257ebc551c0SBarry Smith 
2258ebc551c0SBarry Smith typedef struct {
225968326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2260f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
22619e5bc791SBarry Smith 
22629e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
22634ddd07fcSJed Brown   PetscInt  its;
22649e5bc791SBarry Smith   double    tol;
22654ddd07fcSJed Brown   PetscInt  relax_type;
22664ddd07fcSJed Brown   PetscInt  rap_type;
22674ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
22684ddd07fcSJed Brown   PetscInt  max_levels;
22690be8cd64Sftrigaux   PetscInt  skip_relax;
22700be8cd64Sftrigaux   PetscBool print_statistics;
2271ebc551c0SBarry Smith } PC_PFMG;
2272ebc551c0SBarry Smith 
22739371c9d4SSatish Balay PetscErrorCode PCDestroy_PFMG(PC pc) {
2274f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2275ebc551c0SBarry Smith 
2276ebc551c0SBarry Smith   PetscFunctionBegin;
2277792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
22789566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
22799566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2280ebc551c0SBarry Smith   PetscFunctionReturn(0);
2281ebc551c0SBarry Smith }
2282ebc551c0SBarry Smith 
22839e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
22849e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
22859e5bc791SBarry Smith 
22869371c9d4SSatish Balay PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer) {
2287ace3abfcSBarry Smith   PetscBool iascii;
2288f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2289ebc551c0SBarry Smith 
2290ebc551c0SBarry Smith   PetscFunctionBegin;
22919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
22929e5bc791SBarry Smith   if (iascii) {
22939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
229463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
22959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
22969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
22979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
229863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
229963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
23000be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
23019e5bc791SBarry Smith   }
2302ebc551c0SBarry Smith   PetscFunctionReturn(0);
2303ebc551c0SBarry Smith }
2304ebc551c0SBarry Smith 
23059371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject) {
2306f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2307ebc551c0SBarry Smith 
2308ebc551c0SBarry Smith   PetscFunctionBegin;
2309d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
23100be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
23119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2312792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
23139566063dSJacob 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));
2314792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
23159566063dSJacob 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));
2316792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
23179e5bc791SBarry Smith 
23189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2319792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
23203b46a515SGlenn Hammond 
23219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2322792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2323dd39110bSPierre 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));
2324792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2325dd39110bSPierre 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));
2326792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
23270be8cd64Sftrigaux   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));
23280be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2329d0609cedSBarry Smith   PetscOptionsHeadEnd();
2330ebc551c0SBarry Smith   PetscFunctionReturn(0);
2331ebc551c0SBarry Smith }
2332ebc551c0SBarry Smith 
23339371c9d4SSatish Balay PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y) {
2334f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2335d9ca1df4SBarry Smith   PetscScalar       *yy;
2336d9ca1df4SBarry Smith   const PetscScalar *xx;
23374ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
23382cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
233968326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2340f91d8e95SBarry Smith 
2341f91d8e95SBarry Smith   PetscFunctionBegin;
23429566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
23439566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
23442cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2345f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2346f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2347f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
23482cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
23492cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
23502cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
23512cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
23522cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
23532cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2354f91d8e95SBarry Smith 
2355f91d8e95SBarry Smith   /* copy x values over to hypre */
2356792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
23579566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2358792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
23599566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2360792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2361792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2362f91d8e95SBarry Smith 
2363f91d8e95SBarry Smith   /* copy solution values back to PETSc */
23649566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2365792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
23669566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2367f91d8e95SBarry Smith   PetscFunctionReturn(0);
2368f91d8e95SBarry Smith }
2369f91d8e95SBarry Smith 
23709371c9d4SSatish Balay 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) {
23719e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
23722cf14000SStefano Zampini   HYPRE_Int oits;
23739e5bc791SBarry Smith 
23749e5bc791SBarry Smith   PetscFunctionBegin;
23759566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2376792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2377792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
23789e5bc791SBarry Smith 
23799566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2380792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
23819e5bc791SBarry Smith   *outits = oits;
23829e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
23839e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2384792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2385792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
23869e5bc791SBarry Smith   PetscFunctionReturn(0);
23879e5bc791SBarry Smith }
23889e5bc791SBarry Smith 
23899371c9d4SSatish Balay PetscErrorCode PCSetUp_PFMG(PC pc) {
23903a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
23913a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2392ace3abfcSBarry Smith   PetscBool        flg;
23933a32d3dbSGlenn Hammond 
23943a32d3dbSGlenn Hammond   PetscFunctionBegin;
23959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
239628b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
23973a32d3dbSGlenn Hammond 
23983a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2399792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2400792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
24010be8cd64Sftrigaux 
24020be8cd64Sftrigaux   // Print Hypre statistics about the solve process
24030be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
24040be8cd64Sftrigaux 
24050be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
24060be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24070be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24080be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24090be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24100be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
24110be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
24120be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24130be8cd64Sftrigaux 
2414792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2415792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
24163a32d3dbSGlenn Hammond   PetscFunctionReturn(0);
24173a32d3dbSGlenn Hammond }
24183a32d3dbSGlenn Hammond 
2419ebc551c0SBarry Smith /*MC
2420ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2421ebc551c0SBarry Smith 
2422*f1580f4eSBarry Smith    Options Database Keys:
242367b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
242467b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
242567b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
242667b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
24279e5bc791SBarry 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
24280be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2429*f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2430*f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2431*f1580f4eSBarry Smith 
2432*f1580f4eSBarry Smith    Level: advanced
2433f91d8e95SBarry Smith 
243495452b02SPatrick Sanan    Notes:
243595452b02SPatrick Sanan    This is for CELL-centered descretizations
24369e5bc791SBarry Smith 
2437*f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
24389e5bc791SBarry Smith 
2439*f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2440*f1580f4eSBarry Smith 
2441*f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2442*f1580f4eSBarry Smith 
2443*f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2444*f1580f4eSBarry Smith 
2445*f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2446ebc551c0SBarry Smith M*/
2447ebc551c0SBarry Smith 
24489371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc) {
2449ebc551c0SBarry Smith   PC_PFMG *ex;
2450ebc551c0SBarry Smith 
2451ebc551c0SBarry Smith   PetscFunctionBegin;
24529371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
245368326731SBarry Smith   pc->data = ex;
2454ebc551c0SBarry Smith 
24559e5bc791SBarry Smith   ex->its              = 1;
24569e5bc791SBarry Smith   ex->tol              = 1.e-8;
24579e5bc791SBarry Smith   ex->relax_type       = 1;
24589e5bc791SBarry Smith   ex->rap_type         = 0;
24599e5bc791SBarry Smith   ex->num_pre_relax    = 1;
24609e5bc791SBarry Smith   ex->num_post_relax   = 1;
24613b46a515SGlenn Hammond   ex->max_levels       = 0;
24620be8cd64Sftrigaux   ex->skip_relax       = 0;
24630be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
24649e5bc791SBarry Smith 
2465ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2466ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2467ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2468f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
24699e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
247068326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
24712fa5cd67SKarl Rupp 
24729566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2473792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
2474ebc551c0SBarry Smith   PetscFunctionReturn(0);
2475ebc551c0SBarry Smith }
2476d851a50bSGlenn Hammond 
2477d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2478d851a50bSGlenn Hammond typedef struct {
2479d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2480d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2481d851a50bSGlenn Hammond 
2482d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
24834ddd07fcSJed Brown   PetscInt its;
2484d851a50bSGlenn Hammond   double   tol;
24854ddd07fcSJed Brown   PetscInt relax_type;
24864ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2487d851a50bSGlenn Hammond } PC_SysPFMG;
2488d851a50bSGlenn Hammond 
24899371c9d4SSatish Balay PetscErrorCode PCDestroy_SysPFMG(PC pc) {
2490d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2491d851a50bSGlenn Hammond 
2492d851a50bSGlenn Hammond   PetscFunctionBegin;
2493792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
24949566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
24959566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2496d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2497d851a50bSGlenn Hammond }
2498d851a50bSGlenn Hammond 
2499d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2500d851a50bSGlenn Hammond 
25019371c9d4SSatish Balay PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer) {
2502ace3abfcSBarry Smith   PetscBool   iascii;
2503d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2504d851a50bSGlenn Hammond 
2505d851a50bSGlenn Hammond   PetscFunctionBegin;
25069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2507d851a50bSGlenn Hammond   if (iascii) {
25089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
250963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
25109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
25119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
251263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2513d851a50bSGlenn Hammond   }
2514d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2515d851a50bSGlenn Hammond }
2516d851a50bSGlenn Hammond 
25179371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject) {
2518d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2519ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2520d851a50bSGlenn Hammond 
2521d851a50bSGlenn Hammond   PetscFunctionBegin;
2522d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
25239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
252448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
25259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2526792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
25279566063dSJacob 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));
2528792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
25299566063dSJacob 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));
2530792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2531d851a50bSGlenn Hammond 
25329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2533792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2534dd39110bSPierre 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));
2535792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2536d0609cedSBarry Smith   PetscOptionsHeadEnd();
2537d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2538d851a50bSGlenn Hammond }
2539d851a50bSGlenn Hammond 
25409371c9d4SSatish Balay PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y) {
2541d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2542d9ca1df4SBarry Smith   PetscScalar       *yy;
2543d9ca1df4SBarry Smith   const PetscScalar *xx;
25444ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
25452cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2546d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
25474ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
25484ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
25494ddd07fcSJed Brown   PetscInt           part     = 0;
25504ddd07fcSJed Brown   PetscInt           size;
25514ddd07fcSJed Brown   PetscInt           i;
2552d851a50bSGlenn Hammond 
2553d851a50bSGlenn Hammond   PetscFunctionBegin;
25549566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
25559566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
25562cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2557d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2558d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2559d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
25602cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
25612cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
25622cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
25632cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
25642cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
25652cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2566d851a50bSGlenn Hammond 
2567d851a50bSGlenn Hammond   size = 1;
25682fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
25692fa5cd67SKarl Rupp 
2570d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2571d851a50bSGlenn Hammond   if (ordering) {
2572792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
25739566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2574792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
25759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2576792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2577792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2578792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2579d851a50bSGlenn Hammond 
2580d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
25819566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2582792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
25839566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2584a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2585d851a50bSGlenn Hammond     PetscScalar *z;
25864ddd07fcSJed Brown     PetscInt     j, k;
2587d851a50bSGlenn Hammond 
25889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2589792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
25909566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2591d851a50bSGlenn Hammond 
2592d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2593d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2594d851a50bSGlenn Hammond       k = i * nvars;
25952fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2596d851a50bSGlenn Hammond     }
2597792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
25989566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2599792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2600792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2601d851a50bSGlenn Hammond 
2602d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26039566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2604792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2605d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2606d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2607d851a50bSGlenn Hammond       k = i * nvars;
26082fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2609d851a50bSGlenn Hammond     }
26109566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
26119566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2612d851a50bSGlenn Hammond   }
2613d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2614d851a50bSGlenn Hammond }
2615d851a50bSGlenn Hammond 
26169371c9d4SSatish Balay 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) {
2617d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
26182cf14000SStefano Zampini   HYPRE_Int   oits;
2619d851a50bSGlenn Hammond 
2620d851a50bSGlenn Hammond   PetscFunctionBegin;
26219566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2622792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2623792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
26249566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2625792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2626d851a50bSGlenn Hammond   *outits = oits;
2627d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2628d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2629792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2630792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
2631d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2632d851a50bSGlenn Hammond }
2633d851a50bSGlenn Hammond 
26349371c9d4SSatish Balay PetscErrorCode PCSetUp_SysPFMG(PC pc) {
2635d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2636d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2637ace3abfcSBarry Smith   PetscBool         flg;
2638d851a50bSGlenn Hammond 
2639d851a50bSGlenn Hammond   PetscFunctionBegin;
26409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
264128b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2642d851a50bSGlenn Hammond 
2643d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2644792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2645792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2646792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2647792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2648d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2649d851a50bSGlenn Hammond }
2650d851a50bSGlenn Hammond 
2651d851a50bSGlenn Hammond /*MC
2652*f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2653d851a50bSGlenn Hammond 
2654d851a50bSGlenn Hammond    Level: advanced
2655d851a50bSGlenn Hammond 
2656*f1580f4eSBarry Smith    Options Database Keys:
265767b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
265867b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
265967b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
266067b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
266167b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2662d851a50bSGlenn Hammond 
266395452b02SPatrick Sanan    Notes:
2664*f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2665*f1580f4eSBarry Smith 
2666*f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2667*f1580f4eSBarry Smith 
266895452b02SPatrick Sanan    This is for CELL-centered descretizations
2669d851a50bSGlenn Hammond 
2670*f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2671d851a50bSGlenn Hammond 
2672*f1580f4eSBarry 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`.
2673*f1580f4eSBarry Smith 
2674*f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2675d851a50bSGlenn Hammond M*/
2676d851a50bSGlenn Hammond 
26779371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc) {
2678d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2679d851a50bSGlenn Hammond 
2680d851a50bSGlenn Hammond   PetscFunctionBegin;
26819371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2682d851a50bSGlenn Hammond   pc->data = ex;
2683d851a50bSGlenn Hammond 
2684d851a50bSGlenn Hammond   ex->its            = 1;
2685d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2686d851a50bSGlenn Hammond   ex->relax_type     = 1;
2687d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2688d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2689d851a50bSGlenn Hammond 
2690d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2691d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2692d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2693d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2694d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2695d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
26962fa5cd67SKarl Rupp 
26979566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2698792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2699d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2700d851a50bSGlenn Hammond }
27011c188c59Sftrigaux 
2702*f1580f4eSBarry Smith /* PC SMG */
27031c188c59Sftrigaux typedef struct {
27041c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
27051c188c59Sftrigaux   HYPRE_StructSolver hsolver;
27061c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
27071c188c59Sftrigaux   double             tol;
27081c188c59Sftrigaux   PetscBool          print_statistics;
27091c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
27101c188c59Sftrigaux } PC_SMG;
27111c188c59Sftrigaux 
27129371c9d4SSatish Balay PetscErrorCode PCDestroy_SMG(PC pc) {
27131c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
27141c188c59Sftrigaux 
27151c188c59Sftrigaux   PetscFunctionBegin;
27161c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
27171c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
27181c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
27191c188c59Sftrigaux   PetscFunctionReturn(0);
27201c188c59Sftrigaux }
27211c188c59Sftrigaux 
27229371c9d4SSatish Balay PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer) {
27231c188c59Sftrigaux   PetscBool iascii;
27241c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
27251c188c59Sftrigaux 
27261c188c59Sftrigaux   PetscFunctionBegin;
27271c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
27281c188c59Sftrigaux   if (iascii) {
27291c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
27301c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27311c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27321c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
27331c188c59Sftrigaux   }
27341c188c59Sftrigaux   PetscFunctionReturn(0);
27351c188c59Sftrigaux }
27361c188c59Sftrigaux 
27379371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject) {
27381c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
27391c188c59Sftrigaux 
27401c188c59Sftrigaux   PetscFunctionBegin;
27411c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
27421c188c59Sftrigaux 
27431c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
27441c188c59Sftrigaux   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));
27451c188c59Sftrigaux   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));
27461c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
27471c188c59Sftrigaux 
27481c188c59Sftrigaux   PetscOptionsHeadEnd();
27491c188c59Sftrigaux   PetscFunctionReturn(0);
27501c188c59Sftrigaux }
27511c188c59Sftrigaux 
27529371c9d4SSatish Balay PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y) {
27531c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
27541c188c59Sftrigaux   PetscScalar       *yy;
27551c188c59Sftrigaux   const PetscScalar *xx;
27561c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
27571c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
27581c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
27591c188c59Sftrigaux 
27601c188c59Sftrigaux   PetscFunctionBegin;
27611c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
27621c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
27631c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
27641c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
27651c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
27661c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
27671c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
27681c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
27691c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
27701c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
27711c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
27721c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
27731c188c59Sftrigaux 
27741c188c59Sftrigaux   /* copy x values over to hypre */
27751c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
27761c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
27771c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
27781c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
27791c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
27801c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
27811c188c59Sftrigaux 
27821c188c59Sftrigaux   /* copy solution values back to PETSc */
27831c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
27841c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
27851c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
27861c188c59Sftrigaux   PetscFunctionReturn(0);
27871c188c59Sftrigaux }
27881c188c59Sftrigaux 
27899371c9d4SSatish Balay 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) {
27901c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
27911c188c59Sftrigaux   HYPRE_Int oits;
27921c188c59Sftrigaux 
27931c188c59Sftrigaux   PetscFunctionBegin;
27941c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
27951c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
27961c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
27971c188c59Sftrigaux 
27981c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
27991c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
28001c188c59Sftrigaux   *outits = oits;
28011c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
28021c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
28031c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
28041c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
28051c188c59Sftrigaux   PetscFunctionReturn(0);
28061c188c59Sftrigaux }
28071c188c59Sftrigaux 
28089371c9d4SSatish Balay PetscErrorCode PCSetUp_SMG(PC pc) {
28091c188c59Sftrigaux   PetscInt         i, dim;
28101c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
28111c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28121c188c59Sftrigaux   PetscBool        flg;
28131c188c59Sftrigaux   DMBoundaryType   p[3];
28141c188c59Sftrigaux   PetscInt         M[3];
28151c188c59Sftrigaux 
28161c188c59Sftrigaux   PetscFunctionBegin;
28171c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
28181c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
28191c188c59Sftrigaux 
28201c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
28211c188c59Sftrigaux   // Check if power of 2 in periodic directions
28221c188c59Sftrigaux   for (i = 0; i < dim; i++) {
28231c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
28241c188c59Sftrigaux       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]);
28251c188c59Sftrigaux     }
28261c188c59Sftrigaux   }
28271c188c59Sftrigaux 
28281c188c59Sftrigaux   /* create the hypre solver object and set its information */
28291c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
28301c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
28311c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
28321c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
28331c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28341c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28351c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
28361c188c59Sftrigaux 
28371c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
28381c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
28391c188c59Sftrigaux   PetscFunctionReturn(0);
28401c188c59Sftrigaux }
28411c188c59Sftrigaux 
28421c188c59Sftrigaux /*MC
28435cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
28441c188c59Sftrigaux 
28451c188c59Sftrigaux    Level: advanced
28461c188c59Sftrigaux 
2847*f1580f4eSBarry Smith    Options Database Keys:
28485cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
28495cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
28505cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
28515cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
28521c188c59Sftrigaux 
28531c188c59Sftrigaux    Notes:
28541c188c59Sftrigaux    This is for CELL-centered descretizations
28551c188c59Sftrigaux 
28565cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
28571c188c59Sftrigaux 
2858*f1580f4eSBarry 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`.
2859*f1580f4eSBarry Smith 
2860*f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
2861*f1580f4eSBarry Smith 
2862*f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
28631c188c59Sftrigaux M*/
28641c188c59Sftrigaux 
28659371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc) {
28661c188c59Sftrigaux   PC_SMG *ex;
28671c188c59Sftrigaux 
28681c188c59Sftrigaux   PetscFunctionBegin;
28699371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
28701c188c59Sftrigaux   pc->data = ex;
28711c188c59Sftrigaux 
28721c188c59Sftrigaux   ex->its            = 1;
28731c188c59Sftrigaux   ex->tol            = 1.e-8;
28741c188c59Sftrigaux   ex->num_pre_relax  = 1;
28751c188c59Sftrigaux   ex->num_post_relax = 1;
28761c188c59Sftrigaux 
28771c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
28781c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
28791c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
28801c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
28811c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
28821c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
28831c188c59Sftrigaux 
28841c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28851c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
28861c188c59Sftrigaux   PetscFunctionReturn(0);
28871c188c59Sftrigaux }
2888