xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 6e415bd26dfd0d33b8d7233bdee8a51de4844a26)
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;
663c61a47dSLukas   PetscInt  smoothsweeps;
678131ecf7SEike Mueller   PetscInt  smoothnumlevels;
68ec64516dSEike Mueller   PetscInt  eu_level;         /* Number of levels for ILU(k) in Euclid */
6939accc25SStefano Zampini   PetscReal eu_droptolerance; /* Drop tolerance for ILU(k) in Euclid */
70ec64516dSEike Mueller   PetscInt  eu_bj;            /* Defines use of Block Jacobi ILU in Euclid */
714ddd07fcSJed Brown   PetscInt  relaxtype[3];
7239accc25SStefano Zampini   PetscReal relaxweight;
7339accc25SStefano Zampini   PetscReal outerrelaxweight;
744ddd07fcSJed Brown   PetscInt  relaxorder;
7539accc25SStefano Zampini   PetscReal truncfactor;
76ace3abfcSBarry Smith   PetscBool applyrichardson;
774ddd07fcSJed Brown   PetscInt  pmax;
784ddd07fcSJed Brown   PetscInt  interptype;
79589dcaf0SStefano Zampini   PetscInt  maxc;
80589dcaf0SStefano Zampini   PetscInt  minc;
81db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
82db6f9c32SMark Adams   char *spgemm_type; // this is a global hypre parameter but is closely associated with BoomerAMG
83db6f9c32SMark Adams #endif
846ea7df73SStefano Zampini   /* GPU */
856ea7df73SStefano Zampini   PetscBool keeptranspose;
866ea7df73SStefano Zampini   PetscInt  rap2;
876ea7df73SStefano Zampini   PetscInt  mod_rap2;
886ea7df73SStefano Zampini 
89589dcaf0SStefano Zampini   /* AIR */
90589dcaf0SStefano Zampini   PetscInt  Rtype;
91589dcaf0SStefano Zampini   PetscReal Rstrongthreshold;
92589dcaf0SStefano Zampini   PetscReal Rfilterthreshold;
93589dcaf0SStefano Zampini   PetscInt  Adroptype;
94589dcaf0SStefano Zampini   PetscReal Adroptol;
95589dcaf0SStefano Zampini 
964ddd07fcSJed Brown   PetscInt  agg_nl;
976ea7df73SStefano Zampini   PetscInt  agg_interptype;
984ddd07fcSJed Brown   PetscInt  agg_num_paths;
99ace3abfcSBarry Smith   PetscBool nodal_relax;
1004ddd07fcSJed Brown   PetscInt  nodal_relax_levels;
1014cb006feSStefano Zampini 
1025272c319SBarry Smith   PetscInt  nodal_coarsening;
10322e51d31SStefano Zampini   PetscInt  nodal_coarsening_diag;
1045272c319SBarry Smith   PetscInt  vec_interp_variant;
10522e51d31SStefano Zampini   PetscInt  vec_interp_qmax;
10622e51d31SStefano Zampini   PetscBool vec_interp_smooth;
10722e51d31SStefano Zampini   PetscInt  interp_refine;
10822e51d31SStefano Zampini 
1096ea7df73SStefano Zampini   /* NearNullSpace support */
1106ea7df73SStefano Zampini   VecHYPRE_IJVector *hmnull;
1116ea7df73SStefano Zampini   HYPRE_ParVector   *phmnull;
1125272c319SBarry Smith   PetscInt           n_hmnull;
1135272c319SBarry Smith   Vec                hmnull_constant;
1145272c319SBarry Smith 
115863406b8SStefano Zampini   /* options for AS (Auxiliary Space preconditioners) */
116863406b8SStefano Zampini   PetscInt  as_print;
117863406b8SStefano Zampini   PetscInt  as_max_iter;
118863406b8SStefano Zampini   PetscReal as_tol;
119863406b8SStefano Zampini   PetscInt  as_relax_type;
120863406b8SStefano Zampini   PetscInt  as_relax_times;
121863406b8SStefano Zampini   PetscReal as_relax_weight;
122863406b8SStefano Zampini   PetscReal as_omega;
123863406b8SStefano 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) */
124863406b8SStefano Zampini   PetscReal as_amg_alpha_theta;   /* AMG strength for vector Poisson (AMS) or Curl problem (ADS) */
125863406b8SStefano 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) */
126863406b8SStefano Zampini   PetscReal as_amg_beta_theta;    /* AMG strength for scalar Poisson (AMS) or vector Poisson (ADS)  */
1274cb006feSStefano Zampini   PetscInt  ams_cycle_type;
128863406b8SStefano Zampini   PetscInt  ads_cycle_type;
1294cb006feSStefano Zampini 
1304cb006feSStefano Zampini   /* additional data */
1315ac14e1cSStefano Zampini   Mat G;             /* MatHYPRE */
1325ac14e1cSStefano Zampini   Mat C;             /* MatHYPRE */
1335ac14e1cSStefano Zampini   Mat alpha_Poisson; /* MatHYPRE */
1345ac14e1cSStefano Zampini   Mat beta_Poisson;  /* MatHYPRE */
1355ac14e1cSStefano Zampini 
1365ac14e1cSStefano Zampini   /* extra information for AMS */
1375ac14e1cSStefano Zampini   PetscInt          dim; /* geometrical dimension */
1386ea7df73SStefano Zampini   VecHYPRE_IJVector coords[3];
1396ea7df73SStefano Zampini   VecHYPRE_IJVector constants[3];
140be14dc20SKerry Key   VecHYPRE_IJVector interior;
1416bf688a0SCe Qin   Mat               RT_PiFull, RT_Pi[3];
1426bf688a0SCe Qin   Mat               ND_PiFull, ND_Pi[3];
1434cb006feSStefano Zampini   PetscBool         ams_beta_is_zero;
14423df4f25SStefano Zampini   PetscBool         ams_beta_is_zero_part;
14523df4f25SStefano Zampini   PetscInt          ams_proj_freq;
14616d9e3a6SLisandro Dalcin } PC_HYPRE;
14716d9e3a6SLisandro Dalcin 
148fd2dd295SFande Kong /*
1498a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1508a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1518a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
152fd2dd295SFande Kong */
153d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[])
154d71ae5a4SJacob Faibussowitsch {
1558a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1568a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1578a2c336bSFande Kong   PetscInt             num_levels, l;
1588a2c336bSFande Kong   Mat                 *mattmp;
1598a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1608a2c336bSFande Kong 
1618a2c336bSFande Kong   PetscFunctionBegin;
1629566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1635f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
164f4f49eeaSPierre Jolivet   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)jac->hsolver);
1659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
166f4f49eeaSPierre Jolivet   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)jac->hsolver);
1678a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
168f4f49eeaSPierre Jolivet     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &mattmp[num_levels - 1 - l]));
1698a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1708a2c336bSFande Kong     A_array[l] = NULL;
1718a2c336bSFande Kong   }
1728a2c336bSFande Kong   *nlevels   = num_levels;
1738a2c336bSFande Kong   *operators = mattmp;
1743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1758a2c336bSFande Kong }
1768a2c336bSFande Kong 
177fd2dd295SFande Kong /*
1788a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1798a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1808a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
181fd2dd295SFande Kong */
182d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[])
183d71ae5a4SJacob Faibussowitsch {
1848a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1858a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1868a2c336bSFande Kong   PetscInt             num_levels, l;
1878a2c336bSFande Kong   Mat                 *mattmp;
1888a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1898a2c336bSFande Kong 
1908a2c336bSFande Kong   PetscFunctionBegin;
1919566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1925f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
193f4f49eeaSPierre Jolivet   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)jac->hsolver);
1949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
195f4f49eeaSPierre Jolivet   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)jac->hsolver);
1968a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
197f4f49eeaSPierre Jolivet     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &mattmp[l - 1]));
1988a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1998a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
2008a2c336bSFande Kong   }
2018a2c336bSFande Kong   *nlevels        = num_levels;
2028a2c336bSFande Kong   *interpolations = mattmp;
2033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2048a2c336bSFande Kong }
2058a2c336bSFande Kong 
206ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
207d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
208d71ae5a4SJacob Faibussowitsch {
209ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
210ce6a8a0dSJed Brown   PetscInt  i;
211ce6a8a0dSJed Brown 
2129d678128SJed Brown   PetscFunctionBegin;
21348a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2149566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2159566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2169566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2179d678128SJed Brown   jac->n_hmnull = 0;
2183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219ce6a8a0dSJed Brown }
220ce6a8a0dSJed Brown 
221d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
222d71ae5a4SJacob Faibussowitsch {
22316d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
22449a781f5SStefano Zampini   Mat_HYPRE         *hjac;
22516d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
22616d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
22749a781f5SStefano Zampini   PetscBool          ishypre;
22816d9e3a6SLisandro Dalcin 
22916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2300df1829cSStefano Zampini   /* default type is boomerAMG */
23148a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2325f5c5b43SBarry Smith 
2330df1829cSStefano Zampini   /* get hypre matrix */
2340df1829cSStefano Zampini   if (pc->flag == DIFFERENT_NONZERO_PATTERN) PetscCall(MatDestroy(&jac->hpmat));
2359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
23649a781f5SStefano Zampini   if (!ishypre) {
2370df1829cSStefano Zampini     /* Temporary fix since we do not support MAT_REUSE_MATRIX with HYPRE device */
2380df1829cSStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
2390df1829cSStefano Zampini     PetscBool iscuda, iship, iskokkos;
2400df1829cSStefano Zampini 
2410df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
2420df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
2430df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iskokkos, MATSEQAIJKOKKOS, MATMPIAIJKOKKOS, ""));
2440df1829cSStefano Zampini     if (iscuda || iship || iskokkos) PetscCall(MatDestroy(&jac->hpmat));
2450df1829cSStefano Zampini #endif
2460df1829cSStefano Zampini     PetscCall(MatConvert(pc->pmat, MATHYPRE, jac->hpmat ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &jac->hpmat));
24749a781f5SStefano Zampini   } else {
2489566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2499566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
25049a781f5SStefano Zampini     jac->hpmat = pc->pmat;
25116d9e3a6SLisandro Dalcin   }
2520df1829cSStefano Zampini 
2536ea7df73SStefano Zampini   /* allow debug */
2549566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
255f4f49eeaSPierre Jolivet   hjac = (Mat_HYPRE *)jac->hpmat->data;
2565f5c5b43SBarry Smith 
25716d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25816d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2595272c319SBarry Smith     MatNullSpace mnull;
2605272c319SBarry Smith     PetscBool    has_const;
26149a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2625272c319SBarry Smith     const Vec   *vecs;
2635272c319SBarry Smith 
2649566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
265792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2669566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2675272c319SBarry Smith     if (mnull) {
2689566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2699566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2725272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2739566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2749566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
275792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2765272c319SBarry Smith       }
2775272c319SBarry Smith       if (has_const) {
2789566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2799566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2809566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2819566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2829566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
283792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2845272c319SBarry Smith         nvec++;
2855272c319SBarry Smith       }
286792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2875272c319SBarry Smith       jac->n_hmnull = nvec;
2885272c319SBarry Smith     }
2894cb006feSStefano Zampini   }
290863406b8SStefano Zampini 
2914cb006feSStefano Zampini   /* special case for AMS */
2924cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2935ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
2945ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2956bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
296f1580f4eSBarry 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()");
2976bf688a0SCe Qin     }
29848a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
2995ac14e1cSStefano Zampini     if (jac->constants[0]) {
3005ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
301792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
302792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
30348a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
304792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
3055ac14e1cSStefano Zampini     }
3065ac14e1cSStefano Zampini     if (jac->coords[0]) {
3075ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3085ac14e1cSStefano Zampini       coords[0] = NULL;
3095ac14e1cSStefano Zampini       coords[1] = NULL;
3105ac14e1cSStefano Zampini       coords[2] = NULL;
311792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
312792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
313792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
314792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3155ac14e1cSStefano Zampini     }
3165f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
317f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
318792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
319792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3205ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
321f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->alpha_Poisson->data;
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
323792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3245ac14e1cSStefano Zampini     }
3255ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
326792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3275ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
328f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->beta_Poisson->data;
329792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
330792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
331be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
332be14dc20SKerry Key       if (jac->interior) {
333be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
334be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
335be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
336be14dc20SKerry Key       } else {
337be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
338be14dc20SKerry Key       }
3395ac14e1cSStefano Zampini     }
3406bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3416bf688a0SCe Qin       PetscInt           i;
3426bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3436bf688a0SCe Qin       if (jac->ND_PiFull) {
344f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
345792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3466bf688a0SCe Qin       } else {
3476bf688a0SCe Qin         nd_parcsrfull = NULL;
3486bf688a0SCe Qin       }
3496bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3506bf688a0SCe Qin         if (jac->ND_Pi[i]) {
351f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
352792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3536bf688a0SCe Qin         } else {
3546bf688a0SCe Qin           nd_parcsr[i] = NULL;
3556bf688a0SCe Qin         }
3566bf688a0SCe Qin       }
357792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3586bf688a0SCe Qin     }
3594cb006feSStefano Zampini   }
360863406b8SStefano Zampini   /* special case for ADS */
361863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3625ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3635ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3646bf688a0SCe 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])))) {
3656bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3669371c9d4SSatish 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");
3675f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3685f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3695ac14e1cSStefano Zampini     if (jac->coords[0]) {
3705ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3715ac14e1cSStefano Zampini       coords[0] = NULL;
3725ac14e1cSStefano Zampini       coords[1] = NULL;
3735ac14e1cSStefano Zampini       coords[2] = NULL;
374792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
375792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
376792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
377792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3785ac14e1cSStefano Zampini     }
379f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
380792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
381792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
382f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->C->data;
383792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
384792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3856bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3866bf688a0SCe Qin       PetscInt           i;
3876bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3886bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3896bf688a0SCe Qin       if (jac->RT_PiFull) {
390f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->RT_PiFull->data;
391792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
3926bf688a0SCe Qin       } else {
3936bf688a0SCe Qin         rt_parcsrfull = NULL;
3946bf688a0SCe Qin       }
3956bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3966bf688a0SCe Qin         if (jac->RT_Pi[i]) {
397f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->RT_Pi[i]->data;
398792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
3996bf688a0SCe Qin         } else {
4006bf688a0SCe Qin           rt_parcsr[i] = NULL;
4016bf688a0SCe Qin         }
4026bf688a0SCe Qin       }
4036bf688a0SCe Qin       if (jac->ND_PiFull) {
404f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
405792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4066bf688a0SCe Qin       } else {
4076bf688a0SCe Qin         nd_parcsrfull = NULL;
4086bf688a0SCe Qin       }
4096bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4106bf688a0SCe Qin         if (jac->ND_Pi[i]) {
411f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
412792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4136bf688a0SCe Qin         } else {
4146bf688a0SCe Qin           nd_parcsr[i] = NULL;
4156bf688a0SCe Qin         }
4166bf688a0SCe Qin       }
417792fecdfSBarry 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]);
4186bf688a0SCe Qin     }
419863406b8SStefano Zampini   }
420792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
421792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
422792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
42397c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
424792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
42597c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
4263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42716d9e3a6SLisandro Dalcin }
42816d9e3a6SLisandro Dalcin 
429d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
430d71ae5a4SJacob Faibussowitsch {
43116d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
432f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
43316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
43416d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
43516d9e3a6SLisandro Dalcin 
43616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4379566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4389566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4399566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4409566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4419566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
442792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
443792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
444792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4459371c9d4SSatish Balay   PetscStackCallExternalVoid(
4469371c9d4SSatish Balay     "Hypre solve", do {
4475f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4485f80ce2aSJacob Faibussowitsch       if (hierr) {
4495f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
45085245615SPierre Jolivet         HYPRE_ClearAllErrors();
4515f80ce2aSJacob Faibussowitsch       }
4525f80ce2aSJacob Faibussowitsch     } while (0));
45316d9e3a6SLisandro Dalcin 
45448a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4559566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4569566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
4573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45816d9e3a6SLisandro Dalcin }
45916d9e3a6SLisandro Dalcin 
46085245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
46185245615SPierre Jolivet {
46285245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
463f4f49eeaSPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)jac->hpmat->data;
46485245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
46585245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
46685245615SPierre Jolivet   const PetscScalar  *b;
46785245615SPierre Jolivet   PetscScalar        *x;
46885245615SPierre Jolivet   PetscInt            m, N, lda;
46985245615SPierre Jolivet   hypre_Vector       *x_local;
47085245615SPierre Jolivet   PetscMemType        type;
47185245615SPierre Jolivet 
47285245615SPierre Jolivet   PetscFunctionBegin;
47385245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
47485245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
47585245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
47685245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
47785245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
47885245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
47985245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
48085245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
48185245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
48285245615SPierre 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);
48385245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
48485245615SPierre 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);
48585245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
48685245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
48785245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
48885245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
48985245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
49085245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
49185245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
49285245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
49385245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
49485245615SPierre Jolivet   PetscStackCallExternalVoid(
49585245615SPierre Jolivet     "Hypre solve", do {
49685245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
49785245615SPierre Jolivet       if (hierr) {
49885245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
49985245615SPierre Jolivet         HYPRE_ClearAllErrors();
50085245615SPierre Jolivet       }
50185245615SPierre Jolivet     } while (0));
50285245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
50385245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
50485245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
50585245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
50685245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
50785245615SPierre Jolivet }
50885245615SPierre Jolivet 
509d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
510d71ae5a4SJacob Faibussowitsch {
5118695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5128695de01SBarry Smith 
5138695de01SBarry Smith   PetscFunctionBegin;
5149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
5159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
5169566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
5179566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
5189566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
5199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
5209566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
5219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
5229566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
5239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
5249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
5259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
5269566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
5279566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
5289566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
5299566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
5309566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
5319566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
5329566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
533be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
5349566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
5355ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
536be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
5375ac14e1cSStefano Zampini   jac->dim                   = 0;
5383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5398695de01SBarry Smith }
5408695de01SBarry Smith 
541d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
542d71ae5a4SJacob Faibussowitsch {
54316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
54416d9e3a6SLisandro Dalcin 
54516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5469566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
547792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
5489566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
549db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
5509566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
551db6f9c32SMark Adams #endif
5529566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
5539566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
55416d9e3a6SLisandro Dalcin 
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5632e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
564be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5692e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
5703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57116d9e3a6SLisandro Dalcin }
57216d9e3a6SLisandro Dalcin 
573d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
574d71ae5a4SJacob Faibussowitsch {
57516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
576ace3abfcSBarry Smith   PetscBool flag;
57716d9e3a6SLisandro Dalcin 
57816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
579d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
581792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
583792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
585792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
586d0609cedSBarry Smith   PetscOptionsHeadEnd();
5873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58816d9e3a6SLisandro Dalcin }
58916d9e3a6SLisandro Dalcin 
590d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
591d71ae5a4SJacob Faibussowitsch {
59216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
593ace3abfcSBarry Smith   PetscBool iascii;
59416d9e3a6SLisandro Dalcin 
59516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5969566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
59716d9e3a6SLisandro Dalcin   if (iascii) {
5989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
59916d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
60063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
60116d9e3a6SLisandro Dalcin     } else {
6029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
60316d9e3a6SLisandro Dalcin     }
60416d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
6059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
60616d9e3a6SLisandro Dalcin     } else {
6079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
60816d9e3a6SLisandro Dalcin     }
60916d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
61063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
61116d9e3a6SLisandro Dalcin     } else {
6129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
61316d9e3a6SLisandro Dalcin     }
61416d9e3a6SLisandro Dalcin   }
6153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61616d9e3a6SLisandro Dalcin }
61716d9e3a6SLisandro Dalcin 
6183c61a47dSLukas static const char *HYPREILUType[] = {
6193c61a47dSLukas   "Block-Jacobi-ILUk", "Block-Jacobi-ILUT", "", "", "", "", "", "", "", "", /* 0-9 */
6203c61a47dSLukas   "GMRES-ILUk",        "GMRES-ILUT",        "", "", "", "", "", "", "", "", /* 10-19 */
6213c61a47dSLukas   "NSH-ILUk",          "NSH-ILUT",          "", "", "", "", "", "", "", "", /* 20-29 */
6223c61a47dSLukas   "RAS-ILUk",          "RAS-ILUT",          "", "", "", "", "", "", "", "", /* 30-39 */
6233c61a47dSLukas   "ddPQ-GMRES-ILUk",   "ddPQ-GMRES-ILUT",   "", "", "", "", "", "", "", "", /* 40-49 */
6243c61a47dSLukas   "GMRES-ILU0"                                                              /* 50 */
6253c61a47dSLukas };
6263c61a47dSLukas 
6273c61a47dSLukas static const char *HYPREILUIterSetup[] = {"default", "async-in-place", "async-explicit", "sync-explicit", "semisync-explicit"};
6283c61a47dSLukas 
6293c61a47dSLukas static PetscErrorCode PCSetFromOptions_HYPRE_ILU(PC pc, PetscOptionItems *PetscOptionsObject)
6303c61a47dSLukas {
6313c61a47dSLukas   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6323c61a47dSLukas   PetscBool flg;
6333c61a47dSLukas   PetscInt  indx;
6343c61a47dSLukas   PetscReal tmpdbl;
6353c61a47dSLukas   PetscBool tmp_truth;
6363c61a47dSLukas 
6373c61a47dSLukas   PetscFunctionBegin;
6383c61a47dSLukas   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ILU Options");
6393c61a47dSLukas 
6403c61a47dSLukas   /* ILU: ILU Type */
6413c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
6423c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetType, jac->hsolver, indx); }
6433c61a47dSLukas 
6443c61a47dSLukas   /* ILU: ILU iterative setup type*/
6453c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_iterative_setup_type", "Set ILU iterative setup type", "None", HYPREILUIterSetup, PETSC_STATIC_ARRAY_LENGTH(HYPREILUIterSetup), HYPREILUIterSetup[0], &indx, &flg));
6463c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupType, jac->hsolver, indx); }
6473c61a47dSLukas 
6483c61a47dSLukas   /* ILU: ILU iterative setup option*/
6493c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
6503c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupOption, jac->hsolver, indx); }
6513c61a47dSLukas 
6523c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
6533c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
6543c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupMaxIter, jac->hsolver, indx); }
6553c61a47dSLukas 
6563c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
6573c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
6583c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupTolerance, jac->hsolver, tmpdbl); }
6593c61a47dSLukas 
6603c61a47dSLukas   /* ILU: ILU Print Level */
6613c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
6623c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetPrintLevel, jac->hsolver, indx); }
6633c61a47dSLukas 
6643c61a47dSLukas   /* ILU: Logging */
6653c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
6663c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLogging, jac->hsolver, indx); }
6673c61a47dSLukas 
6683c61a47dSLukas   /* ILU: ILU Level */
6693c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
6703c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLevelOfFill, jac->hsolver, indx); }
6713c61a47dSLukas 
6723c61a47dSLukas   /* ILU: ILU Max NNZ per row */
6733c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
6743c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetMaxNnzPerRow, jac->hsolver, indx); }
6753c61a47dSLukas 
6763c61a47dSLukas   /* ILU: tolerance */
6773c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_tol", "Tolerance for ILU", "None", 0, &tmpdbl, &flg));
6783c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetTol, jac->hsolver, tmpdbl); }
6793c61a47dSLukas 
6803c61a47dSLukas   /* ILU: maximum iteration count */
6813c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
6823c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetMaxIter, jac->hsolver, indx); }
6833c61a47dSLukas 
6843c61a47dSLukas   /* ILU: drop threshold */
6853c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_drop_threshold", "Drop threshold for ILU", "None", 0, &tmpdbl, &flg));
6863c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetDropThreshold, jac->hsolver, tmpdbl); }
6873c61a47dSLukas 
6883c61a47dSLukas   /* ILU: Triangular Solve */
6893c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
6903c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetTriSolve, jac->hsolver, tmp_truth); }
6913c61a47dSLukas 
6923c61a47dSLukas   /* ILU: Lower Jacobi iteration */
6933c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
6943c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLowerJacobiIters, jac->hsolver, indx); }
6953c61a47dSLukas 
6963c61a47dSLukas   /* ILU: Upper Jacobi iteration */
6973c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
6983c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetUpperJacobiIters, jac->hsolver, indx); }
6993c61a47dSLukas 
7003c61a47dSLukas   /* ILU: local reordering */
7013c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
7023c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLocalReordering, jac->hsolver, tmp_truth); }
7033c61a47dSLukas 
7043c61a47dSLukas   PetscOptionsHeadEnd();
7053c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
7063c61a47dSLukas }
7073c61a47dSLukas 
7083c61a47dSLukas static PetscErrorCode PCView_HYPRE_ILU(PC pc, PetscViewer viewer)
7093c61a47dSLukas {
7103c61a47dSLukas   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
7113c61a47dSLukas   hypre_ParILUData *ilu_data = (hypre_ParILUData *)jac->hsolver;
7123c61a47dSLukas   PetscBool         iascii;
7133c61a47dSLukas   PetscInt          indx;
7143c61a47dSLukas   PetscReal         tmpdbl;
7153c61a47dSLukas   PetscReal        *tmpdbl3;
7163c61a47dSLukas 
7173c61a47dSLukas   PetscFunctionBegin;
7183c61a47dSLukas   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
7193c61a47dSLukas   if (iascii) {
7203c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ILU preconditioning\n"));
7213c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIluType", indx = hypre_ParILUDataIluType(ilu_data));
7223c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
7233c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLfil", indx = hypre_ParILUDataLfil(ilu_data));
7243c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
7253c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxIter", indx = hypre_ParILUDataMaxIter(ilu_data));
7263c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
7273c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxRowNnz", indx = hypre_ParILUDataMaxRowNnz(ilu_data));
7283c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
7293c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTriSolve", indx = hypre_ParILUDataTriSolve(ilu_data));
7303c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
7313c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTol", tmpdbl = hypre_ParILUDataTol(ilu_data));
7323c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", tmpdbl));
7333c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataDroptol", tmpdbl3 = hypre_ParILUDataDroptol(ilu_data));
7343c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e / %e / %e\n", tmpdbl3[0], tmpdbl3[1], tmpdbl3[2]));
7353c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataReorderingType", indx = hypre_ParILUDataReorderingType(ilu_data));
7363c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
7373c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLowerJacobiIters", indx = hypre_ParILUDataLowerJacobiIters(ilu_data));
7383c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
7393c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataUpperJacobiIters", indx = hypre_ParILUDataUpperJacobiIters(ilu_data));
7403c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
7413c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataPrintLevel", indx = hypre_ParILUDataPrintLevel(ilu_data));
7423c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
7433c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLogging", indx = hypre_ParILUDataLogging(ilu_data));
7443c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
7453c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupType", indx = hypre_ParILUDataIterativeSetupType(ilu_data));
7463c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
7473c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupOption", indx = hypre_ParILUDataIterativeSetupOption(ilu_data));
7483c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
7493c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupMaxIter", indx = hypre_ParILUDataIterativeSetupMaxIter(ilu_data));
7503c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
7513c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupTolerance", tmpdbl = hypre_ParILUDataIterativeSetupTolerance(ilu_data));
7523c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", tmpdbl));
7533c61a47dSLukas   }
7543c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
7553c61a47dSLukas }
7563c61a47dSLukas 
757d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
758d71ae5a4SJacob Faibussowitsch {
759db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
7608bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
761db966c6cSHong Zhang 
762db966c6cSHong Zhang   PetscFunctionBegin;
763d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
7649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
765792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
7668bf83915SBarry Smith 
7679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
7688bf83915SBarry Smith   if (flag) {
7698bf83915SBarry Smith     PetscMPIInt size;
7708bf83915SBarry Smith 
7719566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
7727827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
773792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
7748bf83915SBarry Smith   }
7758bf83915SBarry Smith 
7769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
7778bf83915SBarry Smith   if (flag) {
7788bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
779792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
7808bf83915SBarry Smith   }
781d0609cedSBarry Smith   PetscOptionsHeadEnd();
7823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
783db966c6cSHong Zhang }
784db966c6cSHong Zhang 
785d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
786d71ae5a4SJacob Faibussowitsch {
787db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
788db966c6cSHong Zhang   PetscBool iascii;
789db966c6cSHong Zhang 
790db966c6cSHong Zhang   PetscFunctionBegin;
7919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
792db966c6cSHong Zhang   if (iascii) {
7939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
794db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
79563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
796db966c6cSHong Zhang     } else {
7979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
798db966c6cSHong Zhang     }
7999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
80063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
801db966c6cSHong Zhang   }
8023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
803db966c6cSHong Zhang }
804db966c6cSHong Zhang 
805d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
806d71ae5a4SJacob Faibussowitsch {
80716d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
808f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
80916d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
81016d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
81116d9e3a6SLisandro Dalcin 
81216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
8139566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
8149566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
8159566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
8169566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
81716d9e3a6SLisandro Dalcin 
818792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
819792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
820792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
82116d9e3a6SLisandro Dalcin 
8229371c9d4SSatish Balay   PetscStackCallExternalVoid(
8239371c9d4SSatish Balay     "Hypre Transpose solve", do {
8245f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
8255f80ce2aSJacob Faibussowitsch       if (hierr) {
82616d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
8275f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
82885245615SPierre Jolivet         HYPRE_ClearAllErrors();
8295f80ce2aSJacob Faibussowitsch       }
8305f80ce2aSJacob Faibussowitsch     } while (0));
83116d9e3a6SLisandro Dalcin 
8329566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
8339566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
8343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83516d9e3a6SLisandro Dalcin }
83616d9e3a6SLisandro Dalcin 
837d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
838d71ae5a4SJacob Faibussowitsch {
839db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
840db6f9c32SMark Adams   PetscBool flag;
841db6f9c32SMark Adams 
842db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
843db6f9c32SMark Adams   PetscFunctionBegin;
844db6f9c32SMark Adams   if (jac->spgemm_type) {
8459566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
84628b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
8473ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
848db6f9c32SMark Adams   } else {
8499566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
850db6f9c32SMark Adams   }
8519566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
852db6f9c32SMark Adams   if (flag) {
853792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
8543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
855db6f9c32SMark Adams   }
8569566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
857db6f9c32SMark Adams   if (flag) {
858792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
8593ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
860db6f9c32SMark Adams   }
861db6f9c32SMark Adams   jac->spgemm_type = NULL;
8622d6c3ceeSStefano Zampini   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEMM type %s; Choices are cusparse, hypre", name);
863db6f9c32SMark Adams #endif
864db6f9c32SMark Adams }
865db6f9c32SMark Adams 
866d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
867d71ae5a4SJacob Faibussowitsch {
868db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
869db6f9c32SMark Adams 
870db6f9c32SMark Adams   PetscFunctionBegin;
871db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
872db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
873db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
874db6f9c32SMark Adams #endif
8753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
876db6f9c32SMark Adams }
877db6f9c32SMark Adams 
87816d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
8790f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
88016d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
88165de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
8823c61a47dSLukas static const char *HYPREBoomerAMGSmoothType[] = {"ILU", "Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
8839371c9d4SSatish 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"};
8849371c9d4SSatish 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"};
885d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
886d71ae5a4SJacob Faibussowitsch {
88716d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
88822e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
889ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
89073dcfd97SStefano Zampini   PetscReal   tmpdbl, twodbl[2];
891589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
892db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
89316d9e3a6SLisandro Dalcin 
89416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
895d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
8969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
89716d9e3a6SLisandro Dalcin   if (flg) {
8984336a9eeSBarry Smith     jac->cycletype = indx + 1;
899792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
90016d9e3a6SLisandro Dalcin   }
90152ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg, 2));
90252ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
90352ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg, 1));
90452ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
90552ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_tol", "Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)", "None", jac->tol, &jac->tol, &flg, 0.0));
90652ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
90722e51d31SStefano Zampini   bs = 1;
90848a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
9099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
91048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
91116d9e3a6SLisandro Dalcin 
91252ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg, 0.0));
91352ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
91416d9e3a6SLisandro Dalcin 
91552ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg, 0));
91652ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
9170f1074feSSatish Balay 
9189566063dSJacob 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));
919792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
9200f1074feSSatish Balay 
92152ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_agg_num_paths", "Number of paths for aggressive coarsening", "None", jac->agg_num_paths, &jac->agg_num_paths, &flg, 1));
92252ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
9230f1074feSSatish Balay 
92452ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg, 0.0));
92552ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
92652ce0ab5SPierre Jolivet   PetscCall(PetscOptionsRangeReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg, 0.0, 1.0));
92752ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
92816d9e3a6SLisandro Dalcin 
92916d9e3a6SLisandro Dalcin   /* Grid sweeps */
9309566063dSJacob 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));
93116d9e3a6SLisandro Dalcin   if (flg) {
932792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
93316d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
93416d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
9350f1074feSSatish Balay     jac->gridsweeps[1] = indx;
9360f1074feSSatish Balay     /*defaults coarse to 1 */
9370f1074feSSatish Balay     jac->gridsweeps[2] = 1;
93816d9e3a6SLisandro Dalcin   }
9399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
94048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
9419566063dSJacob 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));
94248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
9439566063dSJacob 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));
94448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
9459566063dSJacob 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));
94648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
9479566063dSJacob 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));
94848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
9499566063dSJacob 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));
95048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
9519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
95216d9e3a6SLisandro Dalcin   if (flg) {
953792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
9540f1074feSSatish Balay     jac->gridsweeps[0] = indx;
95516d9e3a6SLisandro Dalcin   }
9569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
95716d9e3a6SLisandro Dalcin   if (flg) {
958792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
9590f1074feSSatish Balay     jac->gridsweeps[1] = indx;
96016d9e3a6SLisandro Dalcin   }
9619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
96216d9e3a6SLisandro Dalcin   if (flg) {
963792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
9640f1074feSSatish Balay     jac->gridsweeps[2] = indx;
96516d9e3a6SLisandro Dalcin   }
96616d9e3a6SLisandro Dalcin 
9676a251517SEike Mueller   /* Smooth type */
968dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
9696a251517SEike Mueller   if (flg) {
9706a251517SEike Mueller     jac->smoothtype = indx;
9713c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 5);
9728131ecf7SEike Mueller     jac->smoothnumlevels = 25;
973792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
9748131ecf7SEike Mueller   }
9758131ecf7SEike Mueller 
9768131ecf7SEike Mueller   /* Number of smoothing levels */
9779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
9788131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
9798131ecf7SEike Mueller     jac->smoothnumlevels = indx;
980792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
9816a251517SEike Mueller   }
9826a251517SEike Mueller 
9833c61a47dSLukas   /* Smooth num sweeps */
9843c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_sweeps", "Set number of smoother sweeps", "None", 1, &indx, &flg));
9853c61a47dSLukas   if (flg && indx > 0) {
9863c61a47dSLukas     jac->smoothsweeps = indx;
9873c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumSweeps, jac->hsolver, indx);
9883c61a47dSLukas   }
9893c61a47dSLukas 
9903c61a47dSLukas   /* ILU: ILU Type */
9913c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
9923c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUType, jac->hsolver, indx); }
9933c61a47dSLukas 
9943c61a47dSLukas   /* ILU: ILU iterative setup type*/
9953c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_ilu_iterative_setup_type", "Set ILU iterative setup type", "None", HYPREILUIterSetup, PETSC_STATIC_ARRAY_LENGTH(HYPREILUIterSetup), HYPREILUIterSetup[0], &indx, &flg));
9963c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupType, jac->hsolver, indx); }
9973c61a47dSLukas 
9983c61a47dSLukas   /* ILU: ILU iterative setup option*/
9993c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
10003c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupOption, jac->hsolver, indx); }
10013c61a47dSLukas 
10023c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
10033c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
10043c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupMaxIter, jac->hsolver, indx); }
10053c61a47dSLukas 
10063c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
10073c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
10083c61a47dSLukas   if (flg) { PetscCallExternal(hypre_BoomerAMGSetILUIterSetupTolerance, jac->hsolver, tmpdbl); }
10093c61a47dSLukas 
10103c61a47dSLukas   /* ILU: ILU Print Level */
10113c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
10123c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, indx); }
10133c61a47dSLukas 
10143c61a47dSLukas   /* ILU: Logging */
10153c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
10163c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetLogging, jac->hsolver, indx); }
10173c61a47dSLukas 
10183c61a47dSLukas   /* ILU: ILU Level */
10193c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
10203c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULevel, jac->hsolver, indx); }
10213c61a47dSLukas 
10223c61a47dSLukas   /* ILU: ILU Max NNZ per row */
10233c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
10243c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUMaxRowNnz, jac->hsolver, indx); }
10253c61a47dSLukas 
10263c61a47dSLukas   /* ILU: maximum iteration count */
10273c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
10283c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUMaxIter, jac->hsolver, indx); }
10293c61a47dSLukas 
10303c61a47dSLukas   /* ILU: drop threshold */
10313c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_drop_tol", "Drop tolerance for ILU", "None", 0, &tmpdbl, &flg));
10323c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUDroptol, jac->hsolver, tmpdbl); }
10333c61a47dSLukas 
10343c61a47dSLukas   /* ILU: Triangular Solve */
10353c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
10363c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUTriSolve, jac->hsolver, tmp_truth); }
10373c61a47dSLukas 
10383c61a47dSLukas   /* ILU: Lower Jacobi iteration */
10393c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
10403c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULowerJacobiIters, jac->hsolver, indx); }
10413c61a47dSLukas 
10423c61a47dSLukas   /* ILU: Upper Jacobi iteration */
10433c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
10443c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUUpperJacobiIters, jac->hsolver, indx); }
10453c61a47dSLukas 
10463c61a47dSLukas   /* ILU: local reordering */
10473c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
10483c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULocalReordering, jac->hsolver, tmp_truth); }
10493c61a47dSLukas 
10501810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
10519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
10523c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
10531810e44eSEike Mueller     jac->eu_level = indx;
1054792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
10551810e44eSEike Mueller   }
10561810e44eSEike Mueller 
10571810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
105873dcfd97SStefano Zampini   PetscReal droptolerance;
10599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
10603c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
10611810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
1062792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
10631810e44eSEike Mueller   }
10641810e44eSEike Mueller 
10651810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
10669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
10673c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
10681810e44eSEike Mueller     jac->eu_bj = tmp_truth;
1069792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
10701810e44eSEike Mueller   }
10711810e44eSEike Mueller 
107216d9e3a6SLisandro Dalcin   /* Relax type */
1073dd39110bSPierre 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));
107416d9e3a6SLisandro Dalcin   if (flg) {
10750f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
1076792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
10770f1074feSSatish Balay     /* by default, coarse type set to 9 */
10780f1074feSSatish Balay     jac->relaxtype[2] = 9;
1079792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
108016d9e3a6SLisandro Dalcin   }
1081dd39110bSPierre 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));
108216d9e3a6SLisandro Dalcin   if (flg) {
108316d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
1084792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
108516d9e3a6SLisandro Dalcin   }
1086dd39110bSPierre 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));
108716d9e3a6SLisandro Dalcin   if (flg) {
10880f1074feSSatish Balay     jac->relaxtype[1] = indx;
1089792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
109016d9e3a6SLisandro Dalcin   }
1091dd39110bSPierre 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));
109216d9e3a6SLisandro Dalcin   if (flg) {
10930f1074feSSatish Balay     jac->relaxtype[2] = indx;
1094792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
109516d9e3a6SLisandro Dalcin   }
109616d9e3a6SLisandro Dalcin 
109716d9e3a6SLisandro Dalcin   /* Relaxation Weight */
10989566063dSJacob 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));
109916d9e3a6SLisandro Dalcin   if (flg) {
1100792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
110116d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
110216d9e3a6SLisandro Dalcin   }
110316d9e3a6SLisandro Dalcin 
110416d9e3a6SLisandro Dalcin   n         = 2;
110516d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
11069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
110716d9e3a6SLisandro Dalcin   if (flg) {
11080fdf79fbSJacob 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);
110916d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1110792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
111116d9e3a6SLisandro Dalcin   }
111216d9e3a6SLisandro Dalcin 
111316d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
11149566063dSJacob 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));
111516d9e3a6SLisandro Dalcin   if (flg) {
1116792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
111716d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
111816d9e3a6SLisandro Dalcin   }
111916d9e3a6SLisandro Dalcin 
112016d9e3a6SLisandro Dalcin   n         = 2;
112116d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
11229566063dSJacob 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));
112316d9e3a6SLisandro Dalcin   if (flg) {
11240fdf79fbSJacob 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);
112516d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1126792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
112716d9e3a6SLisandro Dalcin   }
112816d9e3a6SLisandro Dalcin 
112916d9e3a6SLisandro Dalcin   /* the Relax Order */
11309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
113116d9e3a6SLisandro Dalcin 
11328afaa268SBarry Smith   if (flg && tmp_truth) {
113316d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
1134792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
113516d9e3a6SLisandro Dalcin   }
1136dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
113716d9e3a6SLisandro Dalcin   if (flg) {
113816d9e3a6SLisandro Dalcin     jac->measuretype = indx;
1139792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
114016d9e3a6SLisandro Dalcin   }
11410f1074feSSatish Balay   /* update list length 3/07 */
1142dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
114316d9e3a6SLisandro Dalcin   if (flg) {
114416d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
1145792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
114616d9e3a6SLisandro Dalcin   }
11470f1074feSSatish Balay 
11489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
114948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
11509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
115148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
1152db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
1153db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
1154dd39110bSPierre 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));
11552d6c3ceeSStefano Zampini   #if defined(PETSC_HAVE_HYPRE_DEVICE)
1156db6f9c32SMark Adams   if (!flg) indx = 0;
11579566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
11582d6c3ceeSStefano Zampini   #else
11592d6c3ceeSStefano Zampini   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, "hypre"));
11602d6c3ceeSStefano Zampini   #endif
1161db6f9c32SMark Adams #endif
1162589dcaf0SStefano Zampini   /* AIR */
1163589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
11649566063dSJacob 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));
1165792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1166589dcaf0SStefano Zampini   if (jac->Rtype) {
116719be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
116819be502cSAlexander     char       *prerelax[256];
116919be502cSAlexander     char       *postrelax[256];
117019be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
117119be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
117219be502cSAlexander     PetscBool   matchF, matchC, matchA;
117319be502cSAlexander 
1174589dcaf0SStefano 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 */
1175589dcaf0SStefano Zampini 
11769566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
1177792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1178589dcaf0SStefano Zampini 
11799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
1180792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1181589dcaf0SStefano Zampini 
11829566063dSJacob 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));
1183792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1184589dcaf0SStefano Zampini 
11859566063dSJacob 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));
1186792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
118719be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
118819be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
118919be502cSAlexander     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");
119019be502cSAlexander     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");
119119be502cSAlexander 
119219be502cSAlexander     grid_relax_points[0]    = NULL;
119319be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
119419be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
119519be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
119619be502cSAlexander     grid_relax_points[3][0] = 0;
119719be502cSAlexander 
119819be502cSAlexander     // set down relax scheme
119919be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
120019be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
120119be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
120219be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
120319be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
120419be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
120519be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
120619be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
120719be502cSAlexander     }
120819be502cSAlexander 
120919be502cSAlexander     // set up relax scheme
121019be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
121119be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
121219be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
121319be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
121419be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
121519be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
121619be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
121719be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
121819be502cSAlexander     }
121919be502cSAlexander 
122019be502cSAlexander     // set coarse relax scheme
122119be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
122219be502cSAlexander 
122319be502cSAlexander     // Pass relax schemes to hypre
122419be502cSAlexander     PetscCallExternal(HYPRE_BoomerAMGSetGridRelaxPoints, jac->hsolver, grid_relax_points);
122519be502cSAlexander 
122619be502cSAlexander     // cleanup memory
122719be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
122819be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1229589dcaf0SStefano Zampini   }
1230589dcaf0SStefano Zampini #endif
1231589dcaf0SStefano Zampini 
1232ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
123363a3b9bcSJacob 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);
1234ecae95adSPierre Jolivet #endif
1235ecae95adSPierre Jolivet 
12360f1074feSSatish Balay   /* new 3/07 */
1237dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1238589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1239589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1240792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
12410f1074feSSatish Balay   }
12420f1074feSSatish Balay 
12439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
124416d9e3a6SLisandro Dalcin   if (flg) {
1245b96a4a96SBarry Smith     level = 3;
12469566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
12472fa5cd67SKarl Rupp 
1248b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1249792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
12502ae77aedSBarry Smith   }
12512ae77aedSBarry Smith 
12529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
12532ae77aedSBarry Smith   if (flg) {
1254b96a4a96SBarry Smith     level = 3;
12559566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
12562fa5cd67SKarl Rupp 
1257b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1258792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
125916d9e3a6SLisandro Dalcin   }
12608f87f92bSBarry Smith 
12619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
12628f87f92bSBarry Smith   if (flg && tmp_truth) {
12638f87f92bSBarry Smith     PetscInt tmp_int;
12649566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
12658f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1266792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1267792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1268792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1269792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
12708f87f92bSBarry Smith   }
12718f87f92bSBarry Smith 
12729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1273792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1274589dcaf0SStefano Zampini 
1275589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1276dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1277589dcaf0SStefano Zampini   if (flg) {
1278589dcaf0SStefano Zampini     jac->symt = indx;
1279792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1280589dcaf0SStefano Zampini   }
1281589dcaf0SStefano Zampini 
1282d0609cedSBarry Smith   PetscOptionsHeadEnd();
12833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
128416d9e3a6SLisandro Dalcin }
128516d9e3a6SLisandro Dalcin 
1286d71ae5a4SJacob 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)
1287d71ae5a4SJacob Faibussowitsch {
128816d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12892cf14000SStefano Zampini   HYPRE_Int oits;
129016d9e3a6SLisandro Dalcin 
129116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
12929566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1293792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1294792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
129516d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
12969566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
129716d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1298792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
12994d0a8057SBarry Smith   *outits = oits;
13004d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
13014d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1302792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1303792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
13043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
130516d9e3a6SLisandro Dalcin }
130616d9e3a6SLisandro Dalcin 
1307d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1308d71ae5a4SJacob Faibussowitsch {
130916d9e3a6SLisandro Dalcin   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
13103c61a47dSLukas   hypre_ParAMGData *amg_data = (hypre_ParAMGData *)jac->hsolver;
1311ace3abfcSBarry Smith   PetscBool         iascii;
13123c61a47dSLukas   PetscInt          indx;
13133c61a47dSLukas   PetscReal         val;
131416d9e3a6SLisandro Dalcin 
131516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
13169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
131716d9e3a6SLisandro Dalcin   if (iascii) {
13189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
13199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
132063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
132163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
13229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
13239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
13249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
132563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
132648a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
132763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
132863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
13290f1074feSSatish Balay 
13309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
133116d9e3a6SLisandro Dalcin 
133263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
133363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
133463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
133516d9e3a6SLisandro Dalcin 
13369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
13379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
13389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
133916d9e3a6SLisandro Dalcin 
13409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
13419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
134216d9e3a6SLisandro Dalcin 
134319be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
134419be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
134519be502cSAlexander 
134616d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
13479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
134816d9e3a6SLisandro Dalcin     } else {
13499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
135016d9e3a6SLisandro Dalcin     }
13516a251517SEike Mueller     if (jac->smoothtype != -1) {
13529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
135363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
13543c61a47dSLukas       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num sweeps    %" PetscInt_FMT "\n", jac->smoothsweeps));
13553c61a47dSLukas       if (jac->smoothtype == 0) {
13563c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUType", indx = hypre_ParAMGDataILUType(amg_data));
13573c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
13583c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULevel", indx = hypre_ParAMGDataILULevel(amg_data));
13593c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
13603c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxIter", indx = hypre_ParAMGDataILUMaxIter(amg_data));
13613c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
13623c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxRowNnz", indx = hypre_ParAMGDataILUMaxRowNnz(amg_data));
13633c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
13643c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUTriSolve", indx = hypre_ParAMGDataILUTriSolve(amg_data));
13653c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
13663c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataTol", val = hypre_ParAMGDataTol(amg_data));
13673c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", val));
13683c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUDroptol", val = hypre_ParAMGDataILUDroptol(amg_data));
13693c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e\n", val));
13703c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULocalReordering", indx = hypre_ParAMGDataILULocalReordering(amg_data));
13713c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
13723c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULowerJacobiIters", indx = hypre_ParAMGDataILULowerJacobiIters(amg_data));
13733c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
13743c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUUpperJacobiIters", indx = hypre_ParAMGDataILUUpperJacobiIters(amg_data));
13753c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
13763c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataPrintLevel", indx = hypre_ParAMGDataPrintLevel(amg_data));
13773c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
13783c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataLogging", indx = hypre_ParAMGDataLogging(amg_data));
13793c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
13803c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupType", indx = hypre_ParAMGDataILUIterSetupType(amg_data));
13813c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
13823c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupOption", indx = hypre_ParAMGDataILUIterSetupOption(amg_data));
13833c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
13843c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupMaxIter", indx = hypre_ParAMGDataILUIterSetupMaxIter(amg_data));
13853c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
13863c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupTolerance", val = hypre_ParAMGDataILUIterSetupTolerance(amg_data));
13873c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", val));
13883c61a47dSLukas       }
13897e352d70SEike Mueller     } else {
13909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
13911810e44eSEike Mueller     }
13921810e44eSEike Mueller     if (jac->smoothtype == 3) {
139363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
13949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
139563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
13966a251517SEike Mueller     }
13979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
13989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
13999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
140048a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
14015272c319SBarry Smith     if (jac->vec_interp_variant) {
140263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
140363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
14049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
14058f87f92bSBarry Smith     }
140648a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1407db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
14089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
14092d6c3ceeSStefano Zampini #else
14102d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1411db6f9c32SMark Adams #endif
1412589dcaf0SStefano Zampini     /* AIR */
1413589dcaf0SStefano Zampini     if (jac->Rtype) {
141463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
14159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
14169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
14179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
141863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1419589dcaf0SStefano Zampini     }
142016d9e3a6SLisandro Dalcin   }
14213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
142216d9e3a6SLisandro Dalcin }
142316d9e3a6SLisandro Dalcin 
1424d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1425d71ae5a4SJacob Faibussowitsch {
142616d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
14274ddd07fcSJed Brown   PetscInt    indx;
1428ace3abfcSBarry Smith   PetscBool   flag;
142916d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
143016d9e3a6SLisandro Dalcin 
143116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1432d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
14339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
14349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1435792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
143616d9e3a6SLisandro Dalcin 
14379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1438792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
143916d9e3a6SLisandro Dalcin 
14409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1441792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
144216d9e3a6SLisandro Dalcin 
14439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1444792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
144516d9e3a6SLisandro Dalcin 
14469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1447792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
144816d9e3a6SLisandro Dalcin 
1449dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
145016d9e3a6SLisandro Dalcin   if (flag) {
145116d9e3a6SLisandro Dalcin     jac->symt = indx;
1452792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
145316d9e3a6SLisandro Dalcin   }
145416d9e3a6SLisandro Dalcin 
1455d0609cedSBarry Smith   PetscOptionsHeadEnd();
14563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145716d9e3a6SLisandro Dalcin }
145816d9e3a6SLisandro Dalcin 
1459d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1460d71ae5a4SJacob Faibussowitsch {
146116d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1462ace3abfcSBarry Smith   PetscBool   iascii;
1463feb237baSPierre Jolivet   const char *symt = 0;
146416d9e3a6SLisandro Dalcin 
146516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
14669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
146716d9e3a6SLisandro Dalcin   if (iascii) {
14689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
146963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
14709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
14719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
14729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
14739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
14749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
14752fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
14762fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
14772fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
147863a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
14799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
148016d9e3a6SLisandro Dalcin   }
14813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148216d9e3a6SLisandro Dalcin }
1483f1580f4eSBarry Smith 
1484d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1485d71ae5a4SJacob Faibussowitsch {
14864cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14874cb006feSStefano Zampini   PetscInt  n;
14884cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
14894cb006feSStefano Zampini 
14904cb006feSStefano Zampini   PetscFunctionBegin;
1491d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
14929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1493792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
14949566063dSJacob 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));
1495792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
14969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1497792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
14989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1499792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
15009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
15019566063dSJacob 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));
15029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
15039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
150448a46eb9SPierre 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);
15059566063dSJacob 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));
15064cb006feSStefano Zampini   n = 5;
15079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
15084cb006feSStefano Zampini   if (flag || flag2) {
1509792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1510863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1511863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
15129371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1513a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
15144cb006feSStefano Zampini   }
15159566063dSJacob 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));
15164cb006feSStefano Zampini   n = 5;
15179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
15184cb006feSStefano Zampini   if (flag || flag2) {
1519792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1520863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1521863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
15229371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1523a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
15244cb006feSStefano Zampini   }
15259566063dSJacob 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));
152623df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1527792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
152823df4f25SStefano Zampini   }
1529d0609cedSBarry Smith   PetscOptionsHeadEnd();
15303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15314cb006feSStefano Zampini }
15324cb006feSStefano Zampini 
1533d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1534d71ae5a4SJacob Faibussowitsch {
15354cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15364cb006feSStefano Zampini   PetscBool iascii;
15374cb006feSStefano Zampini 
15384cb006feSStefano Zampini   PetscFunctionBegin;
15399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
15404cb006feSStefano Zampini   if (iascii) {
15419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
154263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
154363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
154463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
154563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
154663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
154763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
154863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
15494cb006feSStefano Zampini     if (jac->alpha_Poisson) {
15509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
15514cb006feSStefano Zampini     } else {
15529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
15534cb006feSStefano Zampini     }
155463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
155563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
155663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
155763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
155863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
155963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
15604cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
15614cb006feSStefano Zampini       if (jac->beta_Poisson) {
15629566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
15634cb006feSStefano Zampini       } else {
15649566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
15654cb006feSStefano Zampini       }
156663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
156763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
156863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
156963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
157063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
157163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
157248a46eb9SPierre 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));
157323df4f25SStefano Zampini     } else {
15749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
15754cb006feSStefano Zampini     }
15764cb006feSStefano Zampini   }
15773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15784cb006feSStefano Zampini }
15794cb006feSStefano Zampini 
1580d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1581d71ae5a4SJacob Faibussowitsch {
1582863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1583863406b8SStefano Zampini   PetscInt  n;
1584863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1585863406b8SStefano Zampini 
1586863406b8SStefano Zampini   PetscFunctionBegin;
1587d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
15889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1589792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
15909566063dSJacob 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));
1591792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
15929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1593792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
15949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1595792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
15969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
15979566063dSJacob 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));
15989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
15999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
160048a46eb9SPierre 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);
16019566063dSJacob 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));
1602863406b8SStefano Zampini   n = 5;
16039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
16049566063dSJacob 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));
1605863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1606792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1607863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1608863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1609863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
16109371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1611a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1612863406b8SStefano Zampini   }
16139566063dSJacob 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));
1614863406b8SStefano Zampini   n = 5;
16159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1616863406b8SStefano Zampini   if (flag || flag2) {
1617792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1618863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1619863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
16209371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1621a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1622863406b8SStefano Zampini   }
1623d0609cedSBarry Smith   PetscOptionsHeadEnd();
16243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1625863406b8SStefano Zampini }
1626863406b8SStefano Zampini 
1627d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1628d71ae5a4SJacob Faibussowitsch {
1629863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1630863406b8SStefano Zampini   PetscBool iascii;
1631863406b8SStefano Zampini 
1632863406b8SStefano Zampini   PetscFunctionBegin;
16339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1634863406b8SStefano Zampini   if (iascii) {
16359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
163663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
163763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
163863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
163963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
164063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
164163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
164263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
16439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
164463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
164563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
164663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
164763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
164863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
164963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
165063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
16519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
165263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
165363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
165463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
165563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
165663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
165763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1658863406b8SStefano Zampini   }
16593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1660863406b8SStefano Zampini }
1661863406b8SStefano Zampini 
1662d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1663d71ae5a4SJacob Faibussowitsch {
16644cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16655ac14e1cSStefano Zampini   PetscBool ishypre;
16664cb006feSStefano Zampini 
16674cb006feSStefano Zampini   PetscFunctionBegin;
16689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
16695ac14e1cSStefano Zampini   if (ishypre) {
16709566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
16719566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
16725ac14e1cSStefano Zampini     jac->G = G;
16735ac14e1cSStefano Zampini   } else {
16749566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
16759566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
16765ac14e1cSStefano Zampini   }
16773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16784cb006feSStefano Zampini }
16794cb006feSStefano Zampini 
16804cb006feSStefano Zampini /*@
1681f1580f4eSBarry Smith   PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
16824cb006feSStefano Zampini 
1683c3339decSBarry Smith   Collective
16844cb006feSStefano Zampini 
16854cb006feSStefano Zampini   Input Parameters:
16864cb006feSStefano Zampini + pc - the preconditioning context
16874cb006feSStefano Zampini - G  - the discrete gradient
16884cb006feSStefano Zampini 
16894cb006feSStefano Zampini   Level: intermediate
16904cb006feSStefano Zampini 
169195452b02SPatrick Sanan   Notes:
169295452b02SPatrick Sanan   G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1693147403d9SBarry Smith 
1694863406b8SStefano 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
16954cb006feSStefano Zampini 
1696feefa0e1SJacob Faibussowitsch   Developer Notes:
1697f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1698f1580f4eSBarry Smith 
1699562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
17004cb006feSStefano Zampini @*/
1701d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1702d71ae5a4SJacob Faibussowitsch {
17034cb006feSStefano Zampini   PetscFunctionBegin;
17044cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17054cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
17064cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1707cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
17083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17094cb006feSStefano Zampini }
17104cb006feSStefano Zampini 
1711d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1712d71ae5a4SJacob Faibussowitsch {
1713863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17145ac14e1cSStefano Zampini   PetscBool ishypre;
1715863406b8SStefano Zampini 
1716863406b8SStefano Zampini   PetscFunctionBegin;
17179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
17185ac14e1cSStefano Zampini   if (ishypre) {
17199566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
17209566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
17215ac14e1cSStefano Zampini     jac->C = C;
17225ac14e1cSStefano Zampini   } else {
17239566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
17249566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
17255ac14e1cSStefano Zampini   }
17263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1727863406b8SStefano Zampini }
1728863406b8SStefano Zampini 
1729863406b8SStefano Zampini /*@
1730*6e415bd2SNuno Nobre   PCHYPRESetDiscreteCurl - Set discrete curl matrix for `PCHYPRE` type of ads
1731863406b8SStefano Zampini 
1732c3339decSBarry Smith   Collective
1733863406b8SStefano Zampini 
1734863406b8SStefano Zampini   Input Parameters:
1735863406b8SStefano Zampini + pc - the preconditioning context
1736863406b8SStefano Zampini - C  - the discrete curl
1737863406b8SStefano Zampini 
1738863406b8SStefano Zampini   Level: intermediate
1739863406b8SStefano Zampini 
174095452b02SPatrick Sanan   Notes:
174195452b02SPatrick Sanan   C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1742147403d9SBarry Smith 
1743*6e415bd2SNuno Nobre   Each row of C 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
1744863406b8SStefano Zampini 
1745feefa0e1SJacob Faibussowitsch   Developer Notes:
1746f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1747f1580f4eSBarry Smith 
1748f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1749f1580f4eSBarry Smith 
1750562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1751863406b8SStefano Zampini @*/
1752d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1753d71ae5a4SJacob Faibussowitsch {
1754863406b8SStefano Zampini   PetscFunctionBegin;
1755863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1756863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1757863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1758cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
17593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1760863406b8SStefano Zampini }
1761863406b8SStefano Zampini 
1762d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1763d71ae5a4SJacob Faibussowitsch {
17646bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17656bf688a0SCe Qin   PetscBool ishypre;
17666bf688a0SCe Qin   PetscInt  i;
17676bf688a0SCe Qin 
17684d86920dSPierre Jolivet   PetscFunctionBegin;
17699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
17709566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
17716bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
17729566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
17739566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
17746bf688a0SCe Qin   }
17756bf688a0SCe Qin 
17766bf688a0SCe Qin   jac->dim = dim;
17776bf688a0SCe Qin   if (RT_PiFull) {
17789566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
17796bf688a0SCe Qin     if (ishypre) {
17809566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
17816bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
17826bf688a0SCe Qin     } else {
17839566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
17846bf688a0SCe Qin     }
17856bf688a0SCe Qin   }
17866bf688a0SCe Qin   if (RT_Pi) {
17876bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
17886bf688a0SCe Qin       if (RT_Pi[i]) {
17899566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
17906bf688a0SCe Qin         if (ishypre) {
17919566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
17926bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
17936bf688a0SCe Qin         } else {
17949566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
17956bf688a0SCe Qin         }
17966bf688a0SCe Qin       }
17976bf688a0SCe Qin     }
17986bf688a0SCe Qin   }
17996bf688a0SCe Qin   if (ND_PiFull) {
18009566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
18016bf688a0SCe Qin     if (ishypre) {
18029566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
18036bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
18046bf688a0SCe Qin     } else {
18059566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
18066bf688a0SCe Qin     }
18076bf688a0SCe Qin   }
18086bf688a0SCe Qin   if (ND_Pi) {
18096bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18106bf688a0SCe Qin       if (ND_Pi[i]) {
18119566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
18126bf688a0SCe Qin         if (ishypre) {
18139566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
18146bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
18156bf688a0SCe Qin         } else {
18169566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
18176bf688a0SCe Qin         }
18186bf688a0SCe Qin       }
18196bf688a0SCe Qin     }
18206bf688a0SCe Qin   }
18213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18226bf688a0SCe Qin }
18236bf688a0SCe Qin 
18246bf688a0SCe Qin /*@
1825f1580f4eSBarry Smith   PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
18266bf688a0SCe Qin 
1827c3339decSBarry Smith   Collective
18286bf688a0SCe Qin 
18296bf688a0SCe Qin   Input Parameters:
18306bf688a0SCe Qin + pc        - the preconditioning context
18312fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
18322fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
18332fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
18342fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
18356bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
18366bf688a0SCe Qin 
1837f1580f4eSBarry Smith   Level: intermediate
1838f1580f4eSBarry Smith 
183995452b02SPatrick Sanan   Notes:
184095452b02SPatrick Sanan   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1841147403d9SBarry Smith 
18426bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1843147403d9SBarry Smith 
1844feefa0e1SJacob Faibussowitsch   Developer Notes:
1845f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
18466bf688a0SCe Qin 
1847562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`
18486bf688a0SCe Qin @*/
1849d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1850d71ae5a4SJacob Faibussowitsch {
18516bf688a0SCe Qin   PetscInt i;
18526bf688a0SCe Qin 
18536bf688a0SCe Qin   PetscFunctionBegin;
18546bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
18556bf688a0SCe Qin   if (RT_PiFull) {
18566bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
18576bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
18586bf688a0SCe Qin   }
18596bf688a0SCe Qin   if (RT_Pi) {
18604f572ea9SToby Isaac     PetscAssertPointer(RT_Pi, 4);
18616bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18626bf688a0SCe Qin       if (RT_Pi[i]) {
18636bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
18646bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
18656bf688a0SCe Qin       }
18666bf688a0SCe Qin     }
18676bf688a0SCe Qin   }
18686bf688a0SCe Qin   if (ND_PiFull) {
18696bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
18706bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
18716bf688a0SCe Qin   }
18726bf688a0SCe Qin   if (ND_Pi) {
18734f572ea9SToby Isaac     PetscAssertPointer(ND_Pi, 6);
18746bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18756bf688a0SCe Qin       if (ND_Pi[i]) {
18766bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
18776bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
18786bf688a0SCe Qin       }
18796bf688a0SCe Qin     }
18806bf688a0SCe Qin   }
1881cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
18823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18836bf688a0SCe Qin }
18846bf688a0SCe Qin 
1885d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1886d71ae5a4SJacob Faibussowitsch {
18874cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18885ac14e1cSStefano Zampini   PetscBool ishypre;
18894cb006feSStefano Zampini 
18904cb006feSStefano Zampini   PetscFunctionBegin;
18919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
18925ac14e1cSStefano Zampini   if (ishypre) {
18935ac14e1cSStefano Zampini     if (isalpha) {
18949566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
18959566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
18965ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
18975ac14e1cSStefano Zampini     } else {
18985ac14e1cSStefano Zampini       if (A) {
18999566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
19005ac14e1cSStefano Zampini       } else {
19015ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
19025ac14e1cSStefano Zampini       }
19039566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
19045ac14e1cSStefano Zampini       jac->beta_Poisson = A;
19055ac14e1cSStefano Zampini     }
19065ac14e1cSStefano Zampini   } else {
19075ac14e1cSStefano Zampini     if (isalpha) {
19089566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
19099566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
19105ac14e1cSStefano Zampini     } else {
19115ac14e1cSStefano Zampini       if (A) {
19129566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
19139566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
19145ac14e1cSStefano Zampini       } else {
19159566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
19165ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
19175ac14e1cSStefano Zampini       }
19185ac14e1cSStefano Zampini     }
19195ac14e1cSStefano Zampini   }
19203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19214cb006feSStefano Zampini }
19224cb006feSStefano Zampini 
19234cb006feSStefano Zampini /*@
1924f1580f4eSBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
19254cb006feSStefano Zampini 
1926c3339decSBarry Smith   Collective
19274cb006feSStefano Zampini 
19284cb006feSStefano Zampini   Input Parameters:
19294cb006feSStefano Zampini + pc - the preconditioning context
19304cb006feSStefano Zampini - A  - the matrix
19314cb006feSStefano Zampini 
19324cb006feSStefano Zampini   Level: intermediate
19334cb006feSStefano Zampini 
1934f1580f4eSBarry Smith   Note:
193595452b02SPatrick Sanan   A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
19364cb006feSStefano Zampini 
1937feefa0e1SJacob Faibussowitsch   Developer Notes:
1938f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1939f1580f4eSBarry Smith 
1940f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1941f1580f4eSBarry Smith 
1942562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
19434cb006feSStefano Zampini @*/
1944d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1945d71ae5a4SJacob Faibussowitsch {
19464cb006feSStefano Zampini   PetscFunctionBegin;
19474cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
19484cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
19494cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1950cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
19513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19524cb006feSStefano Zampini }
19534cb006feSStefano Zampini 
19544cb006feSStefano Zampini /*@
1955f1580f4eSBarry Smith   PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
19564cb006feSStefano Zampini 
1957c3339decSBarry Smith   Collective
19584cb006feSStefano Zampini 
19594cb006feSStefano Zampini   Input Parameters:
19604cb006feSStefano Zampini + pc - the preconditioning context
1961f1580f4eSBarry Smith - A  - the matrix, or NULL to turn it off
19624cb006feSStefano Zampini 
19634cb006feSStefano Zampini   Level: intermediate
19644cb006feSStefano Zampini 
1965f1580f4eSBarry Smith   Note:
196695452b02SPatrick Sanan   A should be obtained by discretizing the Poisson problem with linear finite elements.
19674cb006feSStefano Zampini 
1968feefa0e1SJacob Faibussowitsch   Developer Notes:
1969f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1970f1580f4eSBarry Smith 
1971f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1972f1580f4eSBarry Smith 
1973562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
19744cb006feSStefano Zampini @*/
1975d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1976d71ae5a4SJacob Faibussowitsch {
19774cb006feSStefano Zampini   PetscFunctionBegin;
19784cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
19794cb006feSStefano Zampini   if (A) {
19804cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
19814cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
19824cb006feSStefano Zampini   }
1983cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
19843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19854cb006feSStefano Zampini }
19864cb006feSStefano Zampini 
1987d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1988d71ae5a4SJacob Faibussowitsch {
19894cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
19904cb006feSStefano Zampini 
19914cb006feSStefano Zampini   PetscFunctionBegin;
19924cb006feSStefano Zampini   /* throw away any vector if already set */
19939566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
19949566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
19959566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
19969566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
19979566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
19989566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
19999566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
20005ac14e1cSStefano Zampini   jac->dim = 2;
20014cb006feSStefano Zampini   if (zzo) {
20029566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
20039566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
20045ac14e1cSStefano Zampini     jac->dim++;
20054cb006feSStefano Zampini   }
20063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20074cb006feSStefano Zampini }
20084cb006feSStefano Zampini 
20094cb006feSStefano Zampini /*@
2010f1580f4eSBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
20114cb006feSStefano Zampini 
2012c3339decSBarry Smith   Collective
20134cb006feSStefano Zampini 
20144cb006feSStefano Zampini   Input Parameters:
20154cb006feSStefano Zampini + pc  - the preconditioning context
20162fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
20172fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
20184cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
20194cb006feSStefano Zampini 
20204cb006feSStefano Zampini   Level: intermediate
20214cb006feSStefano Zampini 
2022feefa0e1SJacob Faibussowitsch   Developer Notes:
2023f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
2024f1580f4eSBarry Smith 
2025562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
20264cb006feSStefano Zampini @*/
2027d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
2028d71ae5a4SJacob Faibussowitsch {
20294cb006feSStefano Zampini   PetscFunctionBegin;
20304cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20314cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
20324cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
20334cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
20344cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
20354cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
20364cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
2037cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
20383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20394cb006feSStefano Zampini }
20404cb006feSStefano Zampini 
2041d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
2042d71ae5a4SJacob Faibussowitsch {
2043be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2044be14dc20SKerry Key 
2045be14dc20SKerry Key   PetscFunctionBegin;
2046be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
2047be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
2048be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
2049be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
20503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2051be14dc20SKerry Key }
2052be14dc20SKerry Key 
2053be14dc20SKerry Key /*@
2054f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
2055be14dc20SKerry Key 
2056c3339decSBarry Smith   Collective
2057be14dc20SKerry Key 
2058be14dc20SKerry Key   Input Parameters:
2059be14dc20SKerry Key + pc       - the preconditioning context
2060be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
2061be14dc20SKerry Key 
2062be14dc20SKerry Key   Level: intermediate
2063be14dc20SKerry Key 
2064be14dc20SKerry Key   Note:
2065f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
2066f1580f4eSBarry Smith 
2067feefa0e1SJacob Faibussowitsch   Developer Notes:
2068f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
2069f1580f4eSBarry Smith 
2070562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
2071be14dc20SKerry Key @*/
2072d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
2073d71ae5a4SJacob Faibussowitsch {
2074be14dc20SKerry Key   PetscFunctionBegin;
2075be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2076be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
2077be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
2078be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
20793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2080be14dc20SKerry Key }
2081be14dc20SKerry Key 
2082d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2083d71ae5a4SJacob Faibussowitsch {
20844cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
20854cb006feSStefano Zampini   Vec       tv;
20864cb006feSStefano Zampini   PetscInt  i;
20874cb006feSStefano Zampini 
20884cb006feSStefano Zampini   PetscFunctionBegin;
20894cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
20909566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
20919566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
20929566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
20935ac14e1cSStefano Zampini   jac->dim = dim;
20945ac14e1cSStefano Zampini 
20954cb006feSStefano Zampini   /* compute IJ vector for coordinates */
20969566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
20979566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
20989566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
20994cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
21004cb006feSStefano Zampini     PetscScalar *array;
21014cb006feSStefano Zampini     PetscInt     j;
21024cb006feSStefano Zampini 
21039566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
21049566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
21056ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
21069566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
21079566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
21084cb006feSStefano Zampini   }
21099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
21103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21114cb006feSStefano Zampini }
21124cb006feSStefano Zampini 
2113d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
2114d71ae5a4SJacob Faibussowitsch {
211516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
211616d9e3a6SLisandro Dalcin 
211716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
211816d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
21193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212016d9e3a6SLisandro Dalcin }
212116d9e3a6SLisandro Dalcin 
2122d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
2123d71ae5a4SJacob Faibussowitsch {
212416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2125ace3abfcSBarry Smith   PetscBool flag;
212616d9e3a6SLisandro Dalcin 
212716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
212816d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
21299566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
21305f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
21313ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
213216d9e3a6SLisandro Dalcin   } else {
21339566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
213416d9e3a6SLisandro Dalcin   }
213516d9e3a6SLisandro Dalcin 
213616d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
213716d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
213816d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
213916d9e3a6SLisandro Dalcin 
21403c61a47dSLukas   PetscCall(PetscStrcmp("ilu", jac->hypre_type, &flag));
21413c61a47dSLukas   if (flag) {
21423c61a47dSLukas     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
21433c61a47dSLukas     PetscCallExternal(HYPRE_ILUCreate, &jac->hsolver);
21443c61a47dSLukas     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ILU;
21453c61a47dSLukas     pc->ops->view           = PCView_HYPRE_ILU;
21463c61a47dSLukas     jac->destroy            = HYPRE_ILUDestroy;
21473c61a47dSLukas     jac->setup              = HYPRE_ILUSetup;
21483c61a47dSLukas     jac->solve              = HYPRE_ILUSolve;
21493c61a47dSLukas     jac->factorrowsize      = PETSC_DEFAULT;
21503c61a47dSLukas     PetscFunctionReturn(PETSC_SUCCESS);
21513c61a47dSLukas   }
21523c61a47dSLukas 
21539566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
215416d9e3a6SLisandro Dalcin   if (flag) {
21559566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2156792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
215716d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
215816d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
215916d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
216016d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
216116d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
216216d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
21633ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
216416d9e3a6SLisandro Dalcin   }
21659566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
2166db966c6cSHong Zhang   if (flag) {
21674e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
21687de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
21698bf83915SBarry Smith #endif
21709566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2171792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
2172db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
2173db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
2174db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
2175db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
2176db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
2177db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
2178db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
21793ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2180db966c6cSHong Zhang   }
21819566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
218216d9e3a6SLisandro Dalcin   if (flag) {
21839566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2184792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
218516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
218616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
218716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
218816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
218916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
219016d9e3a6SLisandro Dalcin     /* initialize */
219116d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
21928966356dSPierre Jolivet     jac->threshold = .1;
219316d9e3a6SLisandro Dalcin     jac->filter    = .1;
219416d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
21952fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
21962fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
21972fa5cd67SKarl Rupp 
219816d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
219916d9e3a6SLisandro Dalcin     jac->symt = 0;
2200792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
2201792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
2202792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
2203792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
2204792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
2205792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
22063ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
220716d9e3a6SLisandro Dalcin   }
22089566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
220916d9e3a6SLisandro Dalcin   if (flag) {
2210792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
221116d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
221216d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
221316d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
221416d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
221585245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
22169566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
22179566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
221816d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
221916d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
222016d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
222116d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
222216d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
222316d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
222416d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
222516d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
22268f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
222716d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
222816d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
222916d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
223016d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
223116d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
22320f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
22336a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
2234b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
22351810e44eSEike Mueller     jac->eu_level                                                = 0;
22361810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
22371810e44eSEike Mueller     jac->eu_bj                                                   = 0;
2238589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
22390f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
224016d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
224116d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
224216d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
22430f1074feSSatish Balay     jac->interptype                       = 0;
2244589dcaf0SStefano Zampini     jac->Rtype                            = 0;
2245589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
2246589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
2247589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
2248589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
22490f1074feSSatish Balay     jac->agg_nl                           = 0;
22506ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
22510f1074feSSatish Balay     jac->pmax                             = 0;
22520f1074feSSatish Balay     jac->truncfactor                      = 0.0;
22530f1074feSSatish Balay     jac->agg_num_paths                    = 1;
2254589dcaf0SStefano Zampini     jac->maxc                             = 9;
2255589dcaf0SStefano Zampini     jac->minc                             = 1;
225622e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
225722e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
225822e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
225922e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
226022e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
226122e51d31SStefano Zampini     jac->interp_refine                    = 0;
22628f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
22638f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
22646ea7df73SStefano Zampini     jac->rap2                             = 0;
22656ea7df73SStefano Zampini 
22666ea7df73SStefano Zampini     /* GPU defaults
22676ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
22686ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
22696ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22706ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
22716ea7df73SStefano Zampini     jac->mod_rap2       = 1;
22726ea7df73SStefano Zampini     jac->coarsentype    = 8;
22736ea7df73SStefano Zampini     jac->relaxorder     = 0;
22746ea7df73SStefano Zampini     jac->interptype     = 6;
22756ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
22766ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
22776ea7df73SStefano Zampini     jac->agg_interptype = 7;
22786ea7df73SStefano Zampini #else
22796ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
22806ea7df73SStefano Zampini     jac->mod_rap2      = 0;
22816ea7df73SStefano Zampini #endif
2282792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
2283792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
2284792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
2285792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
2286792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
2287792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
2288792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
2289792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
2290792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
2291792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
2292792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
2293792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
2294792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2295792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2296792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2297792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2298792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2299792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2300792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
23016ea7df73SStefano Zampini     /* GPU */
23026ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2303792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2304792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2305792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
23066ea7df73SStefano Zampini #endif
23076ea7df73SStefano Zampini 
2308589dcaf0SStefano Zampini     /* AIR */
23096ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2310792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2311792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2312792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2313792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2314792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
23156ea7df73SStefano Zampini #endif
23163ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
231716d9e3a6SLisandro Dalcin   }
23189566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
23194cb006feSStefano Zampini   if (flag) {
23203ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
23214cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
23224cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
23234cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
23244cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
23254cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
23264cb006feSStefano Zampini     jac->coords[0]          = NULL;
23274cb006feSStefano Zampini     jac->coords[1]          = NULL;
23284cb006feSStefano Zampini     jac->coords[2]          = NULL;
2329be14dc20SKerry Key     jac->interior           = NULL;
23304cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2331863406b8SStefano Zampini     jac->as_print       = 0;
2332863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2333863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
23344cb006feSStefano Zampini     jac->ams_cycle_type = 13;
23354cb006feSStefano Zampini     /* Smoothing options */
2336863406b8SStefano Zampini     jac->as_relax_type   = 2;
2337863406b8SStefano Zampini     jac->as_relax_times  = 1;
2338863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2339863406b8SStefano Zampini     jac->as_omega        = 1.0;
23404cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2341863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2342863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
23430bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2344863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2345863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2346863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
23474cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2348863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2349863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
23500bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2351863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2352863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2353863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2354792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2355792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2356792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2357792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
23589371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2359792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2360863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2361863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
23629371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2363a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2364792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2365863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2366863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
23679371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2368a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
236923df4f25SStefano Zampini     /* Zero conductivity */
237023df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
237123df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
23723ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
23734cb006feSStefano Zampini   }
23749566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2375863406b8SStefano Zampini   if (flag) {
23763ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2377863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2378863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2379863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2380863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2381863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2382863406b8SStefano Zampini     jac->coords[0]          = NULL;
2383863406b8SStefano Zampini     jac->coords[1]          = NULL;
2384863406b8SStefano Zampini     jac->coords[2]          = NULL;
2385863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2386863406b8SStefano Zampini     jac->as_print       = 0;
2387863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2388863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2389863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2390863406b8SStefano Zampini     /* Smoothing options */
2391863406b8SStefano Zampini     jac->as_relax_type   = 2;
2392863406b8SStefano Zampini     jac->as_relax_times  = 1;
2393863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2394863406b8SStefano Zampini     jac->as_omega        = 1.0;
2395863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2396863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2397863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2398863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2399863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2400863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2401863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2402863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2403863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2404863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2405863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2406863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2407863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2408863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2409863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2410792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2411792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2412792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2413792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
24149371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2415792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2416863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2417863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2418863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
24199371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2420a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2421792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2422863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2423863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
24249371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2425a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
24263ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2427863406b8SStefano Zampini   }
24289566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
24292fa5cd67SKarl Rupp 
24300298fd71SBarry Smith   jac->hypre_type = NULL;
243198921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
243216d9e3a6SLisandro Dalcin }
243316d9e3a6SLisandro Dalcin 
243416d9e3a6SLisandro Dalcin /*
243516d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
243616d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
243716d9e3a6SLisandro Dalcin */
2438ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2439d71ae5a4SJacob Faibussowitsch {
24404ddd07fcSJed Brown   PetscInt    indx;
24413c61a47dSLukas   const char *type[] = {"ilu", "euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2442ace3abfcSBarry Smith   PetscBool   flg;
244316d9e3a6SLisandro Dalcin 
244416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2445d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2446dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
244716d9e3a6SLisandro Dalcin   if (flg) {
24489566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
244902a17cd4SBarry Smith   } else {
24509566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
245116d9e3a6SLisandro Dalcin   }
2452dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2453d0609cedSBarry Smith   PetscOptionsHeadEnd();
24543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
245516d9e3a6SLisandro Dalcin }
245616d9e3a6SLisandro Dalcin 
2457cc4c1da9SBarry Smith /*@
245816d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
245916d9e3a6SLisandro Dalcin 
246016d9e3a6SLisandro Dalcin   Input Parameters:
246116d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2462db966c6cSHong Zhang - name - either  euclid, pilut, parasails, boomeramg, ams, ads
246316d9e3a6SLisandro Dalcin 
2464f1580f4eSBarry Smith   Options Database Key:
2465feefa0e1SJacob Faibussowitsch . pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
246616d9e3a6SLisandro Dalcin 
246716d9e3a6SLisandro Dalcin   Level: intermediate
246816d9e3a6SLisandro Dalcin 
2469562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
247016d9e3a6SLisandro Dalcin @*/
2471d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2472d71ae5a4SJacob Faibussowitsch {
247316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
24740700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
24754f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2476cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
24773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
247816d9e3a6SLisandro Dalcin }
247916d9e3a6SLisandro Dalcin 
2480cc4c1da9SBarry Smith /*@
248116d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
248216d9e3a6SLisandro Dalcin 
248316d9e3a6SLisandro Dalcin   Input Parameter:
248416d9e3a6SLisandro Dalcin . pc - the preconditioner context
248516d9e3a6SLisandro Dalcin 
248616d9e3a6SLisandro Dalcin   Output Parameter:
2487db966c6cSHong Zhang . name - either  euclid, pilut, parasails, boomeramg, ams, ads
248816d9e3a6SLisandro Dalcin 
248916d9e3a6SLisandro Dalcin   Level: intermediate
249016d9e3a6SLisandro Dalcin 
2491562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
249216d9e3a6SLisandro Dalcin @*/
2493d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2494d71ae5a4SJacob Faibussowitsch {
249516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
24960700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
24974f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2498cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
24993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250016d9e3a6SLisandro Dalcin }
250116d9e3a6SLisandro Dalcin 
2502cc4c1da9SBarry Smith /*@
2503f1580f4eSBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2504db6f9c32SMark Adams 
2505c3339decSBarry Smith   Logically Collective
2506db6f9c32SMark Adams 
2507db6f9c32SMark Adams   Input Parameters:
2508db6f9c32SMark Adams + pc   - the hypre context
2509feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2510db6f9c32SMark Adams 
2511db6f9c32SMark Adams   Options Database Key:
251267b8a455SSatish Balay . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2513db6f9c32SMark Adams 
2514db6f9c32SMark Adams   Level: intermediate
2515db6f9c32SMark Adams 
2516feefa0e1SJacob Faibussowitsch   Developer Notes:
2517f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2518db6f9c32SMark Adams 
2519562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2520db6f9c32SMark Adams @*/
2521d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2522d71ae5a4SJacob Faibussowitsch {
2523db6f9c32SMark Adams   PetscFunctionBegin;
2524db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2525cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
25263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2527db6f9c32SMark Adams }
2528db6f9c32SMark Adams 
2529cc4c1da9SBarry Smith /*@
2530f1580f4eSBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2531db6f9c32SMark Adams 
2532db6f9c32SMark Adams   Not Collective
2533db6f9c32SMark Adams 
2534db6f9c32SMark Adams   Input Parameter:
2535db6f9c32SMark Adams . pc - the multigrid context
2536db6f9c32SMark Adams 
2537db6f9c32SMark Adams   Output Parameter:
2538db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2539db6f9c32SMark Adams 
2540db6f9c32SMark Adams   Level: intermediate
2541db6f9c32SMark Adams 
2542a94f484eSPierre Jolivet .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinSetMatProductAlgorithm()`
2543db6f9c32SMark Adams @*/
2544d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2545d71ae5a4SJacob Faibussowitsch {
2546db6f9c32SMark Adams   PetscFunctionBegin;
2547db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2548cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
25493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2550db6f9c32SMark Adams }
2551db6f9c32SMark Adams 
255216d9e3a6SLisandro Dalcin /*MC
2553f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
255416d9e3a6SLisandro Dalcin 
255516d9e3a6SLisandro Dalcin    Options Database Keys:
2556e1ded407SBarry Smith +   -pc_hypre_type - One of `euclid`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2557f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2558f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2559e1ded407SBarry Smith -   Many others, run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
256016d9e3a6SLisandro Dalcin 
256116d9e3a6SLisandro Dalcin    Level: intermediate
256216d9e3a6SLisandro Dalcin 
256395452b02SPatrick Sanan    Notes:
2564e1ded407SBarry Smith     Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
256516d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
256649567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
256716d9e3a6SLisandro Dalcin 
2568e1ded407SBarry Smith           The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2569e1ded407SBarry Smith           (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2570e1ded407SBarry Smith           `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2571e1ded407SBarry Smith           (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2572e1ded407SBarry Smith           iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2573e1ded407SBarry Smith           and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2574e1ded407SBarry Smith           then AT MOST twenty V-cycles of boomeramg will be used.
257516d9e3a6SLisandro Dalcin 
2576e1ded407SBarry Smith            Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
25770f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2578e1ded407SBarry Smith            Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
257916d9e3a6SLisandro Dalcin 
2580f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2581e1ded407SBarry Smith           the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
25820b1a5bd9SEric Chamberland 
2583f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2584f1580f4eSBarry Smith 
2585e1ded407SBarry Smith           For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2586f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
258749567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2588f1580f4eSBarry Smith 
2589e1ded407SBarry 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
2590e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2591e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2592e1ded407SBarry Smith 
2593f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
25949e5bc791SBarry Smith 
2595ead8c081SBarry Smith    GPU Notes:
2596ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2597f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2598ead8c081SBarry Smith 
2599ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2600f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2601ead8c081SBarry Smith 
2602562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2603f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2604f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
260516d9e3a6SLisandro Dalcin M*/
260616d9e3a6SLisandro Dalcin 
2607d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2608d71ae5a4SJacob Faibussowitsch {
260916d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
261016d9e3a6SLisandro Dalcin 
261116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
26124dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
26132fa5cd67SKarl Rupp 
261416d9e3a6SLisandro Dalcin   pc->data                = jac;
26158695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
261616d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
261716d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
261816d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
261916d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
262016d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
26219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
26229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
26239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
26249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
26259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
26269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
26279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2628be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
26299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
26309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
26319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
26326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
26336ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
26349566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
26356ea7df73SStefano Zampini   #endif
26366ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
26379566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
26386ea7df73SStefano Zampini   #endif
26396ea7df73SStefano Zampini #endif
2640ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
26413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
264216d9e3a6SLisandro Dalcin }
2643ebc551c0SBarry Smith 
2644ebc551c0SBarry Smith typedef struct {
264568326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2646f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
26479e5bc791SBarry Smith 
26489e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
26494ddd07fcSJed Brown   PetscInt  its;
265073dcfd97SStefano Zampini   PetscReal tol;
26514ddd07fcSJed Brown   PetscInt  relax_type;
26524ddd07fcSJed Brown   PetscInt  rap_type;
26534ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
26544ddd07fcSJed Brown   PetscInt  max_levels;
26550be8cd64Sftrigaux   PetscInt  skip_relax;
26560be8cd64Sftrigaux   PetscBool print_statistics;
2657ebc551c0SBarry Smith } PC_PFMG;
2658ebc551c0SBarry Smith 
2659ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_PFMG(PC pc)
2660d71ae5a4SJacob Faibussowitsch {
2661f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2662ebc551c0SBarry Smith 
2663ebc551c0SBarry Smith   PetscFunctionBegin;
2664792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
26659566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
26669566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
26673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2668ebc551c0SBarry Smith }
2669ebc551c0SBarry Smith 
26709e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
26719e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
26729e5bc791SBarry Smith 
2673ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2674d71ae5a4SJacob Faibussowitsch {
2675ace3abfcSBarry Smith   PetscBool iascii;
2676f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2677ebc551c0SBarry Smith 
2678ebc551c0SBarry Smith   PetscFunctionBegin;
26799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
26809e5bc791SBarry Smith   if (iascii) {
26819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG 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]));
26859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
268663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
268763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
26880be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
26899e5bc791SBarry Smith   }
26903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2691ebc551c0SBarry Smith }
2692ebc551c0SBarry Smith 
2693ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2694d71ae5a4SJacob Faibussowitsch {
2695f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2696ebc551c0SBarry Smith 
2697ebc551c0SBarry Smith   PetscFunctionBegin;
2698d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
26990be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
27009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2701792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
27029566063dSJacob 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));
2703792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
27049566063dSJacob 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));
2705792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
27069e5bc791SBarry Smith 
27079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2708792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
27093b46a515SGlenn Hammond 
27109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2711792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2712dd39110bSPierre 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));
2713792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2714dd39110bSPierre 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));
2715792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
27160be8cd64Sftrigaux   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));
27170be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2718d0609cedSBarry Smith   PetscOptionsHeadEnd();
27193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2720ebc551c0SBarry Smith }
2721ebc551c0SBarry Smith 
2722ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2723d71ae5a4SJacob Faibussowitsch {
2724f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2725d9ca1df4SBarry Smith   PetscScalar       *yy;
2726d9ca1df4SBarry Smith   const PetscScalar *xx;
27274ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
27282cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2729f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
2730f91d8e95SBarry Smith 
2731f91d8e95SBarry Smith   PetscFunctionBegin;
27329566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
27339566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
27342cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2735f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2736f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2737f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
27382cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
27392cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
27402cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
27412cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
27422cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
27432cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2744f91d8e95SBarry Smith 
2745f91d8e95SBarry Smith   /* copy x values over to hypre */
2746792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
27479566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2748792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
27499566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2750792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2751792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2752f91d8e95SBarry Smith 
2753f91d8e95SBarry Smith   /* copy solution values back to PETSc */
27549566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2755792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
27569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
27573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2758f91d8e95SBarry Smith }
2759f91d8e95SBarry Smith 
2760d71ae5a4SJacob 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)
2761d71ae5a4SJacob Faibussowitsch {
27629e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
27632cf14000SStefano Zampini   HYPRE_Int oits;
27649e5bc791SBarry Smith 
27659e5bc791SBarry Smith   PetscFunctionBegin;
27669566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2767792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2768792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
27699e5bc791SBarry Smith 
27709566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2771792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
27729e5bc791SBarry Smith   *outits = oits;
27739e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
27749e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2775792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2776792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
27773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27789e5bc791SBarry Smith }
27799e5bc791SBarry Smith 
2780ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_PFMG(PC pc)
2781d71ae5a4SJacob Faibussowitsch {
27823a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
2783f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
2784ace3abfcSBarry Smith   PetscBool        flg;
27853a32d3dbSGlenn Hammond 
27863a32d3dbSGlenn Hammond   PetscFunctionBegin;
27879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
278828b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
27893a32d3dbSGlenn Hammond 
27903a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2791792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2792792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
27930be8cd64Sftrigaux 
27940be8cd64Sftrigaux   // Print Hypre statistics about the solve process
27950be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
27960be8cd64Sftrigaux 
27970be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
27980be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
27990be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28000be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28010be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
28020be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
28030be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
28040be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
28050be8cd64Sftrigaux 
2806792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2807792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
28083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28093a32d3dbSGlenn Hammond }
28103a32d3dbSGlenn Hammond 
2811ebc551c0SBarry Smith /*MC
2812ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2813ebc551c0SBarry Smith 
2814f1580f4eSBarry Smith    Options Database Keys:
281567b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
281667b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
281767b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
281867b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
28199e5bc791SBarry 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
28200be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2821f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2822f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2823f1580f4eSBarry Smith 
2824f1580f4eSBarry Smith    Level: advanced
2825f91d8e95SBarry Smith 
282695452b02SPatrick Sanan    Notes:
282795452b02SPatrick Sanan    This is for CELL-centered descretizations
28289e5bc791SBarry Smith 
2829f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
28309e5bc791SBarry Smith 
2831f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2832f1580f4eSBarry Smith 
2833f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2834f1580f4eSBarry Smith 
2835f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2836f1580f4eSBarry Smith 
2837562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2838ebc551c0SBarry Smith M*/
2839ebc551c0SBarry Smith 
2840d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2841d71ae5a4SJacob Faibussowitsch {
2842ebc551c0SBarry Smith   PC_PFMG *ex;
2843ebc551c0SBarry Smith 
2844ebc551c0SBarry Smith   PetscFunctionBegin;
28459371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
284668326731SBarry Smith   pc->data = ex;
2847ebc551c0SBarry Smith 
28489e5bc791SBarry Smith   ex->its              = 1;
28499e5bc791SBarry Smith   ex->tol              = 1.e-8;
28509e5bc791SBarry Smith   ex->relax_type       = 1;
28519e5bc791SBarry Smith   ex->rap_type         = 0;
28529e5bc791SBarry Smith   ex->num_pre_relax    = 1;
28539e5bc791SBarry Smith   ex->num_post_relax   = 1;
28543b46a515SGlenn Hammond   ex->max_levels       = 0;
28550be8cd64Sftrigaux   ex->skip_relax       = 0;
28560be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
28579e5bc791SBarry Smith 
2858ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2859ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2860ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2861f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
28629e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
286368326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
28642fa5cd67SKarl Rupp 
28659566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2866ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2867792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
28683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2869ebc551c0SBarry Smith }
2870d851a50bSGlenn Hammond 
2871d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2872d851a50bSGlenn Hammond typedef struct {
2873d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2874d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2875d851a50bSGlenn Hammond 
2876d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
28774ddd07fcSJed Brown   PetscInt  its;
287873dcfd97SStefano Zampini   PetscReal tol;
28794ddd07fcSJed Brown   PetscInt  relax_type;
28804ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
2881d851a50bSGlenn Hammond } PC_SysPFMG;
2882d851a50bSGlenn Hammond 
2883ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SysPFMG(PC pc)
2884d71ae5a4SJacob Faibussowitsch {
2885d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2886d851a50bSGlenn Hammond 
2887d851a50bSGlenn Hammond   PetscFunctionBegin;
2888792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
28899566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28909566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
28913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2892d851a50bSGlenn Hammond }
2893d851a50bSGlenn Hammond 
2894d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2895d851a50bSGlenn Hammond 
2896ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2897d71ae5a4SJacob Faibussowitsch {
2898ace3abfcSBarry Smith   PetscBool   iascii;
2899d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2900d851a50bSGlenn Hammond 
2901d851a50bSGlenn Hammond   PetscFunctionBegin;
29029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2903d851a50bSGlenn Hammond   if (iascii) {
29049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
290563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
29069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
29079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
290863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2909d851a50bSGlenn Hammond   }
29103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2911d851a50bSGlenn Hammond }
2912d851a50bSGlenn Hammond 
2913ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2914d71ae5a4SJacob Faibussowitsch {
2915d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2916ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2917d851a50bSGlenn Hammond 
2918d851a50bSGlenn Hammond   PetscFunctionBegin;
2919d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
29209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
292148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
29229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2923792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
29249566063dSJacob 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));
2925792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
29269566063dSJacob 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));
2927792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2928d851a50bSGlenn Hammond 
29299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2930792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2931dd39110bSPierre 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));
2932792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2933d0609cedSBarry Smith   PetscOptionsHeadEnd();
29343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2935d851a50bSGlenn Hammond }
2936d851a50bSGlenn Hammond 
2937ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2938d71ae5a4SJacob Faibussowitsch {
2939d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2940d9ca1df4SBarry Smith   PetscScalar       *yy;
2941d9ca1df4SBarry Smith   const PetscScalar *xx;
29424ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
29432cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2944f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)pc->pmat->data;
29454ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
29464ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
29474ddd07fcSJed Brown   PetscInt           part     = 0;
29484ddd07fcSJed Brown   PetscInt           size;
29494ddd07fcSJed Brown   PetscInt           i;
2950d851a50bSGlenn Hammond 
2951d851a50bSGlenn Hammond   PetscFunctionBegin;
29529566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29539566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
29542cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2955d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2956d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2957d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
29582cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
29592cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
29602cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
29612cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
29622cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
29632cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2964d851a50bSGlenn Hammond 
2965d851a50bSGlenn Hammond   size = 1;
29662fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
29672fa5cd67SKarl Rupp 
2968d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2969d851a50bSGlenn Hammond   if (ordering) {
2970792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
29719566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2972792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
29739566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2974792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2975792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2976792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2977d851a50bSGlenn Hammond 
2978d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
29799566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2980792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
29819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2982a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2983d851a50bSGlenn Hammond     PetscScalar *z;
29844ddd07fcSJed Brown     PetscInt     j, k;
2985d851a50bSGlenn Hammond 
29869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2987792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
29889566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2989d851a50bSGlenn Hammond 
2990d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2991d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2992d851a50bSGlenn Hammond       k = i * nvars;
29932fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2994d851a50bSGlenn Hammond     }
2995792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
29969566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2997792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2998792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2999d851a50bSGlenn Hammond 
3000d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30019566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3002792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
3003d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
3004d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3005d851a50bSGlenn Hammond       k = i * nvars;
30062fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
3007d851a50bSGlenn Hammond     }
30089566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
30099566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
3010d851a50bSGlenn Hammond   }
30113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3012d851a50bSGlenn Hammond }
3013d851a50bSGlenn Hammond 
3014d71ae5a4SJacob 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)
3015d71ae5a4SJacob Faibussowitsch {
3016d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
30172cf14000SStefano Zampini   HYPRE_Int   oits;
3018d851a50bSGlenn Hammond 
3019d851a50bSGlenn Hammond   PetscFunctionBegin;
30209566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
3021792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
3022792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
30239566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
3024792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
3025d851a50bSGlenn Hammond   *outits = oits;
3026d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
3027d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
3028792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
3029792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
30303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3031d851a50bSGlenn Hammond }
3032d851a50bSGlenn Hammond 
3033ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SysPFMG(PC pc)
3034d71ae5a4SJacob Faibussowitsch {
3035d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
3036f4f49eeaSPierre Jolivet   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)pc->pmat->data;
3037ace3abfcSBarry Smith   PetscBool         flg;
3038d851a50bSGlenn Hammond 
3039d851a50bSGlenn Hammond   PetscFunctionBegin;
30409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
304128b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
3042d851a50bSGlenn Hammond 
3043d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
3044792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
3045792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
3046792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
3047792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
30483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3049d851a50bSGlenn Hammond }
3050d851a50bSGlenn Hammond 
3051d851a50bSGlenn Hammond /*MC
3052f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
3053d851a50bSGlenn Hammond 
3054d851a50bSGlenn Hammond    Level: advanced
3055d851a50bSGlenn Hammond 
3056f1580f4eSBarry Smith    Options Database Keys:
305767b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
305867b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
305967b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
306067b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
306167b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
3062d851a50bSGlenn Hammond 
306395452b02SPatrick Sanan    Notes:
3064f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
3065f1580f4eSBarry Smith 
3066f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
3067f1580f4eSBarry Smith 
306895452b02SPatrick Sanan    This is for CELL-centered descretizations
3069d851a50bSGlenn Hammond 
3070f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
3071d851a50bSGlenn Hammond 
3072f1580f4eSBarry 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`.
3073f1580f4eSBarry Smith 
3074562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
3075d851a50bSGlenn Hammond M*/
3076d851a50bSGlenn Hammond 
3077d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
3078d71ae5a4SJacob Faibussowitsch {
3079d851a50bSGlenn Hammond   PC_SysPFMG *ex;
3080d851a50bSGlenn Hammond 
3081d851a50bSGlenn Hammond   PetscFunctionBegin;
30829371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
3083d851a50bSGlenn Hammond   pc->data = ex;
3084d851a50bSGlenn Hammond 
3085d851a50bSGlenn Hammond   ex->its            = 1;
3086d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
3087d851a50bSGlenn Hammond   ex->relax_type     = 1;
3088d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
3089d851a50bSGlenn Hammond   ex->num_post_relax = 1;
3090d851a50bSGlenn Hammond 
3091d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
3092d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
3093d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
3094d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
3095d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
3096d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
30972fa5cd67SKarl Rupp 
30989566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3099ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
3100792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
31013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3102d851a50bSGlenn Hammond }
31031c188c59Sftrigaux 
3104f1580f4eSBarry Smith /* PC SMG */
31051c188c59Sftrigaux typedef struct {
31061c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
31071c188c59Sftrigaux   HYPRE_StructSolver hsolver;
31081c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
310973dcfd97SStefano Zampini   PetscReal          tol;
31101c188c59Sftrigaux   PetscBool          print_statistics;
31111c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
31121c188c59Sftrigaux } PC_SMG;
31131c188c59Sftrigaux 
3114ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SMG(PC pc)
3115d71ae5a4SJacob Faibussowitsch {
31161c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
31171c188c59Sftrigaux 
31181c188c59Sftrigaux   PetscFunctionBegin;
31191c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
31201c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
31211c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
31223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31231c188c59Sftrigaux }
31241c188c59Sftrigaux 
3125ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
3126d71ae5a4SJacob Faibussowitsch {
31271c188c59Sftrigaux   PetscBool iascii;
31281c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
31291c188c59Sftrigaux 
31301c188c59Sftrigaux   PetscFunctionBegin;
31311c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
31321c188c59Sftrigaux   if (iascii) {
31331c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
31341c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
31351c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
31361c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
31371c188c59Sftrigaux   }
31383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31391c188c59Sftrigaux }
31401c188c59Sftrigaux 
3141ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
3142d71ae5a4SJacob Faibussowitsch {
31431c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
31441c188c59Sftrigaux 
31451c188c59Sftrigaux   PetscFunctionBegin;
31461c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
31471c188c59Sftrigaux 
31481c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
31491c188c59Sftrigaux   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));
31501c188c59Sftrigaux   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));
31511c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
31521c188c59Sftrigaux 
31531c188c59Sftrigaux   PetscOptionsHeadEnd();
31543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31551c188c59Sftrigaux }
31561c188c59Sftrigaux 
3157ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
3158d71ae5a4SJacob Faibussowitsch {
31591c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
31601c188c59Sftrigaux   PetscScalar       *yy;
31611c188c59Sftrigaux   const PetscScalar *xx;
31621c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
31631c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
3164f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
31651c188c59Sftrigaux 
31661c188c59Sftrigaux   PetscFunctionBegin;
31671c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
31681c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
31691c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
31701c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
31711c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
31721c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
31731c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
31741c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
31751c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
31761c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
31771c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
31781c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
31791c188c59Sftrigaux 
31801c188c59Sftrigaux   /* copy x values over to hypre */
31811c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
31821c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
31831c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
31841c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
31851c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
31861c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
31871c188c59Sftrigaux 
31881c188c59Sftrigaux   /* copy solution values back to PETSc */
31891c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
31901c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
31911c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
31923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31931c188c59Sftrigaux }
31941c188c59Sftrigaux 
3195d71ae5a4SJacob 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)
3196d71ae5a4SJacob Faibussowitsch {
31971c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
31981c188c59Sftrigaux   HYPRE_Int oits;
31991c188c59Sftrigaux 
32001c188c59Sftrigaux   PetscFunctionBegin;
32011c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32021c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
32031c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
32041c188c59Sftrigaux 
32051c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
32061c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
32071c188c59Sftrigaux   *outits = oits;
32081c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
32091c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
32101c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
32111c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
32123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32131c188c59Sftrigaux }
32141c188c59Sftrigaux 
3215ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SMG(PC pc)
3216d71ae5a4SJacob Faibussowitsch {
32171c188c59Sftrigaux   PetscInt         i, dim;
32181c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
3219f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
32201c188c59Sftrigaux   PetscBool        flg;
32211c188c59Sftrigaux   DMBoundaryType   p[3];
32221c188c59Sftrigaux   PetscInt         M[3];
32231c188c59Sftrigaux 
32241c188c59Sftrigaux   PetscFunctionBegin;
32251c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
32261c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
32271c188c59Sftrigaux 
32281c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
32291c188c59Sftrigaux   // Check if power of 2 in periodic directions
32301c188c59Sftrigaux   for (i = 0; i < dim; i++) {
32311c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
32321c188c59Sftrigaux       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]);
32331c188c59Sftrigaux     }
32341c188c59Sftrigaux   }
32351c188c59Sftrigaux 
32361c188c59Sftrigaux   /* create the hypre solver object and set its information */
323757508eceSPierre Jolivet   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
32381c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
32391c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
32401c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
32411c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
32421c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
32431c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
32441c188c59Sftrigaux 
32451c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
32461c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
32473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32481c188c59Sftrigaux }
32491c188c59Sftrigaux 
32501c188c59Sftrigaux /*MC
32515cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
32521c188c59Sftrigaux 
32531c188c59Sftrigaux    Level: advanced
32541c188c59Sftrigaux 
3255f1580f4eSBarry Smith    Options Database Keys:
32565cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
32575cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
32585cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
32595cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
32601c188c59Sftrigaux 
32611c188c59Sftrigaux    Notes:
32621c188c59Sftrigaux    This is for CELL-centered descretizations
32631c188c59Sftrigaux 
32645cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
32651c188c59Sftrigaux 
3266f1580f4eSBarry 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`.
3267f1580f4eSBarry Smith 
3268f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3269f1580f4eSBarry Smith 
3270f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
32711c188c59Sftrigaux M*/
32721c188c59Sftrigaux 
3273d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3274d71ae5a4SJacob Faibussowitsch {
32751c188c59Sftrigaux   PC_SMG *ex;
32761c188c59Sftrigaux 
32771c188c59Sftrigaux   PetscFunctionBegin;
32789371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
32791c188c59Sftrigaux   pc->data = ex;
32801c188c59Sftrigaux 
32811c188c59Sftrigaux   ex->its            = 1;
32821c188c59Sftrigaux   ex->tol            = 1.e-8;
32831c188c59Sftrigaux   ex->num_pre_relax  = 1;
32841c188c59Sftrigaux   ex->num_post_relax = 1;
32851c188c59Sftrigaux 
32861c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
32871c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
32881c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
32891c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
32901c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
32911c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
32921c188c59Sftrigaux 
32931c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3294ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
32951c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
32963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32971c188c59Sftrigaux }
3298