xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision feefa0e191a340680bb02e1467a36facdcb0b150)
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;
2380df1829cSStefano Zampini   /* default type is boomerAMG */
23948a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2405f5c5b43SBarry Smith 
2410df1829cSStefano Zampini   /* get hypre matrix */
2420df1829cSStefano Zampini   if (pc->flag == DIFFERENT_NONZERO_PATTERN) PetscCall(MatDestroy(&jac->hpmat));
2439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
24449a781f5SStefano Zampini   if (!ishypre) {
2450df1829cSStefano Zampini     /* Temporary fix since we do not support MAT_REUSE_MATRIX with HYPRE device */
2460df1829cSStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
2470df1829cSStefano Zampini     PetscBool iscuda, iship, iskokkos;
2480df1829cSStefano Zampini 
2490df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
2500df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
2510df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iskokkos, MATSEQAIJKOKKOS, MATMPIAIJKOKKOS, ""));
2520df1829cSStefano Zampini     if (iscuda || iship || iskokkos) PetscCall(MatDestroy(&jac->hpmat));
2530df1829cSStefano Zampini #endif
2540df1829cSStefano 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   }
2600df1829cSStefano 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) {
99419be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
99519be502cSAlexander     char       *prerelax[256];
99619be502cSAlexander     char       *postrelax[256];
99719be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
99819be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
99919be502cSAlexander     PetscBool   matchF, matchC, matchA;
100019be502cSAlexander 
1001589dcaf0SStefano 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 */
1002589dcaf0SStefano Zampini 
10039566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
1004792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1005589dcaf0SStefano Zampini 
10069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
1007792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1008589dcaf0SStefano Zampini 
10099566063dSJacob 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));
1010792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1011589dcaf0SStefano Zampini 
10129566063dSJacob 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));
1013792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
101419be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
101519be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
101619be502cSAlexander     PetscCheck(ns_down == jac->gridsweeps[0], PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_SIZ, "The number of arguments passed to -pc_hypre_boomeramg_prerelax must match the number passed to -pc_hypre_bomeramg_grid_sweeps_down");
101719be502cSAlexander     PetscCheck(ns_up == jac->gridsweeps[1], PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_SIZ, "The number of arguments passed to -pc_hypre_boomeramg_postrelax must match the number passed to -pc_hypre_bomeramg_grid_sweeps_up");
101819be502cSAlexander 
101919be502cSAlexander     grid_relax_points[0]    = NULL;
102019be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
102119be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
102219be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
102319be502cSAlexander     grid_relax_points[3][0] = 0;
102419be502cSAlexander 
102519be502cSAlexander     // set down relax scheme
102619be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
102719be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
102819be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
102919be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
103019be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
103119be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
103219be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
103319be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
103419be502cSAlexander     }
103519be502cSAlexander 
103619be502cSAlexander     // set up relax scheme
103719be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
103819be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
103919be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
104019be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
104119be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
104219be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
104319be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
104419be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
104519be502cSAlexander     }
104619be502cSAlexander 
104719be502cSAlexander     // set coarse relax scheme
104819be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
104919be502cSAlexander 
105019be502cSAlexander     // Pass relax schemes to hypre
105119be502cSAlexander     PetscCallExternal(HYPRE_BoomerAMGSetGridRelaxPoints, jac->hsolver, grid_relax_points);
105219be502cSAlexander 
105319be502cSAlexander     // cleanup memory
105419be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
105519be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1056589dcaf0SStefano Zampini   }
1057589dcaf0SStefano Zampini #endif
1058589dcaf0SStefano Zampini 
1059ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
106063a3b9bcSJacob 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);
1061ecae95adSPierre Jolivet #endif
1062ecae95adSPierre Jolivet 
10630f1074feSSatish Balay   /* new 3/07 */
1064dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1065589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1066589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1067792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
10680f1074feSSatish Balay   }
10690f1074feSSatish Balay 
10709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
107116d9e3a6SLisandro Dalcin   if (flg) {
1072b96a4a96SBarry Smith     level = 3;
10739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
10742fa5cd67SKarl Rupp 
1075b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1076792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
10772ae77aedSBarry Smith   }
10782ae77aedSBarry Smith 
10799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
10802ae77aedSBarry Smith   if (flg) {
1081b96a4a96SBarry Smith     level = 3;
10829566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
10832fa5cd67SKarl Rupp 
1084b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1085792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
108616d9e3a6SLisandro Dalcin   }
10878f87f92bSBarry Smith 
10889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
10898f87f92bSBarry Smith   if (flg && tmp_truth) {
10908f87f92bSBarry Smith     PetscInt tmp_int;
10919566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
10928f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1093792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1094792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1095792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1096792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
10978f87f92bSBarry Smith   }
10988f87f92bSBarry Smith 
10999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1100792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1101589dcaf0SStefano Zampini 
1102589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1103dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1104589dcaf0SStefano Zampini   if (flg) {
1105589dcaf0SStefano Zampini     jac->symt = indx;
1106792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1107589dcaf0SStefano Zampini   }
1108589dcaf0SStefano Zampini 
1109d0609cedSBarry Smith   PetscOptionsHeadEnd();
11103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
111116d9e3a6SLisandro Dalcin }
111216d9e3a6SLisandro Dalcin 
1113d71ae5a4SJacob 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)
1114d71ae5a4SJacob Faibussowitsch {
111516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11162cf14000SStefano Zampini   HYPRE_Int oits;
111716d9e3a6SLisandro Dalcin 
111816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11199566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1120792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1121792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
112216d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
11239566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
112416d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1125792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
11264d0a8057SBarry Smith   *outits = oits;
11274d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
11284d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1129792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1130792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
11313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
113216d9e3a6SLisandro Dalcin }
113316d9e3a6SLisandro Dalcin 
1134d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1135d71ae5a4SJacob Faibussowitsch {
113616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1137ace3abfcSBarry Smith   PetscBool iascii;
113816d9e3a6SLisandro Dalcin 
113916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
114116d9e3a6SLisandro Dalcin   if (iascii) {
11429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
11439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
114463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
114563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
11469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
11479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
11489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
114963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
115048a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
115163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
115263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
11530f1074feSSatish Balay 
11549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
115516d9e3a6SLisandro Dalcin 
115663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
115763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
115863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
115916d9e3a6SLisandro Dalcin 
11609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
11619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
11629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
116316d9e3a6SLisandro Dalcin 
11649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
11659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
116616d9e3a6SLisandro Dalcin 
116719be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
116819be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
116919be502cSAlexander 
117016d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
11719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
117216d9e3a6SLisandro Dalcin     } else {
11739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
117416d9e3a6SLisandro Dalcin     }
11756a251517SEike Mueller     if (jac->smoothtype != -1) {
11769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
117763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
11787e352d70SEike Mueller     } else {
11799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
11801810e44eSEike Mueller     }
11811810e44eSEike Mueller     if (jac->smoothtype == 3) {
118263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
11839566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
118463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
11856a251517SEike Mueller     }
11869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
11879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
11889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
118948a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
11905272c319SBarry Smith     if (jac->vec_interp_variant) {
119163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
119263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
11939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
11948f87f92bSBarry Smith     }
119548a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1196db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
11979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
11982d6c3ceeSStefano Zampini #else
11992d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1200db6f9c32SMark Adams #endif
1201589dcaf0SStefano Zampini     /* AIR */
1202589dcaf0SStefano Zampini     if (jac->Rtype) {
120363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
12049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
12059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
12069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
120763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1208589dcaf0SStefano Zampini     }
120916d9e3a6SLisandro Dalcin   }
12103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121116d9e3a6SLisandro Dalcin }
121216d9e3a6SLisandro Dalcin 
1213d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1214d71ae5a4SJacob Faibussowitsch {
121516d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
12164ddd07fcSJed Brown   PetscInt    indx;
1217ace3abfcSBarry Smith   PetscBool   flag;
121816d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
121916d9e3a6SLisandro Dalcin 
122016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1221d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
12229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
12239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1224792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
122516d9e3a6SLisandro Dalcin 
12269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1227792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
122816d9e3a6SLisandro Dalcin 
12299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1230792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
123116d9e3a6SLisandro Dalcin 
12329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1233792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
123416d9e3a6SLisandro Dalcin 
12359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1236792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
123716d9e3a6SLisandro Dalcin 
1238dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
123916d9e3a6SLisandro Dalcin   if (flag) {
124016d9e3a6SLisandro Dalcin     jac->symt = indx;
1241792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
124216d9e3a6SLisandro Dalcin   }
124316d9e3a6SLisandro Dalcin 
1244d0609cedSBarry Smith   PetscOptionsHeadEnd();
12453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
124616d9e3a6SLisandro Dalcin }
124716d9e3a6SLisandro Dalcin 
1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1249d71ae5a4SJacob Faibussowitsch {
125016d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1251ace3abfcSBarry Smith   PetscBool   iascii;
1252feb237baSPierre Jolivet   const char *symt = 0;
125316d9e3a6SLisandro Dalcin 
125416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
12559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
125616d9e3a6SLisandro Dalcin   if (iascii) {
12579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
125863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
12599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
12609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
12619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
12629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
12639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
12642fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
12652fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
12662fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
126763a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
12689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
126916d9e3a6SLisandro Dalcin   }
12703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
127116d9e3a6SLisandro Dalcin }
1272f1580f4eSBarry Smith 
1273d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1274d71ae5a4SJacob Faibussowitsch {
12754cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12764cb006feSStefano Zampini   PetscInt  n;
12774cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
12784cb006feSStefano Zampini 
12794cb006feSStefano Zampini   PetscFunctionBegin;
1280d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
12819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1282792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
12839566063dSJacob 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));
1284792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
12859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1286792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
12879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1288792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
12899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12909566063dSJacob 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));
12919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
129348a46eb9SPierre 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);
12949566063dSJacob 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));
12954cb006feSStefano Zampini   n = 5;
12969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
12974cb006feSStefano Zampini   if (flag || flag2) {
1298792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1299863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1300863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
13019371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1302a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
13034cb006feSStefano Zampini   }
13049566063dSJacob 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));
13054cb006feSStefano Zampini   n = 5;
13069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
13074cb006feSStefano Zampini   if (flag || flag2) {
1308792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1309863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1310863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
13119371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1312a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
13134cb006feSStefano Zampini   }
13149566063dSJacob 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));
131523df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1316792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
131723df4f25SStefano Zampini   }
1318d0609cedSBarry Smith   PetscOptionsHeadEnd();
13193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13204cb006feSStefano Zampini }
13214cb006feSStefano Zampini 
1322d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1323d71ae5a4SJacob Faibussowitsch {
13244cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13254cb006feSStefano Zampini   PetscBool iascii;
13264cb006feSStefano Zampini 
13274cb006feSStefano Zampini   PetscFunctionBegin;
13289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
13294cb006feSStefano Zampini   if (iascii) {
13309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
133163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
133263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
133363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
133463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
133563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
133663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
133763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13384cb006feSStefano Zampini     if (jac->alpha_Poisson) {
13399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
13404cb006feSStefano Zampini     } else {
13419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
13424cb006feSStefano Zampini     }
134363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
134463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
134563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
134663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
134763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
134863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13494cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
13504cb006feSStefano Zampini       if (jac->beta_Poisson) {
13519566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
13524cb006feSStefano Zampini       } else {
13539566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
13544cb006feSStefano Zampini       }
135563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
135663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
135763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
135863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
135963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
136063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
136148a46eb9SPierre 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));
136223df4f25SStefano Zampini     } else {
13639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
13644cb006feSStefano Zampini     }
13654cb006feSStefano Zampini   }
13663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13674cb006feSStefano Zampini }
13684cb006feSStefano Zampini 
1369d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1370d71ae5a4SJacob Faibussowitsch {
1371863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1372863406b8SStefano Zampini   PetscInt  n;
1373863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1374863406b8SStefano Zampini 
1375863406b8SStefano Zampini   PetscFunctionBegin;
1376d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
13779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1378792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
13799566063dSJacob 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));
1380792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
13819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1382792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
13839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1384792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
13859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
13869566063dSJacob 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));
13879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
13889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
138948a46eb9SPierre 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);
13909566063dSJacob 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));
1391863406b8SStefano Zampini   n = 5;
13929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
13939566063dSJacob 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));
1394863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1395792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1396863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1397863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1398863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
13999371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1400a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1401863406b8SStefano Zampini   }
14029566063dSJacob 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));
1403863406b8SStefano Zampini   n = 5;
14049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1405863406b8SStefano Zampini   if (flag || flag2) {
1406792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1407863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1408863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
14099371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1410a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1411863406b8SStefano Zampini   }
1412d0609cedSBarry Smith   PetscOptionsHeadEnd();
14133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1414863406b8SStefano Zampini }
1415863406b8SStefano Zampini 
1416d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1417d71ae5a4SJacob Faibussowitsch {
1418863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1419863406b8SStefano Zampini   PetscBool iascii;
1420863406b8SStefano Zampini 
1421863406b8SStefano Zampini   PetscFunctionBegin;
14229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1423863406b8SStefano Zampini   if (iascii) {
14249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
142563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
142663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
142763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
142863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
142963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
143063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
143163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
14329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
143363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
143463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
143563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
143663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
143763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
143863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
143963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
14409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
144163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
144263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
144363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
144463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
144563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
144663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1447863406b8SStefano Zampini   }
14483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1449863406b8SStefano Zampini }
1450863406b8SStefano Zampini 
1451d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1452d71ae5a4SJacob Faibussowitsch {
14534cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14545ac14e1cSStefano Zampini   PetscBool ishypre;
14554cb006feSStefano Zampini 
14564cb006feSStefano Zampini   PetscFunctionBegin;
14579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
14585ac14e1cSStefano Zampini   if (ishypre) {
14599566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
14609566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14615ac14e1cSStefano Zampini     jac->G = G;
14625ac14e1cSStefano Zampini   } else {
14639566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14649566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
14655ac14e1cSStefano Zampini   }
14663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14674cb006feSStefano Zampini }
14684cb006feSStefano Zampini 
14694cb006feSStefano Zampini /*@
1470f1580f4eSBarry Smith   PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
14714cb006feSStefano Zampini 
1472c3339decSBarry Smith   Collective
14734cb006feSStefano Zampini 
14744cb006feSStefano Zampini   Input Parameters:
14754cb006feSStefano Zampini + pc - the preconditioning context
14764cb006feSStefano Zampini - G  - the discrete gradient
14774cb006feSStefano Zampini 
14784cb006feSStefano Zampini   Level: intermediate
14794cb006feSStefano Zampini 
148095452b02SPatrick Sanan   Notes:
148195452b02SPatrick Sanan   G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1482147403d9SBarry Smith 
1483863406b8SStefano 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
14844cb006feSStefano Zampini 
1485*feefa0e1SJacob Faibussowitsch   Developer Notes:
1486f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1487f1580f4eSBarry Smith 
1488f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
14894cb006feSStefano Zampini @*/
1490d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1491d71ae5a4SJacob Faibussowitsch {
14924cb006feSStefano Zampini   PetscFunctionBegin;
14934cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14944cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
14954cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1496cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
14973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14984cb006feSStefano Zampini }
14994cb006feSStefano Zampini 
1500d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1501d71ae5a4SJacob Faibussowitsch {
1502863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15035ac14e1cSStefano Zampini   PetscBool ishypre;
1504863406b8SStefano Zampini 
1505863406b8SStefano Zampini   PetscFunctionBegin;
15069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
15075ac14e1cSStefano Zampini   if (ishypre) {
15089566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
15099566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
15105ac14e1cSStefano Zampini     jac->C = C;
15115ac14e1cSStefano Zampini   } else {
15129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
15139566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
15145ac14e1cSStefano Zampini   }
15153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1516863406b8SStefano Zampini }
1517863406b8SStefano Zampini 
1518863406b8SStefano Zampini /*@
1519f1580f4eSBarry Smith   PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1520863406b8SStefano Zampini 
1521c3339decSBarry Smith   Collective
1522863406b8SStefano Zampini 
1523863406b8SStefano Zampini   Input Parameters:
1524863406b8SStefano Zampini + pc - the preconditioning context
1525863406b8SStefano Zampini - C  - the discrete curl
1526863406b8SStefano Zampini 
1527863406b8SStefano Zampini   Level: intermediate
1528863406b8SStefano Zampini 
152995452b02SPatrick Sanan   Notes:
153095452b02SPatrick Sanan   C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1531147403d9SBarry Smith 
1532863406b8SStefano 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
1533863406b8SStefano Zampini 
1534*feefa0e1SJacob Faibussowitsch   Developer Notes:
1535f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1536f1580f4eSBarry Smith 
1537f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1538f1580f4eSBarry Smith 
1539f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1540863406b8SStefano Zampini @*/
1541d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1542d71ae5a4SJacob Faibussowitsch {
1543863406b8SStefano Zampini   PetscFunctionBegin;
1544863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1545863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1546863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1547cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
15483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1549863406b8SStefano Zampini }
1550863406b8SStefano Zampini 
1551d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1552d71ae5a4SJacob Faibussowitsch {
15536bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15546bf688a0SCe Qin   PetscBool ishypre;
15556bf688a0SCe Qin   PetscInt  i;
15566bf688a0SCe Qin   PetscFunctionBegin;
15576bf688a0SCe Qin 
15589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
15599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
15606bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
15619566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
15629566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
15636bf688a0SCe Qin   }
15646bf688a0SCe Qin 
15656bf688a0SCe Qin   jac->dim = dim;
15666bf688a0SCe Qin   if (RT_PiFull) {
15679566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
15686bf688a0SCe Qin     if (ishypre) {
15699566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
15706bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
15716bf688a0SCe Qin     } else {
15729566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
15736bf688a0SCe Qin     }
15746bf688a0SCe Qin   }
15756bf688a0SCe Qin   if (RT_Pi) {
15766bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15776bf688a0SCe Qin       if (RT_Pi[i]) {
15789566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
15796bf688a0SCe Qin         if (ishypre) {
15809566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
15816bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
15826bf688a0SCe Qin         } else {
15839566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
15846bf688a0SCe Qin         }
15856bf688a0SCe Qin       }
15866bf688a0SCe Qin     }
15876bf688a0SCe Qin   }
15886bf688a0SCe Qin   if (ND_PiFull) {
15899566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
15906bf688a0SCe Qin     if (ishypre) {
15919566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
15926bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
15936bf688a0SCe Qin     } else {
15949566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
15956bf688a0SCe Qin     }
15966bf688a0SCe Qin   }
15976bf688a0SCe Qin   if (ND_Pi) {
15986bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15996bf688a0SCe Qin       if (ND_Pi[i]) {
16009566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
16016bf688a0SCe Qin         if (ishypre) {
16029566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
16036bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
16046bf688a0SCe Qin         } else {
16059566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
16066bf688a0SCe Qin         }
16076bf688a0SCe Qin       }
16086bf688a0SCe Qin     }
16096bf688a0SCe Qin   }
16106bf688a0SCe Qin 
16113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16126bf688a0SCe Qin }
16136bf688a0SCe Qin 
16146bf688a0SCe Qin /*@
1615f1580f4eSBarry Smith   PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
16166bf688a0SCe Qin 
1617c3339decSBarry Smith   Collective
16186bf688a0SCe Qin 
16196bf688a0SCe Qin   Input Parameters:
16206bf688a0SCe Qin + pc        - the preconditioning context
16212fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
16222fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
16232fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
16242fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
16256bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
16266bf688a0SCe Qin 
1627f1580f4eSBarry Smith   Level: intermediate
1628f1580f4eSBarry Smith 
162995452b02SPatrick Sanan   Notes:
163095452b02SPatrick Sanan   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1631147403d9SBarry Smith 
16326bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1633147403d9SBarry Smith 
1634*feefa0e1SJacob Faibussowitsch   Developer Notes:
1635f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
16366bf688a0SCe Qin 
1637f1580f4eSBarry Smith .seealso: `PCHYPRE`
16386bf688a0SCe Qin @*/
1639d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1640d71ae5a4SJacob Faibussowitsch {
16416bf688a0SCe Qin   PetscInt i;
16426bf688a0SCe Qin 
16436bf688a0SCe Qin   PetscFunctionBegin;
16446bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16456bf688a0SCe Qin   if (RT_PiFull) {
16466bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
16476bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
16486bf688a0SCe Qin   }
16496bf688a0SCe Qin   if (RT_Pi) {
16506bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
16516bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16526bf688a0SCe Qin       if (RT_Pi[i]) {
16536bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
16546bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
16556bf688a0SCe Qin       }
16566bf688a0SCe Qin     }
16576bf688a0SCe Qin   }
16586bf688a0SCe Qin   if (ND_PiFull) {
16596bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
16606bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
16616bf688a0SCe Qin   }
16626bf688a0SCe Qin   if (ND_Pi) {
16636bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
16646bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16656bf688a0SCe Qin       if (ND_Pi[i]) {
16666bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
16676bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
16686bf688a0SCe Qin       }
16696bf688a0SCe Qin     }
16706bf688a0SCe Qin   }
1671cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
16723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16736bf688a0SCe Qin }
16746bf688a0SCe Qin 
1675d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1676d71ae5a4SJacob Faibussowitsch {
16774cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16785ac14e1cSStefano Zampini   PetscBool ishypre;
16794cb006feSStefano Zampini 
16804cb006feSStefano Zampini   PetscFunctionBegin;
16819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
16825ac14e1cSStefano Zampini   if (ishypre) {
16835ac14e1cSStefano Zampini     if (isalpha) {
16849566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
16859566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16865ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
16875ac14e1cSStefano Zampini     } else {
16885ac14e1cSStefano Zampini       if (A) {
16899566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
16905ac14e1cSStefano Zampini       } else {
16915ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16925ac14e1cSStefano Zampini       }
16939566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
16945ac14e1cSStefano Zampini       jac->beta_Poisson = A;
16955ac14e1cSStefano Zampini     }
16965ac14e1cSStefano Zampini   } else {
16975ac14e1cSStefano Zampini     if (isalpha) {
16989566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16999566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
17005ac14e1cSStefano Zampini     } else {
17015ac14e1cSStefano Zampini       if (A) {
17029566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
17039566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
17045ac14e1cSStefano Zampini       } else {
17059566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
17065ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
17075ac14e1cSStefano Zampini       }
17085ac14e1cSStefano Zampini     }
17095ac14e1cSStefano Zampini   }
17103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17114cb006feSStefano Zampini }
17124cb006feSStefano Zampini 
17134cb006feSStefano Zampini /*@
1714f1580f4eSBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
17154cb006feSStefano Zampini 
1716c3339decSBarry Smith   Collective
17174cb006feSStefano Zampini 
17184cb006feSStefano Zampini   Input Parameters:
17194cb006feSStefano Zampini + pc - the preconditioning context
17204cb006feSStefano Zampini - A  - the matrix
17214cb006feSStefano Zampini 
17224cb006feSStefano Zampini   Level: intermediate
17234cb006feSStefano Zampini 
1724f1580f4eSBarry Smith   Note:
172595452b02SPatrick Sanan   A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
17264cb006feSStefano Zampini 
1727*feefa0e1SJacob Faibussowitsch   Developer Notes:
1728f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1729f1580f4eSBarry Smith 
1730f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1731f1580f4eSBarry Smith 
1732f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
17334cb006feSStefano Zampini @*/
1734d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1735d71ae5a4SJacob Faibussowitsch {
17364cb006feSStefano Zampini   PetscFunctionBegin;
17374cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17384cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17394cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1740cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
17413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17424cb006feSStefano Zampini }
17434cb006feSStefano Zampini 
17444cb006feSStefano Zampini /*@
1745f1580f4eSBarry Smith   PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
17464cb006feSStefano Zampini 
1747c3339decSBarry Smith   Collective
17484cb006feSStefano Zampini 
17494cb006feSStefano Zampini   Input Parameters:
17504cb006feSStefano Zampini + pc - the preconditioning context
1751f1580f4eSBarry Smith - A  - the matrix, or NULL to turn it off
17524cb006feSStefano Zampini 
17534cb006feSStefano Zampini   Level: intermediate
17544cb006feSStefano Zampini 
1755f1580f4eSBarry Smith   Note:
175695452b02SPatrick Sanan   A should be obtained by discretizing the Poisson problem with linear finite elements.
17574cb006feSStefano Zampini 
1758*feefa0e1SJacob Faibussowitsch   Developer Notes:
1759f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1760f1580f4eSBarry Smith 
1761f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1762f1580f4eSBarry Smith 
1763f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17644cb006feSStefano Zampini @*/
1765d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1766d71ae5a4SJacob Faibussowitsch {
17674cb006feSStefano Zampini   PetscFunctionBegin;
17684cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17694cb006feSStefano Zampini   if (A) {
17704cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17714cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
17724cb006feSStefano Zampini   }
1773cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
17743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17754cb006feSStefano Zampini }
17764cb006feSStefano Zampini 
1777d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1778d71ae5a4SJacob Faibussowitsch {
17794cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17804cb006feSStefano Zampini 
17814cb006feSStefano Zampini   PetscFunctionBegin;
17824cb006feSStefano Zampini   /* throw away any vector if already set */
17839566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
17849566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
17859566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
17869566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
17879566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
17889566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
17899566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
17905ac14e1cSStefano Zampini   jac->dim = 2;
17914cb006feSStefano Zampini   if (zzo) {
17929566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
17939566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
17945ac14e1cSStefano Zampini     jac->dim++;
17954cb006feSStefano Zampini   }
17963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17974cb006feSStefano Zampini }
17984cb006feSStefano Zampini 
17994cb006feSStefano Zampini /*@
1800f1580f4eSBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
18014cb006feSStefano Zampini 
1802c3339decSBarry Smith   Collective
18034cb006feSStefano Zampini 
18044cb006feSStefano Zampini   Input Parameters:
18054cb006feSStefano Zampini + pc  - the preconditioning context
18062fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
18072fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
18084cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
18094cb006feSStefano Zampini 
18104cb006feSStefano Zampini   Level: intermediate
18114cb006feSStefano Zampini 
1812*feefa0e1SJacob Faibussowitsch   Developer Notes:
1813f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1814f1580f4eSBarry Smith 
1815f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
18164cb006feSStefano Zampini @*/
1817d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1818d71ae5a4SJacob Faibussowitsch {
18194cb006feSStefano Zampini   PetscFunctionBegin;
18204cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
18214cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
18224cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
18234cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
18244cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
18254cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
18264cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1827cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
18283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18294cb006feSStefano Zampini }
18304cb006feSStefano Zampini 
1831d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1832d71ae5a4SJacob Faibussowitsch {
1833be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1834be14dc20SKerry Key 
1835be14dc20SKerry Key   PetscFunctionBegin;
1836be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1837be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1838be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1839be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
18403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1841be14dc20SKerry Key }
1842be14dc20SKerry Key 
1843be14dc20SKerry Key /*@
1844f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1845be14dc20SKerry Key 
1846c3339decSBarry Smith   Collective
1847be14dc20SKerry Key 
1848be14dc20SKerry Key   Input Parameters:
1849be14dc20SKerry Key + pc       - the preconditioning context
1850be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
1851be14dc20SKerry Key 
1852be14dc20SKerry Key   Level: intermediate
1853be14dc20SKerry Key 
1854be14dc20SKerry Key   Note:
1855f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
1856f1580f4eSBarry Smith 
1857*feefa0e1SJacob Faibussowitsch   Developer Notes:
1858f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1859f1580f4eSBarry Smith 
1860f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1861be14dc20SKerry Key @*/
1862d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1863d71ae5a4SJacob Faibussowitsch {
1864be14dc20SKerry Key   PetscFunctionBegin;
1865be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1866be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1867be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1868be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
18693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1870be14dc20SKerry Key }
1871be14dc20SKerry Key 
1872d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1873d71ae5a4SJacob Faibussowitsch {
18744cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18754cb006feSStefano Zampini   Vec       tv;
18764cb006feSStefano Zampini   PetscInt  i;
18774cb006feSStefano Zampini 
18784cb006feSStefano Zampini   PetscFunctionBegin;
18794cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
18809566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
18819566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
18829566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
18835ac14e1cSStefano Zampini   jac->dim = dim;
18845ac14e1cSStefano Zampini 
18854cb006feSStefano Zampini   /* compute IJ vector for coordinates */
18869566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
18879566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
18889566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
18894cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
18904cb006feSStefano Zampini     PetscScalar *array;
18914cb006feSStefano Zampini     PetscInt     j;
18924cb006feSStefano Zampini 
18939566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
18949566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
18956ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
18969566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
18979566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
18984cb006feSStefano Zampini   }
18999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
19003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19014cb006feSStefano Zampini }
19024cb006feSStefano Zampini 
1903d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1904d71ae5a4SJacob Faibussowitsch {
190516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
190616d9e3a6SLisandro Dalcin 
190716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
190816d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
19093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191016d9e3a6SLisandro Dalcin }
191116d9e3a6SLisandro Dalcin 
1912d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1913d71ae5a4SJacob Faibussowitsch {
191416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1915ace3abfcSBarry Smith   PetscBool flag;
191616d9e3a6SLisandro Dalcin 
191716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
191816d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
19199566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
19205f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
19213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
192216d9e3a6SLisandro Dalcin   } else {
19239566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
192416d9e3a6SLisandro Dalcin   }
192516d9e3a6SLisandro Dalcin 
192616d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
192716d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
192816d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
192916d9e3a6SLisandro Dalcin 
19309566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
193116d9e3a6SLisandro Dalcin   if (flag) {
19329566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1933792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
193416d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
193516d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
193616d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
193716d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
193816d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
193916d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
19403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
194116d9e3a6SLisandro Dalcin   }
19429566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1943db966c6cSHong Zhang   if (flag) {
19444e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
19457de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
19468bf83915SBarry Smith #endif
19479566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1948792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1949db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1950db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1951db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1952db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1953db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1954db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1955db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
19563ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1957db966c6cSHong Zhang   }
19589566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
195916d9e3a6SLisandro Dalcin   if (flag) {
19609566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1961792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
196216d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
196316d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
196416d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
196516d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
196616d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
196716d9e3a6SLisandro Dalcin     /* initialize */
196816d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
19698966356dSPierre Jolivet     jac->threshold = .1;
197016d9e3a6SLisandro Dalcin     jac->filter    = .1;
197116d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
19722fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
19732fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
19742fa5cd67SKarl Rupp 
197516d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
197616d9e3a6SLisandro Dalcin     jac->symt = 0;
1977792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1978792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1979792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1980792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1981792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1982792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
19833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
198416d9e3a6SLisandro Dalcin   }
19859566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
198616d9e3a6SLisandro Dalcin   if (flag) {
1987792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
198816d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
198916d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
199016d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
199116d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
199285245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
19939566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
19949566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
199516d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
199616d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
199716d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
199816d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
199916d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
200016d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
200116d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
200216d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
20038f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
200416d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
200516d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
200616d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
200716d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
200816d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
20090f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
20106a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
2011b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
20121810e44eSEike Mueller     jac->eu_level                                                = 0;
20131810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
20141810e44eSEike Mueller     jac->eu_bj                                                   = 0;
2015589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
20160f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
201716d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
201816d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
201916d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
20200f1074feSSatish Balay     jac->interptype                       = 0;
2021589dcaf0SStefano Zampini     jac->Rtype                            = 0;
2022589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
2023589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
2024589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
2025589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
20260f1074feSSatish Balay     jac->agg_nl                           = 0;
20276ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
20280f1074feSSatish Balay     jac->pmax                             = 0;
20290f1074feSSatish Balay     jac->truncfactor                      = 0.0;
20300f1074feSSatish Balay     jac->agg_num_paths                    = 1;
2031589dcaf0SStefano Zampini     jac->maxc                             = 9;
2032589dcaf0SStefano Zampini     jac->minc                             = 1;
203322e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
203422e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
203522e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
203622e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
203722e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
203822e51d31SStefano Zampini     jac->interp_refine                    = 0;
20398f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
20408f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
20416ea7df73SStefano Zampini     jac->rap2                             = 0;
20426ea7df73SStefano Zampini 
20436ea7df73SStefano Zampini     /* GPU defaults
20446ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
20456ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
20466ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
20476ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
20486ea7df73SStefano Zampini     jac->mod_rap2       = 1;
20496ea7df73SStefano Zampini     jac->coarsentype    = 8;
20506ea7df73SStefano Zampini     jac->relaxorder     = 0;
20516ea7df73SStefano Zampini     jac->interptype     = 6;
20526ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
20536ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
20546ea7df73SStefano Zampini     jac->agg_interptype = 7;
20556ea7df73SStefano Zampini #else
20566ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
20576ea7df73SStefano Zampini     jac->mod_rap2      = 0;
20586ea7df73SStefano Zampini #endif
2059792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
2060792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
2061792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
2062792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
2063792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
2064792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
2065792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
2066792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
2067792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
2068792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
2069792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
2070792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
2071792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2072792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2073792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2074792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2075792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2076792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2077792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
20786ea7df73SStefano Zampini     /* GPU */
20796ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2080792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2081792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2082792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
20836ea7df73SStefano Zampini #endif
20846ea7df73SStefano Zampini 
2085589dcaf0SStefano Zampini     /* AIR */
20866ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2087792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2088792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2089792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2090792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2091792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
20926ea7df73SStefano Zampini #endif
20933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
209416d9e3a6SLisandro Dalcin   }
20959566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
20964cb006feSStefano Zampini   if (flag) {
20973ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
20984cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
20994cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
21004cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
21014cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
21024cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
21034cb006feSStefano Zampini     jac->coords[0]          = NULL;
21044cb006feSStefano Zampini     jac->coords[1]          = NULL;
21054cb006feSStefano Zampini     jac->coords[2]          = NULL;
2106be14dc20SKerry Key     jac->interior           = NULL;
21074cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2108863406b8SStefano Zampini     jac->as_print       = 0;
2109863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2110863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
21114cb006feSStefano Zampini     jac->ams_cycle_type = 13;
21124cb006feSStefano Zampini     /* Smoothing options */
2113863406b8SStefano Zampini     jac->as_relax_type   = 2;
2114863406b8SStefano Zampini     jac->as_relax_times  = 1;
2115863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2116863406b8SStefano Zampini     jac->as_omega        = 1.0;
21174cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2118863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2119863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
21200bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2121863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2122863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2123863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
21244cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2125863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2126863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
21270bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2128863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2129863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2130863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2131792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2132792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2133792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2134792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
21359371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2136792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2137863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2138863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
21399371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2140a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2141792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2142863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2143863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
21449371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2145a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
214623df4f25SStefano Zampini     /* Zero conductivity */
214723df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
214823df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
21493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
21504cb006feSStefano Zampini   }
21519566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2152863406b8SStefano Zampini   if (flag) {
21533ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2154863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2155863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2156863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2157863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2158863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2159863406b8SStefano Zampini     jac->coords[0]          = NULL;
2160863406b8SStefano Zampini     jac->coords[1]          = NULL;
2161863406b8SStefano Zampini     jac->coords[2]          = NULL;
2162863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2163863406b8SStefano Zampini     jac->as_print       = 0;
2164863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2165863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2166863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2167863406b8SStefano Zampini     /* Smoothing options */
2168863406b8SStefano Zampini     jac->as_relax_type   = 2;
2169863406b8SStefano Zampini     jac->as_relax_times  = 1;
2170863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2171863406b8SStefano Zampini     jac->as_omega        = 1.0;
2172863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2173863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2174863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2175863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2176863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2177863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2178863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2179863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2180863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2181863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2182863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2183863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2184863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2185863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2186863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2187792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2188792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2189792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2190792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
21919371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2192792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2193863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2194863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2195863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
21969371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2197a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2198792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2199863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2200863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
22019371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2202a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
22033ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2204863406b8SStefano Zampini   }
22059566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
22062fa5cd67SKarl Rupp 
22070298fd71SBarry Smith   jac->hypre_type = NULL;
220898921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
220916d9e3a6SLisandro Dalcin }
221016d9e3a6SLisandro Dalcin 
221116d9e3a6SLisandro Dalcin /*
221216d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
221316d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
221416d9e3a6SLisandro Dalcin */
2215d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2216d71ae5a4SJacob Faibussowitsch {
22174ddd07fcSJed Brown   PetscInt    indx;
2218db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2219ace3abfcSBarry Smith   PetscBool   flg;
222016d9e3a6SLisandro Dalcin 
222116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2222d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2223dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
222416d9e3a6SLisandro Dalcin   if (flg) {
22259566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
222602a17cd4SBarry Smith   } else {
22279566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
222816d9e3a6SLisandro Dalcin   }
2229dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2230d0609cedSBarry Smith   PetscOptionsHeadEnd();
22313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
223216d9e3a6SLisandro Dalcin }
223316d9e3a6SLisandro Dalcin 
223416d9e3a6SLisandro Dalcin /*@C
223516d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
223616d9e3a6SLisandro Dalcin 
223716d9e3a6SLisandro Dalcin   Input Parameters:
223816d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2239db966c6cSHong Zhang - name - either  euclid, pilut, parasails, boomeramg, ams, ads
224016d9e3a6SLisandro Dalcin 
2241f1580f4eSBarry Smith   Options Database Key:
2242*feefa0e1SJacob Faibussowitsch . pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
224316d9e3a6SLisandro Dalcin 
224416d9e3a6SLisandro Dalcin   Level: intermediate
224516d9e3a6SLisandro Dalcin 
2246f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
224716d9e3a6SLisandro Dalcin @*/
2248d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2249d71ae5a4SJacob Faibussowitsch {
225016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22510700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
225216d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2253cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
22543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225516d9e3a6SLisandro Dalcin }
225616d9e3a6SLisandro Dalcin 
225716d9e3a6SLisandro Dalcin /*@C
225816d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
225916d9e3a6SLisandro Dalcin 
226016d9e3a6SLisandro Dalcin   Input Parameter:
226116d9e3a6SLisandro Dalcin . pc - the preconditioner context
226216d9e3a6SLisandro Dalcin 
226316d9e3a6SLisandro Dalcin   Output Parameter:
2264db966c6cSHong Zhang . name - either  euclid, pilut, parasails, boomeramg, ams, ads
226516d9e3a6SLisandro Dalcin 
226616d9e3a6SLisandro Dalcin   Level: intermediate
226716d9e3a6SLisandro Dalcin 
2268f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
226916d9e3a6SLisandro Dalcin @*/
2270d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2271d71ae5a4SJacob Faibussowitsch {
227216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22730700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
227416d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2275cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
22763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227716d9e3a6SLisandro Dalcin }
227816d9e3a6SLisandro Dalcin 
2279db6f9c32SMark Adams /*@C
2280f1580f4eSBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2281db6f9c32SMark Adams 
2282c3339decSBarry Smith   Logically Collective
2283db6f9c32SMark Adams 
2284db6f9c32SMark Adams   Input Parameters:
2285db6f9c32SMark Adams + pc   - the hypre context
2286*feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2287db6f9c32SMark Adams 
2288db6f9c32SMark Adams   Options Database Key:
228967b8a455SSatish Balay . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2290db6f9c32SMark Adams 
2291db6f9c32SMark Adams   Level: intermediate
2292db6f9c32SMark Adams 
2293*feefa0e1SJacob Faibussowitsch   Developer Notes:
2294f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2295db6f9c32SMark Adams 
2296f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2297db6f9c32SMark Adams @*/
2298d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2299d71ae5a4SJacob Faibussowitsch {
2300db6f9c32SMark Adams   PetscFunctionBegin;
2301db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2302cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
23033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2304db6f9c32SMark Adams }
2305db6f9c32SMark Adams 
2306db6f9c32SMark Adams /*@C
2307f1580f4eSBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2308db6f9c32SMark Adams 
2309db6f9c32SMark Adams   Not Collective
2310db6f9c32SMark Adams 
2311db6f9c32SMark Adams   Input Parameter:
2312db6f9c32SMark Adams . pc - the multigrid context
2313db6f9c32SMark Adams 
2314db6f9c32SMark Adams   Output Parameter:
2315db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2316db6f9c32SMark Adams 
2317db6f9c32SMark Adams   Level: intermediate
2318db6f9c32SMark Adams 
2319f1580f4eSBarry Smith .seealso: `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2320db6f9c32SMark Adams @*/
2321d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2322d71ae5a4SJacob Faibussowitsch {
2323db6f9c32SMark Adams   PetscFunctionBegin;
2324db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2325cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
23263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2327db6f9c32SMark Adams }
2328db6f9c32SMark Adams 
232916d9e3a6SLisandro Dalcin /*MC
2330f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
233116d9e3a6SLisandro Dalcin 
233216d9e3a6SLisandro Dalcin    Options Database Keys:
2333e1ded407SBarry Smith +   -pc_hypre_type - One of `euclid`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2334f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2335f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2336e1ded407SBarry Smith -   Many others, run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
233716d9e3a6SLisandro Dalcin 
233816d9e3a6SLisandro Dalcin    Level: intermediate
233916d9e3a6SLisandro Dalcin 
234095452b02SPatrick Sanan    Notes:
2341e1ded407SBarry Smith     Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
234216d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
234349567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
234416d9e3a6SLisandro Dalcin 
2345e1ded407SBarry Smith           The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2346e1ded407SBarry Smith           (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2347e1ded407SBarry Smith           `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2348e1ded407SBarry Smith           (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2349e1ded407SBarry Smith           iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2350e1ded407SBarry Smith           and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2351e1ded407SBarry Smith           then AT MOST twenty V-cycles of boomeramg will be used.
235216d9e3a6SLisandro Dalcin 
2353e1ded407SBarry Smith            Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
23540f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2355e1ded407SBarry Smith            Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
235616d9e3a6SLisandro Dalcin 
2357f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2358e1ded407SBarry Smith           the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
23590b1a5bd9SEric Chamberland 
2360f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2361f1580f4eSBarry Smith 
2362e1ded407SBarry Smith           For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2363f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
236449567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2365f1580f4eSBarry Smith 
2366e1ded407SBarry Smith   Sometimes people want to try algebraic multigrid as a "standalone" solver, that is not accelerating it with a Krylov method. Though we generally do not recommend this
2367e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2368e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2369e1ded407SBarry Smith 
2370f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
23719e5bc791SBarry Smith 
2372ead8c081SBarry Smith    GPU Notes:
2373ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2374f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2375ead8c081SBarry Smith 
2376ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2377f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2378ead8c081SBarry Smith 
2379f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2380f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2381f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
238216d9e3a6SLisandro Dalcin M*/
238316d9e3a6SLisandro Dalcin 
2384d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2385d71ae5a4SJacob Faibussowitsch {
238616d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
238716d9e3a6SLisandro Dalcin 
238816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23894dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
23902fa5cd67SKarl Rupp 
239116d9e3a6SLisandro Dalcin   pc->data                = jac;
23928695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
239316d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
239416d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
239516d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
239616d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
239716d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
23989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
23999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
24009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
24019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
24029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
24039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
24049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2405be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
24069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
24079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
24089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
24096ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24106ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
24119566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24126ea7df73SStefano Zampini   #endif
24136ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
24149566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24156ea7df73SStefano Zampini   #endif
24166ea7df73SStefano Zampini #endif
2417ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
24183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
241916d9e3a6SLisandro Dalcin }
2420ebc551c0SBarry Smith 
2421ebc551c0SBarry Smith typedef struct {
242268326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2423f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
24249e5bc791SBarry Smith 
24259e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
24264ddd07fcSJed Brown   PetscInt  its;
24279e5bc791SBarry Smith   double    tol;
24284ddd07fcSJed Brown   PetscInt  relax_type;
24294ddd07fcSJed Brown   PetscInt  rap_type;
24304ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
24314ddd07fcSJed Brown   PetscInt  max_levels;
24320be8cd64Sftrigaux   PetscInt  skip_relax;
24330be8cd64Sftrigaux   PetscBool print_statistics;
2434ebc551c0SBarry Smith } PC_PFMG;
2435ebc551c0SBarry Smith 
2436d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_PFMG(PC pc)
2437d71ae5a4SJacob Faibussowitsch {
2438f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2439ebc551c0SBarry Smith 
2440ebc551c0SBarry Smith   PetscFunctionBegin;
2441792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
24429566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
24439566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
24443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2445ebc551c0SBarry Smith }
2446ebc551c0SBarry Smith 
24479e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
24489e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
24499e5bc791SBarry Smith 
2450d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2451d71ae5a4SJacob Faibussowitsch {
2452ace3abfcSBarry Smith   PetscBool iascii;
2453f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2454ebc551c0SBarry Smith 
2455ebc551c0SBarry Smith   PetscFunctionBegin;
24569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
24579e5bc791SBarry Smith   if (iascii) {
24589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
245963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
24609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
24619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
24629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
246363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
246463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
24650be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
24669e5bc791SBarry Smith   }
24673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2468ebc551c0SBarry Smith }
2469ebc551c0SBarry Smith 
2470d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2471d71ae5a4SJacob Faibussowitsch {
2472f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2473ebc551c0SBarry Smith 
2474ebc551c0SBarry Smith   PetscFunctionBegin;
2475d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
24760be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
24779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2478792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24799566063dSJacob 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));
2480792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24819566063dSJacob 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));
2482792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24839e5bc791SBarry Smith 
24849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2485792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24863b46a515SGlenn Hammond 
24879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2488792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2489dd39110bSPierre 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));
2490792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2491dd39110bSPierre 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));
2492792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24930be8cd64Sftrigaux   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));
24940be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2495d0609cedSBarry Smith   PetscOptionsHeadEnd();
24963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2497ebc551c0SBarry Smith }
2498ebc551c0SBarry Smith 
2499d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2500d71ae5a4SJacob Faibussowitsch {
2501f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2502d9ca1df4SBarry Smith   PetscScalar       *yy;
2503d9ca1df4SBarry Smith   const PetscScalar *xx;
25044ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
25052cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
250668326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2507f91d8e95SBarry Smith 
2508f91d8e95SBarry Smith   PetscFunctionBegin;
25099566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
25109566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
25112cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2512f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2513f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2514f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
25152cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
25162cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
25172cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
25182cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
25192cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
25202cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2521f91d8e95SBarry Smith 
2522f91d8e95SBarry Smith   /* copy x values over to hypre */
2523792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
25249566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2525792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
25269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2527792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2528792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2529f91d8e95SBarry Smith 
2530f91d8e95SBarry Smith   /* copy solution values back to PETSc */
25319566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2532792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
25339566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
25343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2535f91d8e95SBarry Smith }
2536f91d8e95SBarry Smith 
2537d71ae5a4SJacob 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)
2538d71ae5a4SJacob Faibussowitsch {
25399e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
25402cf14000SStefano Zampini   HYPRE_Int oits;
25419e5bc791SBarry Smith 
25429e5bc791SBarry Smith   PetscFunctionBegin;
25439566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2544792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2545792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
25469e5bc791SBarry Smith 
25479566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2548792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
25499e5bc791SBarry Smith   *outits = oits;
25509e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
25519e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2552792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2553792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
25543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25559e5bc791SBarry Smith }
25569e5bc791SBarry Smith 
2557d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_PFMG(PC pc)
2558d71ae5a4SJacob Faibussowitsch {
25593a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
25603a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2561ace3abfcSBarry Smith   PetscBool        flg;
25623a32d3dbSGlenn Hammond 
25633a32d3dbSGlenn Hammond   PetscFunctionBegin;
25649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
256528b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
25663a32d3dbSGlenn Hammond 
25673a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2568792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2569792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25700be8cd64Sftrigaux 
25710be8cd64Sftrigaux   // Print Hypre statistics about the solve process
25720be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
25730be8cd64Sftrigaux 
25740be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
25750be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
25760be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
25770be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
25780be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
25790be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
25800be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
25810be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
25820be8cd64Sftrigaux 
2583792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2584792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
25853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25863a32d3dbSGlenn Hammond }
25873a32d3dbSGlenn Hammond 
2588ebc551c0SBarry Smith /*MC
2589ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2590ebc551c0SBarry Smith 
2591f1580f4eSBarry Smith    Options Database Keys:
259267b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
259367b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
259467b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
259567b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
25969e5bc791SBarry 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
25970be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2598f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2599f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2600f1580f4eSBarry Smith 
2601f1580f4eSBarry Smith    Level: advanced
2602f91d8e95SBarry Smith 
260395452b02SPatrick Sanan    Notes:
260495452b02SPatrick Sanan    This is for CELL-centered descretizations
26059e5bc791SBarry Smith 
2606f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
26079e5bc791SBarry Smith 
2608f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2609f1580f4eSBarry Smith 
2610f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2611f1580f4eSBarry Smith 
2612f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2613f1580f4eSBarry Smith 
2614f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2615ebc551c0SBarry Smith M*/
2616ebc551c0SBarry Smith 
2617d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2618d71ae5a4SJacob Faibussowitsch {
2619ebc551c0SBarry Smith   PC_PFMG *ex;
2620ebc551c0SBarry Smith 
2621ebc551c0SBarry Smith   PetscFunctionBegin;
26229371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
262368326731SBarry Smith   pc->data = ex;
2624ebc551c0SBarry Smith 
26259e5bc791SBarry Smith   ex->its              = 1;
26269e5bc791SBarry Smith   ex->tol              = 1.e-8;
26279e5bc791SBarry Smith   ex->relax_type       = 1;
26289e5bc791SBarry Smith   ex->rap_type         = 0;
26299e5bc791SBarry Smith   ex->num_pre_relax    = 1;
26309e5bc791SBarry Smith   ex->num_post_relax   = 1;
26313b46a515SGlenn Hammond   ex->max_levels       = 0;
26320be8cd64Sftrigaux   ex->skip_relax       = 0;
26330be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
26349e5bc791SBarry Smith 
2635ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2636ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2637ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2638f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
26399e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
264068326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
26412fa5cd67SKarl Rupp 
26429566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2643ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2644792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
26453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2646ebc551c0SBarry Smith }
2647d851a50bSGlenn Hammond 
2648d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2649d851a50bSGlenn Hammond typedef struct {
2650d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2651d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2652d851a50bSGlenn Hammond 
2653d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
26544ddd07fcSJed Brown   PetscInt its;
2655d851a50bSGlenn Hammond   double   tol;
26564ddd07fcSJed Brown   PetscInt relax_type;
26574ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2658d851a50bSGlenn Hammond } PC_SysPFMG;
2659d851a50bSGlenn Hammond 
2660d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SysPFMG(PC pc)
2661d71ae5a4SJacob Faibussowitsch {
2662d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2663d851a50bSGlenn Hammond 
2664d851a50bSGlenn Hammond   PetscFunctionBegin;
2665792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
26669566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
26679566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
26683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2669d851a50bSGlenn Hammond }
2670d851a50bSGlenn Hammond 
2671d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2672d851a50bSGlenn Hammond 
2673d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2674d71ae5a4SJacob Faibussowitsch {
2675ace3abfcSBarry Smith   PetscBool   iascii;
2676d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2677d851a50bSGlenn Hammond 
2678d851a50bSGlenn Hammond   PetscFunctionBegin;
26799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2680d851a50bSGlenn Hammond   if (iascii) {
26819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
268263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
26839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
26849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
268563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2686d851a50bSGlenn Hammond   }
26873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2688d851a50bSGlenn Hammond }
2689d851a50bSGlenn Hammond 
2690d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2691d71ae5a4SJacob Faibussowitsch {
2692d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2693ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2694d851a50bSGlenn Hammond 
2695d851a50bSGlenn Hammond   PetscFunctionBegin;
2696d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
26979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
269848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
26999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2700792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
27019566063dSJacob 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));
2702792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
27039566063dSJacob 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));
2704792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2705d851a50bSGlenn Hammond 
27069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2707792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2708dd39110bSPierre 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));
2709792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2710d0609cedSBarry Smith   PetscOptionsHeadEnd();
27113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2712d851a50bSGlenn Hammond }
2713d851a50bSGlenn Hammond 
2714d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2715d71ae5a4SJacob Faibussowitsch {
2716d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2717d9ca1df4SBarry Smith   PetscScalar       *yy;
2718d9ca1df4SBarry Smith   const PetscScalar *xx;
27194ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
27202cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2721d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
27224ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
27234ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
27244ddd07fcSJed Brown   PetscInt           part     = 0;
27254ddd07fcSJed Brown   PetscInt           size;
27264ddd07fcSJed Brown   PetscInt           i;
2727d851a50bSGlenn Hammond 
2728d851a50bSGlenn Hammond   PetscFunctionBegin;
27299566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
27309566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
27312cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2732d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2733d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2734d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
27352cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
27362cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
27372cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
27382cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
27392cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
27402cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2741d851a50bSGlenn Hammond 
2742d851a50bSGlenn Hammond   size = 1;
27432fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
27442fa5cd67SKarl Rupp 
2745d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2746d851a50bSGlenn Hammond   if (ordering) {
2747792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27489566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2749792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
27509566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2751792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2752792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2753792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2754d851a50bSGlenn Hammond 
2755d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27569566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2757792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
27589566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2759a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2760d851a50bSGlenn Hammond     PetscScalar *z;
27614ddd07fcSJed Brown     PetscInt     j, k;
2762d851a50bSGlenn Hammond 
27639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2764792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27659566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2766d851a50bSGlenn Hammond 
2767d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2768d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2769d851a50bSGlenn Hammond       k = i * nvars;
27702fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2771d851a50bSGlenn Hammond     }
2772792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
27739566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2774792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2775792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2776d851a50bSGlenn Hammond 
2777d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27789566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2779792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2780d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2781d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2782d851a50bSGlenn Hammond       k = i * nvars;
27832fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2784d851a50bSGlenn Hammond     }
27859566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
27869566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2787d851a50bSGlenn Hammond   }
27883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2789d851a50bSGlenn Hammond }
2790d851a50bSGlenn Hammond 
2791d71ae5a4SJacob 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)
2792d71ae5a4SJacob Faibussowitsch {
2793d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
27942cf14000SStefano Zampini   HYPRE_Int   oits;
2795d851a50bSGlenn Hammond 
2796d851a50bSGlenn Hammond   PetscFunctionBegin;
27979566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2798792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2799792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
28009566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2801792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2802d851a50bSGlenn Hammond   *outits = oits;
2803d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2804d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2805792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2806792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
28073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2808d851a50bSGlenn Hammond }
2809d851a50bSGlenn Hammond 
2810d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SysPFMG(PC pc)
2811d71ae5a4SJacob Faibussowitsch {
2812d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2813d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2814ace3abfcSBarry Smith   PetscBool         flg;
2815d851a50bSGlenn Hammond 
2816d851a50bSGlenn Hammond   PetscFunctionBegin;
28179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
281828b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2819d851a50bSGlenn Hammond 
2820d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2821792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2822792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2823792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2824792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
28253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2826d851a50bSGlenn Hammond }
2827d851a50bSGlenn Hammond 
2828d851a50bSGlenn Hammond /*MC
2829f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2830d851a50bSGlenn Hammond 
2831d851a50bSGlenn Hammond    Level: advanced
2832d851a50bSGlenn Hammond 
2833f1580f4eSBarry Smith    Options Database Keys:
283467b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
283567b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
283667b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
283767b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
283867b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2839d851a50bSGlenn Hammond 
284095452b02SPatrick Sanan    Notes:
2841f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2842f1580f4eSBarry Smith 
2843f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2844f1580f4eSBarry Smith 
284595452b02SPatrick Sanan    This is for CELL-centered descretizations
2846d851a50bSGlenn Hammond 
2847f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2848d851a50bSGlenn Hammond 
2849f1580f4eSBarry 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`.
2850f1580f4eSBarry Smith 
2851f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2852d851a50bSGlenn Hammond M*/
2853d851a50bSGlenn Hammond 
2854d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2855d71ae5a4SJacob Faibussowitsch {
2856d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2857d851a50bSGlenn Hammond 
2858d851a50bSGlenn Hammond   PetscFunctionBegin;
28599371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2860d851a50bSGlenn Hammond   pc->data = ex;
2861d851a50bSGlenn Hammond 
2862d851a50bSGlenn Hammond   ex->its            = 1;
2863d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2864d851a50bSGlenn Hammond   ex->relax_type     = 1;
2865d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2866d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2867d851a50bSGlenn Hammond 
2868d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2869d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2870d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2871d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2872d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2873d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
28742fa5cd67SKarl Rupp 
28759566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2876ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2877792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
28783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2879d851a50bSGlenn Hammond }
28801c188c59Sftrigaux 
2881f1580f4eSBarry Smith /* PC SMG */
28821c188c59Sftrigaux typedef struct {
28831c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
28841c188c59Sftrigaux   HYPRE_StructSolver hsolver;
28851c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
28861c188c59Sftrigaux   double             tol;
28871c188c59Sftrigaux   PetscBool          print_statistics;
28881c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
28891c188c59Sftrigaux } PC_SMG;
28901c188c59Sftrigaux 
2891d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SMG(PC pc)
2892d71ae5a4SJacob Faibussowitsch {
28931c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28941c188c59Sftrigaux 
28951c188c59Sftrigaux   PetscFunctionBegin;
28961c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
28971c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28981c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
28993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29001c188c59Sftrigaux }
29011c188c59Sftrigaux 
2902d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2903d71ae5a4SJacob Faibussowitsch {
29041c188c59Sftrigaux   PetscBool iascii;
29051c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
29061c188c59Sftrigaux 
29071c188c59Sftrigaux   PetscFunctionBegin;
29081c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
29091c188c59Sftrigaux   if (iascii) {
29101c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
29111c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
29121c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
29131c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
29141c188c59Sftrigaux   }
29153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29161c188c59Sftrigaux }
29171c188c59Sftrigaux 
2918d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2919d71ae5a4SJacob Faibussowitsch {
29201c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
29211c188c59Sftrigaux 
29221c188c59Sftrigaux   PetscFunctionBegin;
29231c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
29241c188c59Sftrigaux 
29251c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
29261c188c59Sftrigaux   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));
29271c188c59Sftrigaux   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));
29281c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
29291c188c59Sftrigaux 
29301c188c59Sftrigaux   PetscOptionsHeadEnd();
29313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29321c188c59Sftrigaux }
29331c188c59Sftrigaux 
2934d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2935d71ae5a4SJacob Faibussowitsch {
29361c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
29371c188c59Sftrigaux   PetscScalar       *yy;
29381c188c59Sftrigaux   const PetscScalar *xx;
29391c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
29401c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
29411c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
29421c188c59Sftrigaux 
29431c188c59Sftrigaux   PetscFunctionBegin;
29441c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29451c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
29461c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
29471c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
29481c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
29491c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
29501c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
29511c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
29521c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
29531c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
29541c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
29551c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
29561c188c59Sftrigaux 
29571c188c59Sftrigaux   /* copy x values over to hypre */
29581c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
29591c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
29601c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
29611c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
29621c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
29631c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29641c188c59Sftrigaux 
29651c188c59Sftrigaux   /* copy solution values back to PETSc */
29661c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
29671c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
29681c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
29693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29701c188c59Sftrigaux }
29711c188c59Sftrigaux 
2972d71ae5a4SJacob 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)
2973d71ae5a4SJacob Faibussowitsch {
29741c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
29751c188c59Sftrigaux   HYPRE_Int oits;
29761c188c59Sftrigaux 
29771c188c59Sftrigaux   PetscFunctionBegin;
29781c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29791c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
29801c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
29811c188c59Sftrigaux 
29821c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
29831c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
29841c188c59Sftrigaux   *outits = oits;
29851c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
29861c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
29871c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
29881c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
29893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29901c188c59Sftrigaux }
29911c188c59Sftrigaux 
2992d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SMG(PC pc)
2993d71ae5a4SJacob Faibussowitsch {
29941c188c59Sftrigaux   PetscInt         i, dim;
29951c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
29961c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
29971c188c59Sftrigaux   PetscBool        flg;
29981c188c59Sftrigaux   DMBoundaryType   p[3];
29991c188c59Sftrigaux   PetscInt         M[3];
30001c188c59Sftrigaux 
30011c188c59Sftrigaux   PetscFunctionBegin;
30021c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
30031c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
30041c188c59Sftrigaux 
30051c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
30061c188c59Sftrigaux   // Check if power of 2 in periodic directions
30071c188c59Sftrigaux   for (i = 0; i < dim; i++) {
30081c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
30091c188c59Sftrigaux       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]);
30101c188c59Sftrigaux     }
30111c188c59Sftrigaux   }
30121c188c59Sftrigaux 
30131c188c59Sftrigaux   /* create the hypre solver object and set its information */
30141c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
30151c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
30161c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
30171c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
30181c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
30191c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
30201c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
30211c188c59Sftrigaux 
30221c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
30231c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
30243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30251c188c59Sftrigaux }
30261c188c59Sftrigaux 
30271c188c59Sftrigaux /*MC
30285cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
30291c188c59Sftrigaux 
30301c188c59Sftrigaux    Level: advanced
30311c188c59Sftrigaux 
3032f1580f4eSBarry Smith    Options Database Keys:
30335cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
30345cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
30355cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
30365cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
30371c188c59Sftrigaux 
30381c188c59Sftrigaux    Notes:
30391c188c59Sftrigaux    This is for CELL-centered descretizations
30401c188c59Sftrigaux 
30415cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
30421c188c59Sftrigaux 
3043f1580f4eSBarry 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`.
3044f1580f4eSBarry Smith 
3045f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3046f1580f4eSBarry Smith 
3047f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
30481c188c59Sftrigaux M*/
30491c188c59Sftrigaux 
3050d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3051d71ae5a4SJacob Faibussowitsch {
30521c188c59Sftrigaux   PC_SMG *ex;
30531c188c59Sftrigaux 
30541c188c59Sftrigaux   PetscFunctionBegin;
30559371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
30561c188c59Sftrigaux   pc->data = ex;
30571c188c59Sftrigaux 
30581c188c59Sftrigaux   ex->its            = 1;
30591c188c59Sftrigaux   ex->tol            = 1.e-8;
30601c188c59Sftrigaux   ex->num_pre_relax  = 1;
30611c188c59Sftrigaux   ex->num_post_relax = 1;
30621c188c59Sftrigaux 
30631c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
30641c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
30651c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
30661c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
30671c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
30681c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
30691c188c59Sftrigaux 
30701c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3071ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
30721c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
30733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30741c188c59Sftrigaux }
3075