xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision e6519f9f8d90f4199bf6bb1df3ffafa56045e5d2)
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;
15642e5ec60SJeff-Hadley   PetscBool            same;
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;
18542e5ec60SJeff-Hadley   PetscBool            same;
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 
20642e5ec60SJeff-Hadley /*
20742e5ec60SJeff-Hadley   Boolean Vecs are created IN PLACE with using data from BoomerAMG.
20842e5ec60SJeff-Hadley */
20942e5ec60SJeff-Hadley static PetscErrorCode PCHYPREGetCFMarkers_BoomerAMG(PC pc, PetscInt *n_per_level[], PetscBT *CFMarkers[])
21042e5ec60SJeff-Hadley {
21142e5ec60SJeff-Hadley   PC_HYPRE        *jac = (PC_HYPRE *)pc->data;
21242e5ec60SJeff-Hadley   PetscBool        same;
21342e5ec60SJeff-Hadley   PetscInt         num_levels, fine_nodes = 0, coarse_nodes;
21442e5ec60SJeff-Hadley   PetscInt        *n_per_temp;
21542e5ec60SJeff-Hadley   PetscBT         *markertmp;
21642e5ec60SJeff-Hadley   hypre_IntArray **CF_marker_array;
21742e5ec60SJeff-Hadley 
21842e5ec60SJeff-Hadley   PetscFunctionBegin;
21942e5ec60SJeff-Hadley   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
22042e5ec60SJeff-Hadley   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG");
22142e5ec60SJeff-Hadley   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)jac->hsolver);
22242e5ec60SJeff-Hadley   PetscCall(PetscMalloc1(num_levels, &n_per_temp));
22342e5ec60SJeff-Hadley   PetscCall(PetscMalloc1(num_levels - 1, &markertmp));
22442e5ec60SJeff-Hadley   CF_marker_array = hypre_ParAMGDataCFMarkerArray((hypre_ParAMGData *)jac->hsolver);
22542e5ec60SJeff-Hadley   for (PetscInt l = 0, CFMaxIndex = num_levels - 2; CFMaxIndex >= 0; l++, CFMaxIndex--) {
22642e5ec60SJeff-Hadley     fine_nodes   = hypre_IntArraySize(CF_marker_array[CFMaxIndex]);
22742e5ec60SJeff-Hadley     coarse_nodes = 0;
22842e5ec60SJeff-Hadley     PetscCall(PetscBTCreate(fine_nodes, &markertmp[l]));
22942e5ec60SJeff-Hadley     for (PetscInt k = 0; k < fine_nodes; k++) {
23042e5ec60SJeff-Hadley       if (hypre_IntArrayDataI(CF_marker_array[CFMaxIndex], k) > 0) {
23142e5ec60SJeff-Hadley         PetscCall(PetscBTSet(markertmp[l], k));
23242e5ec60SJeff-Hadley         coarse_nodes++;
23342e5ec60SJeff-Hadley       }
23442e5ec60SJeff-Hadley     }
23542e5ec60SJeff-Hadley     n_per_temp[l] = coarse_nodes;
23642e5ec60SJeff-Hadley   }
23742e5ec60SJeff-Hadley   n_per_temp[num_levels - 1] = fine_nodes;
23842e5ec60SJeff-Hadley   *n_per_level               = n_per_temp;
23942e5ec60SJeff-Hadley   *CFMarkers                 = markertmp;
24042e5ec60SJeff-Hadley   PetscFunctionReturn(PETSC_SUCCESS);
24142e5ec60SJeff-Hadley }
24242e5ec60SJeff-Hadley 
243ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
244d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
245d71ae5a4SJacob Faibussowitsch {
246ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
247ce6a8a0dSJed Brown   PetscInt  i;
248ce6a8a0dSJed Brown 
2499d678128SJed Brown   PetscFunctionBegin;
25048a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2519566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2529566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2549d678128SJed Brown   jac->n_hmnull = 0;
2553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
256ce6a8a0dSJed Brown }
257ce6a8a0dSJed Brown 
258d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
259d71ae5a4SJacob Faibussowitsch {
26016d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
26149a781f5SStefano Zampini   Mat_HYPRE         *hjac;
26216d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
26316d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
26449a781f5SStefano Zampini   PetscBool          ishypre;
26516d9e3a6SLisandro Dalcin 
26616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2670df1829cSStefano Zampini   /* default type is boomerAMG */
26848a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2695f5c5b43SBarry Smith 
2700df1829cSStefano Zampini   /* get hypre matrix */
2710df1829cSStefano Zampini   if (pc->flag == DIFFERENT_NONZERO_PATTERN) PetscCall(MatDestroy(&jac->hpmat));
2729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
27349a781f5SStefano Zampini   if (!ishypre) {
274*e6519f9fSJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE) && PETSC_PKG_HYPRE_VERSION_LE(2, 30, 0)
2750df1829cSStefano Zampini     /* Temporary fix since we do not support MAT_REUSE_MATRIX with HYPRE device */
2760df1829cSStefano Zampini     PetscBool iscuda, iship, iskokkos;
2770df1829cSStefano Zampini 
2780df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
2790df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
2800df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iskokkos, MATSEQAIJKOKKOS, MATMPIAIJKOKKOS, ""));
2810df1829cSStefano Zampini     if (iscuda || iship || iskokkos) PetscCall(MatDestroy(&jac->hpmat));
2820df1829cSStefano Zampini #endif
2830df1829cSStefano Zampini     PetscCall(MatConvert(pc->pmat, MATHYPRE, jac->hpmat ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &jac->hpmat));
28449a781f5SStefano Zampini   } else {
2859566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2869566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
28749a781f5SStefano Zampini     jac->hpmat = pc->pmat;
28816d9e3a6SLisandro Dalcin   }
2890df1829cSStefano Zampini 
2906ea7df73SStefano Zampini   /* allow debug */
2919566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
292f4f49eeaSPierre Jolivet   hjac = (Mat_HYPRE *)jac->hpmat->data;
2935f5c5b43SBarry Smith 
29416d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
29516d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2965272c319SBarry Smith     MatNullSpace mnull;
2975272c319SBarry Smith     PetscBool    has_const;
29849a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2995272c319SBarry Smith     const Vec   *vecs;
3005272c319SBarry Smith 
3019566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
302792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
3039566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
3045272c319SBarry Smith     if (mnull) {
3059566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
3069566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
3079566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
3089566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
3095272c319SBarry Smith       for (i = 0; i < nvec; i++) {
3109566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
3119566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
312792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
3135272c319SBarry Smith       }
3145272c319SBarry Smith       if (has_const) {
3159566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
3169566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
3179566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
3189566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
3199566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
320792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
3215272c319SBarry Smith         nvec++;
3225272c319SBarry Smith       }
323792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
3245272c319SBarry Smith       jac->n_hmnull = nvec;
3255272c319SBarry Smith     }
3264cb006feSStefano Zampini   }
327863406b8SStefano Zampini 
3284cb006feSStefano Zampini   /* special case for AMS */
3294cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
3305ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3315ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3326bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
333f1580f4eSBarry 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()");
3346bf688a0SCe Qin     }
33548a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
3365ac14e1cSStefano Zampini     if (jac->constants[0]) {
3375ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
338792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
339792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
34048a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
341792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
3425ac14e1cSStefano Zampini     }
3435ac14e1cSStefano Zampini     if (jac->coords[0]) {
3445ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3455ac14e1cSStefano Zampini       coords[0] = NULL;
3465ac14e1cSStefano Zampini       coords[1] = NULL;
3475ac14e1cSStefano Zampini       coords[2] = NULL;
348792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
349792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
350792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
351792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3525ac14e1cSStefano Zampini     }
3535f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
354f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
355792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
356792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3575ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
358f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->alpha_Poisson->data;
359792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
360792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3615ac14e1cSStefano Zampini     }
3625ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
363792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3645ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
365f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->beta_Poisson->data;
366792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
367792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
368be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
369be14dc20SKerry Key       if (jac->interior) {
370be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
371be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
372be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
373be14dc20SKerry Key       } else {
374be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
375be14dc20SKerry Key       }
3765ac14e1cSStefano Zampini     }
3776bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3786bf688a0SCe Qin       PetscInt           i;
3796bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3806bf688a0SCe Qin       if (jac->ND_PiFull) {
381f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
382792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3836bf688a0SCe Qin       } else {
3846bf688a0SCe Qin         nd_parcsrfull = NULL;
3856bf688a0SCe Qin       }
3866bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3876bf688a0SCe Qin         if (jac->ND_Pi[i]) {
388f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
389792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3906bf688a0SCe Qin         } else {
3916bf688a0SCe Qin           nd_parcsr[i] = NULL;
3926bf688a0SCe Qin         }
3936bf688a0SCe Qin       }
394792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3956bf688a0SCe Qin     }
3964cb006feSStefano Zampini   }
397863406b8SStefano Zampini   /* special case for ADS */
398863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3995ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
4005ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
4016bf688a0SCe 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])))) {
4026bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
4039371c9d4SSatish 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");
4045f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
4055f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
4065ac14e1cSStefano Zampini     if (jac->coords[0]) {
4075ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
4085ac14e1cSStefano Zampini       coords[0] = NULL;
4095ac14e1cSStefano Zampini       coords[1] = NULL;
4105ac14e1cSStefano Zampini       coords[2] = NULL;
411792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
412792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
413792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
414792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
4155ac14e1cSStefano Zampini     }
416f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
417792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
418792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
419f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->C->data;
420792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
421792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
4226bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
4236bf688a0SCe Qin       PetscInt           i;
4246bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
4256bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
4266bf688a0SCe Qin       if (jac->RT_PiFull) {
427f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->RT_PiFull->data;
428792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
4296bf688a0SCe Qin       } else {
4306bf688a0SCe Qin         rt_parcsrfull = NULL;
4316bf688a0SCe Qin       }
4326bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4336bf688a0SCe Qin         if (jac->RT_Pi[i]) {
434f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->RT_Pi[i]->data;
435792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
4366bf688a0SCe Qin         } else {
4376bf688a0SCe Qin           rt_parcsr[i] = NULL;
4386bf688a0SCe Qin         }
4396bf688a0SCe Qin       }
4406bf688a0SCe Qin       if (jac->ND_PiFull) {
441f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
442792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4436bf688a0SCe Qin       } else {
4446bf688a0SCe Qin         nd_parcsrfull = NULL;
4456bf688a0SCe Qin       }
4466bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4476bf688a0SCe Qin         if (jac->ND_Pi[i]) {
448f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
449792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4506bf688a0SCe Qin         } else {
4516bf688a0SCe Qin           nd_parcsr[i] = NULL;
4526bf688a0SCe Qin         }
4536bf688a0SCe Qin       }
454792fecdfSBarry 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]);
4556bf688a0SCe Qin     }
456863406b8SStefano Zampini   }
457792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
458792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
459792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
46097c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
461792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
46297c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
4633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46416d9e3a6SLisandro Dalcin }
46516d9e3a6SLisandro Dalcin 
466d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
467d71ae5a4SJacob Faibussowitsch {
46816d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
469f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
47016d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
47116d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
47216d9e3a6SLisandro Dalcin 
47316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4749566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4759566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4769566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4779566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4789566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
479792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
480792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
481792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4829371c9d4SSatish Balay   PetscStackCallExternalVoid(
4839371c9d4SSatish Balay     "Hypre solve", do {
4845f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4855f80ce2aSJacob Faibussowitsch       if (hierr) {
4865f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
48785245615SPierre Jolivet         HYPRE_ClearAllErrors();
4885f80ce2aSJacob Faibussowitsch       }
4895f80ce2aSJacob Faibussowitsch     } while (0));
49016d9e3a6SLisandro Dalcin 
49148a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4929566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4939566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
4943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49516d9e3a6SLisandro Dalcin }
49616d9e3a6SLisandro Dalcin 
49785245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
49885245615SPierre Jolivet {
49985245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
500f4f49eeaSPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)jac->hpmat->data;
50185245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
50285245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
50385245615SPierre Jolivet   const PetscScalar  *b;
50485245615SPierre Jolivet   PetscScalar        *x;
50585245615SPierre Jolivet   PetscInt            m, N, lda;
50685245615SPierre Jolivet   hypre_Vector       *x_local;
50785245615SPierre Jolivet   PetscMemType        type;
50885245615SPierre Jolivet 
50985245615SPierre Jolivet   PetscFunctionBegin;
51085245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
51185245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
51285245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
51385245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
51485245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
51585245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
51685245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
51785245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
51885245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
51985245615SPierre 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);
52085245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
52185245615SPierre 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);
52285245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
52385245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
52485245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
52585245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
52685245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
52785245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
52885245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
52985245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
53085245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
53185245615SPierre Jolivet   PetscStackCallExternalVoid(
53285245615SPierre Jolivet     "Hypre solve", do {
53385245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
53485245615SPierre Jolivet       if (hierr) {
53585245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
53685245615SPierre Jolivet         HYPRE_ClearAllErrors();
53785245615SPierre Jolivet       }
53885245615SPierre Jolivet     } while (0));
53985245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
54085245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
54185245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
54285245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
54385245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
54485245615SPierre Jolivet }
54585245615SPierre Jolivet 
546d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
547d71ae5a4SJacob Faibussowitsch {
5488695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5498695de01SBarry Smith 
5508695de01SBarry Smith   PetscFunctionBegin;
5519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
5529566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
5539566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
5549566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
5559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
5569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
5579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
5589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
5599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
5609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
5619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
5629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
5639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
5649566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
5659566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
5669566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
5679566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
5689566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
5699566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
570be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
5719566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
5725ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
573be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
5745ac14e1cSStefano Zampini   jac->dim                   = 0;
5753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5768695de01SBarry Smith }
5778695de01SBarry Smith 
578d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
579d71ae5a4SJacob Faibussowitsch {
58016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
58116d9e3a6SLisandro Dalcin 
58216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5839566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
584792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
5859566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
586db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
5879566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
588db6f9c32SMark Adams #endif
5899566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
5909566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
59116d9e3a6SLisandro Dalcin 
5929566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
6002e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
601be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
6029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
6039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
60442e5ec60SJeff-Hadley   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", NULL));
6059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
6069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
6072e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
6083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60916d9e3a6SLisandro Dalcin }
61016d9e3a6SLisandro Dalcin 
611d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
612d71ae5a4SJacob Faibussowitsch {
61316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
614ace3abfcSBarry Smith   PetscBool flag;
61516d9e3a6SLisandro Dalcin 
61616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
617d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
6189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
619792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
6209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
621792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
6229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
623792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
624d0609cedSBarry Smith   PetscOptionsHeadEnd();
6253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62616d9e3a6SLisandro Dalcin }
62716d9e3a6SLisandro Dalcin 
628d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
629d71ae5a4SJacob Faibussowitsch {
63016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
631ace3abfcSBarry Smith   PetscBool iascii;
63216d9e3a6SLisandro Dalcin 
63316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
63516d9e3a6SLisandro Dalcin   if (iascii) {
6369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
63716d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
63863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
63916d9e3a6SLisandro Dalcin     } else {
6409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
64116d9e3a6SLisandro Dalcin     }
64216d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
6439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
64416d9e3a6SLisandro Dalcin     } else {
6459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
64616d9e3a6SLisandro Dalcin     }
64716d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
64863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
64916d9e3a6SLisandro Dalcin     } else {
6509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
65116d9e3a6SLisandro Dalcin     }
65216d9e3a6SLisandro Dalcin   }
6533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65416d9e3a6SLisandro Dalcin }
65516d9e3a6SLisandro Dalcin 
6563c61a47dSLukas static const char *HYPREILUType[] = {
6573c61a47dSLukas   "Block-Jacobi-ILUk", "Block-Jacobi-ILUT", "", "", "", "", "", "", "", "", /* 0-9 */
6583c61a47dSLukas   "GMRES-ILUk",        "GMRES-ILUT",        "", "", "", "", "", "", "", "", /* 10-19 */
6593c61a47dSLukas   "NSH-ILUk",          "NSH-ILUT",          "", "", "", "", "", "", "", "", /* 20-29 */
6603c61a47dSLukas   "RAS-ILUk",          "RAS-ILUT",          "", "", "", "", "", "", "", "", /* 30-39 */
6613c61a47dSLukas   "ddPQ-GMRES-ILUk",   "ddPQ-GMRES-ILUT",   "", "", "", "", "", "", "", "", /* 40-49 */
6623c61a47dSLukas   "GMRES-ILU0"                                                              /* 50 */
6633c61a47dSLukas };
6643c61a47dSLukas 
6653c61a47dSLukas static const char *HYPREILUIterSetup[] = {"default", "async-in-place", "async-explicit", "sync-explicit", "semisync-explicit"};
6663c61a47dSLukas 
6673c61a47dSLukas static PetscErrorCode PCSetFromOptions_HYPRE_ILU(PC pc, PetscOptionItems *PetscOptionsObject)
6683c61a47dSLukas {
6693c61a47dSLukas   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6703c61a47dSLukas   PetscBool flg;
6713c61a47dSLukas   PetscInt  indx;
6723c61a47dSLukas   PetscReal tmpdbl;
6733c61a47dSLukas   PetscBool tmp_truth;
6743c61a47dSLukas 
6753c61a47dSLukas   PetscFunctionBegin;
6763c61a47dSLukas   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ILU Options");
6773c61a47dSLukas 
6783c61a47dSLukas   /* ILU: ILU Type */
6793c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
6803c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetType, jac->hsolver, indx); }
6813c61a47dSLukas 
6823c61a47dSLukas   /* ILU: ILU iterative setup type*/
6833c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_iterative_setup_type", "Set ILU iterative setup type", "None", HYPREILUIterSetup, PETSC_STATIC_ARRAY_LENGTH(HYPREILUIterSetup), HYPREILUIterSetup[0], &indx, &flg));
6843c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupType, jac->hsolver, indx); }
6853c61a47dSLukas 
6863c61a47dSLukas   /* ILU: ILU iterative setup option*/
6873c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
6883c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupOption, jac->hsolver, indx); }
6893c61a47dSLukas 
6903c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
6913c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
6923c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupMaxIter, jac->hsolver, indx); }
6933c61a47dSLukas 
6943c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
6953c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
6963c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupTolerance, jac->hsolver, tmpdbl); }
6973c61a47dSLukas 
6983c61a47dSLukas   /* ILU: ILU Print Level */
6993c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
7003c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetPrintLevel, jac->hsolver, indx); }
7013c61a47dSLukas 
7023c61a47dSLukas   /* ILU: Logging */
7033c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
7043c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLogging, jac->hsolver, indx); }
7053c61a47dSLukas 
7063c61a47dSLukas   /* ILU: ILU Level */
7073c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
7083c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLevelOfFill, jac->hsolver, indx); }
7093c61a47dSLukas 
7103c61a47dSLukas   /* ILU: ILU Max NNZ per row */
7113c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
7123c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetMaxNnzPerRow, jac->hsolver, indx); }
7133c61a47dSLukas 
7143c61a47dSLukas   /* ILU: tolerance */
7153c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_tol", "Tolerance for ILU", "None", 0, &tmpdbl, &flg));
7163c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetTol, jac->hsolver, tmpdbl); }
7173c61a47dSLukas 
7183c61a47dSLukas   /* ILU: maximum iteration count */
7193c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
7203c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetMaxIter, jac->hsolver, indx); }
7213c61a47dSLukas 
7223c61a47dSLukas   /* ILU: drop threshold */
7233c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_drop_threshold", "Drop threshold for ILU", "None", 0, &tmpdbl, &flg));
7243c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetDropThreshold, jac->hsolver, tmpdbl); }
7253c61a47dSLukas 
7263c61a47dSLukas   /* ILU: Triangular Solve */
7273c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
7283c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetTriSolve, jac->hsolver, tmp_truth); }
7293c61a47dSLukas 
7303c61a47dSLukas   /* ILU: Lower Jacobi iteration */
7313c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
7323c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLowerJacobiIters, jac->hsolver, indx); }
7333c61a47dSLukas 
7343c61a47dSLukas   /* ILU: Upper Jacobi iteration */
7353c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
7363c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetUpperJacobiIters, jac->hsolver, indx); }
7373c61a47dSLukas 
7383c61a47dSLukas   /* ILU: local reordering */
7393c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
7403c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLocalReordering, jac->hsolver, tmp_truth); }
7413c61a47dSLukas 
7423c61a47dSLukas   PetscOptionsHeadEnd();
7433c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
7443c61a47dSLukas }
7453c61a47dSLukas 
7463c61a47dSLukas static PetscErrorCode PCView_HYPRE_ILU(PC pc, PetscViewer viewer)
7473c61a47dSLukas {
7483c61a47dSLukas   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
7493c61a47dSLukas   hypre_ParILUData *ilu_data = (hypre_ParILUData *)jac->hsolver;
7503c61a47dSLukas   PetscBool         iascii;
7513c61a47dSLukas   PetscInt          indx;
7523c61a47dSLukas   PetscReal         tmpdbl;
7533c61a47dSLukas   PetscReal        *tmpdbl3;
7543c61a47dSLukas 
7553c61a47dSLukas   PetscFunctionBegin;
7563c61a47dSLukas   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
7573c61a47dSLukas   if (iascii) {
7583c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ILU preconditioning\n"));
7593c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIluType", indx = hypre_ParILUDataIluType(ilu_data));
7603c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
7613c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLfil", indx = hypre_ParILUDataLfil(ilu_data));
7623c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
7633c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxIter", indx = hypre_ParILUDataMaxIter(ilu_data));
7643c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
7653c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxRowNnz", indx = hypre_ParILUDataMaxRowNnz(ilu_data));
7663c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
7673c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTriSolve", indx = hypre_ParILUDataTriSolve(ilu_data));
7683c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
7693c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTol", tmpdbl = hypre_ParILUDataTol(ilu_data));
7703c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", tmpdbl));
7713c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataDroptol", tmpdbl3 = hypre_ParILUDataDroptol(ilu_data));
7723c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e / %e / %e\n", tmpdbl3[0], tmpdbl3[1], tmpdbl3[2]));
7733c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataReorderingType", indx = hypre_ParILUDataReorderingType(ilu_data));
7743c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
7753c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLowerJacobiIters", indx = hypre_ParILUDataLowerJacobiIters(ilu_data));
7763c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
7773c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataUpperJacobiIters", indx = hypre_ParILUDataUpperJacobiIters(ilu_data));
7783c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
7793c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataPrintLevel", indx = hypre_ParILUDataPrintLevel(ilu_data));
7803c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
7813c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLogging", indx = hypre_ParILUDataLogging(ilu_data));
7823c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
7833c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupType", indx = hypre_ParILUDataIterativeSetupType(ilu_data));
7843c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
7853c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupOption", indx = hypre_ParILUDataIterativeSetupOption(ilu_data));
7863c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
7873c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupMaxIter", indx = hypre_ParILUDataIterativeSetupMaxIter(ilu_data));
7883c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
7893c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupTolerance", tmpdbl = hypre_ParILUDataIterativeSetupTolerance(ilu_data));
7903c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", tmpdbl));
7913c61a47dSLukas   }
7923c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
7933c61a47dSLukas }
7943c61a47dSLukas 
795d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
796d71ae5a4SJacob Faibussowitsch {
797db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
7988bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
799db966c6cSHong Zhang 
800db966c6cSHong Zhang   PetscFunctionBegin;
801d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
8029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
803792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
8048bf83915SBarry Smith 
8059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
8068bf83915SBarry Smith   if (flag) {
8078bf83915SBarry Smith     PetscMPIInt size;
8088bf83915SBarry Smith 
8099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
8107827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
811792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
8128bf83915SBarry Smith   }
8138bf83915SBarry Smith 
8149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
8158bf83915SBarry Smith   if (flag) {
8168bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
817792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
8188bf83915SBarry Smith   }
819d0609cedSBarry Smith   PetscOptionsHeadEnd();
8203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
821db966c6cSHong Zhang }
822db966c6cSHong Zhang 
823d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
824d71ae5a4SJacob Faibussowitsch {
825db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
826db966c6cSHong Zhang   PetscBool iascii;
827db966c6cSHong Zhang 
828db966c6cSHong Zhang   PetscFunctionBegin;
8299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
830db966c6cSHong Zhang   if (iascii) {
8319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
832db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
83363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
834db966c6cSHong Zhang     } else {
8359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
836db966c6cSHong Zhang     }
8379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
83863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
839db966c6cSHong Zhang   }
8403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
841db966c6cSHong Zhang }
842db966c6cSHong Zhang 
843d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
844d71ae5a4SJacob Faibussowitsch {
84516d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
846f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
84716d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
84816d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
84916d9e3a6SLisandro Dalcin 
85016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
8519566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
8529566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
8539566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
8549566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
85516d9e3a6SLisandro Dalcin 
856792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
857792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
858792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
85916d9e3a6SLisandro Dalcin 
8609371c9d4SSatish Balay   PetscStackCallExternalVoid(
8619371c9d4SSatish Balay     "Hypre Transpose solve", do {
8625f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
8635f80ce2aSJacob Faibussowitsch       if (hierr) {
86416d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
8655f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
86685245615SPierre Jolivet         HYPRE_ClearAllErrors();
8675f80ce2aSJacob Faibussowitsch       }
8685f80ce2aSJacob Faibussowitsch     } while (0));
86916d9e3a6SLisandro Dalcin 
8709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
8719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
8723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
87316d9e3a6SLisandro Dalcin }
87416d9e3a6SLisandro Dalcin 
875d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
876d71ae5a4SJacob Faibussowitsch {
877db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
878db6f9c32SMark Adams   PetscBool flag;
879db6f9c32SMark Adams 
880db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
881db6f9c32SMark Adams   PetscFunctionBegin;
882db6f9c32SMark Adams   if (jac->spgemm_type) {
8839566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
88428b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
8853ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
886db6f9c32SMark Adams   } else {
8879566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
888db6f9c32SMark Adams   }
8899566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
890db6f9c32SMark Adams   if (flag) {
891792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
8923ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
893db6f9c32SMark Adams   }
8949566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
895db6f9c32SMark Adams   if (flag) {
896792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
8973ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
898db6f9c32SMark Adams   }
899db6f9c32SMark Adams   jac->spgemm_type = NULL;
9002d6c3ceeSStefano Zampini   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEMM type %s; Choices are cusparse, hypre", name);
901db6f9c32SMark Adams #endif
902db6f9c32SMark Adams }
903db6f9c32SMark Adams 
904d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
905d71ae5a4SJacob Faibussowitsch {
906db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
907db6f9c32SMark Adams 
908db6f9c32SMark Adams   PetscFunctionBegin;
909db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
910db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
911db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
912db6f9c32SMark Adams #endif
9133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
914db6f9c32SMark Adams }
915db6f9c32SMark Adams 
91616d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
9170f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
91816d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
91965de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
9203c61a47dSLukas static const char *HYPREBoomerAMGSmoothType[] = {"ILU", "Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
9219371c9d4SSatish 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"};
9229371c9d4SSatish 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"};
923d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
924d71ae5a4SJacob Faibussowitsch {
92516d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
92622e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
927ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
92873dcfd97SStefano Zampini   PetscReal   tmpdbl, twodbl[2];
929589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
930db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
93116d9e3a6SLisandro Dalcin 
93216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
933d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
9349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
93516d9e3a6SLisandro Dalcin   if (flg) {
9364336a9eeSBarry Smith     jac->cycletype = indx + 1;
937792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
93816d9e3a6SLisandro Dalcin   }
93952ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg, 2));
94052ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
94152ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg, 1));
94252ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
94352ce0ab5SPierre 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));
94452ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
94522e51d31SStefano Zampini   bs = 1;
94648a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
9479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
94848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
94916d9e3a6SLisandro Dalcin 
95052ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg, 0.0));
95152ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
95216d9e3a6SLisandro Dalcin 
95352ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg, 0));
95452ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
9550f1074feSSatish Balay 
9569566063dSJacob 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));
957792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
9580f1074feSSatish Balay 
95952ce0ab5SPierre 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));
96052ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
9610f1074feSSatish Balay 
96252ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg, 0.0));
96352ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
96452ce0ab5SPierre Jolivet   PetscCall(PetscOptionsRangeReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg, 0.0, 1.0));
96552ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
96616d9e3a6SLisandro Dalcin 
96716d9e3a6SLisandro Dalcin   /* Grid sweeps */
9689566063dSJacob 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));
96916d9e3a6SLisandro Dalcin   if (flg) {
970792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
97116d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
97216d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
9730f1074feSSatish Balay     jac->gridsweeps[1] = indx;
9740f1074feSSatish Balay     /*defaults coarse to 1 */
9750f1074feSSatish Balay     jac->gridsweeps[2] = 1;
97616d9e3a6SLisandro Dalcin   }
9779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
97848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
9799566063dSJacob 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));
98048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
9819566063dSJacob 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));
98248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
9839566063dSJacob 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));
98448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
9859566063dSJacob 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));
98648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
9879566063dSJacob 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));
98848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
9899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
99016d9e3a6SLisandro Dalcin   if (flg) {
991792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
9920f1074feSSatish Balay     jac->gridsweeps[0] = indx;
99316d9e3a6SLisandro Dalcin   }
9949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
99516d9e3a6SLisandro Dalcin   if (flg) {
996792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
9970f1074feSSatish Balay     jac->gridsweeps[1] = indx;
99816d9e3a6SLisandro Dalcin   }
9999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
100016d9e3a6SLisandro Dalcin   if (flg) {
1001792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
10020f1074feSSatish Balay     jac->gridsweeps[2] = indx;
100316d9e3a6SLisandro Dalcin   }
100416d9e3a6SLisandro Dalcin 
10056a251517SEike Mueller   /* Smooth type */
1006dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
10076a251517SEike Mueller   if (flg) {
10086a251517SEike Mueller     jac->smoothtype = indx;
10093c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 5);
10108131ecf7SEike Mueller     jac->smoothnumlevels = 25;
1011792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
10128131ecf7SEike Mueller   }
10138131ecf7SEike Mueller 
10148131ecf7SEike Mueller   /* Number of smoothing levels */
10159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
10168131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
10178131ecf7SEike Mueller     jac->smoothnumlevels = indx;
1018792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
10196a251517SEike Mueller   }
10206a251517SEike Mueller 
10213c61a47dSLukas   /* Smooth num sweeps */
10223c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_sweeps", "Set number of smoother sweeps", "None", 1, &indx, &flg));
10233c61a47dSLukas   if (flg && indx > 0) {
10243c61a47dSLukas     jac->smoothsweeps = indx;
10253c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumSweeps, jac->hsolver, indx);
10263c61a47dSLukas   }
10273c61a47dSLukas 
10283c61a47dSLukas   /* ILU: ILU Type */
10293c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
10303c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUType, jac->hsolver, indx); }
10313c61a47dSLukas 
10323c61a47dSLukas   /* ILU: ILU iterative setup type*/
10333c61a47dSLukas   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));
10343c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupType, jac->hsolver, indx); }
10353c61a47dSLukas 
10363c61a47dSLukas   /* ILU: ILU iterative setup option*/
10373c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
10383c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupOption, jac->hsolver, indx); }
10393c61a47dSLukas 
10403c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
10413c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
10423c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupMaxIter, jac->hsolver, indx); }
10433c61a47dSLukas 
10443c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
10453c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
10463c61a47dSLukas   if (flg) { PetscCallExternal(hypre_BoomerAMGSetILUIterSetupTolerance, jac->hsolver, tmpdbl); }
10473c61a47dSLukas 
10483c61a47dSLukas   /* ILU: ILU Print Level */
10493c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
10503c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, indx); }
10513c61a47dSLukas 
10523c61a47dSLukas   /* ILU: Logging */
10533c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
10543c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetLogging, jac->hsolver, indx); }
10553c61a47dSLukas 
10563c61a47dSLukas   /* ILU: ILU Level */
10573c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
10583c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULevel, jac->hsolver, indx); }
10593c61a47dSLukas 
10603c61a47dSLukas   /* ILU: ILU Max NNZ per row */
10613c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
10623c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUMaxRowNnz, jac->hsolver, indx); }
10633c61a47dSLukas 
10643c61a47dSLukas   /* ILU: maximum iteration count */
10653c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
10663c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUMaxIter, jac->hsolver, indx); }
10673c61a47dSLukas 
10683c61a47dSLukas   /* ILU: drop threshold */
10693c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_drop_tol", "Drop tolerance for ILU", "None", 0, &tmpdbl, &flg));
10703c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUDroptol, jac->hsolver, tmpdbl); }
10713c61a47dSLukas 
10723c61a47dSLukas   /* ILU: Triangular Solve */
10733c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
10743c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUTriSolve, jac->hsolver, tmp_truth); }
10753c61a47dSLukas 
10763c61a47dSLukas   /* ILU: Lower Jacobi iteration */
10773c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
10783c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULowerJacobiIters, jac->hsolver, indx); }
10793c61a47dSLukas 
10803c61a47dSLukas   /* ILU: Upper Jacobi iteration */
10813c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
10823c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUUpperJacobiIters, jac->hsolver, indx); }
10833c61a47dSLukas 
10843c61a47dSLukas   /* ILU: local reordering */
10853c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
10863c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULocalReordering, jac->hsolver, tmp_truth); }
10873c61a47dSLukas 
10881810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
10899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
10903c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
10911810e44eSEike Mueller     jac->eu_level = indx;
1092792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
10931810e44eSEike Mueller   }
10941810e44eSEike Mueller 
10951810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
109673dcfd97SStefano Zampini   PetscReal droptolerance;
10979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
10983c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
10991810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
1100792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
11011810e44eSEike Mueller   }
11021810e44eSEike Mueller 
11031810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
11049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
11053c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11061810e44eSEike Mueller     jac->eu_bj = tmp_truth;
1107792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
11081810e44eSEike Mueller   }
11091810e44eSEike Mueller 
111016d9e3a6SLisandro Dalcin   /* Relax type */
1111dd39110bSPierre 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));
111216d9e3a6SLisandro Dalcin   if (flg) {
11130f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
1114792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
11150f1074feSSatish Balay     /* by default, coarse type set to 9 */
11160f1074feSSatish Balay     jac->relaxtype[2] = 9;
1117792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
111816d9e3a6SLisandro Dalcin   }
1119dd39110bSPierre 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));
112016d9e3a6SLisandro Dalcin   if (flg) {
112116d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
1122792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
112316d9e3a6SLisandro Dalcin   }
1124dd39110bSPierre 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));
112516d9e3a6SLisandro Dalcin   if (flg) {
11260f1074feSSatish Balay     jac->relaxtype[1] = indx;
1127792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
112816d9e3a6SLisandro Dalcin   }
1129dd39110bSPierre 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));
113016d9e3a6SLisandro Dalcin   if (flg) {
11310f1074feSSatish Balay     jac->relaxtype[2] = indx;
1132792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
113316d9e3a6SLisandro Dalcin   }
113416d9e3a6SLisandro Dalcin 
113516d9e3a6SLisandro Dalcin   /* Relaxation Weight */
11369566063dSJacob 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));
113716d9e3a6SLisandro Dalcin   if (flg) {
1138792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
113916d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
114016d9e3a6SLisandro Dalcin   }
114116d9e3a6SLisandro Dalcin 
114216d9e3a6SLisandro Dalcin   n         = 2;
114316d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
11449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
114516d9e3a6SLisandro Dalcin   if (flg) {
11460fdf79fbSJacob 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);
114716d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1148792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
114916d9e3a6SLisandro Dalcin   }
115016d9e3a6SLisandro Dalcin 
115116d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
11529566063dSJacob 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));
115316d9e3a6SLisandro Dalcin   if (flg) {
1154792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
115516d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
115616d9e3a6SLisandro Dalcin   }
115716d9e3a6SLisandro Dalcin 
115816d9e3a6SLisandro Dalcin   n         = 2;
115916d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
11609566063dSJacob 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));
116116d9e3a6SLisandro Dalcin   if (flg) {
11620fdf79fbSJacob 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);
116316d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1164792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
116516d9e3a6SLisandro Dalcin   }
116616d9e3a6SLisandro Dalcin 
116716d9e3a6SLisandro Dalcin   /* the Relax Order */
11689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
116916d9e3a6SLisandro Dalcin 
11708afaa268SBarry Smith   if (flg && tmp_truth) {
117116d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
1172792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
117316d9e3a6SLisandro Dalcin   }
1174dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
117516d9e3a6SLisandro Dalcin   if (flg) {
117616d9e3a6SLisandro Dalcin     jac->measuretype = indx;
1177792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
117816d9e3a6SLisandro Dalcin   }
11790f1074feSSatish Balay   /* update list length 3/07 */
1180dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
118116d9e3a6SLisandro Dalcin   if (flg) {
118216d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
1183792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
118416d9e3a6SLisandro Dalcin   }
11850f1074feSSatish Balay 
11869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
118748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
11889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
118948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
1190db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
1191db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
1192dd39110bSPierre 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));
11932d6c3ceeSStefano Zampini   #if defined(PETSC_HAVE_HYPRE_DEVICE)
1194db6f9c32SMark Adams   if (!flg) indx = 0;
11959566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
11962d6c3ceeSStefano Zampini   #else
11972d6c3ceeSStefano Zampini   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, "hypre"));
11982d6c3ceeSStefano Zampini   #endif
1199db6f9c32SMark Adams #endif
1200589dcaf0SStefano Zampini   /* AIR */
1201589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
12029566063dSJacob 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));
1203792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1204589dcaf0SStefano Zampini   if (jac->Rtype) {
120519be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
120619be502cSAlexander     char       *prerelax[256];
120719be502cSAlexander     char       *postrelax[256];
120819be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
120919be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
121019be502cSAlexander     PetscBool   matchF, matchC, matchA;
121119be502cSAlexander 
1212589dcaf0SStefano 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 */
1213589dcaf0SStefano Zampini 
12149566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
1215792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1216589dcaf0SStefano Zampini 
12179566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
1218792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1219589dcaf0SStefano Zampini 
12209566063dSJacob 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));
1221792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1222589dcaf0SStefano Zampini 
12239566063dSJacob 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));
1224792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
122519be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
122619be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
122719be502cSAlexander     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");
122819be502cSAlexander     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");
122919be502cSAlexander 
123019be502cSAlexander     grid_relax_points[0]    = NULL;
123119be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
123219be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
123319be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
123419be502cSAlexander     grid_relax_points[3][0] = 0;
123519be502cSAlexander 
123619be502cSAlexander     // set down relax scheme
123719be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
123819be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
123919be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
124019be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
124119be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
124219be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
124319be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
124419be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
124519be502cSAlexander     }
124619be502cSAlexander 
124719be502cSAlexander     // set up relax scheme
124819be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
124919be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
125019be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
125119be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
125219be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
125319be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
125419be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
125519be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
125619be502cSAlexander     }
125719be502cSAlexander 
125819be502cSAlexander     // set coarse relax scheme
125919be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
126019be502cSAlexander 
126119be502cSAlexander     // Pass relax schemes to hypre
126219be502cSAlexander     PetscCallExternal(HYPRE_BoomerAMGSetGridRelaxPoints, jac->hsolver, grid_relax_points);
126319be502cSAlexander 
126419be502cSAlexander     // cleanup memory
126519be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
126619be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1267589dcaf0SStefano Zampini   }
1268589dcaf0SStefano Zampini #endif
1269589dcaf0SStefano Zampini 
1270ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
127163a3b9bcSJacob 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);
1272ecae95adSPierre Jolivet #endif
1273ecae95adSPierre Jolivet 
12740f1074feSSatish Balay   /* new 3/07 */
1275dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1276589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1277589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1278792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
12790f1074feSSatish Balay   }
12800f1074feSSatish Balay 
12819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
128216d9e3a6SLisandro Dalcin   if (flg) {
1283b96a4a96SBarry Smith     level = 3;
12849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
12852fa5cd67SKarl Rupp 
1286b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1287792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
12882ae77aedSBarry Smith   }
12892ae77aedSBarry Smith 
12909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
12912ae77aedSBarry Smith   if (flg) {
1292b96a4a96SBarry Smith     level = 3;
12939566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
12942fa5cd67SKarl Rupp 
1295b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1296792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
129716d9e3a6SLisandro Dalcin   }
12988f87f92bSBarry Smith 
12999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
13008f87f92bSBarry Smith   if (flg && tmp_truth) {
13018f87f92bSBarry Smith     PetscInt tmp_int;
13029566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
13038f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1304792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1305792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1306792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1307792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
13088f87f92bSBarry Smith   }
13098f87f92bSBarry Smith 
13109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1311792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1312589dcaf0SStefano Zampini 
1313589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1314dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1315589dcaf0SStefano Zampini   if (flg) {
1316589dcaf0SStefano Zampini     jac->symt = indx;
1317792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1318589dcaf0SStefano Zampini   }
1319589dcaf0SStefano Zampini 
1320d0609cedSBarry Smith   PetscOptionsHeadEnd();
13213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
132216d9e3a6SLisandro Dalcin }
132316d9e3a6SLisandro Dalcin 
1324d71ae5a4SJacob 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)
1325d71ae5a4SJacob Faibussowitsch {
132616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13272cf14000SStefano Zampini   HYPRE_Int oits;
132816d9e3a6SLisandro Dalcin 
132916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
13309566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1331792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1332792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
133316d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
13349566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
133516d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1336792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
13374d0a8057SBarry Smith   *outits = oits;
13384d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
13394d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1340792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1341792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
13423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134316d9e3a6SLisandro Dalcin }
134416d9e3a6SLisandro Dalcin 
1345d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1346d71ae5a4SJacob Faibussowitsch {
134716d9e3a6SLisandro Dalcin   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
13483c61a47dSLukas   hypre_ParAMGData *amg_data = (hypre_ParAMGData *)jac->hsolver;
1349ace3abfcSBarry Smith   PetscBool         iascii;
13503c61a47dSLukas   PetscInt          indx;
13513c61a47dSLukas   PetscReal         val;
135216d9e3a6SLisandro Dalcin 
135316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
13549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
135516d9e3a6SLisandro Dalcin   if (iascii) {
13569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
13579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
135863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
135963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
13609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
13619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
13629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
136363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
136448a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
136563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
136663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
13670f1074feSSatish Balay 
13689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
136916d9e3a6SLisandro Dalcin 
137063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
137163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
137263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
137316d9e3a6SLisandro Dalcin 
13749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
13759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
13769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
137716d9e3a6SLisandro Dalcin 
13789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
13799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
138016d9e3a6SLisandro Dalcin 
138119be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
138219be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
138319be502cSAlexander 
138416d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
13859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
138616d9e3a6SLisandro Dalcin     } else {
13879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
138816d9e3a6SLisandro Dalcin     }
13896a251517SEike Mueller     if (jac->smoothtype != -1) {
13909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
139163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
13923c61a47dSLukas       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num sweeps    %" PetscInt_FMT "\n", jac->smoothsweeps));
13933c61a47dSLukas       if (jac->smoothtype == 0) {
13943c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUType", indx = hypre_ParAMGDataILUType(amg_data));
13953c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
13963c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULevel", indx = hypre_ParAMGDataILULevel(amg_data));
13973c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
13983c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxIter", indx = hypre_ParAMGDataILUMaxIter(amg_data));
13993c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
14003c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxRowNnz", indx = hypre_ParAMGDataILUMaxRowNnz(amg_data));
14013c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
14023c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUTriSolve", indx = hypre_ParAMGDataILUTriSolve(amg_data));
14033c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
14043c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataTol", val = hypre_ParAMGDataTol(amg_data));
14053c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", val));
14063c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUDroptol", val = hypre_ParAMGDataILUDroptol(amg_data));
14073c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e\n", val));
14083c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULocalReordering", indx = hypre_ParAMGDataILULocalReordering(amg_data));
14093c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
14103c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULowerJacobiIters", indx = hypre_ParAMGDataILULowerJacobiIters(amg_data));
14113c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
14123c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUUpperJacobiIters", indx = hypre_ParAMGDataILUUpperJacobiIters(amg_data));
14133c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
14143c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataPrintLevel", indx = hypre_ParAMGDataPrintLevel(amg_data));
14153c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
14163c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataLogging", indx = hypre_ParAMGDataLogging(amg_data));
14173c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
14183c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupType", indx = hypre_ParAMGDataILUIterSetupType(amg_data));
14193c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
14203c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupOption", indx = hypre_ParAMGDataILUIterSetupOption(amg_data));
14213c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
14223c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupMaxIter", indx = hypre_ParAMGDataILUIterSetupMaxIter(amg_data));
14233c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
14243c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupTolerance", val = hypre_ParAMGDataILUIterSetupTolerance(amg_data));
14253c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", val));
14263c61a47dSLukas       }
14277e352d70SEike Mueller     } else {
14289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
14291810e44eSEike Mueller     }
14301810e44eSEike Mueller     if (jac->smoothtype == 3) {
143163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
14329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
143363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
14346a251517SEike Mueller     }
14359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
14369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
14379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
143848a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
14395272c319SBarry Smith     if (jac->vec_interp_variant) {
144063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
144163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
14429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
14438f87f92bSBarry Smith     }
144448a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1445db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
14469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
14472d6c3ceeSStefano Zampini #else
14482d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1449db6f9c32SMark Adams #endif
1450589dcaf0SStefano Zampini     /* AIR */
1451589dcaf0SStefano Zampini     if (jac->Rtype) {
145263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
14539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
14549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
14559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
145663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1457589dcaf0SStefano Zampini     }
145816d9e3a6SLisandro Dalcin   }
14593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146016d9e3a6SLisandro Dalcin }
146116d9e3a6SLisandro Dalcin 
1462d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1463d71ae5a4SJacob Faibussowitsch {
146416d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
14654ddd07fcSJed Brown   PetscInt    indx;
1466ace3abfcSBarry Smith   PetscBool   flag;
146716d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
146816d9e3a6SLisandro Dalcin 
146916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1470d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
14719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
14729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1473792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
147416d9e3a6SLisandro Dalcin 
14759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1476792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
147716d9e3a6SLisandro Dalcin 
14789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1479792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
148016d9e3a6SLisandro Dalcin 
14819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1482792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
148316d9e3a6SLisandro Dalcin 
14849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1485792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
148616d9e3a6SLisandro Dalcin 
1487dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
148816d9e3a6SLisandro Dalcin   if (flag) {
148916d9e3a6SLisandro Dalcin     jac->symt = indx;
1490792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
149116d9e3a6SLisandro Dalcin   }
149216d9e3a6SLisandro Dalcin 
1493d0609cedSBarry Smith   PetscOptionsHeadEnd();
14943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
149516d9e3a6SLisandro Dalcin }
149616d9e3a6SLisandro Dalcin 
1497d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1498d71ae5a4SJacob Faibussowitsch {
149916d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1500ace3abfcSBarry Smith   PetscBool   iascii;
1501feb237baSPierre Jolivet   const char *symt = 0;
150216d9e3a6SLisandro Dalcin 
150316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
15049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
150516d9e3a6SLisandro Dalcin   if (iascii) {
15069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
150763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
15089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
15099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
15109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
15119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
15129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
15132fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
15142fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
15152fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
151663a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
15179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
151816d9e3a6SLisandro Dalcin   }
15193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
152016d9e3a6SLisandro Dalcin }
1521f1580f4eSBarry Smith 
1522d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1523d71ae5a4SJacob Faibussowitsch {
15244cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15254cb006feSStefano Zampini   PetscInt  n;
15264cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
15274cb006feSStefano Zampini 
15284cb006feSStefano Zampini   PetscFunctionBegin;
1529d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
15309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1531792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
15329566063dSJacob 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));
1533792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
15349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1535792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
15369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1537792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
15389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
15399566063dSJacob 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));
15409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
15419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
154248a46eb9SPierre 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);
15439566063dSJacob 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));
15444cb006feSStefano Zampini   n = 5;
15459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
15464cb006feSStefano Zampini   if (flag || flag2) {
1547792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1548863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1549863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
15509371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1551a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
15524cb006feSStefano Zampini   }
15539566063dSJacob 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));
15544cb006feSStefano Zampini   n = 5;
15559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
15564cb006feSStefano Zampini   if (flag || flag2) {
1557792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1558863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1559863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
15609371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1561a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
15624cb006feSStefano Zampini   }
15639566063dSJacob 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));
156423df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1565792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
156623df4f25SStefano Zampini   }
1567d0609cedSBarry Smith   PetscOptionsHeadEnd();
15683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15694cb006feSStefano Zampini }
15704cb006feSStefano Zampini 
1571d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1572d71ae5a4SJacob Faibussowitsch {
15734cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15744cb006feSStefano Zampini   PetscBool iascii;
15754cb006feSStefano Zampini 
15764cb006feSStefano Zampini   PetscFunctionBegin;
15779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
15784cb006feSStefano Zampini   if (iascii) {
15799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
158063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
158163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
158263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
158363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
158463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
158563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
158663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
15874cb006feSStefano Zampini     if (jac->alpha_Poisson) {
15889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
15894cb006feSStefano Zampini     } else {
15909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
15914cb006feSStefano Zampini     }
159263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
159363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
159463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
159563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
159663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
159763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
15984cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
15994cb006feSStefano Zampini       if (jac->beta_Poisson) {
16009566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
16014cb006feSStefano Zampini       } else {
16029566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
16034cb006feSStefano Zampini       }
160463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
160563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
160663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
160763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
160863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
160963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
161048a46eb9SPierre 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));
161123df4f25SStefano Zampini     } else {
16129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
16134cb006feSStefano Zampini     }
16144cb006feSStefano Zampini   }
16153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16164cb006feSStefano Zampini }
16174cb006feSStefano Zampini 
1618d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1619d71ae5a4SJacob Faibussowitsch {
1620863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1621863406b8SStefano Zampini   PetscInt  n;
1622863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1623863406b8SStefano Zampini 
1624863406b8SStefano Zampini   PetscFunctionBegin;
1625d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
16269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1627792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
16289566063dSJacob 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));
1629792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
16309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1631792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
16329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1633792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
16349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
16359566063dSJacob 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));
16369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
16379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
163848a46eb9SPierre 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);
16399566063dSJacob 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));
1640863406b8SStefano Zampini   n = 5;
16419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
16429566063dSJacob 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));
1643863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1644792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1645863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1646863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1647863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
16489371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1649a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1650863406b8SStefano Zampini   }
16519566063dSJacob 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));
1652863406b8SStefano Zampini   n = 5;
16539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1654863406b8SStefano Zampini   if (flag || flag2) {
1655792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1656863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1657863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
16589371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1659a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1660863406b8SStefano Zampini   }
1661d0609cedSBarry Smith   PetscOptionsHeadEnd();
16623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1663863406b8SStefano Zampini }
1664863406b8SStefano Zampini 
1665d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1666d71ae5a4SJacob Faibussowitsch {
1667863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1668863406b8SStefano Zampini   PetscBool iascii;
1669863406b8SStefano Zampini 
1670863406b8SStefano Zampini   PetscFunctionBegin;
16719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1672863406b8SStefano Zampini   if (iascii) {
16739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
167463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
167563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
167663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
167763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
167863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
167963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
168063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
16819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
168263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
168363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
168463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
168563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
168663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
168763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
168863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
16899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
169063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
169163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
169263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
169363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
169463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
169563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1696863406b8SStefano Zampini   }
16973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1698863406b8SStefano Zampini }
1699863406b8SStefano Zampini 
1700d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1701d71ae5a4SJacob Faibussowitsch {
17024cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17035ac14e1cSStefano Zampini   PetscBool ishypre;
17044cb006feSStefano Zampini 
17054cb006feSStefano Zampini   PetscFunctionBegin;
17069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
17075ac14e1cSStefano Zampini   if (ishypre) {
17089566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
17099566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17105ac14e1cSStefano Zampini     jac->G = G;
17115ac14e1cSStefano Zampini   } else {
17129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17139566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
17145ac14e1cSStefano Zampini   }
17153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17164cb006feSStefano Zampini }
17174cb006feSStefano Zampini 
17184cb006feSStefano Zampini /*@
1719f1580f4eSBarry Smith   PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
17204cb006feSStefano Zampini 
1721c3339decSBarry Smith   Collective
17224cb006feSStefano Zampini 
17234cb006feSStefano Zampini   Input Parameters:
17244cb006feSStefano Zampini + pc - the preconditioning context
17254cb006feSStefano Zampini - G  - the discrete gradient
17264cb006feSStefano Zampini 
17274cb006feSStefano Zampini   Level: intermediate
17284cb006feSStefano Zampini 
172995452b02SPatrick Sanan   Notes:
173095452b02SPatrick Sanan   G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1731147403d9SBarry Smith 
1732863406b8SStefano 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
17334cb006feSStefano Zampini 
1734feefa0e1SJacob Faibussowitsch   Developer Notes:
1735f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1736f1580f4eSBarry Smith 
1737562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
17384cb006feSStefano Zampini @*/
1739d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1740d71ae5a4SJacob Faibussowitsch {
17414cb006feSStefano Zampini   PetscFunctionBegin;
17424cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17434cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
17444cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1745cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
17463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17474cb006feSStefano Zampini }
17484cb006feSStefano Zampini 
1749d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1750d71ae5a4SJacob Faibussowitsch {
1751863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17525ac14e1cSStefano Zampini   PetscBool ishypre;
1753863406b8SStefano Zampini 
1754863406b8SStefano Zampini   PetscFunctionBegin;
17559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
17565ac14e1cSStefano Zampini   if (ishypre) {
17579566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
17589566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
17595ac14e1cSStefano Zampini     jac->C = C;
17605ac14e1cSStefano Zampini   } else {
17619566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
17629566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
17635ac14e1cSStefano Zampini   }
17643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1765863406b8SStefano Zampini }
1766863406b8SStefano Zampini 
1767863406b8SStefano Zampini /*@
17686e415bd2SNuno Nobre   PCHYPRESetDiscreteCurl - Set discrete curl matrix for `PCHYPRE` type of ads
1769863406b8SStefano Zampini 
1770c3339decSBarry Smith   Collective
1771863406b8SStefano Zampini 
1772863406b8SStefano Zampini   Input Parameters:
1773863406b8SStefano Zampini + pc - the preconditioning context
1774863406b8SStefano Zampini - C  - the discrete curl
1775863406b8SStefano Zampini 
1776863406b8SStefano Zampini   Level: intermediate
1777863406b8SStefano Zampini 
177895452b02SPatrick Sanan   Notes:
177995452b02SPatrick Sanan   C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1780147403d9SBarry Smith 
17816e415bd2SNuno 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
1782863406b8SStefano Zampini 
1783feefa0e1SJacob Faibussowitsch   Developer Notes:
1784f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1785f1580f4eSBarry Smith 
1786f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1787f1580f4eSBarry Smith 
1788562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1789863406b8SStefano Zampini @*/
1790d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1791d71ae5a4SJacob Faibussowitsch {
1792863406b8SStefano Zampini   PetscFunctionBegin;
1793863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1794863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1795863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1796cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
17973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1798863406b8SStefano Zampini }
1799863406b8SStefano Zampini 
1800d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1801d71ae5a4SJacob Faibussowitsch {
18026bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18036bf688a0SCe Qin   PetscBool ishypre;
18046bf688a0SCe Qin   PetscInt  i;
18056bf688a0SCe Qin 
18064d86920dSPierre Jolivet   PetscFunctionBegin;
18079566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
18089566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
18096bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
18109566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
18119566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
18126bf688a0SCe Qin   }
18136bf688a0SCe Qin 
18146bf688a0SCe Qin   jac->dim = dim;
18156bf688a0SCe Qin   if (RT_PiFull) {
18169566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
18176bf688a0SCe Qin     if (ishypre) {
18189566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
18196bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
18206bf688a0SCe Qin     } else {
18219566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
18226bf688a0SCe Qin     }
18236bf688a0SCe Qin   }
18246bf688a0SCe Qin   if (RT_Pi) {
18256bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18266bf688a0SCe Qin       if (RT_Pi[i]) {
18279566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
18286bf688a0SCe Qin         if (ishypre) {
18299566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
18306bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
18316bf688a0SCe Qin         } else {
18329566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
18336bf688a0SCe Qin         }
18346bf688a0SCe Qin       }
18356bf688a0SCe Qin     }
18366bf688a0SCe Qin   }
18376bf688a0SCe Qin   if (ND_PiFull) {
18389566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
18396bf688a0SCe Qin     if (ishypre) {
18409566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
18416bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
18426bf688a0SCe Qin     } else {
18439566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
18446bf688a0SCe Qin     }
18456bf688a0SCe Qin   }
18466bf688a0SCe Qin   if (ND_Pi) {
18476bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18486bf688a0SCe Qin       if (ND_Pi[i]) {
18499566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
18506bf688a0SCe Qin         if (ishypre) {
18519566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
18526bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
18536bf688a0SCe Qin         } else {
18549566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
18556bf688a0SCe Qin         }
18566bf688a0SCe Qin       }
18576bf688a0SCe Qin     }
18586bf688a0SCe Qin   }
18593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18606bf688a0SCe Qin }
18616bf688a0SCe Qin 
18626bf688a0SCe Qin /*@
1863f1580f4eSBarry Smith   PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
18646bf688a0SCe Qin 
1865c3339decSBarry Smith   Collective
18666bf688a0SCe Qin 
18676bf688a0SCe Qin   Input Parameters:
18686bf688a0SCe Qin + pc        - the preconditioning context
18692fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
18702fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
18712fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
18722fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
18736bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
18746bf688a0SCe Qin 
1875f1580f4eSBarry Smith   Level: intermediate
1876f1580f4eSBarry Smith 
187795452b02SPatrick Sanan   Notes:
187895452b02SPatrick Sanan   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1879147403d9SBarry Smith 
18806bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1881147403d9SBarry Smith 
1882feefa0e1SJacob Faibussowitsch   Developer Notes:
1883f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
18846bf688a0SCe Qin 
1885562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`
18866bf688a0SCe Qin @*/
1887d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1888d71ae5a4SJacob Faibussowitsch {
18896bf688a0SCe Qin   PetscInt i;
18906bf688a0SCe Qin 
18916bf688a0SCe Qin   PetscFunctionBegin;
18926bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
18936bf688a0SCe Qin   if (RT_PiFull) {
18946bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
18956bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
18966bf688a0SCe Qin   }
18976bf688a0SCe Qin   if (RT_Pi) {
18984f572ea9SToby Isaac     PetscAssertPointer(RT_Pi, 4);
18996bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19006bf688a0SCe Qin       if (RT_Pi[i]) {
19016bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
19026bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
19036bf688a0SCe Qin       }
19046bf688a0SCe Qin     }
19056bf688a0SCe Qin   }
19066bf688a0SCe Qin   if (ND_PiFull) {
19076bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
19086bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
19096bf688a0SCe Qin   }
19106bf688a0SCe Qin   if (ND_Pi) {
19114f572ea9SToby Isaac     PetscAssertPointer(ND_Pi, 6);
19126bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19136bf688a0SCe Qin       if (ND_Pi[i]) {
19146bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
19156bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
19166bf688a0SCe Qin       }
19176bf688a0SCe Qin     }
19186bf688a0SCe Qin   }
1919cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
19203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19216bf688a0SCe Qin }
19226bf688a0SCe Qin 
1923d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1924d71ae5a4SJacob Faibussowitsch {
19254cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
19265ac14e1cSStefano Zampini   PetscBool ishypre;
19274cb006feSStefano Zampini 
19284cb006feSStefano Zampini   PetscFunctionBegin;
19299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
19305ac14e1cSStefano Zampini   if (ishypre) {
19315ac14e1cSStefano Zampini     if (isalpha) {
19329566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
19339566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
19345ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
19355ac14e1cSStefano Zampini     } else {
19365ac14e1cSStefano Zampini       if (A) {
19379566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
19385ac14e1cSStefano Zampini       } else {
19395ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
19405ac14e1cSStefano Zampini       }
19419566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
19425ac14e1cSStefano Zampini       jac->beta_Poisson = A;
19435ac14e1cSStefano Zampini     }
19445ac14e1cSStefano Zampini   } else {
19455ac14e1cSStefano Zampini     if (isalpha) {
19469566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
19479566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
19485ac14e1cSStefano Zampini     } else {
19495ac14e1cSStefano Zampini       if (A) {
19509566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
19519566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
19525ac14e1cSStefano Zampini       } else {
19539566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
19545ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
19555ac14e1cSStefano Zampini       }
19565ac14e1cSStefano Zampini     }
19575ac14e1cSStefano Zampini   }
19583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19594cb006feSStefano Zampini }
19604cb006feSStefano Zampini 
19614cb006feSStefano Zampini /*@
1962f1580f4eSBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
19634cb006feSStefano Zampini 
1964c3339decSBarry Smith   Collective
19654cb006feSStefano Zampini 
19664cb006feSStefano Zampini   Input Parameters:
19674cb006feSStefano Zampini + pc - the preconditioning context
19684cb006feSStefano Zampini - A  - the matrix
19694cb006feSStefano Zampini 
19704cb006feSStefano Zampini   Level: intermediate
19714cb006feSStefano Zampini 
1972f1580f4eSBarry Smith   Note:
197395452b02SPatrick Sanan   A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
19744cb006feSStefano Zampini 
1975feefa0e1SJacob Faibussowitsch   Developer Notes:
1976f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1977f1580f4eSBarry Smith 
1978f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1979f1580f4eSBarry Smith 
1980562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
19814cb006feSStefano Zampini @*/
1982d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1983d71ae5a4SJacob Faibussowitsch {
19844cb006feSStefano Zampini   PetscFunctionBegin;
19854cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
19864cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
19874cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1988cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
19893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19904cb006feSStefano Zampini }
19914cb006feSStefano Zampini 
19924cb006feSStefano Zampini /*@
1993f1580f4eSBarry Smith   PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
19944cb006feSStefano Zampini 
1995c3339decSBarry Smith   Collective
19964cb006feSStefano Zampini 
19974cb006feSStefano Zampini   Input Parameters:
19984cb006feSStefano Zampini + pc - the preconditioning context
1999f1580f4eSBarry Smith - A  - the matrix, or NULL to turn it off
20004cb006feSStefano Zampini 
20014cb006feSStefano Zampini   Level: intermediate
20024cb006feSStefano Zampini 
2003f1580f4eSBarry Smith   Note:
200495452b02SPatrick Sanan   A should be obtained by discretizing the Poisson problem with linear finite elements.
20054cb006feSStefano Zampini 
2006feefa0e1SJacob Faibussowitsch   Developer Notes:
2007f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
2008f1580f4eSBarry Smith 
2009f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
2010f1580f4eSBarry Smith 
2011562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
20124cb006feSStefano Zampini @*/
2013d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
2014d71ae5a4SJacob Faibussowitsch {
20154cb006feSStefano Zampini   PetscFunctionBegin;
20164cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20174cb006feSStefano Zampini   if (A) {
20184cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
20194cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
20204cb006feSStefano Zampini   }
2021cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
20223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20234cb006feSStefano Zampini }
20244cb006feSStefano Zampini 
2025d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
2026d71ae5a4SJacob Faibussowitsch {
20274cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
20284cb006feSStefano Zampini 
20294cb006feSStefano Zampini   PetscFunctionBegin;
20304cb006feSStefano Zampini   /* throw away any vector if already set */
20319566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
20329566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
20339566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
20349566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
20359566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
20369566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
20379566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
20385ac14e1cSStefano Zampini   jac->dim = 2;
20394cb006feSStefano Zampini   if (zzo) {
20409566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
20419566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
20425ac14e1cSStefano Zampini     jac->dim++;
20434cb006feSStefano Zampini   }
20443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20454cb006feSStefano Zampini }
20464cb006feSStefano Zampini 
20474cb006feSStefano Zampini /*@
2048f1580f4eSBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
20494cb006feSStefano Zampini 
2050c3339decSBarry Smith   Collective
20514cb006feSStefano Zampini 
20524cb006feSStefano Zampini   Input Parameters:
20534cb006feSStefano Zampini + pc  - the preconditioning context
20542fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
20552fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
20564cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
20574cb006feSStefano Zampini 
20584cb006feSStefano Zampini   Level: intermediate
20594cb006feSStefano Zampini 
2060feefa0e1SJacob Faibussowitsch   Developer Notes:
2061f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
2062f1580f4eSBarry Smith 
2063562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
20644cb006feSStefano Zampini @*/
2065d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
2066d71ae5a4SJacob Faibussowitsch {
20674cb006feSStefano Zampini   PetscFunctionBegin;
20684cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20694cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
20704cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
20714cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
20724cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
20734cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
20744cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
2075cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
20763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20774cb006feSStefano Zampini }
20784cb006feSStefano Zampini 
2079d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
2080d71ae5a4SJacob Faibussowitsch {
2081be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2082be14dc20SKerry Key 
2083be14dc20SKerry Key   PetscFunctionBegin;
2084be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
2085be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
2086be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
2087be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
20883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2089be14dc20SKerry Key }
2090be14dc20SKerry Key 
2091be14dc20SKerry Key /*@
2092f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
2093be14dc20SKerry Key 
2094c3339decSBarry Smith   Collective
2095be14dc20SKerry Key 
2096be14dc20SKerry Key   Input Parameters:
2097be14dc20SKerry Key + pc       - the preconditioning context
2098be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
2099be14dc20SKerry Key 
2100be14dc20SKerry Key   Level: intermediate
2101be14dc20SKerry Key 
2102be14dc20SKerry Key   Note:
2103f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
2104f1580f4eSBarry Smith 
2105feefa0e1SJacob Faibussowitsch   Developer Notes:
2106f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
2107f1580f4eSBarry Smith 
2108562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
2109be14dc20SKerry Key @*/
2110d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
2111d71ae5a4SJacob Faibussowitsch {
2112be14dc20SKerry Key   PetscFunctionBegin;
2113be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2114be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
2115be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
2116be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
21173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2118be14dc20SKerry Key }
2119be14dc20SKerry Key 
2120d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2121d71ae5a4SJacob Faibussowitsch {
21224cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
21234cb006feSStefano Zampini   Vec       tv;
21244cb006feSStefano Zampini   PetscInt  i;
21254cb006feSStefano Zampini 
21264cb006feSStefano Zampini   PetscFunctionBegin;
21274cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
21289566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
21299566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
21309566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
21315ac14e1cSStefano Zampini   jac->dim = dim;
21325ac14e1cSStefano Zampini 
21334cb006feSStefano Zampini   /* compute IJ vector for coordinates */
21349566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
21359566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
21369566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
21374cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
21384cb006feSStefano Zampini     PetscScalar *array;
21394cb006feSStefano Zampini     PetscInt     j;
21404cb006feSStefano Zampini 
21419566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
21429566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
21436ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
21449566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
21459566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
21464cb006feSStefano Zampini   }
21479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
21483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21494cb006feSStefano Zampini }
21504cb006feSStefano Zampini 
2151d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
2152d71ae5a4SJacob Faibussowitsch {
215316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
215416d9e3a6SLisandro Dalcin 
215516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
215616d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
21573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
215816d9e3a6SLisandro Dalcin }
215916d9e3a6SLisandro Dalcin 
2160d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
2161d71ae5a4SJacob Faibussowitsch {
216216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2163ace3abfcSBarry Smith   PetscBool flag;
216416d9e3a6SLisandro Dalcin 
216516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
216616d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
21679566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
21685f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
21693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
217016d9e3a6SLisandro Dalcin   } else {
21719566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
217216d9e3a6SLisandro Dalcin   }
217316d9e3a6SLisandro Dalcin 
217416d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
217516d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
217616d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
217716d9e3a6SLisandro Dalcin 
21783c61a47dSLukas   PetscCall(PetscStrcmp("ilu", jac->hypre_type, &flag));
21793c61a47dSLukas   if (flag) {
21803c61a47dSLukas     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
21813c61a47dSLukas     PetscCallExternal(HYPRE_ILUCreate, &jac->hsolver);
21823c61a47dSLukas     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ILU;
21833c61a47dSLukas     pc->ops->view           = PCView_HYPRE_ILU;
21843c61a47dSLukas     jac->destroy            = HYPRE_ILUDestroy;
21853c61a47dSLukas     jac->setup              = HYPRE_ILUSetup;
21863c61a47dSLukas     jac->solve              = HYPRE_ILUSolve;
21873c61a47dSLukas     jac->factorrowsize      = PETSC_DEFAULT;
21883c61a47dSLukas     PetscFunctionReturn(PETSC_SUCCESS);
21893c61a47dSLukas   }
21903c61a47dSLukas 
21919566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
219216d9e3a6SLisandro Dalcin   if (flag) {
21939566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2194792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
219516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
219616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
219716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
219816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
219916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
220016d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
22013ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
220216d9e3a6SLisandro Dalcin   }
22039566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
2204db966c6cSHong Zhang   if (flag) {
22054e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
22067de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
22078bf83915SBarry Smith #endif
22089566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2209792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
2210db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
2211db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
2212db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
2213db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
2214db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
2215db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
2216db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
22173ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2218db966c6cSHong Zhang   }
22199566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
222016d9e3a6SLisandro Dalcin   if (flag) {
22219566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2222792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
222316d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
222416d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
222516d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
222616d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
222716d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
222816d9e3a6SLisandro Dalcin     /* initialize */
222916d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
22308966356dSPierre Jolivet     jac->threshold = .1;
223116d9e3a6SLisandro Dalcin     jac->filter    = .1;
223216d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
22332fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
22342fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
22352fa5cd67SKarl Rupp 
223616d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
223716d9e3a6SLisandro Dalcin     jac->symt = 0;
2238792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
2239792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
2240792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
2241792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
2242792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
2243792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
22443ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
224516d9e3a6SLisandro Dalcin   }
22469566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
224716d9e3a6SLisandro Dalcin   if (flag) {
2248792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
224916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
225016d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
225116d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
225216d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
225385245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
22549566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
22559566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
225642e5ec60SJeff-Hadley     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", PCHYPREGetCFMarkers_BoomerAMG));
225716d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
225816d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
225916d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
226016d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
226116d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
226216d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
226316d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
226416d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
22658f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
226616d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
226716d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
226816d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
226916d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
227016d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
22710f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
22726a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
2273b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
22741810e44eSEike Mueller     jac->eu_level                                                = 0;
22751810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
22761810e44eSEike Mueller     jac->eu_bj                                                   = 0;
2277589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
22780f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
227916d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
228016d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
228116d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
22820f1074feSSatish Balay     jac->interptype                       = 0;
2283589dcaf0SStefano Zampini     jac->Rtype                            = 0;
2284589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
2285589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
2286589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
2287589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
22880f1074feSSatish Balay     jac->agg_nl                           = 0;
22896ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
22900f1074feSSatish Balay     jac->pmax                             = 0;
22910f1074feSSatish Balay     jac->truncfactor                      = 0.0;
22920f1074feSSatish Balay     jac->agg_num_paths                    = 1;
2293589dcaf0SStefano Zampini     jac->maxc                             = 9;
2294589dcaf0SStefano Zampini     jac->minc                             = 1;
229522e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
229622e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
229722e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
229822e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
229922e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
230022e51d31SStefano Zampini     jac->interp_refine                    = 0;
23018f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
23028f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
23036ea7df73SStefano Zampini     jac->rap2                             = 0;
23046ea7df73SStefano Zampini 
23056ea7df73SStefano Zampini     /* GPU defaults
23066ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
23076ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
23086ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23096ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
23106ea7df73SStefano Zampini     jac->mod_rap2       = 1;
23116ea7df73SStefano Zampini     jac->coarsentype    = 8;
23126ea7df73SStefano Zampini     jac->relaxorder     = 0;
23136ea7df73SStefano Zampini     jac->interptype     = 6;
23146ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
23156ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
23166ea7df73SStefano Zampini     jac->agg_interptype = 7;
23176ea7df73SStefano Zampini #else
23186ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
23196ea7df73SStefano Zampini     jac->mod_rap2      = 0;
23206ea7df73SStefano Zampini #endif
2321792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
2322792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
2323792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
2324792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
2325792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
2326792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
2327792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
2328792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
2329792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
2330792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
2331792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
2332792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
2333792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2334792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2335792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2336792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2337792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2338792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2339792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
23406ea7df73SStefano Zampini     /* GPU */
23416ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2342792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2343792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2344792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
23456ea7df73SStefano Zampini #endif
23466ea7df73SStefano Zampini 
2347589dcaf0SStefano Zampini     /* AIR */
23486ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2349792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2350792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2351792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2352792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2353792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
23546ea7df73SStefano Zampini #endif
23553ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
235616d9e3a6SLisandro Dalcin   }
23579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
23584cb006feSStefano Zampini   if (flag) {
23593ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
23604cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
23614cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
23624cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
23634cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
23644cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
23654cb006feSStefano Zampini     jac->coords[0]          = NULL;
23664cb006feSStefano Zampini     jac->coords[1]          = NULL;
23674cb006feSStefano Zampini     jac->coords[2]          = NULL;
2368be14dc20SKerry Key     jac->interior           = NULL;
23694cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2370863406b8SStefano Zampini     jac->as_print       = 0;
2371863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2372863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
23734cb006feSStefano Zampini     jac->ams_cycle_type = 13;
23744cb006feSStefano Zampini     /* Smoothing options */
2375863406b8SStefano Zampini     jac->as_relax_type   = 2;
2376863406b8SStefano Zampini     jac->as_relax_times  = 1;
2377863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2378863406b8SStefano Zampini     jac->as_omega        = 1.0;
23794cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2380863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2381863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
23820bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2383863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2384863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2385863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
23864cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2387863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2388863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
23890bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2390863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2391863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2392863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2393792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2394792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2395792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2396792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
23979371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2398792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2399863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2400863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
24019371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2402a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2403792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2404863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2405863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
24069371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2407a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
240823df4f25SStefano Zampini     /* Zero conductivity */
240923df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
241023df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
24113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
24124cb006feSStefano Zampini   }
24139566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2414863406b8SStefano Zampini   if (flag) {
24153ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2416863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2417863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2418863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2419863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2420863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2421863406b8SStefano Zampini     jac->coords[0]          = NULL;
2422863406b8SStefano Zampini     jac->coords[1]          = NULL;
2423863406b8SStefano Zampini     jac->coords[2]          = NULL;
2424863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2425863406b8SStefano Zampini     jac->as_print       = 0;
2426863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2427863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2428863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2429863406b8SStefano Zampini     /* Smoothing options */
2430863406b8SStefano Zampini     jac->as_relax_type   = 2;
2431863406b8SStefano Zampini     jac->as_relax_times  = 1;
2432863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2433863406b8SStefano Zampini     jac->as_omega        = 1.0;
2434863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2435863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2436863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2437863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2438863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2439863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2440863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2441863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2442863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2443863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2444863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2445863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2446863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2447863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2448863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2449792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2450792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2451792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2452792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
24539371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2454792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2455863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2456863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2457863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
24589371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2459a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2460792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2461863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2462863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
24639371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2464a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
24653ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2466863406b8SStefano Zampini   }
24679566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
24682fa5cd67SKarl Rupp 
24690298fd71SBarry Smith   jac->hypre_type = NULL;
247098921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
247116d9e3a6SLisandro Dalcin }
247216d9e3a6SLisandro Dalcin 
247316d9e3a6SLisandro Dalcin /*
247416d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
247516d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
247616d9e3a6SLisandro Dalcin */
2477ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2478d71ae5a4SJacob Faibussowitsch {
24794ddd07fcSJed Brown   PetscInt    indx;
24803c61a47dSLukas   const char *type[] = {"ilu", "euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2481ace3abfcSBarry Smith   PetscBool   flg;
248216d9e3a6SLisandro Dalcin 
248316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2484d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2485dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
248616d9e3a6SLisandro Dalcin   if (flg) {
24879566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
248802a17cd4SBarry Smith   } else {
24899566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
249016d9e3a6SLisandro Dalcin   }
2491dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2492d0609cedSBarry Smith   PetscOptionsHeadEnd();
24933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
249416d9e3a6SLisandro Dalcin }
249516d9e3a6SLisandro Dalcin 
2496cc4c1da9SBarry Smith /*@
249716d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
249816d9e3a6SLisandro Dalcin 
249916d9e3a6SLisandro Dalcin   Input Parameters:
250016d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2501db966c6cSHong Zhang - name - either  euclid, pilut, parasails, boomeramg, ams, ads
250216d9e3a6SLisandro Dalcin 
2503f1580f4eSBarry Smith   Options Database Key:
2504feefa0e1SJacob Faibussowitsch . pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
250516d9e3a6SLisandro Dalcin 
250616d9e3a6SLisandro Dalcin   Level: intermediate
250716d9e3a6SLisandro Dalcin 
2508562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
250916d9e3a6SLisandro Dalcin @*/
2510d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2511d71ae5a4SJacob Faibussowitsch {
251216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25130700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25144f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2515cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
25163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
251716d9e3a6SLisandro Dalcin }
251816d9e3a6SLisandro Dalcin 
251942e5ec60SJeff-Hadley /*@C
252042e5ec60SJeff-Hadley   PCHYPREGetCFMarkers - Gets CF marker arrays for all levels (except the finest level)
252142e5ec60SJeff-Hadley 
252242e5ec60SJeff-Hadley   Logically Collective
252342e5ec60SJeff-Hadley 
252442e5ec60SJeff-Hadley   Input Parameter:
252542e5ec60SJeff-Hadley . pc - the preconditioner context
252642e5ec60SJeff-Hadley 
252742e5ec60SJeff-Hadley   Output Parameters:
252842e5ec60SJeff-Hadley + n_per_level - the number of nodes per level (size of `num_levels`)
252942e5ec60SJeff-Hadley - CFMarkers   - the Coarse/Fine Boolean arrays (size of `num_levels` - 1)
253042e5ec60SJeff-Hadley 
253142e5ec60SJeff-Hadley   Note:
253242e5ec60SJeff-Hadley   Caller is responsible for memory management of `n_per_level` and `CFMarkers` pointers. That is they should free them with `PetscFree()` when no longer needed.
253342e5ec60SJeff-Hadley 
253442e5ec60SJeff-Hadley   Level: advanced
253542e5ec60SJeff-Hadley 
253642e5ec60SJeff-Hadley .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
253742e5ec60SJeff-Hadley @*/
253842e5ec60SJeff-Hadley PetscErrorCode PCHYPREGetCFMarkers(PC pc, PetscInt *n_per_level[], PetscBT *CFMarkers[])
253942e5ec60SJeff-Hadley {
254042e5ec60SJeff-Hadley   PetscFunctionBegin;
254142e5ec60SJeff-Hadley   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
254242e5ec60SJeff-Hadley   PetscAssertPointer(n_per_level, 2);
254342e5ec60SJeff-Hadley   PetscAssertPointer(CFMarkers, 3);
254442e5ec60SJeff-Hadley   PetscUseMethod(pc, "PCHYPREGetCFMarkers_C", (PC, PetscInt *[], PetscBT *[]), (pc, n_per_level, CFMarkers));
254542e5ec60SJeff-Hadley   PetscFunctionReturn(PETSC_SUCCESS);
254642e5ec60SJeff-Hadley }
254742e5ec60SJeff-Hadley 
2548cc4c1da9SBarry Smith /*@
254916d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
255016d9e3a6SLisandro Dalcin 
255116d9e3a6SLisandro Dalcin   Input Parameter:
255216d9e3a6SLisandro Dalcin . pc - the preconditioner context
255316d9e3a6SLisandro Dalcin 
255416d9e3a6SLisandro Dalcin   Output Parameter:
2555db966c6cSHong Zhang . name - either  euclid, pilut, parasails, boomeramg, ams, ads
255616d9e3a6SLisandro Dalcin 
255716d9e3a6SLisandro Dalcin   Level: intermediate
255816d9e3a6SLisandro Dalcin 
2559562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
256016d9e3a6SLisandro Dalcin @*/
2561d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2562d71ae5a4SJacob Faibussowitsch {
256316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25640700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25654f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2566cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
25673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
256816d9e3a6SLisandro Dalcin }
256916d9e3a6SLisandro Dalcin 
2570cc4c1da9SBarry Smith /*@
2571f1580f4eSBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2572db6f9c32SMark Adams 
2573c3339decSBarry Smith   Logically Collective
2574db6f9c32SMark Adams 
2575db6f9c32SMark Adams   Input Parameters:
2576db6f9c32SMark Adams + pc   - the hypre context
2577feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2578db6f9c32SMark Adams 
2579db6f9c32SMark Adams   Options Database Key:
258067b8a455SSatish Balay . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2581db6f9c32SMark Adams 
2582db6f9c32SMark Adams   Level: intermediate
2583db6f9c32SMark Adams 
2584feefa0e1SJacob Faibussowitsch   Developer Notes:
2585f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2586db6f9c32SMark Adams 
2587562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2588db6f9c32SMark Adams @*/
2589d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2590d71ae5a4SJacob Faibussowitsch {
2591db6f9c32SMark Adams   PetscFunctionBegin;
2592db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2593cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
25943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2595db6f9c32SMark Adams }
2596db6f9c32SMark Adams 
2597cc4c1da9SBarry Smith /*@
2598f1580f4eSBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2599db6f9c32SMark Adams 
2600db6f9c32SMark Adams   Not Collective
2601db6f9c32SMark Adams 
2602db6f9c32SMark Adams   Input Parameter:
2603db6f9c32SMark Adams . pc - the multigrid context
2604db6f9c32SMark Adams 
2605db6f9c32SMark Adams   Output Parameter:
2606db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2607db6f9c32SMark Adams 
2608db6f9c32SMark Adams   Level: intermediate
2609db6f9c32SMark Adams 
2610a94f484eSPierre Jolivet .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinSetMatProductAlgorithm()`
2611db6f9c32SMark Adams @*/
2612d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2613d71ae5a4SJacob Faibussowitsch {
2614db6f9c32SMark Adams   PetscFunctionBegin;
2615db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2616cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
26173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2618db6f9c32SMark Adams }
2619db6f9c32SMark Adams 
262016d9e3a6SLisandro Dalcin /*MC
2621f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
262216d9e3a6SLisandro Dalcin 
262316d9e3a6SLisandro Dalcin    Options Database Keys:
2624e1ded407SBarry Smith +   -pc_hypre_type - One of `euclid`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2625f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2626f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2627e1ded407SBarry Smith -   Many others, run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
262816d9e3a6SLisandro Dalcin 
262916d9e3a6SLisandro Dalcin    Level: intermediate
263016d9e3a6SLisandro Dalcin 
263195452b02SPatrick Sanan    Notes:
2632e1ded407SBarry Smith     Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
263316d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
263449567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
263516d9e3a6SLisandro Dalcin 
2636e1ded407SBarry Smith           The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2637e1ded407SBarry Smith           (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2638e1ded407SBarry Smith           `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2639e1ded407SBarry Smith           (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2640e1ded407SBarry Smith           iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2641e1ded407SBarry Smith           and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2642e1ded407SBarry Smith           then AT MOST twenty V-cycles of boomeramg will be used.
264316d9e3a6SLisandro Dalcin 
2644e1ded407SBarry Smith            Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
26450f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2646e1ded407SBarry Smith            Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
264716d9e3a6SLisandro Dalcin 
2648f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2649e1ded407SBarry Smith           the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
26500b1a5bd9SEric Chamberland 
2651f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2652f1580f4eSBarry Smith 
2653e1ded407SBarry Smith           For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2654f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
265549567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2656f1580f4eSBarry Smith 
2657e1ded407SBarry 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
2658e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2659e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2660e1ded407SBarry Smith 
2661f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
26629e5bc791SBarry Smith 
2663ead8c081SBarry Smith    GPU Notes:
2664ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2665f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2666ead8c081SBarry Smith 
2667ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2668f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2669ead8c081SBarry Smith 
2670562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2671f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2672f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
267316d9e3a6SLisandro Dalcin M*/
267416d9e3a6SLisandro Dalcin 
2675d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2676d71ae5a4SJacob Faibussowitsch {
267716d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
267816d9e3a6SLisandro Dalcin 
267916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
26804dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
26812fa5cd67SKarl Rupp 
268216d9e3a6SLisandro Dalcin   pc->data                = jac;
26838695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
268416d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
268516d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
268616d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
268716d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
268816d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
26899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
26909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
26919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
26929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
26939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
26949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
26959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2696be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
26979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
26989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
26999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
27006ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
27016ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
27029566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
27036ea7df73SStefano Zampini   #endif
27046ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
27059566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
27066ea7df73SStefano Zampini   #endif
27076ea7df73SStefano Zampini #endif
2708ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
27093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
271016d9e3a6SLisandro Dalcin }
2711ebc551c0SBarry Smith 
2712ebc551c0SBarry Smith typedef struct {
271368326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2714f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
27159e5bc791SBarry Smith 
27169e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
27174ddd07fcSJed Brown   PetscInt  its;
271873dcfd97SStefano Zampini   PetscReal tol;
27194ddd07fcSJed Brown   PetscInt  relax_type;
27204ddd07fcSJed Brown   PetscInt  rap_type;
27214ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
27224ddd07fcSJed Brown   PetscInt  max_levels;
27230be8cd64Sftrigaux   PetscInt  skip_relax;
27240be8cd64Sftrigaux   PetscBool print_statistics;
2725ebc551c0SBarry Smith } PC_PFMG;
2726ebc551c0SBarry Smith 
2727ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_PFMG(PC pc)
2728d71ae5a4SJacob Faibussowitsch {
2729f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2730ebc551c0SBarry Smith 
2731ebc551c0SBarry Smith   PetscFunctionBegin;
2732792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
27339566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
27349566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
27353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2736ebc551c0SBarry Smith }
2737ebc551c0SBarry Smith 
27389e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
27399e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
27409e5bc791SBarry Smith 
2741ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2742d71ae5a4SJacob Faibussowitsch {
2743ace3abfcSBarry Smith   PetscBool iascii;
2744f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2745ebc551c0SBarry Smith 
2746ebc551c0SBarry Smith   PetscFunctionBegin;
27479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
27489e5bc791SBarry Smith   if (iascii) {
27499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
275063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
27539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
275463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
275563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
27560be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
27579e5bc791SBarry Smith   }
27583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2759ebc551c0SBarry Smith }
2760ebc551c0SBarry Smith 
2761ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2762d71ae5a4SJacob Faibussowitsch {
2763f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2764ebc551c0SBarry Smith 
2765ebc551c0SBarry Smith   PetscFunctionBegin;
2766d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
27670be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
27689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2769792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
27709566063dSJacob 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));
2771792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
27729566063dSJacob 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));
2773792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
27749e5bc791SBarry Smith 
27759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2776792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
27773b46a515SGlenn Hammond 
27789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2779792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2780dd39110bSPierre 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));
2781792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2782dd39110bSPierre 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));
2783792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
27840be8cd64Sftrigaux   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));
27850be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2786d0609cedSBarry Smith   PetscOptionsHeadEnd();
27873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2788ebc551c0SBarry Smith }
2789ebc551c0SBarry Smith 
2790ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2791d71ae5a4SJacob Faibussowitsch {
2792f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2793d9ca1df4SBarry Smith   PetscScalar       *yy;
2794d9ca1df4SBarry Smith   const PetscScalar *xx;
27954ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
27962cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2797f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
2798f91d8e95SBarry Smith 
2799f91d8e95SBarry Smith   PetscFunctionBegin;
28009566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28019566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28022cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2803f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2804f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2805f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
28062cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
28072cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
28082cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
28092cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
28102cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
28112cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2812f91d8e95SBarry Smith 
2813f91d8e95SBarry Smith   /* copy x values over to hypre */
2814792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
28159566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2816792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
28179566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2818792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2819792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2820f91d8e95SBarry Smith 
2821f91d8e95SBarry Smith   /* copy solution values back to PETSc */
28229566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2823792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
28249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
28253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2826f91d8e95SBarry Smith }
2827f91d8e95SBarry Smith 
2828d71ae5a4SJacob 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)
2829d71ae5a4SJacob Faibussowitsch {
28309e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
28312cf14000SStefano Zampini   HYPRE_Int oits;
28329e5bc791SBarry Smith 
28339e5bc791SBarry Smith   PetscFunctionBegin;
28349566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2835792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2836792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
28379e5bc791SBarry Smith 
28389566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2839792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
28409e5bc791SBarry Smith   *outits = oits;
28419e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
28429e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2843792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2844792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
28453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28469e5bc791SBarry Smith }
28479e5bc791SBarry Smith 
2848ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_PFMG(PC pc)
2849d71ae5a4SJacob Faibussowitsch {
28503a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
2851f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
2852ace3abfcSBarry Smith   PetscBool        flg;
28533a32d3dbSGlenn Hammond 
28543a32d3dbSGlenn Hammond   PetscFunctionBegin;
28559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
285628b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
28573a32d3dbSGlenn Hammond 
28583a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2859792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2860792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
28610be8cd64Sftrigaux 
28620be8cd64Sftrigaux   // Print Hypre statistics about the solve process
28630be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
28640be8cd64Sftrigaux 
28650be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
28660be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
28670be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28680be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28690be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
28700be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
28710be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
28720be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
28730be8cd64Sftrigaux 
2874792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2875792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
28763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28773a32d3dbSGlenn Hammond }
28783a32d3dbSGlenn Hammond 
2879ebc551c0SBarry Smith /*MC
2880ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2881ebc551c0SBarry Smith 
2882f1580f4eSBarry Smith    Options Database Keys:
288367b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
288467b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
288567b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
288667b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
28879e5bc791SBarry 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
28880be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2889f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2890f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2891f1580f4eSBarry Smith 
2892f1580f4eSBarry Smith    Level: advanced
2893f91d8e95SBarry Smith 
289495452b02SPatrick Sanan    Notes:
289595452b02SPatrick Sanan    This is for CELL-centered descretizations
28969e5bc791SBarry Smith 
2897f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
28989e5bc791SBarry Smith 
2899f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2900f1580f4eSBarry Smith 
2901f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2902f1580f4eSBarry Smith 
2903f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2904f1580f4eSBarry Smith 
2905562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2906ebc551c0SBarry Smith M*/
2907ebc551c0SBarry Smith 
2908d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2909d71ae5a4SJacob Faibussowitsch {
2910ebc551c0SBarry Smith   PC_PFMG *ex;
2911ebc551c0SBarry Smith 
2912ebc551c0SBarry Smith   PetscFunctionBegin;
29139371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
291468326731SBarry Smith   pc->data = ex;
2915ebc551c0SBarry Smith 
29169e5bc791SBarry Smith   ex->its              = 1;
29179e5bc791SBarry Smith   ex->tol              = 1.e-8;
29189e5bc791SBarry Smith   ex->relax_type       = 1;
29199e5bc791SBarry Smith   ex->rap_type         = 0;
29209e5bc791SBarry Smith   ex->num_pre_relax    = 1;
29219e5bc791SBarry Smith   ex->num_post_relax   = 1;
29223b46a515SGlenn Hammond   ex->max_levels       = 0;
29230be8cd64Sftrigaux   ex->skip_relax       = 0;
29240be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
29259e5bc791SBarry Smith 
2926ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2927ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2928ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2929f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
29309e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
293168326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
29322fa5cd67SKarl Rupp 
29339566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2934ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2935792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
29363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2937ebc551c0SBarry Smith }
2938d851a50bSGlenn Hammond 
2939d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2940d851a50bSGlenn Hammond typedef struct {
2941d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2942d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2943d851a50bSGlenn Hammond 
2944d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
29454ddd07fcSJed Brown   PetscInt  its;
294673dcfd97SStefano Zampini   PetscReal tol;
29474ddd07fcSJed Brown   PetscInt  relax_type;
29484ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
2949d851a50bSGlenn Hammond } PC_SysPFMG;
2950d851a50bSGlenn Hammond 
2951ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SysPFMG(PC pc)
2952d71ae5a4SJacob Faibussowitsch {
2953d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2954d851a50bSGlenn Hammond 
2955d851a50bSGlenn Hammond   PetscFunctionBegin;
2956792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
29579566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
29589566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
29593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2960d851a50bSGlenn Hammond }
2961d851a50bSGlenn Hammond 
2962d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2963d851a50bSGlenn Hammond 
2964ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2965d71ae5a4SJacob Faibussowitsch {
2966ace3abfcSBarry Smith   PetscBool   iascii;
2967d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2968d851a50bSGlenn Hammond 
2969d851a50bSGlenn Hammond   PetscFunctionBegin;
29709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2971d851a50bSGlenn Hammond   if (iascii) {
29729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
297363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
29749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
29759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
297663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2977d851a50bSGlenn Hammond   }
29783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2979d851a50bSGlenn Hammond }
2980d851a50bSGlenn Hammond 
2981ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2982d71ae5a4SJacob Faibussowitsch {
2983d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2984ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2985d851a50bSGlenn Hammond 
2986d851a50bSGlenn Hammond   PetscFunctionBegin;
2987d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
29889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
298948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
29909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2991792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
29929566063dSJacob 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));
2993792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
29949566063dSJacob 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));
2995792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2996d851a50bSGlenn Hammond 
29979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2998792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2999dd39110bSPierre 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));
3000792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
3001d0609cedSBarry Smith   PetscOptionsHeadEnd();
30023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3003d851a50bSGlenn Hammond }
3004d851a50bSGlenn Hammond 
3005ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
3006d71ae5a4SJacob Faibussowitsch {
3007d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
3008d9ca1df4SBarry Smith   PetscScalar       *yy;
3009d9ca1df4SBarry Smith   const PetscScalar *xx;
30104ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
30112cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
3012f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)pc->pmat->data;
30134ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
30144ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
30154ddd07fcSJed Brown   PetscInt           part     = 0;
30164ddd07fcSJed Brown   PetscInt           size;
30174ddd07fcSJed Brown   PetscInt           i;
3018d851a50bSGlenn Hammond 
3019d851a50bSGlenn Hammond   PetscFunctionBegin;
30209566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
30219566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
30222cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
3023d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
3024d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
3025d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
30262cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
30272cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
30282cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
30292cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
30302cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
30312cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
3032d851a50bSGlenn Hammond 
3033d851a50bSGlenn Hammond   size = 1;
30342fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
30352fa5cd67SKarl Rupp 
3036d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
3037d851a50bSGlenn Hammond   if (ordering) {
3038792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
30399566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3040792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
30419566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3042792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
3043792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
3044792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
3045d851a50bSGlenn Hammond 
3046d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30479566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3048792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
30499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
3050a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
3051d851a50bSGlenn Hammond     PetscScalar *z;
30524ddd07fcSJed Brown     PetscInt     j, k;
3053d851a50bSGlenn Hammond 
30549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
3055792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
30569566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3057d851a50bSGlenn Hammond 
3058d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
3059d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3060d851a50bSGlenn Hammond       k = i * nvars;
30612fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
3062d851a50bSGlenn Hammond     }
3063792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
30649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3065792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
3066792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
3067d851a50bSGlenn Hammond 
3068d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30699566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3070792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
3071d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
3072d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3073d851a50bSGlenn Hammond       k = i * nvars;
30742fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
3075d851a50bSGlenn Hammond     }
30769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
30779566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
3078d851a50bSGlenn Hammond   }
30793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3080d851a50bSGlenn Hammond }
3081d851a50bSGlenn Hammond 
3082d71ae5a4SJacob 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)
3083d71ae5a4SJacob Faibussowitsch {
3084d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
30852cf14000SStefano Zampini   HYPRE_Int   oits;
3086d851a50bSGlenn Hammond 
3087d851a50bSGlenn Hammond   PetscFunctionBegin;
30889566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
3089792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
3090792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
30919566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
3092792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
3093d851a50bSGlenn Hammond   *outits = oits;
3094d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
3095d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
3096792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
3097792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
30983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3099d851a50bSGlenn Hammond }
3100d851a50bSGlenn Hammond 
3101ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SysPFMG(PC pc)
3102d71ae5a4SJacob Faibussowitsch {
3103d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
3104f4f49eeaSPierre Jolivet   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)pc->pmat->data;
3105ace3abfcSBarry Smith   PetscBool         flg;
3106d851a50bSGlenn Hammond 
3107d851a50bSGlenn Hammond   PetscFunctionBegin;
31089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
310928b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
3110d851a50bSGlenn Hammond 
3111d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
3112792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
3113792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
3114792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
3115792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
31163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3117d851a50bSGlenn Hammond }
3118d851a50bSGlenn Hammond 
3119d851a50bSGlenn Hammond /*MC
3120f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
3121d851a50bSGlenn Hammond 
3122d851a50bSGlenn Hammond    Level: advanced
3123d851a50bSGlenn Hammond 
3124f1580f4eSBarry Smith    Options Database Keys:
312567b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
312667b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
312767b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
312867b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
312967b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
3130d851a50bSGlenn Hammond 
313195452b02SPatrick Sanan    Notes:
3132f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
3133f1580f4eSBarry Smith 
3134f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
3135f1580f4eSBarry Smith 
313695452b02SPatrick Sanan    This is for CELL-centered descretizations
3137d851a50bSGlenn Hammond 
3138f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
3139d851a50bSGlenn Hammond 
3140f1580f4eSBarry 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`.
3141f1580f4eSBarry Smith 
3142562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
3143d851a50bSGlenn Hammond M*/
3144d851a50bSGlenn Hammond 
3145d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
3146d71ae5a4SJacob Faibussowitsch {
3147d851a50bSGlenn Hammond   PC_SysPFMG *ex;
3148d851a50bSGlenn Hammond 
3149d851a50bSGlenn Hammond   PetscFunctionBegin;
31509371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
3151d851a50bSGlenn Hammond   pc->data = ex;
3152d851a50bSGlenn Hammond 
3153d851a50bSGlenn Hammond   ex->its            = 1;
3154d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
3155d851a50bSGlenn Hammond   ex->relax_type     = 1;
3156d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
3157d851a50bSGlenn Hammond   ex->num_post_relax = 1;
3158d851a50bSGlenn Hammond 
3159d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
3160d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
3161d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
3162d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
3163d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
3164d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
31652fa5cd67SKarl Rupp 
31669566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3167ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
3168792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
31693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3170d851a50bSGlenn Hammond }
31711c188c59Sftrigaux 
3172f1580f4eSBarry Smith /* PC SMG */
31731c188c59Sftrigaux typedef struct {
31741c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
31751c188c59Sftrigaux   HYPRE_StructSolver hsolver;
31761c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
317773dcfd97SStefano Zampini   PetscReal          tol;
31781c188c59Sftrigaux   PetscBool          print_statistics;
31791c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
31801c188c59Sftrigaux } PC_SMG;
31811c188c59Sftrigaux 
3182ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SMG(PC pc)
3183d71ae5a4SJacob Faibussowitsch {
31841c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
31851c188c59Sftrigaux 
31861c188c59Sftrigaux   PetscFunctionBegin;
31871c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
31881c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
31891c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
31903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31911c188c59Sftrigaux }
31921c188c59Sftrigaux 
3193ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
3194d71ae5a4SJacob Faibussowitsch {
31951c188c59Sftrigaux   PetscBool iascii;
31961c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
31971c188c59Sftrigaux 
31981c188c59Sftrigaux   PetscFunctionBegin;
31991c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
32001c188c59Sftrigaux   if (iascii) {
32011c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
32021c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
32031c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
32041c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
32051c188c59Sftrigaux   }
32063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32071c188c59Sftrigaux }
32081c188c59Sftrigaux 
3209ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
3210d71ae5a4SJacob Faibussowitsch {
32111c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
32121c188c59Sftrigaux 
32131c188c59Sftrigaux   PetscFunctionBegin;
32141c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
32151c188c59Sftrigaux 
32161c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
32171c188c59Sftrigaux   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));
32181c188c59Sftrigaux   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));
32191c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
32201c188c59Sftrigaux 
32211c188c59Sftrigaux   PetscOptionsHeadEnd();
32223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32231c188c59Sftrigaux }
32241c188c59Sftrigaux 
3225ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
3226d71ae5a4SJacob Faibussowitsch {
32271c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
32281c188c59Sftrigaux   PetscScalar       *yy;
32291c188c59Sftrigaux   const PetscScalar *xx;
32301c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
32311c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
3232f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
32331c188c59Sftrigaux 
32341c188c59Sftrigaux   PetscFunctionBegin;
32351c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32361c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
32371c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
32381c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
32391c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
32401c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
32411c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
32421c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
32431c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
32441c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
32451c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
32461c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
32471c188c59Sftrigaux 
32481c188c59Sftrigaux   /* copy x values over to hypre */
32491c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
32501c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
32511c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
32521c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
32531c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
32541c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
32551c188c59Sftrigaux 
32561c188c59Sftrigaux   /* copy solution values back to PETSc */
32571c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
32581c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
32591c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
32603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32611c188c59Sftrigaux }
32621c188c59Sftrigaux 
3263d71ae5a4SJacob 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)
3264d71ae5a4SJacob Faibussowitsch {
32651c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
32661c188c59Sftrigaux   HYPRE_Int oits;
32671c188c59Sftrigaux 
32681c188c59Sftrigaux   PetscFunctionBegin;
32691c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32701c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
32711c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
32721c188c59Sftrigaux 
32731c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
32741c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
32751c188c59Sftrigaux   *outits = oits;
32761c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
32771c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
32781c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
32791c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
32803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32811c188c59Sftrigaux }
32821c188c59Sftrigaux 
3283ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SMG(PC pc)
3284d71ae5a4SJacob Faibussowitsch {
32851c188c59Sftrigaux   PetscInt         i, dim;
32861c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
3287f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
32881c188c59Sftrigaux   PetscBool        flg;
32891c188c59Sftrigaux   DMBoundaryType   p[3];
32901c188c59Sftrigaux   PetscInt         M[3];
32911c188c59Sftrigaux 
32921c188c59Sftrigaux   PetscFunctionBegin;
32931c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
32941c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
32951c188c59Sftrigaux 
32961c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
32971c188c59Sftrigaux   // Check if power of 2 in periodic directions
32981c188c59Sftrigaux   for (i = 0; i < dim; i++) {
32991c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
33001c188c59Sftrigaux       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]);
33011c188c59Sftrigaux     }
33021c188c59Sftrigaux   }
33031c188c59Sftrigaux 
33041c188c59Sftrigaux   /* create the hypre solver object and set its information */
330557508eceSPierre Jolivet   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
33061c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
33071c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
33081c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
33091c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
33101c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
33111c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
33121c188c59Sftrigaux 
33131c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
33141c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
33153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33161c188c59Sftrigaux }
33171c188c59Sftrigaux 
33181c188c59Sftrigaux /*MC
33195cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
33201c188c59Sftrigaux 
33211c188c59Sftrigaux    Level: advanced
33221c188c59Sftrigaux 
3323f1580f4eSBarry Smith    Options Database Keys:
33245cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
33255cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
33265cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
33275cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
33281c188c59Sftrigaux 
33291c188c59Sftrigaux    Notes:
33301c188c59Sftrigaux    This is for CELL-centered descretizations
33311c188c59Sftrigaux 
33325cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
33331c188c59Sftrigaux 
3334f1580f4eSBarry 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`.
3335f1580f4eSBarry Smith 
3336f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3337f1580f4eSBarry Smith 
3338f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
33391c188c59Sftrigaux M*/
33401c188c59Sftrigaux 
3341d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3342d71ae5a4SJacob Faibussowitsch {
33431c188c59Sftrigaux   PC_SMG *ex;
33441c188c59Sftrigaux 
33451c188c59Sftrigaux   PetscFunctionBegin;
33469371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
33471c188c59Sftrigaux   pc->data = ex;
33481c188c59Sftrigaux 
33491c188c59Sftrigaux   ex->its            = 1;
33501c188c59Sftrigaux   ex->tol            = 1.e-8;
33511c188c59Sftrigaux   ex->num_pre_relax  = 1;
33521c188c59Sftrigaux   ex->num_post_relax = 1;
33531c188c59Sftrigaux 
33541c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
33551c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
33561c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
33571c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
33581c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
33591c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
33601c188c59Sftrigaux 
33611c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3362ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
33631c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
33643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33651c188c59Sftrigaux }
3366