xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 0fdf79fb08699bf9be0aa4d8ba0185e387a216c8)
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 
147d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetSolver(PC pc, HYPRE_Solver *hsolver)
148d71ae5a4SJacob Faibussowitsch {
149d2128fa2SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
150d2128fa2SBarry Smith 
151d2128fa2SBarry Smith   PetscFunctionBegin;
152d2128fa2SBarry Smith   *hsolver = jac->hsolver;
153d2128fa2SBarry Smith   PetscFunctionReturn(0);
154d2128fa2SBarry Smith }
15516d9e3a6SLisandro Dalcin 
156fd2dd295SFande Kong /*
1578a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1588a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1598a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
160fd2dd295SFande Kong */
161d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[])
162d71ae5a4SJacob Faibussowitsch {
1638a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1648a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1658a2c336bSFande Kong   PetscInt             num_levels, l;
1668a2c336bSFande Kong   Mat                 *mattmp;
1678a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1688a2c336bSFande Kong 
1698a2c336bSFande Kong   PetscFunctionBegin;
1709566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1715f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1728a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1748a2c336bSFande Kong   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)(jac->hsolver));
1758a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1769566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[num_levels - 1 - l])));
1778a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1788a2c336bSFande Kong     A_array[l] = NULL;
1798a2c336bSFande Kong   }
1808a2c336bSFande Kong   *nlevels   = num_levels;
1818a2c336bSFande Kong   *operators = mattmp;
1828a2c336bSFande Kong   PetscFunctionReturn(0);
1838a2c336bSFande Kong }
1848a2c336bSFande Kong 
185fd2dd295SFande Kong /*
1868a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1878a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1888a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
189fd2dd295SFande Kong */
190d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[])
191d71ae5a4SJacob Faibussowitsch {
1928a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1938a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1948a2c336bSFande Kong   PetscInt             num_levels, l;
1958a2c336bSFande Kong   Mat                 *mattmp;
1968a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1978a2c336bSFande Kong 
1988a2c336bSFande Kong   PetscFunctionBegin;
1999566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
2005f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
2018a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
2029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
2038a2c336bSFande Kong   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)(jac->hsolver));
2048a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
2059566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[l - 1])));
2068a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
2078a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
2088a2c336bSFande Kong   }
2098a2c336bSFande Kong   *nlevels        = num_levels;
2108a2c336bSFande Kong   *interpolations = mattmp;
2118a2c336bSFande Kong   PetscFunctionReturn(0);
2128a2c336bSFande Kong }
2138a2c336bSFande Kong 
214ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
215d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
216d71ae5a4SJacob Faibussowitsch {
217ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
218ce6a8a0dSJed Brown   PetscInt  i;
219ce6a8a0dSJed Brown 
2209d678128SJed Brown   PetscFunctionBegin;
22148a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2229566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2259d678128SJed Brown   jac->n_hmnull = 0;
226ce6a8a0dSJed Brown   PetscFunctionReturn(0);
227ce6a8a0dSJed Brown }
228ce6a8a0dSJed Brown 
229d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
230d71ae5a4SJacob Faibussowitsch {
23116d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
23249a781f5SStefano Zampini   Mat_HYPRE         *hjac;
23316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
23416d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
23549a781f5SStefano Zampini   PetscBool          ishypre;
23616d9e3a6SLisandro Dalcin 
23716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23848a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2395f5c5b43SBarry Smith 
2409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
24149a781f5SStefano Zampini   if (!ishypre) {
2429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
2439566063dSJacob Faibussowitsch     PetscCall(MatConvert(pc->pmat, MATHYPRE, MAT_INITIAL_MATRIX, &jac->hpmat));
24449a781f5SStefano Zampini   } else {
2459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
24749a781f5SStefano Zampini     jac->hpmat = pc->pmat;
24816d9e3a6SLisandro Dalcin   }
2496ea7df73SStefano Zampini   /* allow debug */
2509566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
25149a781f5SStefano Zampini   hjac = (Mat_HYPRE *)(jac->hpmat->data);
2525f5c5b43SBarry Smith 
25316d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25416d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2555272c319SBarry Smith     MatNullSpace mnull;
2565272c319SBarry Smith     PetscBool    has_const;
25749a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2585272c319SBarry Smith     const Vec   *vecs;
2595272c319SBarry Smith 
2609566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
261792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2629566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2635272c319SBarry Smith     if (mnull) {
2649566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2659566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2685272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2699566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2709566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
271792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2725272c319SBarry Smith       }
2735272c319SBarry Smith       if (has_const) {
2749566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2759566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2769566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2779566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2789566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
279792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2805272c319SBarry Smith         nvec++;
2815272c319SBarry Smith       }
282792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2835272c319SBarry Smith       jac->n_hmnull = nvec;
2845272c319SBarry Smith     }
2854cb006feSStefano Zampini   }
286863406b8SStefano Zampini 
2874cb006feSStefano Zampini   /* special case for AMS */
2884cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2895ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
2905ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2916bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
292f1580f4eSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the edge constant vectors via PCHYPRESetEdgeConstantVectors() or the interpolation matrix via PCHYPRESetInterpolations()");
2936bf688a0SCe Qin     }
29448a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
2955ac14e1cSStefano Zampini     if (jac->constants[0]) {
2965ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
297792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
298792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
29948a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
300792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
3015ac14e1cSStefano Zampini     }
3025ac14e1cSStefano Zampini     if (jac->coords[0]) {
3035ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3045ac14e1cSStefano Zampini       coords[0] = NULL;
3055ac14e1cSStefano Zampini       coords[1] = NULL;
3065ac14e1cSStefano Zampini       coords[2] = NULL;
307792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
308792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
309792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
310792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3115ac14e1cSStefano Zampini     }
3125f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3135ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
314792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
315792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3165ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3175ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->alpha_Poisson->data);
318792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
319792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3205ac14e1cSStefano Zampini     }
3215ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3235ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3245ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->beta_Poisson->data);
325792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
326792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
327be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
328be14dc20SKerry Key       if (jac->interior) {
329be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
330be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
331be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
332be14dc20SKerry Key       } else {
333be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
334be14dc20SKerry Key       }
3355ac14e1cSStefano Zampini     }
3366bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3376bf688a0SCe Qin       PetscInt           i;
3386bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3396bf688a0SCe Qin       if (jac->ND_PiFull) {
3406bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
341792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3426bf688a0SCe Qin       } else {
3436bf688a0SCe Qin         nd_parcsrfull = NULL;
3446bf688a0SCe Qin       }
3456bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3466bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3476bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
348792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3496bf688a0SCe Qin         } else {
3506bf688a0SCe Qin           nd_parcsr[i] = NULL;
3516bf688a0SCe Qin         }
3526bf688a0SCe Qin       }
353792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3546bf688a0SCe Qin     }
3554cb006feSStefano Zampini   }
356863406b8SStefano Zampini   /* special case for ADS */
357863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3585ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3595ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3606bf688a0SCe Qin     if (!jac->coords[0] && !((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])))) {
3616bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3629371c9d4SSatish Balay     } else PetscCheck(jac->coords[1] && jac->coords[2], PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner has been designed for three dimensional problems! For two dimensional problems, use HYPRE AMS instead");
3635f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3645f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3655ac14e1cSStefano Zampini     if (jac->coords[0]) {
3665ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3675ac14e1cSStefano Zampini       coords[0] = NULL;
3685ac14e1cSStefano Zampini       coords[1] = NULL;
3695ac14e1cSStefano Zampini       coords[2] = NULL;
370792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
371792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
372792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
373792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3745ac14e1cSStefano Zampini     }
3755ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
376792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
377792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
3785ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->C->data);
379792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
380792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3816bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3826bf688a0SCe Qin       PetscInt           i;
3836bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3846bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3856bf688a0SCe Qin       if (jac->RT_PiFull) {
3866bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->RT_PiFull->data);
387792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
3886bf688a0SCe Qin       } else {
3896bf688a0SCe Qin         rt_parcsrfull = NULL;
3906bf688a0SCe Qin       }
3916bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3926bf688a0SCe Qin         if (jac->RT_Pi[i]) {
3936bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->RT_Pi[i]->data);
394792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
3956bf688a0SCe Qin         } else {
3966bf688a0SCe Qin           rt_parcsr[i] = NULL;
3976bf688a0SCe Qin         }
3986bf688a0SCe Qin       }
3996bf688a0SCe Qin       if (jac->ND_PiFull) {
4006bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
401792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4026bf688a0SCe Qin       } else {
4036bf688a0SCe Qin         nd_parcsrfull = NULL;
4046bf688a0SCe Qin       }
4056bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4066bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4076bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
408792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4096bf688a0SCe Qin         } else {
4106bf688a0SCe Qin           nd_parcsr[i] = NULL;
4116bf688a0SCe Qin         }
4126bf688a0SCe Qin       }
413792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetInterpolations, jac->hsolver, rt_parcsrfull, rt_parcsr[0], rt_parcsr[1], rt_parcsr[2], nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
4146bf688a0SCe Qin     }
415863406b8SStefano Zampini   }
416792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
417792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
418792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
419792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
42016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
42116d9e3a6SLisandro Dalcin }
42216d9e3a6SLisandro Dalcin 
423d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
424d71ae5a4SJacob Faibussowitsch {
42516d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
42649a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
42716d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
42816d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
42916d9e3a6SLisandro Dalcin 
43016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4319566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4329566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4339566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4349566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4359566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
436792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
437792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
438792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4399371c9d4SSatish Balay   PetscStackCallExternalVoid(
4409371c9d4SSatish Balay     "Hypre solve", do {
4415f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4425f80ce2aSJacob Faibussowitsch       if (hierr) {
4435f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
4445f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
4455f80ce2aSJacob Faibussowitsch       }
4465f80ce2aSJacob Faibussowitsch     } while (0));
44716d9e3a6SLisandro Dalcin 
44848a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4499566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4509566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
45116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
45216d9e3a6SLisandro Dalcin }
45316d9e3a6SLisandro Dalcin 
454d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
455d71ae5a4SJacob Faibussowitsch {
4568695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
4578695de01SBarry Smith 
4588695de01SBarry Smith   PetscFunctionBegin;
4599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
4609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
4619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
4629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
4639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
4649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
4659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
4669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
4679566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
4689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
4699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
4709566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
4719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
4729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
4739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
4749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
4759566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
4769566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
4779566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
478be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
4799566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
4805ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
481be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
4825ac14e1cSStefano Zampini   jac->dim                   = 0;
4838695de01SBarry Smith   PetscFunctionReturn(0);
4848695de01SBarry Smith }
4858695de01SBarry Smith 
486d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
487d71ae5a4SJacob Faibussowitsch {
48816d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
48916d9e3a6SLisandro Dalcin 
49016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4919566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
492792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
4939566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
494db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
4959566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
496db6f9c32SMark Adams #endif
4979566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
4989566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
49916d9e3a6SLisandro Dalcin 
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5082e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
509be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5142e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
51516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
51616d9e3a6SLisandro Dalcin }
51716d9e3a6SLisandro Dalcin 
518d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
519d71ae5a4SJacob Faibussowitsch {
52016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
521ace3abfcSBarry Smith   PetscBool flag;
52216d9e3a6SLisandro Dalcin 
52316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
524d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
526792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
528792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
530792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
531d0609cedSBarry Smith   PetscOptionsHeadEnd();
53216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
53316d9e3a6SLisandro Dalcin }
53416d9e3a6SLisandro Dalcin 
535d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
536d71ae5a4SJacob Faibussowitsch {
53716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
538ace3abfcSBarry Smith   PetscBool iascii;
53916d9e3a6SLisandro Dalcin 
54016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
54216d9e3a6SLisandro Dalcin   if (iascii) {
5439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
54416d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
54563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
54616d9e3a6SLisandro Dalcin     } else {
5479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
54816d9e3a6SLisandro Dalcin     }
54916d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
5509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
55116d9e3a6SLisandro Dalcin     } else {
5529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
55316d9e3a6SLisandro Dalcin     }
55416d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
55563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
55616d9e3a6SLisandro Dalcin     } else {
5579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
55816d9e3a6SLisandro Dalcin     }
55916d9e3a6SLisandro Dalcin   }
56016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
56116d9e3a6SLisandro Dalcin }
56216d9e3a6SLisandro Dalcin 
563d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
564d71ae5a4SJacob Faibussowitsch {
565db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5668bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
567db966c6cSHong Zhang 
568db966c6cSHong Zhang   PetscFunctionBegin;
569d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
5709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
571792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
5728bf83915SBarry Smith 
5739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
5748bf83915SBarry Smith   if (flag) {
5758bf83915SBarry Smith     PetscMPIInt size;
5768bf83915SBarry Smith 
5779566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
5787827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
579792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
5808bf83915SBarry Smith   }
5818bf83915SBarry Smith 
5829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
5838bf83915SBarry Smith   if (flag) {
5848bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
585792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
5868bf83915SBarry Smith   }
587d0609cedSBarry Smith   PetscOptionsHeadEnd();
588db966c6cSHong Zhang   PetscFunctionReturn(0);
589db966c6cSHong Zhang }
590db966c6cSHong Zhang 
591d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
592d71ae5a4SJacob Faibussowitsch {
593db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
594db966c6cSHong Zhang   PetscBool iascii;
595db966c6cSHong Zhang 
596db966c6cSHong Zhang   PetscFunctionBegin;
5979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
598db966c6cSHong Zhang   if (iascii) {
5999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
600db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
60163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
602db966c6cSHong Zhang     } else {
6039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
604db966c6cSHong Zhang     }
6059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
60663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
607db966c6cSHong Zhang   }
608db966c6cSHong Zhang   PetscFunctionReturn(0);
609db966c6cSHong Zhang }
610db966c6cSHong Zhang 
611d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
612d71ae5a4SJacob Faibussowitsch {
61316d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
61449a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
61516d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
61616d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
61716d9e3a6SLisandro Dalcin 
61816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6199566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6209566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6219566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6229566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
62316d9e3a6SLisandro Dalcin 
624792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
625792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
626792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
62716d9e3a6SLisandro Dalcin 
6289371c9d4SSatish Balay   PetscStackCallExternalVoid(
6299371c9d4SSatish Balay     "Hypre Transpose solve", do {
6305f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6315f80ce2aSJacob Faibussowitsch       if (hierr) {
63216d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6335f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
6345f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
6355f80ce2aSJacob Faibussowitsch       }
6365f80ce2aSJacob Faibussowitsch     } while (0));
63716d9e3a6SLisandro Dalcin 
6389566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6399566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
64016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
64116d9e3a6SLisandro Dalcin }
64216d9e3a6SLisandro Dalcin 
643d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
644d71ae5a4SJacob Faibussowitsch {
645db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
646db6f9c32SMark Adams   PetscBool flag;
647db6f9c32SMark Adams 
648db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
649db6f9c32SMark Adams   PetscFunctionBegin;
650db6f9c32SMark Adams   if (jac->spgemm_type) {
6519566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
65228b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
653db6f9c32SMark Adams     PetscFunctionReturn(0);
654db6f9c32SMark Adams   } else {
6559566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
656db6f9c32SMark Adams   }
6579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
658db6f9c32SMark Adams   if (flag) {
659792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
660db6f9c32SMark Adams     PetscFunctionReturn(0);
661db6f9c32SMark Adams   }
6629566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
663db6f9c32SMark Adams   if (flag) {
664792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
665db6f9c32SMark Adams     PetscFunctionReturn(0);
666db6f9c32SMark Adams   }
667db6f9c32SMark Adams   jac->spgemm_type = NULL;
66898921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEM type %s; Choices are cusparse, hypre", name);
669db6f9c32SMark Adams #endif
670db6f9c32SMark Adams }
671db6f9c32SMark Adams 
672d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
673d71ae5a4SJacob Faibussowitsch {
674db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
675db6f9c32SMark Adams 
676db6f9c32SMark Adams   PetscFunctionBegin;
677db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
678db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
679db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
680db6f9c32SMark Adams #endif
681db6f9c32SMark Adams   PetscFunctionReturn(0);
682db6f9c32SMark Adams }
683db6f9c32SMark Adams 
68416d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
6850f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
68616d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
68765de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
6886a251517SEike Mueller static const char *HYPREBoomerAMGSmoothType[] = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
6899371c9d4SSatish 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"};
6909371c9d4SSatish 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"};
691d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
692d71ae5a4SJacob Faibussowitsch {
69316d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
69422e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
695ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
69616d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
697589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
698db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
69916d9e3a6SLisandro Dalcin 
70016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
701d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
7029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
70316d9e3a6SLisandro Dalcin   if (flg) {
7044336a9eeSBarry Smith     jac->cycletype = indx + 1;
705792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
70616d9e3a6SLisandro Dalcin   }
7079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
70816d9e3a6SLisandro Dalcin   if (flg) {
70963a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
710792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
71116d9e3a6SLisandro Dalcin   }
7129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
71316d9e3a6SLisandro Dalcin   if (flg) {
71463a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
715792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
71616d9e3a6SLisandro Dalcin   }
7179566063dSJacob 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));
71816d9e3a6SLisandro Dalcin   if (flg) {
71908401ef6SPierre 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);
720792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
72116d9e3a6SLisandro Dalcin   }
72222e51d31SStefano Zampini   bs = 1;
72348a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
72548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
72616d9e3a6SLisandro Dalcin 
7279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
72816d9e3a6SLisandro Dalcin   if (flg) {
72908401ef6SPierre 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);
730792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
73116d9e3a6SLisandro Dalcin   }
73216d9e3a6SLisandro Dalcin 
7339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7340f1074feSSatish Balay   if (flg) {
73563a3b9bcSJacob 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);
736792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7370f1074feSSatish Balay   }
7380f1074feSSatish Balay 
7399566063dSJacob 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));
740792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7410f1074feSSatish Balay 
7429566063dSJacob 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));
7430f1074feSSatish Balay   if (flg) {
74463a3b9bcSJacob 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);
745792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
7460f1074feSSatish Balay   }
7470f1074feSSatish Balay 
7489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
74916d9e3a6SLisandro Dalcin   if (flg) {
75008401ef6SPierre 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);
751792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
75216d9e3a6SLisandro Dalcin   }
7539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
75416d9e3a6SLisandro Dalcin   if (flg) {
75508401ef6SPierre 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);
75608401ef6SPierre 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);
757792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
75816d9e3a6SLisandro Dalcin   }
75916d9e3a6SLisandro Dalcin 
76016d9e3a6SLisandro Dalcin   /* Grid sweeps */
7619566063dSJacob 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));
76216d9e3a6SLisandro Dalcin   if (flg) {
763792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
76416d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
76516d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
7660f1074feSSatish Balay     jac->gridsweeps[1] = indx;
7670f1074feSSatish Balay     /*defaults coarse to 1 */
7680f1074feSSatish Balay     jac->gridsweeps[2] = 1;
76916d9e3a6SLisandro Dalcin   }
7709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
77148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
7729566063dSJacob 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));
77348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
7749566063dSJacob 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));
77548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
7769566063dSJacob 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));
77748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
7789566063dSJacob 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));
77948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
7809566063dSJacob 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));
78148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
7829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
78316d9e3a6SLisandro Dalcin   if (flg) {
784792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
7850f1074feSSatish Balay     jac->gridsweeps[0] = indx;
78616d9e3a6SLisandro Dalcin   }
7879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
78816d9e3a6SLisandro Dalcin   if (flg) {
789792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
7900f1074feSSatish Balay     jac->gridsweeps[1] = indx;
79116d9e3a6SLisandro Dalcin   }
7929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
79316d9e3a6SLisandro Dalcin   if (flg) {
794792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
7950f1074feSSatish Balay     jac->gridsweeps[2] = indx;
79616d9e3a6SLisandro Dalcin   }
79716d9e3a6SLisandro Dalcin 
7986a251517SEike Mueller   /* Smooth type */
799dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
8006a251517SEike Mueller   if (flg) {
8016a251517SEike Mueller     jac->smoothtype = indx;
802792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
8038131ecf7SEike Mueller     jac->smoothnumlevels = 25;
804792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
8058131ecf7SEike Mueller   }
8068131ecf7SEike Mueller 
8078131ecf7SEike Mueller   /* Number of smoothing levels */
8089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
8098131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8108131ecf7SEike Mueller     jac->smoothnumlevels = indx;
811792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8126a251517SEike Mueller   }
8136a251517SEike Mueller 
8141810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8161810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8171810e44eSEike Mueller     jac->eu_level = indx;
818792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8191810e44eSEike Mueller   }
8201810e44eSEike Mueller 
8211810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8221810e44eSEike Mueller   double droptolerance;
8239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8241810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8251810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
826792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8271810e44eSEike Mueller   }
8281810e44eSEike Mueller 
8291810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8311810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8321810e44eSEike Mueller     jac->eu_bj = tmp_truth;
833792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8341810e44eSEike Mueller   }
8351810e44eSEike Mueller 
83616d9e3a6SLisandro Dalcin   /* Relax type */
837dd39110bSPierre 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));
83816d9e3a6SLisandro Dalcin   if (flg) {
8390f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
840792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8410f1074feSSatish Balay     /* by default, coarse type set to 9 */
8420f1074feSSatish Balay     jac->relaxtype[2] = 9;
843792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
84416d9e3a6SLisandro Dalcin   }
845dd39110bSPierre 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));
84616d9e3a6SLisandro Dalcin   if (flg) {
84716d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
848792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
84916d9e3a6SLisandro Dalcin   }
850dd39110bSPierre 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));
85116d9e3a6SLisandro Dalcin   if (flg) {
8520f1074feSSatish Balay     jac->relaxtype[1] = indx;
853792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
85416d9e3a6SLisandro Dalcin   }
855dd39110bSPierre 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));
85616d9e3a6SLisandro Dalcin   if (flg) {
8570f1074feSSatish Balay     jac->relaxtype[2] = indx;
858792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
85916d9e3a6SLisandro Dalcin   }
86016d9e3a6SLisandro Dalcin 
86116d9e3a6SLisandro Dalcin   /* Relaxation Weight */
8629566063dSJacob 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));
86316d9e3a6SLisandro Dalcin   if (flg) {
864792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
86516d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
86616d9e3a6SLisandro Dalcin   }
86716d9e3a6SLisandro Dalcin 
86816d9e3a6SLisandro Dalcin   n         = 2;
86916d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
87116d9e3a6SLisandro Dalcin   if (flg) {
872*0fdf79fbSJacob Faibussowitsch     PetscCheck(n == 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT, n);
87316d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
874792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
87516d9e3a6SLisandro Dalcin   }
87616d9e3a6SLisandro Dalcin 
87716d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
8789566063dSJacob 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));
87916d9e3a6SLisandro Dalcin   if (flg) {
880792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
88116d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
88216d9e3a6SLisandro Dalcin   }
88316d9e3a6SLisandro Dalcin 
88416d9e3a6SLisandro Dalcin   n         = 2;
88516d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8869566063dSJacob 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));
88716d9e3a6SLisandro Dalcin   if (flg) {
888*0fdf79fbSJacob Faibussowitsch     PetscCheck(n == 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT, n);
88916d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
890792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
89116d9e3a6SLisandro Dalcin   }
89216d9e3a6SLisandro Dalcin 
89316d9e3a6SLisandro Dalcin   /* the Relax Order */
8949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
89516d9e3a6SLisandro Dalcin 
8968afaa268SBarry Smith   if (flg && tmp_truth) {
89716d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
898792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
89916d9e3a6SLisandro Dalcin   }
900dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
90116d9e3a6SLisandro Dalcin   if (flg) {
90216d9e3a6SLisandro Dalcin     jac->measuretype = indx;
903792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
90416d9e3a6SLisandro Dalcin   }
9050f1074feSSatish Balay   /* update list length 3/07 */
906dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
90716d9e3a6SLisandro Dalcin   if (flg) {
90816d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
909792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
91016d9e3a6SLisandro Dalcin   }
9110f1074feSSatish Balay 
9129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
91348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
91548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
916db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
917db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
918dd39110bSPierre 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));
919db6f9c32SMark Adams   if (!flg) indx = 0;
9209566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
921db6f9c32SMark Adams #endif
922589dcaf0SStefano Zampini   /* AIR */
923589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9249566063dSJacob 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));
925792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
926589dcaf0SStefano Zampini   if (jac->Rtype) {
927589dcaf0SStefano 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 */
928589dcaf0SStefano Zampini 
9299566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
930792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
931589dcaf0SStefano Zampini 
9329566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
933792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
934589dcaf0SStefano Zampini 
9359566063dSJacob 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));
936792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
937589dcaf0SStefano Zampini 
9389566063dSJacob 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));
939792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
940589dcaf0SStefano Zampini   }
941589dcaf0SStefano Zampini #endif
942589dcaf0SStefano Zampini 
943ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
94463a3b9bcSJacob 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);
945ecae95adSPierre Jolivet #endif
946ecae95adSPierre Jolivet 
9470f1074feSSatish Balay   /* new 3/07 */
948dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
949589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
950589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
951792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
9520f1074feSSatish Balay   }
9530f1074feSSatish Balay 
9549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
95516d9e3a6SLisandro Dalcin   if (flg) {
956b96a4a96SBarry Smith     level = 3;
9579566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
9582fa5cd67SKarl Rupp 
959b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
960792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
9612ae77aedSBarry Smith   }
9622ae77aedSBarry Smith 
9639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
9642ae77aedSBarry Smith   if (flg) {
965b96a4a96SBarry Smith     level = 3;
9669566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
9672fa5cd67SKarl Rupp 
968b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
969792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
97016d9e3a6SLisandro Dalcin   }
9718f87f92bSBarry Smith 
9729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
9738f87f92bSBarry Smith   if (flg && tmp_truth) {
9748f87f92bSBarry Smith     PetscInt tmp_int;
9759566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
9768f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
977792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
978792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
979792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
980792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
9818f87f92bSBarry Smith   }
9828f87f92bSBarry Smith 
9839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
984792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
985589dcaf0SStefano Zampini 
986589dcaf0SStefano Zampini   /* options for ParaSails solvers */
987dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
988589dcaf0SStefano Zampini   if (flg) {
989589dcaf0SStefano Zampini     jac->symt = indx;
990792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
991589dcaf0SStefano Zampini   }
992589dcaf0SStefano Zampini 
993d0609cedSBarry Smith   PetscOptionsHeadEnd();
99416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
99516d9e3a6SLisandro Dalcin }
99616d9e3a6SLisandro Dalcin 
997d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
998d71ae5a4SJacob Faibussowitsch {
99916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
10002cf14000SStefano Zampini   HYPRE_Int oits;
100116d9e3a6SLisandro Dalcin 
100216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10039566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1004792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1005792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
100616d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
10079566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
100816d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1009792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
10104d0a8057SBarry Smith   *outits = oits;
10114d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10124d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1013792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1014792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
101516d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
101616d9e3a6SLisandro Dalcin }
101716d9e3a6SLisandro Dalcin 
1018d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1019d71ae5a4SJacob Faibussowitsch {
102016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1021ace3abfcSBarry Smith   PetscBool iascii;
102216d9e3a6SLisandro Dalcin 
102316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
102516d9e3a6SLisandro Dalcin   if (iascii) {
10269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
10279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
102863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
102963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
10309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
10319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
10329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
103363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
103448a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
103563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
103663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
10370f1074feSSatish Balay 
10389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
103916d9e3a6SLisandro Dalcin 
104063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
104163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
104263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
104316d9e3a6SLisandro Dalcin 
10449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
10459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
10469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
104716d9e3a6SLisandro Dalcin 
10489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
10499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
105016d9e3a6SLisandro Dalcin 
105116d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
10529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
105316d9e3a6SLisandro Dalcin     } else {
10549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
105516d9e3a6SLisandro Dalcin     }
10566a251517SEike Mueller     if (jac->smoothtype != -1) {
10579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
105863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
10597e352d70SEike Mueller     } else {
10609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
10611810e44eSEike Mueller     }
10621810e44eSEike Mueller     if (jac->smoothtype == 3) {
106363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
10649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
106563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
10666a251517SEike Mueller     }
10679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
10689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
10699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
107048a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
10715272c319SBarry Smith     if (jac->vec_interp_variant) {
107263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
107363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
10749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
10758f87f92bSBarry Smith     }
107648a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1077db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
10789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
1079db6f9c32SMark Adams #endif
1080589dcaf0SStefano Zampini     /* AIR */
1081589dcaf0SStefano Zampini     if (jac->Rtype) {
108263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
10839566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
10849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
10859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
108663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1087589dcaf0SStefano Zampini     }
108816d9e3a6SLisandro Dalcin   }
108916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
109016d9e3a6SLisandro Dalcin }
109116d9e3a6SLisandro Dalcin 
1092d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1093d71ae5a4SJacob Faibussowitsch {
109416d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
10954ddd07fcSJed Brown   PetscInt    indx;
1096ace3abfcSBarry Smith   PetscBool   flag;
109716d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
109816d9e3a6SLisandro Dalcin 
109916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1100d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
11019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
11029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1103792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
110416d9e3a6SLisandro Dalcin 
11059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1106792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
110716d9e3a6SLisandro Dalcin 
11089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1109792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
111016d9e3a6SLisandro Dalcin 
11119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1112792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
111316d9e3a6SLisandro Dalcin 
11149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1115792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
111616d9e3a6SLisandro Dalcin 
1117dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
111816d9e3a6SLisandro Dalcin   if (flag) {
111916d9e3a6SLisandro Dalcin     jac->symt = indx;
1120792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
112116d9e3a6SLisandro Dalcin   }
112216d9e3a6SLisandro Dalcin 
1123d0609cedSBarry Smith   PetscOptionsHeadEnd();
112416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
112516d9e3a6SLisandro Dalcin }
112616d9e3a6SLisandro Dalcin 
1127d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1128d71ae5a4SJacob Faibussowitsch {
112916d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1130ace3abfcSBarry Smith   PetscBool   iascii;
1131feb237baSPierre Jolivet   const char *symt = 0;
113216d9e3a6SLisandro Dalcin 
113316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
113516d9e3a6SLisandro Dalcin   if (iascii) {
11369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
113763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
11389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
11399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
11409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
11419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
11429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
11432fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
11442fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
11452fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
114663a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
11479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
114816d9e3a6SLisandro Dalcin   }
114916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
115016d9e3a6SLisandro Dalcin }
1151f1580f4eSBarry Smith 
1152d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1153d71ae5a4SJacob Faibussowitsch {
11544cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11554cb006feSStefano Zampini   PetscInt  n;
11564cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
11574cb006feSStefano Zampini 
11584cb006feSStefano Zampini   PetscFunctionBegin;
1159d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
11609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1161792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
11629566063dSJacob 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));
1163792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
11649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1165792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
11669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1167792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
11689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
11699566063dSJacob 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));
11709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
11719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
117248a46eb9SPierre 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);
11739566063dSJacob 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));
11744cb006feSStefano Zampini   n = 5;
11759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
11764cb006feSStefano Zampini   if (flag || flag2) {
1177792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1178863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1179863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
11809371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1181a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
11824cb006feSStefano Zampini   }
11839566063dSJacob 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));
11844cb006feSStefano Zampini   n = 5;
11859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
11864cb006feSStefano Zampini   if (flag || flag2) {
1187792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1188863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1189863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
11909371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1191a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
11924cb006feSStefano Zampini   }
11939566063dSJacob 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));
119423df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1195792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
119623df4f25SStefano Zampini   }
1197d0609cedSBarry Smith   PetscOptionsHeadEnd();
11984cb006feSStefano Zampini   PetscFunctionReturn(0);
11994cb006feSStefano Zampini }
12004cb006feSStefano Zampini 
1201d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1202d71ae5a4SJacob Faibussowitsch {
12034cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12044cb006feSStefano Zampini   PetscBool iascii;
12054cb006feSStefano Zampini 
12064cb006feSStefano Zampini   PetscFunctionBegin;
12079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
12084cb006feSStefano Zampini   if (iascii) {
12099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
121063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
121163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
121263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
121363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
121463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
121563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
121663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12174cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
12194cb006feSStefano Zampini     } else {
12209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
12214cb006feSStefano Zampini     }
122263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
122363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
122463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
122563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
122663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
122763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12284cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12294cb006feSStefano Zampini       if (jac->beta_Poisson) {
12309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
12314cb006feSStefano Zampini       } else {
12329566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
12334cb006feSStefano Zampini       }
123463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
123563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
123663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
123763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
123863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
123963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
124048a46eb9SPierre 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));
124123df4f25SStefano Zampini     } else {
12429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
12434cb006feSStefano Zampini     }
12444cb006feSStefano Zampini   }
12454cb006feSStefano Zampini   PetscFunctionReturn(0);
12464cb006feSStefano Zampini }
12474cb006feSStefano Zampini 
1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1249d71ae5a4SJacob Faibussowitsch {
1250863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1251863406b8SStefano Zampini   PetscInt  n;
1252863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1253863406b8SStefano Zampini 
1254863406b8SStefano Zampini   PetscFunctionBegin;
1255d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
12569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1257792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
12589566063dSJacob 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));
1259792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
12609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1261792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
12629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1263792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
12649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12659566063dSJacob 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));
12669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
126848a46eb9SPierre 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);
12699566063dSJacob 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));
1270863406b8SStefano Zampini   n = 5;
12719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
12729566063dSJacob 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));
1273863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1274792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1275863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1276863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1277863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
12789371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1279a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1280863406b8SStefano Zampini   }
12819566063dSJacob 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));
1282863406b8SStefano Zampini   n = 5;
12839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1284863406b8SStefano Zampini   if (flag || flag2) {
1285792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1286863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1287863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
12889371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1289a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1290863406b8SStefano Zampini   }
1291d0609cedSBarry Smith   PetscOptionsHeadEnd();
1292863406b8SStefano Zampini   PetscFunctionReturn(0);
1293863406b8SStefano Zampini }
1294863406b8SStefano Zampini 
1295d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1296d71ae5a4SJacob Faibussowitsch {
1297863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1298863406b8SStefano Zampini   PetscBool iascii;
1299863406b8SStefano Zampini 
1300863406b8SStefano Zampini   PetscFunctionBegin;
13019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1302863406b8SStefano Zampini   if (iascii) {
13039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
130463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
130563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
130663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
130763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
130863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
130963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
131063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
131263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
131363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
131463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
131563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
131663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
131763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
131863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
132063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
132163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
132263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
132363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
132463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
132563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1326863406b8SStefano Zampini   }
1327863406b8SStefano Zampini   PetscFunctionReturn(0);
1328863406b8SStefano Zampini }
1329863406b8SStefano Zampini 
1330d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1331d71ae5a4SJacob Faibussowitsch {
13324cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13335ac14e1cSStefano Zampini   PetscBool ishypre;
13344cb006feSStefano Zampini 
13354cb006feSStefano Zampini   PetscFunctionBegin;
13369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
13375ac14e1cSStefano Zampini   if (ishypre) {
13389566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
13399566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13405ac14e1cSStefano Zampini     jac->G = G;
13415ac14e1cSStefano Zampini   } else {
13429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13439566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
13445ac14e1cSStefano Zampini   }
13454cb006feSStefano Zampini   PetscFunctionReturn(0);
13464cb006feSStefano Zampini }
13474cb006feSStefano Zampini 
13484cb006feSStefano Zampini /*@
1349f1580f4eSBarry Smith    PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
13504cb006feSStefano Zampini 
1351f1580f4eSBarry Smith    Collective on pc
13524cb006feSStefano Zampini 
13534cb006feSStefano Zampini    Input Parameters:
13544cb006feSStefano Zampini +  pc - the preconditioning context
13554cb006feSStefano Zampini -  G - the discrete gradient
13564cb006feSStefano Zampini 
13574cb006feSStefano Zampini    Level: intermediate
13584cb006feSStefano Zampini 
135995452b02SPatrick Sanan    Notes:
136095452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1361147403d9SBarry Smith 
1362863406b8SStefano 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
13634cb006feSStefano Zampini 
1364f1580f4eSBarry Smith    Developer Note:
1365f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1366f1580f4eSBarry Smith 
1367f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
13684cb006feSStefano Zampini @*/
1369d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1370d71ae5a4SJacob Faibussowitsch {
13714cb006feSStefano Zampini   PetscFunctionBegin;
13724cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
13734cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
13744cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1375cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
13764cb006feSStefano Zampini   PetscFunctionReturn(0);
13774cb006feSStefano Zampini }
13784cb006feSStefano Zampini 
1379d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1380d71ae5a4SJacob Faibussowitsch {
1381863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13825ac14e1cSStefano Zampini   PetscBool ishypre;
1383863406b8SStefano Zampini 
1384863406b8SStefano Zampini   PetscFunctionBegin;
13859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
13865ac14e1cSStefano Zampini   if (ishypre) {
13879566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
13889566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13895ac14e1cSStefano Zampini     jac->C = C;
13905ac14e1cSStefano Zampini   } else {
13919566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13929566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
13935ac14e1cSStefano Zampini   }
1394863406b8SStefano Zampini   PetscFunctionReturn(0);
1395863406b8SStefano Zampini }
1396863406b8SStefano Zampini 
1397863406b8SStefano Zampini /*@
1398f1580f4eSBarry Smith    PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1399863406b8SStefano Zampini 
1400f1580f4eSBarry Smith    Collective on pc
1401863406b8SStefano Zampini 
1402863406b8SStefano Zampini    Input Parameters:
1403863406b8SStefano Zampini +  pc - the preconditioning context
1404863406b8SStefano Zampini -  C - the discrete curl
1405863406b8SStefano Zampini 
1406863406b8SStefano Zampini    Level: intermediate
1407863406b8SStefano Zampini 
140895452b02SPatrick Sanan    Notes:
140995452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1410147403d9SBarry Smith 
1411863406b8SStefano 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
1412863406b8SStefano Zampini 
1413f1580f4eSBarry Smith    Developer Note:
1414f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1415f1580f4eSBarry Smith 
1416f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1417f1580f4eSBarry Smith 
1418f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1419863406b8SStefano Zampini @*/
1420d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1421d71ae5a4SJacob Faibussowitsch {
1422863406b8SStefano Zampini   PetscFunctionBegin;
1423863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1424863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1425863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1426cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
1427863406b8SStefano Zampini   PetscFunctionReturn(0);
1428863406b8SStefano Zampini }
1429863406b8SStefano Zampini 
1430d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1431d71ae5a4SJacob Faibussowitsch {
14326bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14336bf688a0SCe Qin   PetscBool ishypre;
14346bf688a0SCe Qin   PetscInt  i;
14356bf688a0SCe Qin   PetscFunctionBegin;
14366bf688a0SCe Qin 
14379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
14389566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
14396bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
14409566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
14419566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
14426bf688a0SCe Qin   }
14436bf688a0SCe Qin 
14446bf688a0SCe Qin   jac->dim = dim;
14456bf688a0SCe Qin   if (RT_PiFull) {
14469566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
14476bf688a0SCe Qin     if (ishypre) {
14489566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
14496bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
14506bf688a0SCe Qin     } else {
14519566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
14526bf688a0SCe Qin     }
14536bf688a0SCe Qin   }
14546bf688a0SCe Qin   if (RT_Pi) {
14556bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14566bf688a0SCe Qin       if (RT_Pi[i]) {
14579566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
14586bf688a0SCe Qin         if (ishypre) {
14599566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
14606bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
14616bf688a0SCe Qin         } else {
14629566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
14636bf688a0SCe Qin         }
14646bf688a0SCe Qin       }
14656bf688a0SCe Qin     }
14666bf688a0SCe Qin   }
14676bf688a0SCe Qin   if (ND_PiFull) {
14689566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
14696bf688a0SCe Qin     if (ishypre) {
14709566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
14716bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
14726bf688a0SCe Qin     } else {
14739566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
14746bf688a0SCe Qin     }
14756bf688a0SCe Qin   }
14766bf688a0SCe Qin   if (ND_Pi) {
14776bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14786bf688a0SCe Qin       if (ND_Pi[i]) {
14799566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
14806bf688a0SCe Qin         if (ishypre) {
14819566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
14826bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
14836bf688a0SCe Qin         } else {
14849566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
14856bf688a0SCe Qin         }
14866bf688a0SCe Qin       }
14876bf688a0SCe Qin     }
14886bf688a0SCe Qin   }
14896bf688a0SCe Qin 
14906bf688a0SCe Qin   PetscFunctionReturn(0);
14916bf688a0SCe Qin }
14926bf688a0SCe Qin 
14936bf688a0SCe Qin /*@
1494f1580f4eSBarry Smith    PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
14956bf688a0SCe Qin 
1496f1580f4eSBarry Smith    Collective on pc
14976bf688a0SCe Qin 
14986bf688a0SCe Qin    Input Parameters:
14996bf688a0SCe Qin +  pc - the preconditioning context
15006bf688a0SCe Qin -  dim - the dimension of the problem, only used in AMS
15016bf688a0SCe Qin -  RT_PiFull - Raviart-Thomas interpolation matrix
15026bf688a0SCe Qin -  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
15036bf688a0SCe Qin -  ND_PiFull - Nedelec interpolation matrix
15046bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
15056bf688a0SCe Qin 
1506f1580f4eSBarry Smith    Level: intermediate
1507f1580f4eSBarry Smith 
150895452b02SPatrick Sanan    Notes:
150995452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1510147403d9SBarry Smith 
15116bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1512147403d9SBarry Smith 
1513f1580f4eSBarry Smith    Developer Note:
1514f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
15156bf688a0SCe Qin 
1516f1580f4eSBarry Smith .seealso: `PCHYPRE`
15176bf688a0SCe Qin @*/
1518d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1519d71ae5a4SJacob Faibussowitsch {
15206bf688a0SCe Qin   PetscInt i;
15216bf688a0SCe Qin 
15226bf688a0SCe Qin   PetscFunctionBegin;
15236bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15246bf688a0SCe Qin   if (RT_PiFull) {
15256bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
15266bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
15276bf688a0SCe Qin   }
15286bf688a0SCe Qin   if (RT_Pi) {
15296bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
15306bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15316bf688a0SCe Qin       if (RT_Pi[i]) {
15326bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
15336bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
15346bf688a0SCe Qin       }
15356bf688a0SCe Qin     }
15366bf688a0SCe Qin   }
15376bf688a0SCe Qin   if (ND_PiFull) {
15386bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
15396bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
15406bf688a0SCe Qin   }
15416bf688a0SCe Qin   if (ND_Pi) {
15426bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
15436bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15446bf688a0SCe Qin       if (ND_Pi[i]) {
15456bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
15466bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
15476bf688a0SCe Qin       }
15486bf688a0SCe Qin     }
15496bf688a0SCe Qin   }
1550cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
15516bf688a0SCe Qin   PetscFunctionReturn(0);
15526bf688a0SCe Qin }
15536bf688a0SCe Qin 
1554d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1555d71ae5a4SJacob Faibussowitsch {
15564cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15575ac14e1cSStefano Zampini   PetscBool ishypre;
15584cb006feSStefano Zampini 
15594cb006feSStefano Zampini   PetscFunctionBegin;
15609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
15615ac14e1cSStefano Zampini   if (ishypre) {
15625ac14e1cSStefano Zampini     if (isalpha) {
15639566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
15649566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15655ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
15665ac14e1cSStefano Zampini     } else {
15675ac14e1cSStefano Zampini       if (A) {
15689566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
15695ac14e1cSStefano Zampini       } else {
15705ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15715ac14e1cSStefano Zampini       }
15729566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
15735ac14e1cSStefano Zampini       jac->beta_Poisson = A;
15745ac14e1cSStefano Zampini     }
15755ac14e1cSStefano Zampini   } else {
15765ac14e1cSStefano Zampini     if (isalpha) {
15779566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15789566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
15795ac14e1cSStefano Zampini     } else {
15805ac14e1cSStefano Zampini       if (A) {
15819566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15829566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
15835ac14e1cSStefano Zampini       } else {
15849566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15855ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15865ac14e1cSStefano Zampini       }
15875ac14e1cSStefano Zampini     }
15885ac14e1cSStefano Zampini   }
15894cb006feSStefano Zampini   PetscFunctionReturn(0);
15904cb006feSStefano Zampini }
15914cb006feSStefano Zampini 
15924cb006feSStefano Zampini /*@
1593f1580f4eSBarry Smith    PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
15944cb006feSStefano Zampini 
1595f1580f4eSBarry Smith    Collective on pc
15964cb006feSStefano Zampini 
15974cb006feSStefano Zampini    Input Parameters:
15984cb006feSStefano Zampini +  pc - the preconditioning context
15994cb006feSStefano Zampini -  A - the matrix
16004cb006feSStefano Zampini 
16014cb006feSStefano Zampini    Level: intermediate
16024cb006feSStefano Zampini 
1603f1580f4eSBarry Smith    Note:
160495452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
16054cb006feSStefano Zampini 
1606f1580f4eSBarry Smith    Developer Note:
1607f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1608f1580f4eSBarry Smith 
1609f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1610f1580f4eSBarry Smith 
1611f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
16124cb006feSStefano Zampini @*/
1613d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1614d71ae5a4SJacob Faibussowitsch {
16154cb006feSStefano Zampini   PetscFunctionBegin;
16164cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16174cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16184cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1619cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
16204cb006feSStefano Zampini   PetscFunctionReturn(0);
16214cb006feSStefano Zampini }
16224cb006feSStefano Zampini 
16234cb006feSStefano Zampini /*@
1624f1580f4eSBarry Smith    PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
16254cb006feSStefano Zampini 
1626f1580f4eSBarry Smith    Collective on pc
16274cb006feSStefano Zampini 
16284cb006feSStefano Zampini    Input Parameters:
16294cb006feSStefano Zampini +  pc - the preconditioning context
1630f1580f4eSBarry Smith -  A - the matrix, or NULL to turn it off
16314cb006feSStefano Zampini 
16324cb006feSStefano Zampini    Level: intermediate
16334cb006feSStefano Zampini 
1634f1580f4eSBarry Smith    Note:
163595452b02SPatrick Sanan    A should be obtained by discretizing the Poisson problem with linear finite elements.
16364cb006feSStefano Zampini 
1637f1580f4eSBarry Smith    Developer Note:
1638f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1639f1580f4eSBarry Smith 
1640f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1641f1580f4eSBarry Smith 
1642f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16434cb006feSStefano Zampini @*/
1644d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1645d71ae5a4SJacob Faibussowitsch {
16464cb006feSStefano Zampini   PetscFunctionBegin;
16474cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16484cb006feSStefano Zampini   if (A) {
16494cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16504cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
16514cb006feSStefano Zampini   }
1652cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
16534cb006feSStefano Zampini   PetscFunctionReturn(0);
16544cb006feSStefano Zampini }
16554cb006feSStefano Zampini 
1656d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1657d71ae5a4SJacob Faibussowitsch {
16584cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16594cb006feSStefano Zampini 
16604cb006feSStefano Zampini   PetscFunctionBegin;
16614cb006feSStefano Zampini   /* throw away any vector if already set */
16629566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
16639566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
16649566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
16659566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
16669566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
16679566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
16689566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
16695ac14e1cSStefano Zampini   jac->dim = 2;
16704cb006feSStefano Zampini   if (zzo) {
16719566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
16729566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
16735ac14e1cSStefano Zampini     jac->dim++;
16744cb006feSStefano Zampini   }
16754cb006feSStefano Zampini   PetscFunctionReturn(0);
16764cb006feSStefano Zampini }
16774cb006feSStefano Zampini 
16784cb006feSStefano Zampini /*@
1679f1580f4eSBarry Smith    PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
16804cb006feSStefano Zampini 
1681f1580f4eSBarry Smith    Collective on pc
16824cb006feSStefano Zampini 
16834cb006feSStefano Zampini    Input Parameters:
16844cb006feSStefano Zampini +  pc - the preconditioning context
16854cb006feSStefano Zampini -  ozz - vector representing (1,0,0) (or (1,0) in 2D)
16864cb006feSStefano Zampini -  zoz - vector representing (0,1,0) (or (0,1) in 2D)
16874cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
16884cb006feSStefano Zampini 
16894cb006feSStefano Zampini    Level: intermediate
16904cb006feSStefano Zampini 
1691f1580f4eSBarry Smith    Developer Note:
1692f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1693f1580f4eSBarry Smith 
1694f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16954cb006feSStefano Zampini @*/
1696d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1697d71ae5a4SJacob Faibussowitsch {
16984cb006feSStefano Zampini   PetscFunctionBegin;
16994cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17004cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
17014cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
17024cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
17034cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
17044cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
17054cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1706cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
17074cb006feSStefano Zampini   PetscFunctionReturn(0);
17084cb006feSStefano Zampini }
17094cb006feSStefano Zampini 
1710d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1711d71ae5a4SJacob Faibussowitsch {
1712be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1713be14dc20SKerry Key 
1714be14dc20SKerry Key   PetscFunctionBegin;
1715be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1716be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1717be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1718be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
1719be14dc20SKerry Key   PetscFunctionReturn(0);
1720be14dc20SKerry Key }
1721be14dc20SKerry Key 
1722be14dc20SKerry Key /*@
1723f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1724be14dc20SKerry Key 
1725f1580f4eSBarry Smith    Collective on pc
1726be14dc20SKerry Key 
1727be14dc20SKerry Key    Input Parameters:
1728be14dc20SKerry Key +  pc - the preconditioning context
1729be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1730be14dc20SKerry Key 
1731be14dc20SKerry Key    Level: intermediate
1732be14dc20SKerry Key 
1733be14dc20SKerry Key    Note:
1734f1580f4eSBarry Smith    This calls `HYPRE_AMSSetInteriorNodes()`
1735f1580f4eSBarry Smith 
1736f1580f4eSBarry Smith    Developer Note:
1737f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1738f1580f4eSBarry Smith 
1739f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1740be14dc20SKerry Key @*/
1741d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1742d71ae5a4SJacob Faibussowitsch {
1743be14dc20SKerry Key   PetscFunctionBegin;
1744be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1745be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1746be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1747be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
1748be14dc20SKerry Key   PetscFunctionReturn(0);
1749be14dc20SKerry Key }
1750be14dc20SKerry Key 
1751d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1752d71ae5a4SJacob Faibussowitsch {
17534cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17544cb006feSStefano Zampini   Vec       tv;
17554cb006feSStefano Zampini   PetscInt  i;
17564cb006feSStefano Zampini 
17574cb006feSStefano Zampini   PetscFunctionBegin;
17584cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
17599566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
17609566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
17619566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
17625ac14e1cSStefano Zampini   jac->dim = dim;
17635ac14e1cSStefano Zampini 
17644cb006feSStefano Zampini   /* compute IJ vector for coordinates */
17659566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
17669566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
17679566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
17684cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
17694cb006feSStefano Zampini     PetscScalar *array;
17704cb006feSStefano Zampini     PetscInt     j;
17714cb006feSStefano Zampini 
17729566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
17739566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
17746ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
17759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
17769566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
17774cb006feSStefano Zampini   }
17789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
17794cb006feSStefano Zampini   PetscFunctionReturn(0);
17804cb006feSStefano Zampini }
17814cb006feSStefano Zampini 
1782d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1783d71ae5a4SJacob Faibussowitsch {
178416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
178516d9e3a6SLisandro Dalcin 
178616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
178716d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
178816d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
178916d9e3a6SLisandro Dalcin }
179016d9e3a6SLisandro Dalcin 
1791d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1792d71ae5a4SJacob Faibussowitsch {
179316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1794ace3abfcSBarry Smith   PetscBool flag;
179516d9e3a6SLisandro Dalcin 
179616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
179716d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
17989566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
17995f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
180016d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
180116d9e3a6SLisandro Dalcin   } else {
18029566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
180316d9e3a6SLisandro Dalcin   }
180416d9e3a6SLisandro Dalcin 
180516d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
180616d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
180716d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
180816d9e3a6SLisandro Dalcin 
18099566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
181016d9e3a6SLisandro Dalcin   if (flag) {
18119566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1812792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
181316d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
181416d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
181516d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
181616d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
181716d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
181816d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
181916d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
182016d9e3a6SLisandro Dalcin   }
18219566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1822db966c6cSHong Zhang   if (flag) {
18234e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
18244e3c431bSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64 bit indices");
18258bf83915SBarry Smith #endif
18269566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1827792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1828db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1829db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1830db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1831db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1832db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1833db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1834db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
1835db966c6cSHong Zhang     PetscFunctionReturn(0);
1836db966c6cSHong Zhang   }
18379566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
183816d9e3a6SLisandro Dalcin   if (flag) {
18399566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1840792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
184116d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
184216d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
184316d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
184416d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
184516d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
184616d9e3a6SLisandro Dalcin     /* initialize */
184716d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
18488966356dSPierre Jolivet     jac->threshold = .1;
184916d9e3a6SLisandro Dalcin     jac->filter    = .1;
185016d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
18512fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
18522fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
18532fa5cd67SKarl Rupp 
185416d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
185516d9e3a6SLisandro Dalcin     jac->symt = 0;
1856792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1857792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1858792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1859792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1860792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1861792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
186216d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
186316d9e3a6SLisandro Dalcin   }
18649566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
186516d9e3a6SLisandro Dalcin   if (flag) {
1866792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
186716d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
186816d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
186916d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
187016d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
18719566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
18729566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
187316d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
187416d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
187516d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
187616d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
187716d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
187816d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
187916d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
188016d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
18818f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
188216d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
188316d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
188416d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
188516d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
188616d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
18870f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
18886a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1889b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
18901810e44eSEike Mueller     jac->eu_level                                                = 0;
18911810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
18921810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1893589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
18940f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
189516d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
189616d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
189716d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
18980f1074feSSatish Balay     jac->interptype                       = 0;
1899589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1900589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1901589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1902589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1903589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
19040f1074feSSatish Balay     jac->agg_nl                           = 0;
19056ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
19060f1074feSSatish Balay     jac->pmax                             = 0;
19070f1074feSSatish Balay     jac->truncfactor                      = 0.0;
19080f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1909589dcaf0SStefano Zampini     jac->maxc                             = 9;
1910589dcaf0SStefano Zampini     jac->minc                             = 1;
191122e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
191222e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
191322e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
191422e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
191522e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
191622e51d31SStefano Zampini     jac->interp_refine                    = 0;
19178f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
19188f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
19196ea7df73SStefano Zampini     jac->rap2                             = 0;
19206ea7df73SStefano Zampini 
19216ea7df73SStefano Zampini     /* GPU defaults
19226ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
19236ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
19246ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
19256ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
19266ea7df73SStefano Zampini     jac->mod_rap2       = 1;
19276ea7df73SStefano Zampini     jac->coarsentype    = 8;
19286ea7df73SStefano Zampini     jac->relaxorder     = 0;
19296ea7df73SStefano Zampini     jac->interptype     = 6;
19306ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
19316ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
19326ea7df73SStefano Zampini     jac->agg_interptype = 7;
19336ea7df73SStefano Zampini #else
19346ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
19356ea7df73SStefano Zampini     jac->mod_rap2      = 0;
19366ea7df73SStefano Zampini #endif
1937792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
1938792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
1939792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
1940792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1941792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
1942792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
1943792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
1944792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
1945792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
1946792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
1947792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
1948792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
1949792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
1950792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
1951792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
1952792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
1953792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
1954792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
1955792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
19566ea7df73SStefano Zampini     /* GPU */
19576ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1958792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1959792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
1960792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
19616ea7df73SStefano Zampini #endif
19626ea7df73SStefano Zampini 
1963589dcaf0SStefano Zampini     /* AIR */
19646ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1965792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1966792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1967792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1968792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1969792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
19706ea7df73SStefano Zampini #endif
197116d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
197216d9e3a6SLisandro Dalcin   }
19739566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
19744cb006feSStefano Zampini   if (flag) {
19759566063dSJacob Faibussowitsch     PetscCall(HYPRE_AMSCreate(&jac->hsolver));
19764cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
19774cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
19784cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
19794cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
19804cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
19814cb006feSStefano Zampini     jac->coords[0]          = NULL;
19824cb006feSStefano Zampini     jac->coords[1]          = NULL;
19834cb006feSStefano Zampini     jac->coords[2]          = NULL;
1984be14dc20SKerry Key     jac->interior           = NULL;
19854cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
1986863406b8SStefano Zampini     jac->as_print       = 0;
1987863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
1988863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
19894cb006feSStefano Zampini     jac->ams_cycle_type = 13;
19904cb006feSStefano Zampini     /* Smoothing options */
1991863406b8SStefano Zampini     jac->as_relax_type   = 2;
1992863406b8SStefano Zampini     jac->as_relax_times  = 1;
1993863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
1994863406b8SStefano Zampini     jac->as_omega        = 1.0;
19954cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1996863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
1997863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
19980bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
1999863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2000863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2001863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
20024cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2003863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2004863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
20050bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2006863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2007863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2008863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2009792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2010792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2011792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2012792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
20139371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2014792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2015863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2016863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
20179371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2018a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2019792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2020863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2021863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
20229371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2023a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
202423df4f25SStefano Zampini     /* Zero conductivity */
202523df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
202623df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
20274cb006feSStefano Zampini     PetscFunctionReturn(0);
20284cb006feSStefano Zampini   }
20299566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2030863406b8SStefano Zampini   if (flag) {
20319566063dSJacob Faibussowitsch     PetscCall(HYPRE_ADSCreate(&jac->hsolver));
2032863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2033863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2034863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2035863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2036863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2037863406b8SStefano Zampini     jac->coords[0]          = NULL;
2038863406b8SStefano Zampini     jac->coords[1]          = NULL;
2039863406b8SStefano Zampini     jac->coords[2]          = NULL;
2040863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2041863406b8SStefano Zampini     jac->as_print       = 0;
2042863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2043863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2044863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2045863406b8SStefano Zampini     /* Smoothing options */
2046863406b8SStefano Zampini     jac->as_relax_type   = 2;
2047863406b8SStefano Zampini     jac->as_relax_times  = 1;
2048863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2049863406b8SStefano Zampini     jac->as_omega        = 1.0;
2050863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2051863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2052863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2053863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2054863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2055863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2056863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2057863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2058863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2059863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2060863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2061863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2062863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2063863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2064863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2065792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2066792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2067792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2068792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
20699371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2070792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2071863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2072863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2073863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
20749371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2075a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2076792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2077863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2078863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
20799371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2080a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
2081863406b8SStefano Zampini     PetscFunctionReturn(0);
2082863406b8SStefano Zampini   }
20839566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
20842fa5cd67SKarl Rupp 
20850298fd71SBarry Smith   jac->hypre_type = NULL;
208698921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
208716d9e3a6SLisandro Dalcin }
208816d9e3a6SLisandro Dalcin 
208916d9e3a6SLisandro Dalcin /*
209016d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
209116d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
209216d9e3a6SLisandro Dalcin */
2093d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2094d71ae5a4SJacob Faibussowitsch {
20954ddd07fcSJed Brown   PetscInt    indx;
2096db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2097ace3abfcSBarry Smith   PetscBool   flg;
209816d9e3a6SLisandro Dalcin 
209916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2100d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2101dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
210216d9e3a6SLisandro Dalcin   if (flg) {
21039566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
210402a17cd4SBarry Smith   } else {
21059566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
210616d9e3a6SLisandro Dalcin   }
2107dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2108d0609cedSBarry Smith   PetscOptionsHeadEnd();
210916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
211016d9e3a6SLisandro Dalcin }
211116d9e3a6SLisandro Dalcin 
211216d9e3a6SLisandro Dalcin /*@C
211316d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
211416d9e3a6SLisandro Dalcin 
211516d9e3a6SLisandro Dalcin    Input Parameters:
211616d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2117db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
211816d9e3a6SLisandro Dalcin 
2119f1580f4eSBarry Smith    Options Database Key:
2120db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
212116d9e3a6SLisandro Dalcin 
212216d9e3a6SLisandro Dalcin    Level: intermediate
212316d9e3a6SLisandro Dalcin 
2124f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
212516d9e3a6SLisandro Dalcin @*/
2126d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2127d71ae5a4SJacob Faibussowitsch {
212816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21290700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
213016d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2131cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
213216d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
213316d9e3a6SLisandro Dalcin }
213416d9e3a6SLisandro Dalcin 
213516d9e3a6SLisandro Dalcin /*@C
213616d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
213716d9e3a6SLisandro Dalcin 
213816d9e3a6SLisandro Dalcin    Input Parameter:
213916d9e3a6SLisandro Dalcin .     pc - the preconditioner context
214016d9e3a6SLisandro Dalcin 
214116d9e3a6SLisandro Dalcin    Output Parameter:
2142db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
214316d9e3a6SLisandro Dalcin 
214416d9e3a6SLisandro Dalcin    Level: intermediate
214516d9e3a6SLisandro Dalcin 
2146f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
214716d9e3a6SLisandro Dalcin @*/
2148d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2149d71ae5a4SJacob Faibussowitsch {
215016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21510700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
215216d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2153cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
215416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
215516d9e3a6SLisandro Dalcin }
215616d9e3a6SLisandro Dalcin 
2157db6f9c32SMark Adams /*@C
2158f1580f4eSBarry Smith    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2159db6f9c32SMark Adams 
2160f1580f4eSBarry Smith    Logically Collective on pc
2161db6f9c32SMark Adams 
2162db6f9c32SMark Adams    Input Parameters:
2163db6f9c32SMark Adams +  pc - the hypre context
2164db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2165db6f9c32SMark Adams 
2166db6f9c32SMark Adams    Options Database Key:
216767b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2168db6f9c32SMark Adams 
2169db6f9c32SMark Adams    Level: intermediate
2170db6f9c32SMark Adams 
2171f1580f4eSBarry Smith    Developer Note:
2172f1580f4eSBarry Smith    How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2173db6f9c32SMark Adams 
2174f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2175db6f9c32SMark Adams @*/
2176d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2177d71ae5a4SJacob Faibussowitsch {
2178db6f9c32SMark Adams   PetscFunctionBegin;
2179db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2180cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
2181db6f9c32SMark Adams   PetscFunctionReturn(0);
2182db6f9c32SMark Adams }
2183db6f9c32SMark Adams 
2184db6f9c32SMark Adams /*@C
2185f1580f4eSBarry Smith    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2186db6f9c32SMark Adams 
2187db6f9c32SMark Adams    Not Collective
2188db6f9c32SMark Adams 
2189db6f9c32SMark Adams    Input Parameter:
2190db6f9c32SMark Adams .  pc - the multigrid context
2191db6f9c32SMark Adams 
2192db6f9c32SMark Adams    Output Parameter:
2193db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2194db6f9c32SMark Adams 
2195db6f9c32SMark Adams    Level: intermediate
2196db6f9c32SMark Adams 
2197f1580f4eSBarry Smith .seealso: `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2198db6f9c32SMark Adams @*/
2199d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2200d71ae5a4SJacob Faibussowitsch {
2201db6f9c32SMark Adams   PetscFunctionBegin;
2202db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2203cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
2204db6f9c32SMark Adams   PetscFunctionReturn(0);
2205db6f9c32SMark Adams }
2206db6f9c32SMark Adams 
220716d9e3a6SLisandro Dalcin /*MC
2208f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
220916d9e3a6SLisandro Dalcin 
221016d9e3a6SLisandro Dalcin    Options Database Keys:
2211db966c6cSHong Zhang +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2212f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2213f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2214ead8c081SBarry Smith -   Many others, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX preconditioner
221516d9e3a6SLisandro Dalcin 
221616d9e3a6SLisandro Dalcin    Level: intermediate
221716d9e3a6SLisandro Dalcin 
221895452b02SPatrick Sanan    Notes:
2219f1580f4eSBarry Smith     Apart from pc_hypre_type (for which there is `PCHYPRESetType()`),
222016d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
222149567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
222216d9e3a6SLisandro Dalcin 
2223c231f9e3SBarryFSmith           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
22240f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
22250f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2226c231f9e3SBarryFSmith           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
22278f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
22280f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
22290f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
223016d9e3a6SLisandro Dalcin 
22310f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
22320f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
22330f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
223416d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
223516d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
223616d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
223716d9e3a6SLisandro Dalcin 
2238f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
223949567fc5SPierre Jolivet           the following two options: ``-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>``
22400b1a5bd9SEric Chamberland 
2241f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2242f1580f4eSBarry Smith 
2243f1580f4eSBarry Smith           For `PCHYPRE` type of ams or ads auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2244f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
224549567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2246f1580f4eSBarry Smith 
2247f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
22489e5bc791SBarry Smith 
2249ead8c081SBarry Smith    GPU Notes:
2250ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2251f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2252ead8c081SBarry Smith 
2253ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2254f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2255ead8c081SBarry Smith 
2256f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2257f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2258f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
225916d9e3a6SLisandro Dalcin M*/
226016d9e3a6SLisandro Dalcin 
2261d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2262d71ae5a4SJacob Faibussowitsch {
226316d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
226416d9e3a6SLisandro Dalcin 
226516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22664dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
22672fa5cd67SKarl Rupp 
226816d9e3a6SLisandro Dalcin   pc->data                = jac;
22698695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
227016d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
227116d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
227216d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
227316d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
227416d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
22759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
22769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
22779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
22789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
22799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
22809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
22819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2282be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
22839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
22849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
22859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
22866ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22876ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
22889566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
22896ea7df73SStefano Zampini   #endif
22906ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
22919566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
22926ea7df73SStefano Zampini   #endif
22936ea7df73SStefano Zampini #endif
229416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
229516d9e3a6SLisandro Dalcin }
2296ebc551c0SBarry Smith 
2297ebc551c0SBarry Smith typedef struct {
229868326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2299f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
23009e5bc791SBarry Smith 
23019e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
23024ddd07fcSJed Brown   PetscInt  its;
23039e5bc791SBarry Smith   double    tol;
23044ddd07fcSJed Brown   PetscInt  relax_type;
23054ddd07fcSJed Brown   PetscInt  rap_type;
23064ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
23074ddd07fcSJed Brown   PetscInt  max_levels;
23080be8cd64Sftrigaux   PetscInt  skip_relax;
23090be8cd64Sftrigaux   PetscBool print_statistics;
2310ebc551c0SBarry Smith } PC_PFMG;
2311ebc551c0SBarry Smith 
2312d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_PFMG(PC pc)
2313d71ae5a4SJacob Faibussowitsch {
2314f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2315ebc551c0SBarry Smith 
2316ebc551c0SBarry Smith   PetscFunctionBegin;
2317792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
23189566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
23199566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2320ebc551c0SBarry Smith   PetscFunctionReturn(0);
2321ebc551c0SBarry Smith }
2322ebc551c0SBarry Smith 
23239e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
23249e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
23259e5bc791SBarry Smith 
2326d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2327d71ae5a4SJacob Faibussowitsch {
2328ace3abfcSBarry Smith   PetscBool iascii;
2329f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2330ebc551c0SBarry Smith 
2331ebc551c0SBarry Smith   PetscFunctionBegin;
23329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
23339e5bc791SBarry Smith   if (iascii) {
23349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
233563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
23369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
23379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
23389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
233963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
234063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
23410be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
23429e5bc791SBarry Smith   }
2343ebc551c0SBarry Smith   PetscFunctionReturn(0);
2344ebc551c0SBarry Smith }
2345ebc551c0SBarry Smith 
2346d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2347d71ae5a4SJacob Faibussowitsch {
2348f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2349ebc551c0SBarry Smith 
2350ebc551c0SBarry Smith   PetscFunctionBegin;
2351d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
23520be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
23539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2354792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
23559566063dSJacob 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));
2356792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
23579566063dSJacob 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));
2358792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
23599e5bc791SBarry Smith 
23609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2361792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
23623b46a515SGlenn Hammond 
23639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2364792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2365dd39110bSPierre 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));
2366792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2367dd39110bSPierre 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));
2368792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
23690be8cd64Sftrigaux   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));
23700be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2371d0609cedSBarry Smith   PetscOptionsHeadEnd();
2372ebc551c0SBarry Smith   PetscFunctionReturn(0);
2373ebc551c0SBarry Smith }
2374ebc551c0SBarry Smith 
2375d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2376d71ae5a4SJacob Faibussowitsch {
2377f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2378d9ca1df4SBarry Smith   PetscScalar       *yy;
2379d9ca1df4SBarry Smith   const PetscScalar *xx;
23804ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
23812cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
238268326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2383f91d8e95SBarry Smith 
2384f91d8e95SBarry Smith   PetscFunctionBegin;
23859566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
23869566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
23872cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2388f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2389f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2390f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
23912cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
23922cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
23932cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
23942cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
23952cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
23962cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2397f91d8e95SBarry Smith 
2398f91d8e95SBarry Smith   /* copy x values over to hypre */
2399792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
24009566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2401792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
24029566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2403792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2404792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2405f91d8e95SBarry Smith 
2406f91d8e95SBarry Smith   /* copy solution values back to PETSc */
24079566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2408792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
24099566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2410f91d8e95SBarry Smith   PetscFunctionReturn(0);
2411f91d8e95SBarry Smith }
2412f91d8e95SBarry Smith 
2413d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_PFMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
2414d71ae5a4SJacob Faibussowitsch {
24159e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
24162cf14000SStefano Zampini   HYPRE_Int oits;
24179e5bc791SBarry Smith 
24189e5bc791SBarry Smith   PetscFunctionBegin;
24199566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2420792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2421792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
24229e5bc791SBarry Smith 
24239566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2424792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
24259e5bc791SBarry Smith   *outits = oits;
24269e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
24279e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2428792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2429792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
24309e5bc791SBarry Smith   PetscFunctionReturn(0);
24319e5bc791SBarry Smith }
24329e5bc791SBarry Smith 
2433d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_PFMG(PC pc)
2434d71ae5a4SJacob Faibussowitsch {
24353a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
24363a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2437ace3abfcSBarry Smith   PetscBool        flg;
24383a32d3dbSGlenn Hammond 
24393a32d3dbSGlenn Hammond   PetscFunctionBegin;
24409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
244128b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
24423a32d3dbSGlenn Hammond 
24433a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2444792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2445792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
24460be8cd64Sftrigaux 
24470be8cd64Sftrigaux   // Print Hypre statistics about the solve process
24480be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
24490be8cd64Sftrigaux 
24500be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
24510be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24520be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24530be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24540be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24550be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
24560be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
24570be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24580be8cd64Sftrigaux 
2459792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2460792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
24613a32d3dbSGlenn Hammond   PetscFunctionReturn(0);
24623a32d3dbSGlenn Hammond }
24633a32d3dbSGlenn Hammond 
2464ebc551c0SBarry Smith /*MC
2465ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2466ebc551c0SBarry Smith 
2467f1580f4eSBarry Smith    Options Database Keys:
246867b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
246967b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
247067b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
247167b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
24729e5bc791SBarry 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
24730be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2474f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2475f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2476f1580f4eSBarry Smith 
2477f1580f4eSBarry Smith    Level: advanced
2478f91d8e95SBarry Smith 
247995452b02SPatrick Sanan    Notes:
248095452b02SPatrick Sanan    This is for CELL-centered descretizations
24819e5bc791SBarry Smith 
2482f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
24839e5bc791SBarry Smith 
2484f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2485f1580f4eSBarry Smith 
2486f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2487f1580f4eSBarry Smith 
2488f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2489f1580f4eSBarry Smith 
2490f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2491ebc551c0SBarry Smith M*/
2492ebc551c0SBarry Smith 
2493d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2494d71ae5a4SJacob Faibussowitsch {
2495ebc551c0SBarry Smith   PC_PFMG *ex;
2496ebc551c0SBarry Smith 
2497ebc551c0SBarry Smith   PetscFunctionBegin;
24989371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
249968326731SBarry Smith   pc->data = ex;
2500ebc551c0SBarry Smith 
25019e5bc791SBarry Smith   ex->its              = 1;
25029e5bc791SBarry Smith   ex->tol              = 1.e-8;
25039e5bc791SBarry Smith   ex->relax_type       = 1;
25049e5bc791SBarry Smith   ex->rap_type         = 0;
25059e5bc791SBarry Smith   ex->num_pre_relax    = 1;
25069e5bc791SBarry Smith   ex->num_post_relax   = 1;
25073b46a515SGlenn Hammond   ex->max_levels       = 0;
25080be8cd64Sftrigaux   ex->skip_relax       = 0;
25090be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
25109e5bc791SBarry Smith 
2511ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2512ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2513ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2514f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
25159e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
251668326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
25172fa5cd67SKarl Rupp 
25189566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2519792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
2520ebc551c0SBarry Smith   PetscFunctionReturn(0);
2521ebc551c0SBarry Smith }
2522d851a50bSGlenn Hammond 
2523d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2524d851a50bSGlenn Hammond typedef struct {
2525d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2526d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2527d851a50bSGlenn Hammond 
2528d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
25294ddd07fcSJed Brown   PetscInt its;
2530d851a50bSGlenn Hammond   double   tol;
25314ddd07fcSJed Brown   PetscInt relax_type;
25324ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2533d851a50bSGlenn Hammond } PC_SysPFMG;
2534d851a50bSGlenn Hammond 
2535d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SysPFMG(PC pc)
2536d71ae5a4SJacob Faibussowitsch {
2537d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2538d851a50bSGlenn Hammond 
2539d851a50bSGlenn Hammond   PetscFunctionBegin;
2540792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
25419566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
25429566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2543d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2544d851a50bSGlenn Hammond }
2545d851a50bSGlenn Hammond 
2546d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2547d851a50bSGlenn Hammond 
2548d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2549d71ae5a4SJacob Faibussowitsch {
2550ace3abfcSBarry Smith   PetscBool   iascii;
2551d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2552d851a50bSGlenn Hammond 
2553d851a50bSGlenn Hammond   PetscFunctionBegin;
25549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2555d851a50bSGlenn Hammond   if (iascii) {
25569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
255763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
25589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
25599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
256063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2561d851a50bSGlenn Hammond   }
2562d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2563d851a50bSGlenn Hammond }
2564d851a50bSGlenn Hammond 
2565d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2566d71ae5a4SJacob Faibussowitsch {
2567d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2568ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2569d851a50bSGlenn Hammond 
2570d851a50bSGlenn Hammond   PetscFunctionBegin;
2571d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
25729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
257348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
25749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2575792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
25769566063dSJacob 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));
2577792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
25789566063dSJacob 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));
2579792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2580d851a50bSGlenn Hammond 
25819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2582792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2583dd39110bSPierre 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));
2584792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2585d0609cedSBarry Smith   PetscOptionsHeadEnd();
2586d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2587d851a50bSGlenn Hammond }
2588d851a50bSGlenn Hammond 
2589d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2590d71ae5a4SJacob Faibussowitsch {
2591d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2592d9ca1df4SBarry Smith   PetscScalar       *yy;
2593d9ca1df4SBarry Smith   const PetscScalar *xx;
25944ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
25952cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2596d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
25974ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
25984ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
25994ddd07fcSJed Brown   PetscInt           part     = 0;
26004ddd07fcSJed Brown   PetscInt           size;
26014ddd07fcSJed Brown   PetscInt           i;
2602d851a50bSGlenn Hammond 
2603d851a50bSGlenn Hammond   PetscFunctionBegin;
26049566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
26059566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
26062cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2607d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2608d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2609d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
26102cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
26112cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
26122cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
26132cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
26142cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
26152cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2616d851a50bSGlenn Hammond 
2617d851a50bSGlenn Hammond   size = 1;
26182fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
26192fa5cd67SKarl Rupp 
2620d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2621d851a50bSGlenn Hammond   if (ordering) {
2622792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26239566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2624792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
26259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2626792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2627792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2628792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2629d851a50bSGlenn Hammond 
2630d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26319566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2632792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
26339566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2634a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2635d851a50bSGlenn Hammond     PetscScalar *z;
26364ddd07fcSJed Brown     PetscInt     j, k;
2637d851a50bSGlenn Hammond 
26389566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2639792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26409566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2641d851a50bSGlenn Hammond 
2642d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2643d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2644d851a50bSGlenn Hammond       k = i * nvars;
26452fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2646d851a50bSGlenn Hammond     }
2647792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
26489566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2649792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2650792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2651d851a50bSGlenn Hammond 
2652d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26539566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2654792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2655d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2656d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2657d851a50bSGlenn Hammond       k = i * nvars;
26582fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2659d851a50bSGlenn Hammond     }
26609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
26619566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2662d851a50bSGlenn Hammond   }
2663d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2664d851a50bSGlenn Hammond }
2665d851a50bSGlenn Hammond 
2666d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_SysPFMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
2667d71ae5a4SJacob Faibussowitsch {
2668d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
26692cf14000SStefano Zampini   HYPRE_Int   oits;
2670d851a50bSGlenn Hammond 
2671d851a50bSGlenn Hammond   PetscFunctionBegin;
26729566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2673792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2674792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
26759566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2676792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2677d851a50bSGlenn Hammond   *outits = oits;
2678d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2679d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2680792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2681792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
2682d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2683d851a50bSGlenn Hammond }
2684d851a50bSGlenn Hammond 
2685d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SysPFMG(PC pc)
2686d71ae5a4SJacob Faibussowitsch {
2687d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2688d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2689ace3abfcSBarry Smith   PetscBool         flg;
2690d851a50bSGlenn Hammond 
2691d851a50bSGlenn Hammond   PetscFunctionBegin;
26929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
269328b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2694d851a50bSGlenn Hammond 
2695d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2696792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2697792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2698792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2699792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2700d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2701d851a50bSGlenn Hammond }
2702d851a50bSGlenn Hammond 
2703d851a50bSGlenn Hammond /*MC
2704f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2705d851a50bSGlenn Hammond 
2706d851a50bSGlenn Hammond    Level: advanced
2707d851a50bSGlenn Hammond 
2708f1580f4eSBarry Smith    Options Database Keys:
270967b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
271067b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
271167b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
271267b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
271367b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2714d851a50bSGlenn Hammond 
271595452b02SPatrick Sanan    Notes:
2716f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2717f1580f4eSBarry Smith 
2718f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2719f1580f4eSBarry Smith 
272095452b02SPatrick Sanan    This is for CELL-centered descretizations
2721d851a50bSGlenn Hammond 
2722f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2723d851a50bSGlenn Hammond 
2724f1580f4eSBarry 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`.
2725f1580f4eSBarry Smith 
2726f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2727d851a50bSGlenn Hammond M*/
2728d851a50bSGlenn Hammond 
2729d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2730d71ae5a4SJacob Faibussowitsch {
2731d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2732d851a50bSGlenn Hammond 
2733d851a50bSGlenn Hammond   PetscFunctionBegin;
27349371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2735d851a50bSGlenn Hammond   pc->data = ex;
2736d851a50bSGlenn Hammond 
2737d851a50bSGlenn Hammond   ex->its            = 1;
2738d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2739d851a50bSGlenn Hammond   ex->relax_type     = 1;
2740d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2741d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2742d851a50bSGlenn Hammond 
2743d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2744d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2745d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2746d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2747d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2748d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
27492fa5cd67SKarl Rupp 
27509566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2751792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2752d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2753d851a50bSGlenn Hammond }
27541c188c59Sftrigaux 
2755f1580f4eSBarry Smith /* PC SMG */
27561c188c59Sftrigaux typedef struct {
27571c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
27581c188c59Sftrigaux   HYPRE_StructSolver hsolver;
27591c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
27601c188c59Sftrigaux   double             tol;
27611c188c59Sftrigaux   PetscBool          print_statistics;
27621c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
27631c188c59Sftrigaux } PC_SMG;
27641c188c59Sftrigaux 
2765d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SMG(PC pc)
2766d71ae5a4SJacob Faibussowitsch {
27671c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
27681c188c59Sftrigaux 
27691c188c59Sftrigaux   PetscFunctionBegin;
27701c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
27711c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
27721c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
27731c188c59Sftrigaux   PetscFunctionReturn(0);
27741c188c59Sftrigaux }
27751c188c59Sftrigaux 
2776d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2777d71ae5a4SJacob Faibussowitsch {
27781c188c59Sftrigaux   PetscBool iascii;
27791c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
27801c188c59Sftrigaux 
27811c188c59Sftrigaux   PetscFunctionBegin;
27821c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
27831c188c59Sftrigaux   if (iascii) {
27841c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
27851c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27861c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27871c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
27881c188c59Sftrigaux   }
27891c188c59Sftrigaux   PetscFunctionReturn(0);
27901c188c59Sftrigaux }
27911c188c59Sftrigaux 
2792d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2793d71ae5a4SJacob Faibussowitsch {
27941c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
27951c188c59Sftrigaux 
27961c188c59Sftrigaux   PetscFunctionBegin;
27971c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
27981c188c59Sftrigaux 
27991c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
28001c188c59Sftrigaux   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));
28011c188c59Sftrigaux   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));
28021c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
28031c188c59Sftrigaux 
28041c188c59Sftrigaux   PetscOptionsHeadEnd();
28051c188c59Sftrigaux   PetscFunctionReturn(0);
28061c188c59Sftrigaux }
28071c188c59Sftrigaux 
2808d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2809d71ae5a4SJacob Faibussowitsch {
28101c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
28111c188c59Sftrigaux   PetscScalar       *yy;
28121c188c59Sftrigaux   const PetscScalar *xx;
28131c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
28141c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
28151c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28161c188c59Sftrigaux 
28171c188c59Sftrigaux   PetscFunctionBegin;
28181c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28191c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28201c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
28211c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
28221c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
28231c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
28241c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
28251c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
28261c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
28271c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
28281c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
28291c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
28301c188c59Sftrigaux 
28311c188c59Sftrigaux   /* copy x values over to hypre */
28321c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
28331c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
28341c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
28351c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
28361c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
28371c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
28381c188c59Sftrigaux 
28391c188c59Sftrigaux   /* copy solution values back to PETSc */
28401c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
28411c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
28421c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
28431c188c59Sftrigaux   PetscFunctionReturn(0);
28441c188c59Sftrigaux }
28451c188c59Sftrigaux 
2846d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_SMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
2847d71ae5a4SJacob Faibussowitsch {
28481c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
28491c188c59Sftrigaux   HYPRE_Int oits;
28501c188c59Sftrigaux 
28511c188c59Sftrigaux   PetscFunctionBegin;
28521c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28531c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
28541c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
28551c188c59Sftrigaux 
28561c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
28571c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
28581c188c59Sftrigaux   *outits = oits;
28591c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
28601c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
28611c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
28621c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
28631c188c59Sftrigaux   PetscFunctionReturn(0);
28641c188c59Sftrigaux }
28651c188c59Sftrigaux 
2866d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SMG(PC pc)
2867d71ae5a4SJacob Faibussowitsch {
28681c188c59Sftrigaux   PetscInt         i, dim;
28691c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
28701c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28711c188c59Sftrigaux   PetscBool        flg;
28721c188c59Sftrigaux   DMBoundaryType   p[3];
28731c188c59Sftrigaux   PetscInt         M[3];
28741c188c59Sftrigaux 
28751c188c59Sftrigaux   PetscFunctionBegin;
28761c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
28771c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
28781c188c59Sftrigaux 
28791c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
28801c188c59Sftrigaux   // Check if power of 2 in periodic directions
28811c188c59Sftrigaux   for (i = 0; i < dim; i++) {
28821c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
28831c188c59Sftrigaux       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]);
28841c188c59Sftrigaux     }
28851c188c59Sftrigaux   }
28861c188c59Sftrigaux 
28871c188c59Sftrigaux   /* create the hypre solver object and set its information */
28881c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
28891c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
28901c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
28911c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
28921c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28931c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28941c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
28951c188c59Sftrigaux 
28961c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
28971c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
28981c188c59Sftrigaux   PetscFunctionReturn(0);
28991c188c59Sftrigaux }
29001c188c59Sftrigaux 
29011c188c59Sftrigaux /*MC
29025cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
29031c188c59Sftrigaux 
29041c188c59Sftrigaux    Level: advanced
29051c188c59Sftrigaux 
2906f1580f4eSBarry Smith    Options Database Keys:
29075cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
29085cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
29095cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
29105cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
29111c188c59Sftrigaux 
29121c188c59Sftrigaux    Notes:
29131c188c59Sftrigaux    This is for CELL-centered descretizations
29141c188c59Sftrigaux 
29155cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
29161c188c59Sftrigaux 
2917f1580f4eSBarry 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`.
2918f1580f4eSBarry Smith 
2919f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
2920f1580f4eSBarry Smith 
2921f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
29221c188c59Sftrigaux M*/
29231c188c59Sftrigaux 
2924d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
2925d71ae5a4SJacob Faibussowitsch {
29261c188c59Sftrigaux   PC_SMG *ex;
29271c188c59Sftrigaux 
29281c188c59Sftrigaux   PetscFunctionBegin;
29299371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
29301c188c59Sftrigaux   pc->data = ex;
29311c188c59Sftrigaux 
29321c188c59Sftrigaux   ex->its            = 1;
29331c188c59Sftrigaux   ex->tol            = 1.e-8;
29341c188c59Sftrigaux   ex->num_pre_relax  = 1;
29351c188c59Sftrigaux   ex->num_post_relax = 1;
29361c188c59Sftrigaux 
29371c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
29381c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
29391c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
29401c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
29411c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
29421c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
29431c188c59Sftrigaux 
29441c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
29451c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
29461c188c59Sftrigaux   PetscFunctionReturn(0);
29471c188c59Sftrigaux }
2948