xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 0df1829c822d5ea78ef18e1c38d3e8afa8384ef9)
116d9e3a6SLisandro Dalcin /*
216d9e3a6SLisandro Dalcin    Provides an interface to the LLNL package hypre
316d9e3a6SLisandro Dalcin */
40f1074feSSatish Balay 
5589dcaf0SStefano Zampini #include <petscpkg_version.h>
6af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/
749a781f5SStefano Zampini /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */
849a781f5SStefano Zampini #include <petsc/private/matimpl.h>
96ea7df73SStefano Zampini #include <petsc/private/vecimpl.h>
1058968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1149a781f5SStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
12c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
134cb006feSStefano Zampini #include <_hypre_parcsr_ls.h>
148a2c336bSFande Kong #include <petscmathypre.h>
1516d9e3a6SLisandro Dalcin 
16a4af0ceeSJacob Faibussowitsch #if defined(PETSC_HAVE_HYPRE_DEVICE)
17a4af0ceeSJacob Faibussowitsch   #include <petsc/private/deviceimpl.h>
18a4af0ceeSJacob Faibussowitsch #endif
19a4af0ceeSJacob Faibussowitsch 
20dff31646SBarry Smith static PetscBool  cite            = PETSC_FALSE;
219371c9d4SSatish Balay static const char hypreCitation[] = "@manual{hypre-web-page,\n  title  = {{\\sl hypre}: High Performance Preconditioners},\n  organization = {Lawrence Livermore National Laboratory},\n  note  = "
22bd87328aSJed Brown                                     "{\\url{https://www.llnl.gov/casc/hypre}}\n}\n";
231f817a21SBarry Smith 
2416d9e3a6SLisandro Dalcin /*
2516d9e3a6SLisandro Dalcin    Private context (data structure) for the  preconditioner.
2616d9e3a6SLisandro Dalcin */
2716d9e3a6SLisandro Dalcin typedef struct {
2816d9e3a6SLisandro Dalcin   HYPRE_Solver hsolver;
2949a781f5SStefano Zampini   Mat          hpmat; /* MatHYPRE */
3016d9e3a6SLisandro Dalcin 
314ddd07fcSJed Brown   HYPRE_Int (*destroy)(HYPRE_Solver);
324ddd07fcSJed Brown   HYPRE_Int (*solve)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
334ddd07fcSJed Brown   HYPRE_Int (*setup)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
3416d9e3a6SLisandro Dalcin 
3516d9e3a6SLisandro Dalcin   MPI_Comm comm_hypre;
3616d9e3a6SLisandro Dalcin   char    *hypre_type;
3716d9e3a6SLisandro Dalcin 
3816d9e3a6SLisandro Dalcin   /* options for Pilut and BoomerAMG*/
394ddd07fcSJed Brown   PetscInt  maxiter;
4039accc25SStefano Zampini   PetscReal tol;
4116d9e3a6SLisandro Dalcin 
4216d9e3a6SLisandro Dalcin   /* options for Pilut */
434ddd07fcSJed Brown   PetscInt factorrowsize;
4416d9e3a6SLisandro Dalcin 
4516d9e3a6SLisandro Dalcin   /* options for ParaSails */
464ddd07fcSJed Brown   PetscInt  nlevels;
478966356dSPierre Jolivet   PetscReal threshold;
4839accc25SStefano Zampini   PetscReal filter;
4939accc25SStefano Zampini   PetscReal loadbal;
504ddd07fcSJed Brown   PetscInt  logging;
514ddd07fcSJed Brown   PetscInt  ruse;
524ddd07fcSJed Brown   PetscInt  symt;
5316d9e3a6SLisandro Dalcin 
5422b6d1caSBarry Smith   /* options for BoomerAMG */
55ace3abfcSBarry Smith   PetscBool printstatistics;
5616d9e3a6SLisandro Dalcin 
5716d9e3a6SLisandro Dalcin   /* options for BoomerAMG */
584ddd07fcSJed Brown   PetscInt  cycletype;
594ddd07fcSJed Brown   PetscInt  maxlevels;
6039accc25SStefano Zampini   PetscReal strongthreshold;
6139accc25SStefano Zampini   PetscReal maxrowsum;
624ddd07fcSJed Brown   PetscInt  gridsweeps[3];
634ddd07fcSJed Brown   PetscInt  coarsentype;
644ddd07fcSJed Brown   PetscInt  measuretype;
656a251517SEike Mueller   PetscInt  smoothtype;
668131ecf7SEike Mueller   PetscInt  smoothnumlevels;
67ec64516dSEike Mueller   PetscInt  eu_level;         /* Number of levels for ILU(k) in Euclid */
6839accc25SStefano Zampini   PetscReal eu_droptolerance; /* Drop tolerance for ILU(k) in Euclid */
69ec64516dSEike Mueller   PetscInt  eu_bj;            /* Defines use of Block Jacobi ILU in Euclid */
704ddd07fcSJed Brown   PetscInt  relaxtype[3];
7139accc25SStefano Zampini   PetscReal relaxweight;
7239accc25SStefano Zampini   PetscReal outerrelaxweight;
734ddd07fcSJed Brown   PetscInt  relaxorder;
7439accc25SStefano Zampini   PetscReal truncfactor;
75ace3abfcSBarry Smith   PetscBool applyrichardson;
764ddd07fcSJed Brown   PetscInt  pmax;
774ddd07fcSJed Brown   PetscInt  interptype;
78589dcaf0SStefano Zampini   PetscInt  maxc;
79589dcaf0SStefano Zampini   PetscInt  minc;
80db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
81db6f9c32SMark Adams   char *spgemm_type; // this is a global hypre parameter but is closely associated with BoomerAMG
82db6f9c32SMark Adams #endif
836ea7df73SStefano Zampini   /* GPU */
846ea7df73SStefano Zampini   PetscBool keeptranspose;
856ea7df73SStefano Zampini   PetscInt  rap2;
866ea7df73SStefano Zampini   PetscInt  mod_rap2;
876ea7df73SStefano Zampini 
88589dcaf0SStefano Zampini   /* AIR */
89589dcaf0SStefano Zampini   PetscInt  Rtype;
90589dcaf0SStefano Zampini   PetscReal Rstrongthreshold;
91589dcaf0SStefano Zampini   PetscReal Rfilterthreshold;
92589dcaf0SStefano Zampini   PetscInt  Adroptype;
93589dcaf0SStefano Zampini   PetscReal Adroptol;
94589dcaf0SStefano Zampini 
954ddd07fcSJed Brown   PetscInt  agg_nl;
966ea7df73SStefano Zampini   PetscInt  agg_interptype;
974ddd07fcSJed Brown   PetscInt  agg_num_paths;
98ace3abfcSBarry Smith   PetscBool nodal_relax;
994ddd07fcSJed Brown   PetscInt  nodal_relax_levels;
1004cb006feSStefano Zampini 
1015272c319SBarry Smith   PetscInt  nodal_coarsening;
10222e51d31SStefano Zampini   PetscInt  nodal_coarsening_diag;
1035272c319SBarry Smith   PetscInt  vec_interp_variant;
10422e51d31SStefano Zampini   PetscInt  vec_interp_qmax;
10522e51d31SStefano Zampini   PetscBool vec_interp_smooth;
10622e51d31SStefano Zampini   PetscInt  interp_refine;
10722e51d31SStefano Zampini 
1086ea7df73SStefano Zampini   /* NearNullSpace support */
1096ea7df73SStefano Zampini   VecHYPRE_IJVector *hmnull;
1106ea7df73SStefano Zampini   HYPRE_ParVector   *phmnull;
1115272c319SBarry Smith   PetscInt           n_hmnull;
1125272c319SBarry Smith   Vec                hmnull_constant;
1135272c319SBarry Smith 
114863406b8SStefano Zampini   /* options for AS (Auxiliary Space preconditioners) */
115863406b8SStefano Zampini   PetscInt  as_print;
116863406b8SStefano Zampini   PetscInt  as_max_iter;
117863406b8SStefano Zampini   PetscReal as_tol;
118863406b8SStefano Zampini   PetscInt  as_relax_type;
119863406b8SStefano Zampini   PetscInt  as_relax_times;
120863406b8SStefano Zampini   PetscReal as_relax_weight;
121863406b8SStefano Zampini   PetscReal as_omega;
122863406b8SStefano Zampini   PetscInt  as_amg_alpha_opts[5]; /* AMG coarsen type, agg_levels, relax_type, interp_type, Pmax for vector Poisson (AMS) or Curl problem (ADS) */
123863406b8SStefano Zampini   PetscReal as_amg_alpha_theta;   /* AMG strength for vector Poisson (AMS) or Curl problem (ADS) */
124863406b8SStefano Zampini   PetscInt  as_amg_beta_opts[5];  /* AMG coarsen type, agg_levels, relax_type, interp_type, Pmax for scalar Poisson (AMS) or vector Poisson (ADS) */
125863406b8SStefano Zampini   PetscReal as_amg_beta_theta;    /* AMG strength for scalar Poisson (AMS) or vector Poisson (ADS)  */
1264cb006feSStefano Zampini   PetscInt  ams_cycle_type;
127863406b8SStefano Zampini   PetscInt  ads_cycle_type;
1284cb006feSStefano Zampini 
1294cb006feSStefano Zampini   /* additional data */
1305ac14e1cSStefano Zampini   Mat G;             /* MatHYPRE */
1315ac14e1cSStefano Zampini   Mat C;             /* MatHYPRE */
1325ac14e1cSStefano Zampini   Mat alpha_Poisson; /* MatHYPRE */
1335ac14e1cSStefano Zampini   Mat beta_Poisson;  /* MatHYPRE */
1345ac14e1cSStefano Zampini 
1355ac14e1cSStefano Zampini   /* extra information for AMS */
1365ac14e1cSStefano Zampini   PetscInt          dim; /* geometrical dimension */
1376ea7df73SStefano Zampini   VecHYPRE_IJVector coords[3];
1386ea7df73SStefano Zampini   VecHYPRE_IJVector constants[3];
139be14dc20SKerry Key   VecHYPRE_IJVector interior;
1406bf688a0SCe Qin   Mat               RT_PiFull, RT_Pi[3];
1416bf688a0SCe Qin   Mat               ND_PiFull, ND_Pi[3];
1424cb006feSStefano Zampini   PetscBool         ams_beta_is_zero;
14323df4f25SStefano Zampini   PetscBool         ams_beta_is_zero_part;
14423df4f25SStefano Zampini   PetscInt          ams_proj_freq;
14516d9e3a6SLisandro Dalcin } PC_HYPRE;
14616d9e3a6SLisandro Dalcin 
147d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetSolver(PC pc, HYPRE_Solver *hsolver)
148d71ae5a4SJacob Faibussowitsch {
149d2128fa2SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
150d2128fa2SBarry Smith 
151d2128fa2SBarry Smith   PetscFunctionBegin;
152d2128fa2SBarry Smith   *hsolver = jac->hsolver;
1533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
154d2128fa2SBarry Smith }
15516d9e3a6SLisandro Dalcin 
156fd2dd295SFande Kong /*
1578a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1588a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1598a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
160fd2dd295SFande Kong */
161d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[])
162d71ae5a4SJacob Faibussowitsch {
1638a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1648a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1658a2c336bSFande Kong   PetscInt             num_levels, l;
1668a2c336bSFande Kong   Mat                 *mattmp;
1678a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1688a2c336bSFande Kong 
1698a2c336bSFande Kong   PetscFunctionBegin;
1709566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1715f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1728a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1748a2c336bSFande Kong   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)(jac->hsolver));
1758a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1769566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[num_levels - 1 - l])));
1778a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1788a2c336bSFande Kong     A_array[l] = NULL;
1798a2c336bSFande Kong   }
1808a2c336bSFande Kong   *nlevels   = num_levels;
1818a2c336bSFande Kong   *operators = mattmp;
1823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1838a2c336bSFande Kong }
1848a2c336bSFande Kong 
185fd2dd295SFande Kong /*
1868a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1878a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1888a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
189fd2dd295SFande Kong */
190d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[])
191d71ae5a4SJacob Faibussowitsch {
1928a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1938a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1948a2c336bSFande Kong   PetscInt             num_levels, l;
1958a2c336bSFande Kong   Mat                 *mattmp;
1968a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1978a2c336bSFande Kong 
1988a2c336bSFande Kong   PetscFunctionBegin;
1999566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
2005f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
2018a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
2029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
2038a2c336bSFande Kong   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)(jac->hsolver));
2048a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
2059566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[l - 1])));
2068a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
2078a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
2088a2c336bSFande Kong   }
2098a2c336bSFande Kong   *nlevels        = num_levels;
2108a2c336bSFande Kong   *interpolations = mattmp;
2113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2128a2c336bSFande Kong }
2138a2c336bSFande Kong 
214ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
215d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
216d71ae5a4SJacob Faibussowitsch {
217ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
218ce6a8a0dSJed Brown   PetscInt  i;
219ce6a8a0dSJed Brown 
2209d678128SJed Brown   PetscFunctionBegin;
22148a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2229566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2259d678128SJed Brown   jac->n_hmnull = 0;
2263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227ce6a8a0dSJed Brown }
228ce6a8a0dSJed Brown 
229d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
230d71ae5a4SJacob Faibussowitsch {
23116d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
23249a781f5SStefano Zampini   Mat_HYPRE         *hjac;
23316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
23416d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
23549a781f5SStefano Zampini   PetscBool          ishypre;
23616d9e3a6SLisandro Dalcin 
23716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
238*0df1829cSStefano Zampini   /* default type is boomerAMG */
23948a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2405f5c5b43SBarry Smith 
241*0df1829cSStefano Zampini   /* get hypre matrix */
242*0df1829cSStefano Zampini   if (pc->flag == DIFFERENT_NONZERO_PATTERN) PetscCall(MatDestroy(&jac->hpmat));
2439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
24449a781f5SStefano Zampini   if (!ishypre) {
245*0df1829cSStefano Zampini     /* Temporary fix since we do not support MAT_REUSE_MATRIX with HYPRE device */
246*0df1829cSStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
247*0df1829cSStefano Zampini     PetscBool iscuda, iship, iskokkos;
248*0df1829cSStefano Zampini 
249*0df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
250*0df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
251*0df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iskokkos, MATSEQAIJKOKKOS, MATMPIAIJKOKKOS, ""));
252*0df1829cSStefano Zampini     if (iscuda || iship || iskokkos) PetscCall(MatDestroy(&jac->hpmat));
253*0df1829cSStefano Zampini #endif
254*0df1829cSStefano Zampini     PetscCall(MatConvert(pc->pmat, MATHYPRE, jac->hpmat ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &jac->hpmat));
25549a781f5SStefano Zampini   } else {
2569566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2579566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
25849a781f5SStefano Zampini     jac->hpmat = pc->pmat;
25916d9e3a6SLisandro Dalcin   }
260*0df1829cSStefano Zampini 
2616ea7df73SStefano Zampini   /* allow debug */
2629566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
26349a781f5SStefano Zampini   hjac = (Mat_HYPRE *)(jac->hpmat->data);
2645f5c5b43SBarry Smith 
26516d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
26616d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2675272c319SBarry Smith     MatNullSpace mnull;
2685272c319SBarry Smith     PetscBool    has_const;
26949a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2705272c319SBarry Smith     const Vec   *vecs;
2715272c319SBarry Smith 
2729566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
273792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2749566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2755272c319SBarry Smith     if (mnull) {
2769566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2779566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2789566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2805272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2819566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2829566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
283792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2845272c319SBarry Smith       }
2855272c319SBarry Smith       if (has_const) {
2869566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2879566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2889566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2899566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2909566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
291792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2925272c319SBarry Smith         nvec++;
2935272c319SBarry Smith       }
294792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2955272c319SBarry Smith       jac->n_hmnull = nvec;
2965272c319SBarry Smith     }
2974cb006feSStefano Zampini   }
298863406b8SStefano Zampini 
2994cb006feSStefano Zampini   /* special case for AMS */
3004cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
3015ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3025ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3036bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
304f1580f4eSBarry 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()");
3056bf688a0SCe Qin     }
30648a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
3075ac14e1cSStefano Zampini     if (jac->constants[0]) {
3085ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
309792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
310792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
31148a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
312792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
3135ac14e1cSStefano Zampini     }
3145ac14e1cSStefano Zampini     if (jac->coords[0]) {
3155ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3165ac14e1cSStefano Zampini       coords[0] = NULL;
3175ac14e1cSStefano Zampini       coords[1] = NULL;
3185ac14e1cSStefano Zampini       coords[2] = NULL;
319792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
320792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
321792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3235ac14e1cSStefano Zampini     }
3245f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3255ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
326792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
327792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3285ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3295ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->alpha_Poisson->data);
330792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
331792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3325ac14e1cSStefano Zampini     }
3335ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
334792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3355ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3365ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->beta_Poisson->data);
337792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
338792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
339be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
340be14dc20SKerry Key       if (jac->interior) {
341be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
342be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
343be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
344be14dc20SKerry Key       } else {
345be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
346be14dc20SKerry Key       }
3475ac14e1cSStefano Zampini     }
3486bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3496bf688a0SCe Qin       PetscInt           i;
3506bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3516bf688a0SCe Qin       if (jac->ND_PiFull) {
3526bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
353792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3546bf688a0SCe Qin       } else {
3556bf688a0SCe Qin         nd_parcsrfull = NULL;
3566bf688a0SCe Qin       }
3576bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3586bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3596bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
360792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3616bf688a0SCe Qin         } else {
3626bf688a0SCe Qin           nd_parcsr[i] = NULL;
3636bf688a0SCe Qin         }
3646bf688a0SCe Qin       }
365792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3666bf688a0SCe Qin     }
3674cb006feSStefano Zampini   }
368863406b8SStefano Zampini   /* special case for ADS */
369863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3705ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3715ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3726bf688a0SCe 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])))) {
3736bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3749371c9d4SSatish 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");
3755f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3765f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3775ac14e1cSStefano Zampini     if (jac->coords[0]) {
3785ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3795ac14e1cSStefano Zampini       coords[0] = NULL;
3805ac14e1cSStefano Zampini       coords[1] = NULL;
3815ac14e1cSStefano Zampini       coords[2] = NULL;
382792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
383792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
384792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
385792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3865ac14e1cSStefano Zampini     }
3875ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
388792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
389792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
3905ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->C->data);
391792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
392792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3936bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3946bf688a0SCe Qin       PetscInt           i;
3956bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3966bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3976bf688a0SCe Qin       if (jac->RT_PiFull) {
3986bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->RT_PiFull->data);
399792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
4006bf688a0SCe Qin       } else {
4016bf688a0SCe Qin         rt_parcsrfull = NULL;
4026bf688a0SCe Qin       }
4036bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4046bf688a0SCe Qin         if (jac->RT_Pi[i]) {
4056bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->RT_Pi[i]->data);
406792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
4076bf688a0SCe Qin         } else {
4086bf688a0SCe Qin           rt_parcsr[i] = NULL;
4096bf688a0SCe Qin         }
4106bf688a0SCe Qin       }
4116bf688a0SCe Qin       if (jac->ND_PiFull) {
4126bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
413792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4146bf688a0SCe Qin       } else {
4156bf688a0SCe Qin         nd_parcsrfull = NULL;
4166bf688a0SCe Qin       }
4176bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4186bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4196bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
420792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4216bf688a0SCe Qin         } else {
4226bf688a0SCe Qin           nd_parcsr[i] = NULL;
4236bf688a0SCe Qin         }
4246bf688a0SCe Qin       }
425792fecdfSBarry 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]);
4266bf688a0SCe Qin     }
427863406b8SStefano Zampini   }
428792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
429792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
430792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
43197c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
432792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
43397c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
4343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43516d9e3a6SLisandro Dalcin }
43616d9e3a6SLisandro Dalcin 
437d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
438d71ae5a4SJacob Faibussowitsch {
43916d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
44049a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
44116d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
44216d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
44316d9e3a6SLisandro Dalcin 
44416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4459566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4469566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4479566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4489566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4499566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
450792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
451792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
452792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4539371c9d4SSatish Balay   PetscStackCallExternalVoid(
4549371c9d4SSatish Balay     "Hypre solve", do {
4555f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4565f80ce2aSJacob Faibussowitsch       if (hierr) {
4575f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
45885245615SPierre Jolivet         HYPRE_ClearAllErrors();
4595f80ce2aSJacob Faibussowitsch       }
4605f80ce2aSJacob Faibussowitsch     } while (0));
46116d9e3a6SLisandro Dalcin 
46248a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4639566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4649566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
4653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46616d9e3a6SLisandro Dalcin }
46716d9e3a6SLisandro Dalcin 
46885245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
46985245615SPierre Jolivet {
47085245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
47185245615SPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)(jac->hpmat->data);
47285245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
47385245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
47485245615SPierre Jolivet   const PetscScalar  *b;
47585245615SPierre Jolivet   PetscScalar        *x;
47685245615SPierre Jolivet   PetscInt            m, N, lda;
47785245615SPierre Jolivet   hypre_Vector       *x_local;
47885245615SPierre Jolivet   PetscMemType        type;
47985245615SPierre Jolivet 
48085245615SPierre Jolivet   PetscFunctionBegin;
48185245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
48285245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
48385245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
48485245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
48585245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
48685245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
48785245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
48885245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
48985245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
49085245615SPierre Jolivet   PetscCheck(lda == m, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot use a LDA different than the number of local rows: % " PetscInt_FMT " != % " PetscInt_FMT, lda, m);
49185245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
49285245615SPierre Jolivet   PetscCheck(lda == m, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot use a LDA different than the number of local rows: % " PetscInt_FMT " != % " PetscInt_FMT, lda, m);
49385245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
49485245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
49585245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
49685245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
49785245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
49885245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
49985245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
50085245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
50185245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
50285245615SPierre Jolivet   PetscStackCallExternalVoid(
50385245615SPierre Jolivet     "Hypre solve", do {
50485245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
50585245615SPierre Jolivet       if (hierr) {
50685245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
50785245615SPierre Jolivet         HYPRE_ClearAllErrors();
50885245615SPierre Jolivet       }
50985245615SPierre Jolivet     } while (0));
51085245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
51185245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
51285245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
51385245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
51485245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
51585245615SPierre Jolivet }
51685245615SPierre Jolivet 
517d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
518d71ae5a4SJacob Faibussowitsch {
5198695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5208695de01SBarry Smith 
5218695de01SBarry Smith   PetscFunctionBegin;
5229566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
5239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
5249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
5259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
5269566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
5279566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
5289566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
5299566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
5309566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
5319566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
5329566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
5339566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
5349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
5359566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
5369566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
5379566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
5389566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
5399566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
5409566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
541be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
5429566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
5435ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
544be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
5455ac14e1cSStefano Zampini   jac->dim                   = 0;
5463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5478695de01SBarry Smith }
5488695de01SBarry Smith 
549d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
550d71ae5a4SJacob Faibussowitsch {
55116d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
55216d9e3a6SLisandro Dalcin 
55316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5549566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
555792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
5569566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
557db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
5589566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
559db6f9c32SMark Adams #endif
5609566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
5619566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
56216d9e3a6SLisandro Dalcin 
5639566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5712e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
572be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5772e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57916d9e3a6SLisandro Dalcin }
58016d9e3a6SLisandro Dalcin 
581d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
582d71ae5a4SJacob Faibussowitsch {
58316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
584ace3abfcSBarry Smith   PetscBool flag;
58516d9e3a6SLisandro Dalcin 
58616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
587d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
589792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
591792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
593792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
594d0609cedSBarry Smith   PetscOptionsHeadEnd();
5953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59616d9e3a6SLisandro Dalcin }
59716d9e3a6SLisandro Dalcin 
598d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
599d71ae5a4SJacob Faibussowitsch {
60016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
601ace3abfcSBarry Smith   PetscBool iascii;
60216d9e3a6SLisandro Dalcin 
60316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
60516d9e3a6SLisandro Dalcin   if (iascii) {
6069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
60716d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
60863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
60916d9e3a6SLisandro Dalcin     } else {
6109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
61116d9e3a6SLisandro Dalcin     }
61216d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
6139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
61416d9e3a6SLisandro Dalcin     } else {
6159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
61616d9e3a6SLisandro Dalcin     }
61716d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
61863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
61916d9e3a6SLisandro Dalcin     } else {
6209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
62116d9e3a6SLisandro Dalcin     }
62216d9e3a6SLisandro Dalcin   }
6233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62416d9e3a6SLisandro Dalcin }
62516d9e3a6SLisandro Dalcin 
626d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
627d71ae5a4SJacob Faibussowitsch {
628db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6298bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
630db966c6cSHong Zhang 
631db966c6cSHong Zhang   PetscFunctionBegin;
632d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
6339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
634792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
6358bf83915SBarry Smith 
6369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
6378bf83915SBarry Smith   if (flag) {
6388bf83915SBarry Smith     PetscMPIInt size;
6398bf83915SBarry Smith 
6409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
6417827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
642792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
6438bf83915SBarry Smith   }
6448bf83915SBarry Smith 
6459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
6468bf83915SBarry Smith   if (flag) {
6478bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
648792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
6498bf83915SBarry Smith   }
650d0609cedSBarry Smith   PetscOptionsHeadEnd();
6513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
652db966c6cSHong Zhang }
653db966c6cSHong Zhang 
654d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
655d71ae5a4SJacob Faibussowitsch {
656db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
657db966c6cSHong Zhang   PetscBool iascii;
658db966c6cSHong Zhang 
659db966c6cSHong Zhang   PetscFunctionBegin;
6609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
661db966c6cSHong Zhang   if (iascii) {
6629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
663db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
66463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
665db966c6cSHong Zhang     } else {
6669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
667db966c6cSHong Zhang     }
6689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
66963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
670db966c6cSHong Zhang   }
6713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
672db966c6cSHong Zhang }
673db966c6cSHong Zhang 
674d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
675d71ae5a4SJacob Faibussowitsch {
67616d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
67749a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
67816d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
67916d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
68016d9e3a6SLisandro Dalcin 
68116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6829566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6839566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6849566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6859566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
68616d9e3a6SLisandro Dalcin 
687792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
688792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
689792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
69016d9e3a6SLisandro Dalcin 
6919371c9d4SSatish Balay   PetscStackCallExternalVoid(
6929371c9d4SSatish Balay     "Hypre Transpose solve", do {
6935f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6945f80ce2aSJacob Faibussowitsch       if (hierr) {
69516d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6965f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
69785245615SPierre Jolivet         HYPRE_ClearAllErrors();
6985f80ce2aSJacob Faibussowitsch       }
6995f80ce2aSJacob Faibussowitsch     } while (0));
70016d9e3a6SLisandro Dalcin 
7019566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
7029566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
7033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70416d9e3a6SLisandro Dalcin }
70516d9e3a6SLisandro Dalcin 
706d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
707d71ae5a4SJacob Faibussowitsch {
708db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
709db6f9c32SMark Adams   PetscBool flag;
710db6f9c32SMark Adams 
711db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
712db6f9c32SMark Adams   PetscFunctionBegin;
713db6f9c32SMark Adams   if (jac->spgemm_type) {
7149566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
71528b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
7163ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
717db6f9c32SMark Adams   } else {
7189566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
719db6f9c32SMark Adams   }
7209566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
721db6f9c32SMark Adams   if (flag) {
722792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
7233ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
724db6f9c32SMark Adams   }
7259566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
726db6f9c32SMark Adams   if (flag) {
727792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
7283ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
729db6f9c32SMark Adams   }
730db6f9c32SMark Adams   jac->spgemm_type = NULL;
7312d6c3ceeSStefano Zampini   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEMM type %s; Choices are cusparse, hypre", name);
732db6f9c32SMark Adams #endif
733db6f9c32SMark Adams }
734db6f9c32SMark Adams 
735d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
736d71ae5a4SJacob Faibussowitsch {
737db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
738db6f9c32SMark Adams 
739db6f9c32SMark Adams   PetscFunctionBegin;
740db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
741db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
742db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
743db6f9c32SMark Adams #endif
7443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
745db6f9c32SMark Adams }
746db6f9c32SMark Adams 
74716d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
7480f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
74916d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
75065de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
7516a251517SEike Mueller static const char *HYPREBoomerAMGSmoothType[] = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
7529371c9d4SSatish 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"};
7539371c9d4SSatish 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"};
754d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
755d71ae5a4SJacob Faibussowitsch {
75616d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
75722e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
758ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
75916d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
760589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
761db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
76216d9e3a6SLisandro Dalcin 
76316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
764d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
7659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
76616d9e3a6SLisandro Dalcin   if (flg) {
7674336a9eeSBarry Smith     jac->cycletype = indx + 1;
768792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
76916d9e3a6SLisandro Dalcin   }
7709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
77116d9e3a6SLisandro Dalcin   if (flg) {
77263a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
773792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
77416d9e3a6SLisandro Dalcin   }
7759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
77616d9e3a6SLisandro Dalcin   if (flg) {
77763a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
778792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
77916d9e3a6SLisandro Dalcin   }
7809566063dSJacob 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));
78116d9e3a6SLisandro Dalcin   if (flg) {
78208401ef6SPierre 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);
783792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
78416d9e3a6SLisandro Dalcin   }
78522e51d31SStefano Zampini   bs = 1;
78648a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
78848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
78916d9e3a6SLisandro Dalcin 
7909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
79116d9e3a6SLisandro Dalcin   if (flg) {
79208401ef6SPierre 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);
793792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
79416d9e3a6SLisandro Dalcin   }
79516d9e3a6SLisandro Dalcin 
7969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7970f1074feSSatish Balay   if (flg) {
79863a3b9bcSJacob 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);
799792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
8000f1074feSSatish Balay   }
8010f1074feSSatish Balay 
8029566063dSJacob 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));
803792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
8040f1074feSSatish Balay 
8059566063dSJacob 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));
8060f1074feSSatish Balay   if (flg) {
80763a3b9bcSJacob 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);
808792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
8090f1074feSSatish Balay   }
8100f1074feSSatish Balay 
8119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
81216d9e3a6SLisandro Dalcin   if (flg) {
81308401ef6SPierre 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);
814792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
81516d9e3a6SLisandro Dalcin   }
8169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
81716d9e3a6SLisandro Dalcin   if (flg) {
81808401ef6SPierre 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);
81908401ef6SPierre 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);
820792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
82116d9e3a6SLisandro Dalcin   }
82216d9e3a6SLisandro Dalcin 
82316d9e3a6SLisandro Dalcin   /* Grid sweeps */
8249566063dSJacob 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));
82516d9e3a6SLisandro Dalcin   if (flg) {
826792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
82716d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
82816d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
8290f1074feSSatish Balay     jac->gridsweeps[1] = indx;
8300f1074feSSatish Balay     /*defaults coarse to 1 */
8310f1074feSSatish Balay     jac->gridsweeps[2] = 1;
83216d9e3a6SLisandro Dalcin   }
8339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
83448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
8359566063dSJacob 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));
83648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
8379566063dSJacob 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));
83848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
8399566063dSJacob 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));
84048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
8419566063dSJacob 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));
84248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
8439566063dSJacob 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));
84448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
8459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
84616d9e3a6SLisandro Dalcin   if (flg) {
847792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
8480f1074feSSatish Balay     jac->gridsweeps[0] = indx;
84916d9e3a6SLisandro Dalcin   }
8509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
85116d9e3a6SLisandro Dalcin   if (flg) {
852792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
8530f1074feSSatish Balay     jac->gridsweeps[1] = indx;
85416d9e3a6SLisandro Dalcin   }
8559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
85616d9e3a6SLisandro Dalcin   if (flg) {
857792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
8580f1074feSSatish Balay     jac->gridsweeps[2] = indx;
85916d9e3a6SLisandro Dalcin   }
86016d9e3a6SLisandro Dalcin 
8616a251517SEike Mueller   /* Smooth type */
862dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
8636a251517SEike Mueller   if (flg) {
8646a251517SEike Mueller     jac->smoothtype = indx;
865792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
8668131ecf7SEike Mueller     jac->smoothnumlevels = 25;
867792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
8688131ecf7SEike Mueller   }
8698131ecf7SEike Mueller 
8708131ecf7SEike Mueller   /* Number of smoothing levels */
8719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
8728131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8738131ecf7SEike Mueller     jac->smoothnumlevels = indx;
874792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8756a251517SEike Mueller   }
8766a251517SEike Mueller 
8771810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8791810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8801810e44eSEike Mueller     jac->eu_level = indx;
881792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8821810e44eSEike Mueller   }
8831810e44eSEike Mueller 
8841810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8851810e44eSEike Mueller   double droptolerance;
8869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8871810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8881810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
889792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8901810e44eSEike Mueller   }
8911810e44eSEike Mueller 
8921810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8941810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8951810e44eSEike Mueller     jac->eu_bj = tmp_truth;
896792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8971810e44eSEike Mueller   }
8981810e44eSEike Mueller 
89916d9e3a6SLisandro Dalcin   /* Relax type */
900dd39110bSPierre 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));
90116d9e3a6SLisandro Dalcin   if (flg) {
9020f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
903792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
9040f1074feSSatish Balay     /* by default, coarse type set to 9 */
9050f1074feSSatish Balay     jac->relaxtype[2] = 9;
906792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
90716d9e3a6SLisandro Dalcin   }
908dd39110bSPierre 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));
90916d9e3a6SLisandro Dalcin   if (flg) {
91016d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
911792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
91216d9e3a6SLisandro Dalcin   }
913dd39110bSPierre 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));
91416d9e3a6SLisandro Dalcin   if (flg) {
9150f1074feSSatish Balay     jac->relaxtype[1] = indx;
916792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
91716d9e3a6SLisandro Dalcin   }
918dd39110bSPierre 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));
91916d9e3a6SLisandro Dalcin   if (flg) {
9200f1074feSSatish Balay     jac->relaxtype[2] = indx;
921792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
92216d9e3a6SLisandro Dalcin   }
92316d9e3a6SLisandro Dalcin 
92416d9e3a6SLisandro Dalcin   /* Relaxation Weight */
9259566063dSJacob 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));
92616d9e3a6SLisandro Dalcin   if (flg) {
927792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
92816d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
92916d9e3a6SLisandro Dalcin   }
93016d9e3a6SLisandro Dalcin 
93116d9e3a6SLisandro Dalcin   n         = 2;
93216d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
93416d9e3a6SLisandro Dalcin   if (flg) {
9350fdf79fbSJacob 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);
93616d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
937792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
93816d9e3a6SLisandro Dalcin   }
93916d9e3a6SLisandro Dalcin 
94016d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
9419566063dSJacob 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));
94216d9e3a6SLisandro Dalcin   if (flg) {
943792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
94416d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
94516d9e3a6SLisandro Dalcin   }
94616d9e3a6SLisandro Dalcin 
94716d9e3a6SLisandro Dalcin   n         = 2;
94816d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9499566063dSJacob 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));
95016d9e3a6SLisandro Dalcin   if (flg) {
9510fdf79fbSJacob 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);
95216d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
953792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
95416d9e3a6SLisandro Dalcin   }
95516d9e3a6SLisandro Dalcin 
95616d9e3a6SLisandro Dalcin   /* the Relax Order */
9579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
95816d9e3a6SLisandro Dalcin 
9598afaa268SBarry Smith   if (flg && tmp_truth) {
96016d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
961792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
96216d9e3a6SLisandro Dalcin   }
963dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
96416d9e3a6SLisandro Dalcin   if (flg) {
96516d9e3a6SLisandro Dalcin     jac->measuretype = indx;
966792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
96716d9e3a6SLisandro Dalcin   }
9680f1074feSSatish Balay   /* update list length 3/07 */
969dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
97016d9e3a6SLisandro Dalcin   if (flg) {
97116d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
972792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
97316d9e3a6SLisandro Dalcin   }
9740f1074feSSatish Balay 
9759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
97648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
97848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
979db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
980db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
981dd39110bSPierre 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));
9822d6c3ceeSStefano Zampini   #if defined(PETSC_HAVE_HYPRE_DEVICE)
983db6f9c32SMark Adams   if (!flg) indx = 0;
9849566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
9852d6c3ceeSStefano Zampini   #else
9862d6c3ceeSStefano Zampini   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, "hypre"));
9872d6c3ceeSStefano Zampini   #endif
988db6f9c32SMark Adams #endif
989589dcaf0SStefano Zampini   /* AIR */
990589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9919566063dSJacob 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));
992792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
993589dcaf0SStefano Zampini   if (jac->Rtype) {
994589dcaf0SStefano 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 */
995589dcaf0SStefano Zampini 
9969566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
997792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
998589dcaf0SStefano Zampini 
9999566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
1000792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1001589dcaf0SStefano Zampini 
10029566063dSJacob 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));
1003792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1004589dcaf0SStefano Zampini 
10059566063dSJacob 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));
1006792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
1007589dcaf0SStefano Zampini   }
1008589dcaf0SStefano Zampini #endif
1009589dcaf0SStefano Zampini 
1010ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
101163a3b9bcSJacob 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);
1012ecae95adSPierre Jolivet #endif
1013ecae95adSPierre Jolivet 
10140f1074feSSatish Balay   /* new 3/07 */
1015dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1016589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1017589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1018792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
10190f1074feSSatish Balay   }
10200f1074feSSatish Balay 
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
102216d9e3a6SLisandro Dalcin   if (flg) {
1023b96a4a96SBarry Smith     level = 3;
10249566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
10252fa5cd67SKarl Rupp 
1026b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1027792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
10282ae77aedSBarry Smith   }
10292ae77aedSBarry Smith 
10309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
10312ae77aedSBarry Smith   if (flg) {
1032b96a4a96SBarry Smith     level = 3;
10339566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
10342fa5cd67SKarl Rupp 
1035b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1036792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
103716d9e3a6SLisandro Dalcin   }
10388f87f92bSBarry Smith 
10399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
10408f87f92bSBarry Smith   if (flg && tmp_truth) {
10418f87f92bSBarry Smith     PetscInt tmp_int;
10429566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
10438f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1044792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1045792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1046792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1047792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
10488f87f92bSBarry Smith   }
10498f87f92bSBarry Smith 
10509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1051792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1052589dcaf0SStefano Zampini 
1053589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1054dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1055589dcaf0SStefano Zampini   if (flg) {
1056589dcaf0SStefano Zampini     jac->symt = indx;
1057792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1058589dcaf0SStefano Zampini   }
1059589dcaf0SStefano Zampini 
1060d0609cedSBarry Smith   PetscOptionsHeadEnd();
10613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106216d9e3a6SLisandro Dalcin }
106316d9e3a6SLisandro Dalcin 
1064d71ae5a4SJacob 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)
1065d71ae5a4SJacob Faibussowitsch {
106616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
10672cf14000SStefano Zampini   HYPRE_Int oits;
106816d9e3a6SLisandro Dalcin 
106916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10709566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1071792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1072792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
107316d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
10749566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
107516d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1076792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
10774d0a8057SBarry Smith   *outits = oits;
10784d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10794d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1080792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1081792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
10823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
108316d9e3a6SLisandro Dalcin }
108416d9e3a6SLisandro Dalcin 
1085d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1086d71ae5a4SJacob Faibussowitsch {
108716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1088ace3abfcSBarry Smith   PetscBool iascii;
108916d9e3a6SLisandro Dalcin 
109016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
109216d9e3a6SLisandro Dalcin   if (iascii) {
10939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
10949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
109563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
109663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
10979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
10989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
10999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
110063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
110148a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
110263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
110363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
11040f1074feSSatish Balay 
11059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
110616d9e3a6SLisandro Dalcin 
110763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
110863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
110963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
111016d9e3a6SLisandro Dalcin 
11119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
11129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
11139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
111416d9e3a6SLisandro Dalcin 
11159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
11169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
111716d9e3a6SLisandro Dalcin 
111816d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
11199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
112016d9e3a6SLisandro Dalcin     } else {
11219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
112216d9e3a6SLisandro Dalcin     }
11236a251517SEike Mueller     if (jac->smoothtype != -1) {
11249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
112563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
11267e352d70SEike Mueller     } else {
11279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
11281810e44eSEike Mueller     }
11291810e44eSEike Mueller     if (jac->smoothtype == 3) {
113063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
11319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
113263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
11336a251517SEike Mueller     }
11349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
11359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
11369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
113748a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
11385272c319SBarry Smith     if (jac->vec_interp_variant) {
113963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
114063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
11419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
11428f87f92bSBarry Smith     }
114348a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1144db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
11459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
11462d6c3ceeSStefano Zampini #else
11472d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1148db6f9c32SMark Adams #endif
1149589dcaf0SStefano Zampini     /* AIR */
1150589dcaf0SStefano Zampini     if (jac->Rtype) {
115163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
11529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
11539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
11549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
115563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1156589dcaf0SStefano Zampini     }
115716d9e3a6SLisandro Dalcin   }
11583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
115916d9e3a6SLisandro Dalcin }
116016d9e3a6SLisandro Dalcin 
1161d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1162d71ae5a4SJacob Faibussowitsch {
116316d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
11644ddd07fcSJed Brown   PetscInt    indx;
1165ace3abfcSBarry Smith   PetscBool   flag;
116616d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
116716d9e3a6SLisandro Dalcin 
116816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1169d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
11709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
11719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1172792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
117316d9e3a6SLisandro Dalcin 
11749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1175792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
117616d9e3a6SLisandro Dalcin 
11779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1178792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
117916d9e3a6SLisandro Dalcin 
11809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1181792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
118216d9e3a6SLisandro Dalcin 
11839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1184792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
118516d9e3a6SLisandro Dalcin 
1186dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
118716d9e3a6SLisandro Dalcin   if (flag) {
118816d9e3a6SLisandro Dalcin     jac->symt = indx;
1189792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
119016d9e3a6SLisandro Dalcin   }
119116d9e3a6SLisandro Dalcin 
1192d0609cedSBarry Smith   PetscOptionsHeadEnd();
11933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119416d9e3a6SLisandro Dalcin }
119516d9e3a6SLisandro Dalcin 
1196d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1197d71ae5a4SJacob Faibussowitsch {
119816d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1199ace3abfcSBarry Smith   PetscBool   iascii;
1200feb237baSPierre Jolivet   const char *symt = 0;
120116d9e3a6SLisandro Dalcin 
120216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
12039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
120416d9e3a6SLisandro Dalcin   if (iascii) {
12059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
120663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
12079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
12089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
12099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
12109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
12119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
12122fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
12132fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
12142fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
121563a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
12169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
121716d9e3a6SLisandro Dalcin   }
12183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121916d9e3a6SLisandro Dalcin }
1220f1580f4eSBarry Smith 
1221d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1222d71ae5a4SJacob Faibussowitsch {
12234cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12244cb006feSStefano Zampini   PetscInt  n;
12254cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
12264cb006feSStefano Zampini 
12274cb006feSStefano Zampini   PetscFunctionBegin;
1228d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
12299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1230792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
12319566063dSJacob 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));
1232792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
12339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1234792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
12359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1236792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
12379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12389566063dSJacob 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));
12399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
124148a46eb9SPierre 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);
12429566063dSJacob 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));
12434cb006feSStefano Zampini   n = 5;
12449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
12454cb006feSStefano Zampini   if (flag || flag2) {
1246792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1247863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1248863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
12499371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1250a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
12514cb006feSStefano Zampini   }
12529566063dSJacob 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));
12534cb006feSStefano Zampini   n = 5;
12549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
12554cb006feSStefano Zampini   if (flag || flag2) {
1256792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1257863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1258863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
12599371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1260a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
12614cb006feSStefano Zampini   }
12629566063dSJacob 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));
126323df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1264792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
126523df4f25SStefano Zampini   }
1266d0609cedSBarry Smith   PetscOptionsHeadEnd();
12673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12684cb006feSStefano Zampini }
12694cb006feSStefano Zampini 
1270d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1271d71ae5a4SJacob Faibussowitsch {
12724cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12734cb006feSStefano Zampini   PetscBool iascii;
12744cb006feSStefano Zampini 
12754cb006feSStefano Zampini   PetscFunctionBegin;
12769566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
12774cb006feSStefano Zampini   if (iascii) {
12789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
127963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
128063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
128163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
128263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
128363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
128463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
128563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12864cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
12884cb006feSStefano Zampini     } else {
12899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
12904cb006feSStefano Zampini     }
129163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
129263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
129363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
129463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
129563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
129663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12974cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12984cb006feSStefano Zampini       if (jac->beta_Poisson) {
12999566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
13004cb006feSStefano Zampini       } else {
13019566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
13024cb006feSStefano Zampini       }
130363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
130463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
130563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
130663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
130763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
130863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
130948a46eb9SPierre 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));
131023df4f25SStefano Zampini     } else {
13119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
13124cb006feSStefano Zampini     }
13134cb006feSStefano Zampini   }
13143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13154cb006feSStefano Zampini }
13164cb006feSStefano Zampini 
1317d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1318d71ae5a4SJacob Faibussowitsch {
1319863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1320863406b8SStefano Zampini   PetscInt  n;
1321863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1322863406b8SStefano Zampini 
1323863406b8SStefano Zampini   PetscFunctionBegin;
1324d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
13259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1326792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
13279566063dSJacob 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));
1328792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
13299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1330792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
13319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1332792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
13339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
13349566063dSJacob 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));
13359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
13369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
133748a46eb9SPierre 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);
13389566063dSJacob 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));
1339863406b8SStefano Zampini   n = 5;
13409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
13419566063dSJacob 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));
1342863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1343792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1344863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1345863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1346863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
13479371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1348a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1349863406b8SStefano Zampini   }
13509566063dSJacob 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));
1351863406b8SStefano Zampini   n = 5;
13529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1353863406b8SStefano Zampini   if (flag || flag2) {
1354792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1355863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1356863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
13579371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1358a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1359863406b8SStefano Zampini   }
1360d0609cedSBarry Smith   PetscOptionsHeadEnd();
13613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1362863406b8SStefano Zampini }
1363863406b8SStefano Zampini 
1364d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1365d71ae5a4SJacob Faibussowitsch {
1366863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1367863406b8SStefano Zampini   PetscBool iascii;
1368863406b8SStefano Zampini 
1369863406b8SStefano Zampini   PetscFunctionBegin;
13709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1371863406b8SStefano Zampini   if (iascii) {
13729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
137363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
137463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
137563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
137663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
137763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
137863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
137963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
138163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
138263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
138363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
138463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
138563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
138663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
138763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
138963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
139063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
139163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
139263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
139363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
139463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1395863406b8SStefano Zampini   }
13963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1397863406b8SStefano Zampini }
1398863406b8SStefano Zampini 
1399d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1400d71ae5a4SJacob Faibussowitsch {
14014cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14025ac14e1cSStefano Zampini   PetscBool ishypre;
14034cb006feSStefano Zampini 
14044cb006feSStefano Zampini   PetscFunctionBegin;
14059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
14065ac14e1cSStefano Zampini   if (ishypre) {
14079566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
14089566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14095ac14e1cSStefano Zampini     jac->G = G;
14105ac14e1cSStefano Zampini   } else {
14119566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14129566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
14135ac14e1cSStefano Zampini   }
14143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14154cb006feSStefano Zampini }
14164cb006feSStefano Zampini 
14174cb006feSStefano Zampini /*@
1418f1580f4eSBarry Smith    PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
14194cb006feSStefano Zampini 
1420c3339decSBarry Smith    Collective
14214cb006feSStefano Zampini 
14224cb006feSStefano Zampini    Input Parameters:
14234cb006feSStefano Zampini +  pc - the preconditioning context
14244cb006feSStefano Zampini -  G - the discrete gradient
14254cb006feSStefano Zampini 
14264cb006feSStefano Zampini    Level: intermediate
14274cb006feSStefano Zampini 
142895452b02SPatrick Sanan    Notes:
142995452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1430147403d9SBarry Smith 
1431863406b8SStefano 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
14324cb006feSStefano Zampini 
1433f1580f4eSBarry Smith    Developer Note:
1434f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1435f1580f4eSBarry Smith 
1436f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
14374cb006feSStefano Zampini @*/
1438d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1439d71ae5a4SJacob Faibussowitsch {
14404cb006feSStefano Zampini   PetscFunctionBegin;
14414cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14424cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
14434cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1444cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
14453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14464cb006feSStefano Zampini }
14474cb006feSStefano Zampini 
1448d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1449d71ae5a4SJacob Faibussowitsch {
1450863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14515ac14e1cSStefano Zampini   PetscBool ishypre;
1452863406b8SStefano Zampini 
1453863406b8SStefano Zampini   PetscFunctionBegin;
14549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
14555ac14e1cSStefano Zampini   if (ishypre) {
14569566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
14579566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14585ac14e1cSStefano Zampini     jac->C = C;
14595ac14e1cSStefano Zampini   } else {
14609566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14619566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
14625ac14e1cSStefano Zampini   }
14633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1464863406b8SStefano Zampini }
1465863406b8SStefano Zampini 
1466863406b8SStefano Zampini /*@
1467f1580f4eSBarry Smith    PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1468863406b8SStefano Zampini 
1469c3339decSBarry Smith    Collective
1470863406b8SStefano Zampini 
1471863406b8SStefano Zampini    Input Parameters:
1472863406b8SStefano Zampini +  pc - the preconditioning context
1473863406b8SStefano Zampini -  C - the discrete curl
1474863406b8SStefano Zampini 
1475863406b8SStefano Zampini    Level: intermediate
1476863406b8SStefano Zampini 
147795452b02SPatrick Sanan    Notes:
147895452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1479147403d9SBarry Smith 
1480863406b8SStefano 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
1481863406b8SStefano Zampini 
1482f1580f4eSBarry Smith    Developer Note:
1483f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1484f1580f4eSBarry Smith 
1485f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1486f1580f4eSBarry Smith 
1487f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1488863406b8SStefano Zampini @*/
1489d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1490d71ae5a4SJacob Faibussowitsch {
1491863406b8SStefano Zampini   PetscFunctionBegin;
1492863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1493863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1494863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1495cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
14963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1497863406b8SStefano Zampini }
1498863406b8SStefano Zampini 
1499d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1500d71ae5a4SJacob Faibussowitsch {
15016bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15026bf688a0SCe Qin   PetscBool ishypre;
15036bf688a0SCe Qin   PetscInt  i;
15046bf688a0SCe Qin   PetscFunctionBegin;
15056bf688a0SCe Qin 
15069566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
15079566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
15086bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
15099566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
15109566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
15116bf688a0SCe Qin   }
15126bf688a0SCe Qin 
15136bf688a0SCe Qin   jac->dim = dim;
15146bf688a0SCe Qin   if (RT_PiFull) {
15159566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
15166bf688a0SCe Qin     if (ishypre) {
15179566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
15186bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
15196bf688a0SCe Qin     } else {
15209566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
15216bf688a0SCe Qin     }
15226bf688a0SCe Qin   }
15236bf688a0SCe Qin   if (RT_Pi) {
15246bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15256bf688a0SCe Qin       if (RT_Pi[i]) {
15269566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
15276bf688a0SCe Qin         if (ishypre) {
15289566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
15296bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
15306bf688a0SCe Qin         } else {
15319566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
15326bf688a0SCe Qin         }
15336bf688a0SCe Qin       }
15346bf688a0SCe Qin     }
15356bf688a0SCe Qin   }
15366bf688a0SCe Qin   if (ND_PiFull) {
15379566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
15386bf688a0SCe Qin     if (ishypre) {
15399566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
15406bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
15416bf688a0SCe Qin     } else {
15429566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
15436bf688a0SCe Qin     }
15446bf688a0SCe Qin   }
15456bf688a0SCe Qin   if (ND_Pi) {
15466bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15476bf688a0SCe Qin       if (ND_Pi[i]) {
15489566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
15496bf688a0SCe Qin         if (ishypre) {
15509566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
15516bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
15526bf688a0SCe Qin         } else {
15539566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
15546bf688a0SCe Qin         }
15556bf688a0SCe Qin       }
15566bf688a0SCe Qin     }
15576bf688a0SCe Qin   }
15586bf688a0SCe Qin 
15593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15606bf688a0SCe Qin }
15616bf688a0SCe Qin 
15626bf688a0SCe Qin /*@
1563f1580f4eSBarry Smith    PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
15646bf688a0SCe Qin 
1565c3339decSBarry Smith    Collective
15666bf688a0SCe Qin 
15676bf688a0SCe Qin    Input Parameters:
15686bf688a0SCe Qin +  pc - the preconditioning context
15692fe279fdSBarry Smith .  dim - the dimension of the problem, only used in AMS
15702fe279fdSBarry Smith .  RT_PiFull - Raviart-Thomas interpolation matrix
15712fe279fdSBarry Smith .  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
15722fe279fdSBarry Smith .  ND_PiFull - Nedelec interpolation matrix
15736bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
15746bf688a0SCe Qin 
1575f1580f4eSBarry Smith    Level: intermediate
1576f1580f4eSBarry Smith 
157795452b02SPatrick Sanan    Notes:
157895452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1579147403d9SBarry Smith 
15806bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1581147403d9SBarry Smith 
1582f1580f4eSBarry Smith    Developer Note:
1583f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
15846bf688a0SCe Qin 
1585f1580f4eSBarry Smith .seealso: `PCHYPRE`
15866bf688a0SCe Qin @*/
1587d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1588d71ae5a4SJacob Faibussowitsch {
15896bf688a0SCe Qin   PetscInt i;
15906bf688a0SCe Qin 
15916bf688a0SCe Qin   PetscFunctionBegin;
15926bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15936bf688a0SCe Qin   if (RT_PiFull) {
15946bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
15956bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
15966bf688a0SCe Qin   }
15976bf688a0SCe Qin   if (RT_Pi) {
15986bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
15996bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16006bf688a0SCe Qin       if (RT_Pi[i]) {
16016bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
16026bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
16036bf688a0SCe Qin       }
16046bf688a0SCe Qin     }
16056bf688a0SCe Qin   }
16066bf688a0SCe Qin   if (ND_PiFull) {
16076bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
16086bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
16096bf688a0SCe Qin   }
16106bf688a0SCe Qin   if (ND_Pi) {
16116bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
16126bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16136bf688a0SCe Qin       if (ND_Pi[i]) {
16146bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
16156bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
16166bf688a0SCe Qin       }
16176bf688a0SCe Qin     }
16186bf688a0SCe Qin   }
1619cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
16203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16216bf688a0SCe Qin }
16226bf688a0SCe Qin 
1623d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1624d71ae5a4SJacob Faibussowitsch {
16254cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16265ac14e1cSStefano Zampini   PetscBool ishypre;
16274cb006feSStefano Zampini 
16284cb006feSStefano Zampini   PetscFunctionBegin;
16299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
16305ac14e1cSStefano Zampini   if (ishypre) {
16315ac14e1cSStefano Zampini     if (isalpha) {
16329566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
16339566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16345ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
16355ac14e1cSStefano Zampini     } else {
16365ac14e1cSStefano Zampini       if (A) {
16379566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
16385ac14e1cSStefano Zampini       } else {
16395ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16405ac14e1cSStefano Zampini       }
16419566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
16425ac14e1cSStefano Zampini       jac->beta_Poisson = A;
16435ac14e1cSStefano Zampini     }
16445ac14e1cSStefano Zampini   } else {
16455ac14e1cSStefano Zampini     if (isalpha) {
16469566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16479566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
16485ac14e1cSStefano Zampini     } else {
16495ac14e1cSStefano Zampini       if (A) {
16509566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16519566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
16525ac14e1cSStefano Zampini       } else {
16539566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16545ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16555ac14e1cSStefano Zampini       }
16565ac14e1cSStefano Zampini     }
16575ac14e1cSStefano Zampini   }
16583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16594cb006feSStefano Zampini }
16604cb006feSStefano Zampini 
16614cb006feSStefano Zampini /*@
1662f1580f4eSBarry Smith    PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
16634cb006feSStefano Zampini 
1664c3339decSBarry Smith    Collective
16654cb006feSStefano Zampini 
16664cb006feSStefano Zampini    Input Parameters:
16674cb006feSStefano Zampini +  pc - the preconditioning context
16684cb006feSStefano Zampini -  A - the matrix
16694cb006feSStefano Zampini 
16704cb006feSStefano Zampini    Level: intermediate
16714cb006feSStefano Zampini 
1672f1580f4eSBarry Smith    Note:
167395452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
16744cb006feSStefano Zampini 
1675f1580f4eSBarry Smith    Developer Note:
1676f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1677f1580f4eSBarry Smith 
1678f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1679f1580f4eSBarry Smith 
1680f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
16814cb006feSStefano Zampini @*/
1682d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1683d71ae5a4SJacob Faibussowitsch {
16844cb006feSStefano Zampini   PetscFunctionBegin;
16854cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16864cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16874cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1688cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
16893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16904cb006feSStefano Zampini }
16914cb006feSStefano Zampini 
16924cb006feSStefano Zampini /*@
1693f1580f4eSBarry Smith    PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
16944cb006feSStefano Zampini 
1695c3339decSBarry Smith    Collective
16964cb006feSStefano Zampini 
16974cb006feSStefano Zampini    Input Parameters:
16984cb006feSStefano Zampini +  pc - the preconditioning context
1699f1580f4eSBarry Smith -  A - the matrix, or NULL to turn it off
17004cb006feSStefano Zampini 
17014cb006feSStefano Zampini    Level: intermediate
17024cb006feSStefano Zampini 
1703f1580f4eSBarry Smith    Note:
170495452b02SPatrick Sanan    A should be obtained by discretizing the Poisson problem with linear finite elements.
17054cb006feSStefano Zampini 
1706f1580f4eSBarry Smith    Developer Note:
1707f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1708f1580f4eSBarry Smith 
1709f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1710f1580f4eSBarry Smith 
1711f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17124cb006feSStefano Zampini @*/
1713d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1714d71ae5a4SJacob Faibussowitsch {
17154cb006feSStefano Zampini   PetscFunctionBegin;
17164cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17174cb006feSStefano Zampini   if (A) {
17184cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17194cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
17204cb006feSStefano Zampini   }
1721cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
17223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17234cb006feSStefano Zampini }
17244cb006feSStefano Zampini 
1725d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1726d71ae5a4SJacob Faibussowitsch {
17274cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17284cb006feSStefano Zampini 
17294cb006feSStefano Zampini   PetscFunctionBegin;
17304cb006feSStefano Zampini   /* throw away any vector if already set */
17319566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
17329566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
17339566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
17349566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
17359566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
17369566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
17379566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
17385ac14e1cSStefano Zampini   jac->dim = 2;
17394cb006feSStefano Zampini   if (zzo) {
17409566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
17419566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
17425ac14e1cSStefano Zampini     jac->dim++;
17434cb006feSStefano Zampini   }
17443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17454cb006feSStefano Zampini }
17464cb006feSStefano Zampini 
17474cb006feSStefano Zampini /*@
1748f1580f4eSBarry Smith    PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
17494cb006feSStefano Zampini 
1750c3339decSBarry Smith    Collective
17514cb006feSStefano Zampini 
17524cb006feSStefano Zampini    Input Parameters:
17534cb006feSStefano Zampini +  pc - the preconditioning context
17542fe279fdSBarry Smith .  ozz - vector representing (1,0,0) (or (1,0) in 2D)
17552fe279fdSBarry Smith .  zoz - vector representing (0,1,0) (or (0,1) in 2D)
17564cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
17574cb006feSStefano Zampini 
17584cb006feSStefano Zampini    Level: intermediate
17594cb006feSStefano Zampini 
1760f1580f4eSBarry Smith    Developer Note:
1761f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1762f1580f4eSBarry Smith 
1763f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17644cb006feSStefano Zampini @*/
1765d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1766d71ae5a4SJacob Faibussowitsch {
17674cb006feSStefano Zampini   PetscFunctionBegin;
17684cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17694cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
17704cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
17714cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
17724cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
17734cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
17744cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1775cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
17763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17774cb006feSStefano Zampini }
17784cb006feSStefano Zampini 
1779d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1780d71ae5a4SJacob Faibussowitsch {
1781be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1782be14dc20SKerry Key 
1783be14dc20SKerry Key   PetscFunctionBegin;
1784be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1785be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1786be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1787be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
17883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1789be14dc20SKerry Key }
1790be14dc20SKerry Key 
1791be14dc20SKerry Key /*@
1792f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1793be14dc20SKerry Key 
1794c3339decSBarry Smith    Collective
1795be14dc20SKerry Key 
1796be14dc20SKerry Key    Input Parameters:
1797be14dc20SKerry Key +  pc - the preconditioning context
1798be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1799be14dc20SKerry Key 
1800be14dc20SKerry Key    Level: intermediate
1801be14dc20SKerry Key 
1802be14dc20SKerry Key    Note:
1803f1580f4eSBarry Smith    This calls `HYPRE_AMSSetInteriorNodes()`
1804f1580f4eSBarry Smith 
1805f1580f4eSBarry Smith    Developer Note:
1806f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1807f1580f4eSBarry Smith 
1808f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1809be14dc20SKerry Key @*/
1810d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1811d71ae5a4SJacob Faibussowitsch {
1812be14dc20SKerry Key   PetscFunctionBegin;
1813be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1814be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1815be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1816be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
18173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1818be14dc20SKerry Key }
1819be14dc20SKerry Key 
1820d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1821d71ae5a4SJacob Faibussowitsch {
18224cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18234cb006feSStefano Zampini   Vec       tv;
18244cb006feSStefano Zampini   PetscInt  i;
18254cb006feSStefano Zampini 
18264cb006feSStefano Zampini   PetscFunctionBegin;
18274cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
18289566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
18299566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
18309566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
18315ac14e1cSStefano Zampini   jac->dim = dim;
18325ac14e1cSStefano Zampini 
18334cb006feSStefano Zampini   /* compute IJ vector for coordinates */
18349566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
18359566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
18369566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
18374cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
18384cb006feSStefano Zampini     PetscScalar *array;
18394cb006feSStefano Zampini     PetscInt     j;
18404cb006feSStefano Zampini 
18419566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
18429566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
18436ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
18449566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
18459566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
18464cb006feSStefano Zampini   }
18479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
18483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18494cb006feSStefano Zampini }
18504cb006feSStefano Zampini 
1851d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1852d71ae5a4SJacob Faibussowitsch {
185316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
185416d9e3a6SLisandro Dalcin 
185516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
185616d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
18573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185816d9e3a6SLisandro Dalcin }
185916d9e3a6SLisandro Dalcin 
1860d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1861d71ae5a4SJacob Faibussowitsch {
186216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1863ace3abfcSBarry Smith   PetscBool flag;
186416d9e3a6SLisandro Dalcin 
186516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
186616d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
18679566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
18685f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
18693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
187016d9e3a6SLisandro Dalcin   } else {
18719566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
187216d9e3a6SLisandro Dalcin   }
187316d9e3a6SLisandro Dalcin 
187416d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
187516d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
187616d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
187716d9e3a6SLisandro Dalcin 
18789566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
187916d9e3a6SLisandro Dalcin   if (flag) {
18809566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1881792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
188216d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
188316d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
188416d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
188516d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
188616d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
188716d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
18883ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
188916d9e3a6SLisandro Dalcin   }
18909566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1891db966c6cSHong Zhang   if (flag) {
18924e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
18937de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
18948bf83915SBarry Smith #endif
18959566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1896792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1897db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1898db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1899db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1900db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1901db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1902db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1903db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
19043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1905db966c6cSHong Zhang   }
19069566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
190716d9e3a6SLisandro Dalcin   if (flag) {
19089566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1909792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
191016d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
191116d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
191216d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
191316d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
191416d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
191516d9e3a6SLisandro Dalcin     /* initialize */
191616d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
19178966356dSPierre Jolivet     jac->threshold = .1;
191816d9e3a6SLisandro Dalcin     jac->filter    = .1;
191916d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
19202fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
19212fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
19222fa5cd67SKarl Rupp 
192316d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
192416d9e3a6SLisandro Dalcin     jac->symt = 0;
1925792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1926792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1927792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1928792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1929792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1930792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
19313ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
193216d9e3a6SLisandro Dalcin   }
19339566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
193416d9e3a6SLisandro Dalcin   if (flag) {
1935792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
193616d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
193716d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
193816d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
193916d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
194085245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
19419566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
19429566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
194316d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
194416d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
194516d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
194616d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
194716d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
194816d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
194916d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
195016d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
19518f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
195216d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
195316d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
195416d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
195516d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
195616d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
19570f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
19586a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1959b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
19601810e44eSEike Mueller     jac->eu_level                                                = 0;
19611810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
19621810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1963589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
19640f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
196516d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
196616d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
196716d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
19680f1074feSSatish Balay     jac->interptype                       = 0;
1969589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1970589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1971589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1972589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1973589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
19740f1074feSSatish Balay     jac->agg_nl                           = 0;
19756ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
19760f1074feSSatish Balay     jac->pmax                             = 0;
19770f1074feSSatish Balay     jac->truncfactor                      = 0.0;
19780f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1979589dcaf0SStefano Zampini     jac->maxc                             = 9;
1980589dcaf0SStefano Zampini     jac->minc                             = 1;
198122e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
198222e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
198322e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
198422e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
198522e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
198622e51d31SStefano Zampini     jac->interp_refine                    = 0;
19878f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
19888f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
19896ea7df73SStefano Zampini     jac->rap2                             = 0;
19906ea7df73SStefano Zampini 
19916ea7df73SStefano Zampini     /* GPU defaults
19926ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
19936ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
19946ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
19956ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
19966ea7df73SStefano Zampini     jac->mod_rap2       = 1;
19976ea7df73SStefano Zampini     jac->coarsentype    = 8;
19986ea7df73SStefano Zampini     jac->relaxorder     = 0;
19996ea7df73SStefano Zampini     jac->interptype     = 6;
20006ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
20016ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
20026ea7df73SStefano Zampini     jac->agg_interptype = 7;
20036ea7df73SStefano Zampini #else
20046ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
20056ea7df73SStefano Zampini     jac->mod_rap2      = 0;
20066ea7df73SStefano Zampini #endif
2007792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
2008792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
2009792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
2010792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
2011792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
2012792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
2013792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
2014792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
2015792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
2016792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
2017792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
2018792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
2019792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2020792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2021792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2022792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2023792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2024792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2025792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
20266ea7df73SStefano Zampini     /* GPU */
20276ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2028792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2029792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2030792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
20316ea7df73SStefano Zampini #endif
20326ea7df73SStefano Zampini 
2033589dcaf0SStefano Zampini     /* AIR */
20346ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2035792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2036792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2037792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2038792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2039792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
20406ea7df73SStefano Zampini #endif
20413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
204216d9e3a6SLisandro Dalcin   }
20439566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
20444cb006feSStefano Zampini   if (flag) {
20453ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
20464cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
20474cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
20484cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
20494cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
20504cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
20514cb006feSStefano Zampini     jac->coords[0]          = NULL;
20524cb006feSStefano Zampini     jac->coords[1]          = NULL;
20534cb006feSStefano Zampini     jac->coords[2]          = NULL;
2054be14dc20SKerry Key     jac->interior           = NULL;
20554cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2056863406b8SStefano Zampini     jac->as_print       = 0;
2057863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2058863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
20594cb006feSStefano Zampini     jac->ams_cycle_type = 13;
20604cb006feSStefano Zampini     /* Smoothing options */
2061863406b8SStefano Zampini     jac->as_relax_type   = 2;
2062863406b8SStefano Zampini     jac->as_relax_times  = 1;
2063863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2064863406b8SStefano Zampini     jac->as_omega        = 1.0;
20654cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2066863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2067863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
20680bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2069863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2070863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2071863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
20724cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2073863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2074863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
20750bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2076863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2077863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2078863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2079792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2080792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2081792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2082792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
20839371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2084792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2085863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2086863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
20879371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2088a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2089792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2090863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2091863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
20929371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2093a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
209423df4f25SStefano Zampini     /* Zero conductivity */
209523df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
209623df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
20973ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
20984cb006feSStefano Zampini   }
20999566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2100863406b8SStefano Zampini   if (flag) {
21013ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2102863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2103863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2104863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2105863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2106863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2107863406b8SStefano Zampini     jac->coords[0]          = NULL;
2108863406b8SStefano Zampini     jac->coords[1]          = NULL;
2109863406b8SStefano Zampini     jac->coords[2]          = NULL;
2110863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2111863406b8SStefano Zampini     jac->as_print       = 0;
2112863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2113863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2114863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2115863406b8SStefano Zampini     /* Smoothing options */
2116863406b8SStefano Zampini     jac->as_relax_type   = 2;
2117863406b8SStefano Zampini     jac->as_relax_times  = 1;
2118863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2119863406b8SStefano Zampini     jac->as_omega        = 1.0;
2120863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2121863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2122863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2123863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2124863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2125863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2126863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2127863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2128863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2129863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2130863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2131863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2132863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2133863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2134863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2135792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2136792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2137792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2138792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
21399371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2140792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2141863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2142863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2143863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
21449371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2145a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2146792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2147863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2148863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
21499371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2150a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
21513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2152863406b8SStefano Zampini   }
21539566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
21542fa5cd67SKarl Rupp 
21550298fd71SBarry Smith   jac->hypre_type = NULL;
215698921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
215716d9e3a6SLisandro Dalcin }
215816d9e3a6SLisandro Dalcin 
215916d9e3a6SLisandro Dalcin /*
216016d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
216116d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
216216d9e3a6SLisandro Dalcin */
2163d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2164d71ae5a4SJacob Faibussowitsch {
21654ddd07fcSJed Brown   PetscInt    indx;
2166db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2167ace3abfcSBarry Smith   PetscBool   flg;
216816d9e3a6SLisandro Dalcin 
216916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2170d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2171dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
217216d9e3a6SLisandro Dalcin   if (flg) {
21739566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
217402a17cd4SBarry Smith   } else {
21759566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
217616d9e3a6SLisandro Dalcin   }
2177dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2178d0609cedSBarry Smith   PetscOptionsHeadEnd();
21793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218016d9e3a6SLisandro Dalcin }
218116d9e3a6SLisandro Dalcin 
218216d9e3a6SLisandro Dalcin /*@C
218316d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
218416d9e3a6SLisandro Dalcin 
218516d9e3a6SLisandro Dalcin    Input Parameters:
218616d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2187db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
218816d9e3a6SLisandro Dalcin 
2189f1580f4eSBarry Smith    Options Database Key:
2190db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
219116d9e3a6SLisandro Dalcin 
219216d9e3a6SLisandro Dalcin    Level: intermediate
219316d9e3a6SLisandro Dalcin 
2194f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
219516d9e3a6SLisandro Dalcin @*/
2196d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2197d71ae5a4SJacob Faibussowitsch {
219816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21990700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
220016d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2201cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
22023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
220316d9e3a6SLisandro Dalcin }
220416d9e3a6SLisandro Dalcin 
220516d9e3a6SLisandro Dalcin /*@C
220616d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
220716d9e3a6SLisandro Dalcin 
220816d9e3a6SLisandro Dalcin    Input Parameter:
220916d9e3a6SLisandro Dalcin .     pc - the preconditioner context
221016d9e3a6SLisandro Dalcin 
221116d9e3a6SLisandro Dalcin    Output Parameter:
2212db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
221316d9e3a6SLisandro Dalcin 
221416d9e3a6SLisandro Dalcin    Level: intermediate
221516d9e3a6SLisandro Dalcin 
2216f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
221716d9e3a6SLisandro Dalcin @*/
2218d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2219d71ae5a4SJacob Faibussowitsch {
222016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22210700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
222216d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2223cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
22243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
222516d9e3a6SLisandro Dalcin }
222616d9e3a6SLisandro Dalcin 
2227db6f9c32SMark Adams /*@C
2228f1580f4eSBarry Smith    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2229db6f9c32SMark Adams 
2230c3339decSBarry Smith    Logically Collective
2231db6f9c32SMark Adams 
2232db6f9c32SMark Adams    Input Parameters:
2233db6f9c32SMark Adams +  pc - the hypre context
2234db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2235db6f9c32SMark Adams 
2236db6f9c32SMark Adams    Options Database Key:
223767b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2238db6f9c32SMark Adams 
2239db6f9c32SMark Adams    Level: intermediate
2240db6f9c32SMark Adams 
2241f1580f4eSBarry Smith    Developer Note:
2242f1580f4eSBarry Smith    How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2243db6f9c32SMark Adams 
2244f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2245db6f9c32SMark Adams @*/
2246d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2247d71ae5a4SJacob Faibussowitsch {
2248db6f9c32SMark Adams   PetscFunctionBegin;
2249db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2250cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
22513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2252db6f9c32SMark Adams }
2253db6f9c32SMark Adams 
2254db6f9c32SMark Adams /*@C
2255f1580f4eSBarry Smith    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2256db6f9c32SMark Adams 
2257db6f9c32SMark Adams    Not Collective
2258db6f9c32SMark Adams 
2259db6f9c32SMark Adams    Input Parameter:
2260db6f9c32SMark Adams .  pc - the multigrid context
2261db6f9c32SMark Adams 
2262db6f9c32SMark Adams    Output Parameter:
2263db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2264db6f9c32SMark Adams 
2265db6f9c32SMark Adams    Level: intermediate
2266db6f9c32SMark Adams 
2267f1580f4eSBarry Smith .seealso: `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2268db6f9c32SMark Adams @*/
2269d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2270d71ae5a4SJacob Faibussowitsch {
2271db6f9c32SMark Adams   PetscFunctionBegin;
2272db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2273cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
22743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2275db6f9c32SMark Adams }
2276db6f9c32SMark Adams 
227716d9e3a6SLisandro Dalcin /*MC
2278f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
227916d9e3a6SLisandro Dalcin 
228016d9e3a6SLisandro Dalcin    Options Database Keys:
2281db966c6cSHong Zhang +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2282f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2283f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2284ead8c081SBarry Smith -   Many others, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX preconditioner
228516d9e3a6SLisandro Dalcin 
228616d9e3a6SLisandro Dalcin    Level: intermediate
228716d9e3a6SLisandro Dalcin 
228895452b02SPatrick Sanan    Notes:
2289f1580f4eSBarry Smith     Apart from pc_hypre_type (for which there is `PCHYPRESetType()`),
229016d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
229149567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
229216d9e3a6SLisandro Dalcin 
2293c231f9e3SBarryFSmith           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
22940f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
22950f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2296c231f9e3SBarryFSmith           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
22978f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
22980f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
22990f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
230016d9e3a6SLisandro Dalcin 
23010f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
23020f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
23030f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
230416d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
230516d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
230616d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
230716d9e3a6SLisandro Dalcin 
2308f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
230949567fc5SPierre Jolivet           the following two options: ``-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>``
23100b1a5bd9SEric Chamberland 
2311f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2312f1580f4eSBarry Smith 
2313f1580f4eSBarry Smith           For `PCHYPRE` type of ams or ads auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2314f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
231549567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2316f1580f4eSBarry Smith 
2317f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
23189e5bc791SBarry Smith 
2319ead8c081SBarry Smith    GPU Notes:
2320ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2321f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2322ead8c081SBarry Smith 
2323ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2324f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2325ead8c081SBarry Smith 
2326f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2327f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2328f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
232916d9e3a6SLisandro Dalcin M*/
233016d9e3a6SLisandro Dalcin 
2331d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2332d71ae5a4SJacob Faibussowitsch {
233316d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
233416d9e3a6SLisandro Dalcin 
233516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23364dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
23372fa5cd67SKarl Rupp 
233816d9e3a6SLisandro Dalcin   pc->data                = jac;
23398695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
234016d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
234116d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
234216d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
234316d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
234416d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
23459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
23469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
23479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
23489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
23499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
23509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
23519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2352be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
23539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
23549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
23559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
23566ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23576ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
23589566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
23596ea7df73SStefano Zampini   #endif
23606ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
23619566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
23626ea7df73SStefano Zampini   #endif
23636ea7df73SStefano Zampini #endif
2364ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
23653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
236616d9e3a6SLisandro Dalcin }
2367ebc551c0SBarry Smith 
2368ebc551c0SBarry Smith typedef struct {
236968326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2370f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
23719e5bc791SBarry Smith 
23729e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
23734ddd07fcSJed Brown   PetscInt  its;
23749e5bc791SBarry Smith   double    tol;
23754ddd07fcSJed Brown   PetscInt  relax_type;
23764ddd07fcSJed Brown   PetscInt  rap_type;
23774ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
23784ddd07fcSJed Brown   PetscInt  max_levels;
23790be8cd64Sftrigaux   PetscInt  skip_relax;
23800be8cd64Sftrigaux   PetscBool print_statistics;
2381ebc551c0SBarry Smith } PC_PFMG;
2382ebc551c0SBarry Smith 
2383d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_PFMG(PC pc)
2384d71ae5a4SJacob Faibussowitsch {
2385f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2386ebc551c0SBarry Smith 
2387ebc551c0SBarry Smith   PetscFunctionBegin;
2388792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
23899566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
23909566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
23913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2392ebc551c0SBarry Smith }
2393ebc551c0SBarry Smith 
23949e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
23959e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
23969e5bc791SBarry Smith 
2397d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2398d71ae5a4SJacob Faibussowitsch {
2399ace3abfcSBarry Smith   PetscBool iascii;
2400f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2401ebc551c0SBarry Smith 
2402ebc551c0SBarry Smith   PetscFunctionBegin;
24039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
24049e5bc791SBarry Smith   if (iascii) {
24059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
240663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
24079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
24089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
24099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
241063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
241163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
24120be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
24139e5bc791SBarry Smith   }
24143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2415ebc551c0SBarry Smith }
2416ebc551c0SBarry Smith 
2417d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2418d71ae5a4SJacob Faibussowitsch {
2419f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2420ebc551c0SBarry Smith 
2421ebc551c0SBarry Smith   PetscFunctionBegin;
2422d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
24230be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
24249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2425792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24269566063dSJacob 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));
2427792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24289566063dSJacob 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));
2429792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24309e5bc791SBarry Smith 
24319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2432792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24333b46a515SGlenn Hammond 
24349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2435792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2436dd39110bSPierre 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));
2437792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2438dd39110bSPierre 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));
2439792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24400be8cd64Sftrigaux   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));
24410be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2442d0609cedSBarry Smith   PetscOptionsHeadEnd();
24433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2444ebc551c0SBarry Smith }
2445ebc551c0SBarry Smith 
2446d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2447d71ae5a4SJacob Faibussowitsch {
2448f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2449d9ca1df4SBarry Smith   PetscScalar       *yy;
2450d9ca1df4SBarry Smith   const PetscScalar *xx;
24514ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
24522cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
245368326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2454f91d8e95SBarry Smith 
2455f91d8e95SBarry Smith   PetscFunctionBegin;
24569566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
24579566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
24582cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2459f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2460f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2461f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
24622cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
24632cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
24642cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
24652cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
24662cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
24672cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2468f91d8e95SBarry Smith 
2469f91d8e95SBarry Smith   /* copy x values over to hypre */
2470792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
24719566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2472792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
24739566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2474792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2475792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2476f91d8e95SBarry Smith 
2477f91d8e95SBarry Smith   /* copy solution values back to PETSc */
24789566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2479792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
24809566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
24813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2482f91d8e95SBarry Smith }
2483f91d8e95SBarry Smith 
2484d71ae5a4SJacob 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)
2485d71ae5a4SJacob Faibussowitsch {
24869e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
24872cf14000SStefano Zampini   HYPRE_Int oits;
24889e5bc791SBarry Smith 
24899e5bc791SBarry Smith   PetscFunctionBegin;
24909566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2491792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2492792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
24939e5bc791SBarry Smith 
24949566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2495792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
24969e5bc791SBarry Smith   *outits = oits;
24979e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
24989e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2499792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2500792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
25013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25029e5bc791SBarry Smith }
25039e5bc791SBarry Smith 
2504d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_PFMG(PC pc)
2505d71ae5a4SJacob Faibussowitsch {
25063a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
25073a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2508ace3abfcSBarry Smith   PetscBool        flg;
25093a32d3dbSGlenn Hammond 
25103a32d3dbSGlenn Hammond   PetscFunctionBegin;
25119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
251228b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
25133a32d3dbSGlenn Hammond 
25143a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2515792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2516792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25170be8cd64Sftrigaux 
25180be8cd64Sftrigaux   // Print Hypre statistics about the solve process
25190be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
25200be8cd64Sftrigaux 
25210be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
25220be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
25230be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
25240be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
25250be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
25260be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
25270be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
25280be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
25290be8cd64Sftrigaux 
2530792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2531792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
25323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25333a32d3dbSGlenn Hammond }
25343a32d3dbSGlenn Hammond 
2535ebc551c0SBarry Smith /*MC
2536ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2537ebc551c0SBarry Smith 
2538f1580f4eSBarry Smith    Options Database Keys:
253967b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
254067b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
254167b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
254267b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
25439e5bc791SBarry 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
25440be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2545f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2546f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2547f1580f4eSBarry Smith 
2548f1580f4eSBarry Smith    Level: advanced
2549f91d8e95SBarry Smith 
255095452b02SPatrick Sanan    Notes:
255195452b02SPatrick Sanan    This is for CELL-centered descretizations
25529e5bc791SBarry Smith 
2553f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
25549e5bc791SBarry Smith 
2555f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2556f1580f4eSBarry Smith 
2557f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2558f1580f4eSBarry Smith 
2559f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2560f1580f4eSBarry Smith 
2561f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2562ebc551c0SBarry Smith M*/
2563ebc551c0SBarry Smith 
2564d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2565d71ae5a4SJacob Faibussowitsch {
2566ebc551c0SBarry Smith   PC_PFMG *ex;
2567ebc551c0SBarry Smith 
2568ebc551c0SBarry Smith   PetscFunctionBegin;
25699371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
257068326731SBarry Smith   pc->data = ex;
2571ebc551c0SBarry Smith 
25729e5bc791SBarry Smith   ex->its              = 1;
25739e5bc791SBarry Smith   ex->tol              = 1.e-8;
25749e5bc791SBarry Smith   ex->relax_type       = 1;
25759e5bc791SBarry Smith   ex->rap_type         = 0;
25769e5bc791SBarry Smith   ex->num_pre_relax    = 1;
25779e5bc791SBarry Smith   ex->num_post_relax   = 1;
25783b46a515SGlenn Hammond   ex->max_levels       = 0;
25790be8cd64Sftrigaux   ex->skip_relax       = 0;
25800be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
25819e5bc791SBarry Smith 
2582ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2583ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2584ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2585f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
25869e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
258768326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
25882fa5cd67SKarl Rupp 
25899566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2590ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2591792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2593ebc551c0SBarry Smith }
2594d851a50bSGlenn Hammond 
2595d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2596d851a50bSGlenn Hammond typedef struct {
2597d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2598d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2599d851a50bSGlenn Hammond 
2600d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
26014ddd07fcSJed Brown   PetscInt its;
2602d851a50bSGlenn Hammond   double   tol;
26034ddd07fcSJed Brown   PetscInt relax_type;
26044ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2605d851a50bSGlenn Hammond } PC_SysPFMG;
2606d851a50bSGlenn Hammond 
2607d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SysPFMG(PC pc)
2608d71ae5a4SJacob Faibussowitsch {
2609d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2610d851a50bSGlenn Hammond 
2611d851a50bSGlenn Hammond   PetscFunctionBegin;
2612792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
26139566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
26149566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
26153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2616d851a50bSGlenn Hammond }
2617d851a50bSGlenn Hammond 
2618d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2619d851a50bSGlenn Hammond 
2620d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2621d71ae5a4SJacob Faibussowitsch {
2622ace3abfcSBarry Smith   PetscBool   iascii;
2623d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2624d851a50bSGlenn Hammond 
2625d851a50bSGlenn Hammond   PetscFunctionBegin;
26269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2627d851a50bSGlenn Hammond   if (iascii) {
26289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
262963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
26309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
26319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
263263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2633d851a50bSGlenn Hammond   }
26343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2635d851a50bSGlenn Hammond }
2636d851a50bSGlenn Hammond 
2637d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2638d71ae5a4SJacob Faibussowitsch {
2639d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2640ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2641d851a50bSGlenn Hammond 
2642d851a50bSGlenn Hammond   PetscFunctionBegin;
2643d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
26449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
264548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
26469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2647792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
26489566063dSJacob 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));
2649792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
26509566063dSJacob 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));
2651792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2652d851a50bSGlenn Hammond 
26539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2654792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2655dd39110bSPierre 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));
2656792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2657d0609cedSBarry Smith   PetscOptionsHeadEnd();
26583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2659d851a50bSGlenn Hammond }
2660d851a50bSGlenn Hammond 
2661d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2662d71ae5a4SJacob Faibussowitsch {
2663d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2664d9ca1df4SBarry Smith   PetscScalar       *yy;
2665d9ca1df4SBarry Smith   const PetscScalar *xx;
26664ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
26672cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2668d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
26694ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
26704ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
26714ddd07fcSJed Brown   PetscInt           part     = 0;
26724ddd07fcSJed Brown   PetscInt           size;
26734ddd07fcSJed Brown   PetscInt           i;
2674d851a50bSGlenn Hammond 
2675d851a50bSGlenn Hammond   PetscFunctionBegin;
26769566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
26779566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
26782cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2679d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2680d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2681d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
26822cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
26832cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
26842cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
26852cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
26862cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
26872cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2688d851a50bSGlenn Hammond 
2689d851a50bSGlenn Hammond   size = 1;
26902fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
26912fa5cd67SKarl Rupp 
2692d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2693d851a50bSGlenn Hammond   if (ordering) {
2694792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26959566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2696792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
26979566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2698792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2699792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2700792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2701d851a50bSGlenn Hammond 
2702d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27039566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2704792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
27059566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2706a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2707d851a50bSGlenn Hammond     PetscScalar *z;
27084ddd07fcSJed Brown     PetscInt     j, k;
2709d851a50bSGlenn Hammond 
27109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2711792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27129566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2713d851a50bSGlenn Hammond 
2714d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2715d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2716d851a50bSGlenn Hammond       k = i * nvars;
27172fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2718d851a50bSGlenn Hammond     }
2719792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
27209566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2721792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2722792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2723d851a50bSGlenn Hammond 
2724d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27259566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2726792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2727d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2728d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2729d851a50bSGlenn Hammond       k = i * nvars;
27302fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2731d851a50bSGlenn Hammond     }
27329566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
27339566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2734d851a50bSGlenn Hammond   }
27353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2736d851a50bSGlenn Hammond }
2737d851a50bSGlenn Hammond 
2738d71ae5a4SJacob 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)
2739d71ae5a4SJacob Faibussowitsch {
2740d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
27412cf14000SStefano Zampini   HYPRE_Int   oits;
2742d851a50bSGlenn Hammond 
2743d851a50bSGlenn Hammond   PetscFunctionBegin;
27449566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2745792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2746792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
27479566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2748792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2749d851a50bSGlenn Hammond   *outits = oits;
2750d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2751d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2752792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2753792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
27543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2755d851a50bSGlenn Hammond }
2756d851a50bSGlenn Hammond 
2757d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SysPFMG(PC pc)
2758d71ae5a4SJacob Faibussowitsch {
2759d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2760d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2761ace3abfcSBarry Smith   PetscBool         flg;
2762d851a50bSGlenn Hammond 
2763d851a50bSGlenn Hammond   PetscFunctionBegin;
27649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
276528b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2766d851a50bSGlenn Hammond 
2767d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2768792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2769792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2770792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2771792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
27723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2773d851a50bSGlenn Hammond }
2774d851a50bSGlenn Hammond 
2775d851a50bSGlenn Hammond /*MC
2776f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2777d851a50bSGlenn Hammond 
2778d851a50bSGlenn Hammond    Level: advanced
2779d851a50bSGlenn Hammond 
2780f1580f4eSBarry Smith    Options Database Keys:
278167b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
278267b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
278367b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
278467b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
278567b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2786d851a50bSGlenn Hammond 
278795452b02SPatrick Sanan    Notes:
2788f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2789f1580f4eSBarry Smith 
2790f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2791f1580f4eSBarry Smith 
279295452b02SPatrick Sanan    This is for CELL-centered descretizations
2793d851a50bSGlenn Hammond 
2794f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2795d851a50bSGlenn Hammond 
2796f1580f4eSBarry 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`.
2797f1580f4eSBarry Smith 
2798f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2799d851a50bSGlenn Hammond M*/
2800d851a50bSGlenn Hammond 
2801d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2802d71ae5a4SJacob Faibussowitsch {
2803d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2804d851a50bSGlenn Hammond 
2805d851a50bSGlenn Hammond   PetscFunctionBegin;
28069371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2807d851a50bSGlenn Hammond   pc->data = ex;
2808d851a50bSGlenn Hammond 
2809d851a50bSGlenn Hammond   ex->its            = 1;
2810d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2811d851a50bSGlenn Hammond   ex->relax_type     = 1;
2812d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2813d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2814d851a50bSGlenn Hammond 
2815d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2816d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2817d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2818d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2819d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2820d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
28212fa5cd67SKarl Rupp 
28229566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2823ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2824792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
28253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2826d851a50bSGlenn Hammond }
28271c188c59Sftrigaux 
2828f1580f4eSBarry Smith /* PC SMG */
28291c188c59Sftrigaux typedef struct {
28301c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
28311c188c59Sftrigaux   HYPRE_StructSolver hsolver;
28321c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
28331c188c59Sftrigaux   double             tol;
28341c188c59Sftrigaux   PetscBool          print_statistics;
28351c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
28361c188c59Sftrigaux } PC_SMG;
28371c188c59Sftrigaux 
2838d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SMG(PC pc)
2839d71ae5a4SJacob Faibussowitsch {
28401c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28411c188c59Sftrigaux 
28421c188c59Sftrigaux   PetscFunctionBegin;
28431c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
28441c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28451c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
28463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28471c188c59Sftrigaux }
28481c188c59Sftrigaux 
2849d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2850d71ae5a4SJacob Faibussowitsch {
28511c188c59Sftrigaux   PetscBool iascii;
28521c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
28531c188c59Sftrigaux 
28541c188c59Sftrigaux   PetscFunctionBegin;
28551c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
28561c188c59Sftrigaux   if (iascii) {
28571c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
28581c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
28591c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
28601c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
28611c188c59Sftrigaux   }
28623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28631c188c59Sftrigaux }
28641c188c59Sftrigaux 
2865d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2866d71ae5a4SJacob Faibussowitsch {
28671c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28681c188c59Sftrigaux 
28691c188c59Sftrigaux   PetscFunctionBegin;
28701c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
28711c188c59Sftrigaux 
28721c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
28731c188c59Sftrigaux   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));
28741c188c59Sftrigaux   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));
28751c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
28761c188c59Sftrigaux 
28771c188c59Sftrigaux   PetscOptionsHeadEnd();
28783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28791c188c59Sftrigaux }
28801c188c59Sftrigaux 
2881d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2882d71ae5a4SJacob Faibussowitsch {
28831c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
28841c188c59Sftrigaux   PetscScalar       *yy;
28851c188c59Sftrigaux   const PetscScalar *xx;
28861c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
28871c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
28881c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28891c188c59Sftrigaux 
28901c188c59Sftrigaux   PetscFunctionBegin;
28911c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28921c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28931c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
28941c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
28951c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
28961c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
28971c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
28981c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
28991c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
29001c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
29011c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
29021c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
29031c188c59Sftrigaux 
29041c188c59Sftrigaux   /* copy x values over to hypre */
29051c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
29061c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
29071c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
29081c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
29091c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
29101c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29111c188c59Sftrigaux 
29121c188c59Sftrigaux   /* copy solution values back to PETSc */
29131c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
29141c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
29151c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
29163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29171c188c59Sftrigaux }
29181c188c59Sftrigaux 
2919d71ae5a4SJacob 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)
2920d71ae5a4SJacob Faibussowitsch {
29211c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
29221c188c59Sftrigaux   HYPRE_Int oits;
29231c188c59Sftrigaux 
29241c188c59Sftrigaux   PetscFunctionBegin;
29251c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29261c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
29271c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
29281c188c59Sftrigaux 
29291c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
29301c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
29311c188c59Sftrigaux   *outits = oits;
29321c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
29331c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
29341c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
29351c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
29363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29371c188c59Sftrigaux }
29381c188c59Sftrigaux 
2939d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SMG(PC pc)
2940d71ae5a4SJacob Faibussowitsch {
29411c188c59Sftrigaux   PetscInt         i, dim;
29421c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
29431c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
29441c188c59Sftrigaux   PetscBool        flg;
29451c188c59Sftrigaux   DMBoundaryType   p[3];
29461c188c59Sftrigaux   PetscInt         M[3];
29471c188c59Sftrigaux 
29481c188c59Sftrigaux   PetscFunctionBegin;
29491c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
29501c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
29511c188c59Sftrigaux 
29521c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
29531c188c59Sftrigaux   // Check if power of 2 in periodic directions
29541c188c59Sftrigaux   for (i = 0; i < dim; i++) {
29551c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
29561c188c59Sftrigaux       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]);
29571c188c59Sftrigaux     }
29581c188c59Sftrigaux   }
29591c188c59Sftrigaux 
29601c188c59Sftrigaux   /* create the hypre solver object and set its information */
29611c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
29621c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
29631c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
29641c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
29651c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
29661c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
29671c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
29681c188c59Sftrigaux 
29691c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29701c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
29713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29721c188c59Sftrigaux }
29731c188c59Sftrigaux 
29741c188c59Sftrigaux /*MC
29755cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
29761c188c59Sftrigaux 
29771c188c59Sftrigaux    Level: advanced
29781c188c59Sftrigaux 
2979f1580f4eSBarry Smith    Options Database Keys:
29805cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
29815cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
29825cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
29835cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
29841c188c59Sftrigaux 
29851c188c59Sftrigaux    Notes:
29861c188c59Sftrigaux    This is for CELL-centered descretizations
29871c188c59Sftrigaux 
29885cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
29891c188c59Sftrigaux 
2990f1580f4eSBarry 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`.
2991f1580f4eSBarry Smith 
2992f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
2993f1580f4eSBarry Smith 
2994f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
29951c188c59Sftrigaux M*/
29961c188c59Sftrigaux 
2997d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
2998d71ae5a4SJacob Faibussowitsch {
29991c188c59Sftrigaux   PC_SMG *ex;
30001c188c59Sftrigaux 
30011c188c59Sftrigaux   PetscFunctionBegin;
30029371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
30031c188c59Sftrigaux   pc->data = ex;
30041c188c59Sftrigaux 
30051c188c59Sftrigaux   ex->its            = 1;
30061c188c59Sftrigaux   ex->tol            = 1.e-8;
30071c188c59Sftrigaux   ex->num_pre_relax  = 1;
30081c188c59Sftrigaux   ex->num_post_relax = 1;
30091c188c59Sftrigaux 
30101c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
30111c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
30121c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
30131c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
30141c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
30151c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
30161c188c59Sftrigaux 
30171c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3018ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
30191c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
30203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30211c188c59Sftrigaux }
3022