xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision c3466c22aa7e5055d36fd49d0eb04ec5feea77f3)
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];
63d7185485SAlex Lindsay   PetscObjectParameterDeclare(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 */
71d7185485SAlex Lindsay   PetscObjectParameterDeclare(PetscInt, relaxtype[3]);
7239accc25SStefano Zampini   PetscReal relaxweight;
7339accc25SStefano Zampini   PetscReal outerrelaxweight;
74d7185485SAlex Lindsay   PetscObjectParameterDeclare(PetscInt, relaxorder);
7539accc25SStefano Zampini   PetscReal truncfactor;
76ace3abfcSBarry Smith   PetscBool applyrichardson;
774ddd07fcSJed Brown   PetscInt  pmax;
78d7185485SAlex Lindsay   PetscObjectParameterDeclare(PetscInt, interptype);
79589dcaf0SStefano Zampini   PetscInt maxc;
80589dcaf0SStefano Zampini   PetscInt minc;
81db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
82d7185485SAlex Lindsay   PetscObjectParameterDeclarePtr(const char, spgemm_type); // this is a global hypre parameter but is closely associated with BoomerAMG
83db6f9c32SMark Adams #endif
846ea7df73SStefano Zampini   /* GPU */
85d7185485SAlex Lindsay   PetscObjectParameterDeclare(PetscBool, keeptranspose);
866ea7df73SStefano Zampini   PetscInt rap2;
87d7185485SAlex Lindsay   PetscObjectParameterDeclare(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;
97d7185485SAlex Lindsay   PetscObjectParameterDeclare(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 
258d7185485SAlex Lindsay static const char    *HYPRESpgemmTypes[] = {"cusparse", "hypre"};
259d7185485SAlex Lindsay static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
260d7185485SAlex Lindsay {
261d7185485SAlex Lindsay   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
262d7185485SAlex Lindsay   PetscBool flag;
263d7185485SAlex Lindsay 
264d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
265d7185485SAlex Lindsay   PetscFunctionBegin;
266d7185485SAlex Lindsay   if (jac->spgemm_type) {
267d7185485SAlex Lindsay     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
268d7185485SAlex Lindsay     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "PETSc support for resetting the HYPRE SpGEMM is not implemented");
269d7185485SAlex Lindsay     PetscFunctionReturn(PETSC_SUCCESS);
270d7185485SAlex Lindsay   } else jac->spgemm_type = name;
271d7185485SAlex Lindsay 
272d7185485SAlex Lindsay   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
273d7185485SAlex Lindsay   if (flag) {
274d7185485SAlex Lindsay     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
275d7185485SAlex Lindsay     PetscFunctionReturn(PETSC_SUCCESS);
276d7185485SAlex Lindsay   }
277d7185485SAlex Lindsay   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
278d7185485SAlex Lindsay   if (flag) {
279d7185485SAlex Lindsay     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
280d7185485SAlex Lindsay     PetscFunctionReturn(PETSC_SUCCESS);
281d7185485SAlex Lindsay   }
282d7185485SAlex Lindsay   jac->spgemm_type = NULL;
283d7185485SAlex Lindsay   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEMM type %s; Choices are cusparse, hypre", name);
284d7185485SAlex Lindsay #endif
285d7185485SAlex Lindsay }
286d7185485SAlex Lindsay 
287d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
288d71ae5a4SJacob Faibussowitsch {
28916d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
29049a781f5SStefano Zampini   Mat_HYPRE         *hjac;
29116d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
29216d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
29349a781f5SStefano Zampini   PetscBool          ishypre;
29416d9e3a6SLisandro Dalcin 
29516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2960df1829cSStefano Zampini   /* default type is boomerAMG */
29748a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2985f5c5b43SBarry Smith 
2990df1829cSStefano Zampini   /* get hypre matrix */
3000df1829cSStefano Zampini   if (pc->flag == DIFFERENT_NONZERO_PATTERN) PetscCall(MatDestroy(&jac->hpmat));
3019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
30249a781f5SStefano Zampini   if (!ishypre) {
303e6519f9fSJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE) && PETSC_PKG_HYPRE_VERSION_LE(2, 30, 0)
3040df1829cSStefano Zampini     /* Temporary fix since we do not support MAT_REUSE_MATRIX with HYPRE device */
3050df1829cSStefano Zampini     PetscBool iscuda, iship, iskokkos;
3060df1829cSStefano Zampini 
3070df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
3080df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
3090df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iskokkos, MATSEQAIJKOKKOS, MATMPIAIJKOKKOS, ""));
3100df1829cSStefano Zampini     if (iscuda || iship || iskokkos) PetscCall(MatDestroy(&jac->hpmat));
3110df1829cSStefano Zampini #endif
3120df1829cSStefano Zampini     PetscCall(MatConvert(pc->pmat, MATHYPRE, jac->hpmat ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &jac->hpmat));
31349a781f5SStefano Zampini   } else {
3149566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
3159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
31649a781f5SStefano Zampini     jac->hpmat = pc->pmat;
31716d9e3a6SLisandro Dalcin   }
3180df1829cSStefano Zampini 
3196ea7df73SStefano Zampini   /* allow debug */
3209566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
321f4f49eeaSPierre Jolivet   hjac = (Mat_HYPRE *)jac->hpmat->data;
3225f5c5b43SBarry Smith 
32316d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
32416d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
3255272c319SBarry Smith     MatNullSpace mnull;
3265272c319SBarry Smith     PetscBool    has_const;
32749a781f5SStefano Zampini     PetscInt     bs, nvec, i;
328d7185485SAlex Lindsay     PetscMemType memtype;
3295272c319SBarry Smith     const Vec   *vecs;
3305272c319SBarry Smith 
331d7185485SAlex Lindsay     PetscCall(MatGetCurrentMemType(jac->hpmat, &memtype));
332d7185485SAlex Lindsay     if (PetscMemTypeDevice(memtype)) {
333d7185485SAlex Lindsay       /* GPU defaults
334d7185485SAlex Lindsay          From https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
335d7185485SAlex Lindsay          and /src/parcsr_ls/par_amg.c
336d7185485SAlex Lindsay          First handle options which users have interfaces for changing */
337d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, coarsentype, 8);
338d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxorder, 0);
339d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, interptype, 6);
340d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[0], 18);
341d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[1], 18);
342d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
343d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, spgemm_type, HYPRESpgemmTypes[0]);
344d7185485SAlex Lindsay #endif
345d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
346d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, keeptranspose, PETSC_TRUE);
347d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, mod_rap2, 1);
348d7185485SAlex Lindsay #endif
349d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, agg_interptype, 7);
350d7185485SAlex Lindsay     } else {
351d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, coarsentype, 6);
352d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxorder, 1);
353d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, interptype, 0);
354d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[0], 6);
355d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[1], 6); /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
356d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
357d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, spgemm_type, "hypre");
358d7185485SAlex Lindsay #endif
359d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
360d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, keeptranspose, PETSC_FALSE);
361d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, mod_rap2, 0);
362d7185485SAlex Lindsay #endif
363d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, agg_interptype, 4);
364d7185485SAlex Lindsay     }
365d7185485SAlex Lindsay     PetscObjectParameterSetDefault(jac, relaxtype[2], 9); /*G.E. */
366d7185485SAlex Lindsay 
367d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
368d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
369d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
370d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
371d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
372d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
373d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
374d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
375d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
376d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
377d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
378d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, jac->gridsweeps[0], 1);
379d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, jac->gridsweeps[1], 2);
380d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, jac->gridsweeps[2], 3);
381d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
382d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
383d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
384d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
385d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
386d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);
387d7185485SAlex Lindsay     /* GPU */
388d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
389d7185485SAlex Lindsay     PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, jac->spgemm_type));
390d7185485SAlex Lindsay #endif
391d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
392d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
393d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
394d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
395d7185485SAlex Lindsay #endif
396d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
397d7185485SAlex Lindsay 
398d7185485SAlex Lindsay     /* AIR */
399d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
400d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
401d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
402d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
403d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
404d7185485SAlex Lindsay     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
405d7185485SAlex Lindsay #endif
406d7185485SAlex Lindsay 
4079566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
408792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
4099566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
4105272c319SBarry Smith     if (mnull) {
4119566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
4129566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
4139566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
4149566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
4155272c319SBarry Smith       for (i = 0; i < nvec; i++) {
4169566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
4179566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
418792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
4195272c319SBarry Smith       }
4205272c319SBarry Smith       if (has_const) {
4219566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
4229566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
4239566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
4249566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
4259566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
426792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
4275272c319SBarry Smith         nvec++;
4285272c319SBarry Smith       }
429792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
4305272c319SBarry Smith       jac->n_hmnull = nvec;
4315272c319SBarry Smith     }
4324cb006feSStefano Zampini   }
433863406b8SStefano Zampini 
4344cb006feSStefano Zampini   /* special case for AMS */
4354cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
4365ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
4375ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
438966bd95aSPierre Jolivet     PetscCheck(jac->coords[0] || jac->constants[0] || jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]), 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()");
43948a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
4405ac14e1cSStefano Zampini     if (jac->constants[0]) {
4415ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
442792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
443792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
44448a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
445792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
4465ac14e1cSStefano Zampini     }
4475ac14e1cSStefano Zampini     if (jac->coords[0]) {
4485ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
4495ac14e1cSStefano Zampini       coords[0] = NULL;
4505ac14e1cSStefano Zampini       coords[1] = NULL;
4515ac14e1cSStefano Zampini       coords[2] = NULL;
452792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
453792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
454792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
455792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
4565ac14e1cSStefano Zampini     }
4575f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
458f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
459792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
460792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
4615ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
462f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->alpha_Poisson->data;
463792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
464792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
4655ac14e1cSStefano Zampini     }
4665ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
467792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
4685ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
469f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->beta_Poisson->data;
470792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
471792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
472be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
473be14dc20SKerry Key       if (jac->interior) {
474be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
475be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
476be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
477be14dc20SKerry Key       } else {
478be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
479be14dc20SKerry Key       }
4805ac14e1cSStefano Zampini     }
4816bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
4826bf688a0SCe Qin       PetscInt           i;
4836bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
4846bf688a0SCe Qin       if (jac->ND_PiFull) {
485f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
486792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4876bf688a0SCe Qin       } else {
4886bf688a0SCe Qin         nd_parcsrfull = NULL;
4896bf688a0SCe Qin       }
4906bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4916bf688a0SCe Qin         if (jac->ND_Pi[i]) {
492f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
493792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4946bf688a0SCe Qin         } else {
4956bf688a0SCe Qin           nd_parcsr[i] = NULL;
4966bf688a0SCe Qin         }
4976bf688a0SCe Qin       }
498792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
4996bf688a0SCe Qin     }
5004cb006feSStefano Zampini   }
501863406b8SStefano Zampini   /* special case for ADS */
502863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
5035ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
5045ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
5056bf688a0SCe 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])))) {
5066bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
5079371c9d4SSatish 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");
5085f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
5095f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
5105ac14e1cSStefano Zampini     if (jac->coords[0]) {
5115ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
5125ac14e1cSStefano Zampini       coords[0] = NULL;
5135ac14e1cSStefano Zampini       coords[1] = NULL;
5145ac14e1cSStefano Zampini       coords[2] = NULL;
515792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
516792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
517792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
518792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
5195ac14e1cSStefano Zampini     }
520f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
521792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
522792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
523f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->C->data;
524792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
525792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
5266bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
5276bf688a0SCe Qin       PetscInt           i;
5286bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
5296bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
5306bf688a0SCe Qin       if (jac->RT_PiFull) {
531f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->RT_PiFull->data;
532792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
5336bf688a0SCe Qin       } else {
5346bf688a0SCe Qin         rt_parcsrfull = NULL;
5356bf688a0SCe Qin       }
5366bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
5376bf688a0SCe Qin         if (jac->RT_Pi[i]) {
538f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->RT_Pi[i]->data;
539792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
5406bf688a0SCe Qin         } else {
5416bf688a0SCe Qin           rt_parcsr[i] = NULL;
5426bf688a0SCe Qin         }
5436bf688a0SCe Qin       }
5446bf688a0SCe Qin       if (jac->ND_PiFull) {
545f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
546792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
5476bf688a0SCe Qin       } else {
5486bf688a0SCe Qin         nd_parcsrfull = NULL;
5496bf688a0SCe Qin       }
5506bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
5516bf688a0SCe Qin         if (jac->ND_Pi[i]) {
552f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
553792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
5546bf688a0SCe Qin         } else {
5556bf688a0SCe Qin           nd_parcsr[i] = NULL;
5566bf688a0SCe Qin         }
5576bf688a0SCe Qin       }
558792fecdfSBarry 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]);
5596bf688a0SCe Qin     }
560863406b8SStefano Zampini   }
561792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
562792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
563792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
56497c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
565792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
56697c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
5673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56816d9e3a6SLisandro Dalcin }
56916d9e3a6SLisandro Dalcin 
570d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
571d71ae5a4SJacob Faibussowitsch {
57216d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
573f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
57416d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
57516d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
57616d9e3a6SLisandro Dalcin 
57716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5789566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
5799566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
5809566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
5819566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
5829566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
583792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
584792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
585792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
5869371c9d4SSatish Balay   PetscStackCallExternalVoid(
5879371c9d4SSatish Balay     "Hypre solve", do {
5885f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
5895f80ce2aSJacob Faibussowitsch       if (hierr) {
5905f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
59185245615SPierre Jolivet         HYPRE_ClearAllErrors();
5925f80ce2aSJacob Faibussowitsch       }
5935f80ce2aSJacob Faibussowitsch     } while (0));
59416d9e3a6SLisandro Dalcin 
59548a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
5969566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
5979566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
5983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59916d9e3a6SLisandro Dalcin }
60016d9e3a6SLisandro Dalcin 
60185245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
60285245615SPierre Jolivet {
60385245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
604f4f49eeaSPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)jac->hpmat->data;
60585245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
60685245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
60785245615SPierre Jolivet   const PetscScalar  *b;
60885245615SPierre Jolivet   PetscScalar        *x;
60985245615SPierre Jolivet   PetscInt            m, N, lda;
61085245615SPierre Jolivet   hypre_Vector       *x_local;
61185245615SPierre Jolivet   PetscMemType        type;
61285245615SPierre Jolivet 
61385245615SPierre Jolivet   PetscFunctionBegin;
61485245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
61585245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
61685245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
61785245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
61885245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
61985245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
62085245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
62185245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
62285245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
62385245615SPierre 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);
62485245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
62585245615SPierre 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);
62685245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
62785245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
62885245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
62985245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
63085245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
63185245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
63285245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
63385245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
63485245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
63585245615SPierre Jolivet   PetscStackCallExternalVoid(
63685245615SPierre Jolivet     "Hypre solve", do {
63785245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
63885245615SPierre Jolivet       if (hierr) {
63985245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
64085245615SPierre Jolivet         HYPRE_ClearAllErrors();
64185245615SPierre Jolivet       }
64285245615SPierre Jolivet     } while (0));
64385245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
64485245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
64585245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
64685245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
64785245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
64885245615SPierre Jolivet }
64985245615SPierre Jolivet 
650d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
651d71ae5a4SJacob Faibussowitsch {
6528695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6538695de01SBarry Smith 
6548695de01SBarry Smith   PetscFunctionBegin;
6559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
6569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
6579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
6589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
6599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
6609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
6619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
6629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
6639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
6649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
6659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
6669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
6679566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
6689566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
6699566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
6709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
6719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
6729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
6739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
674be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
6759566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
6765ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
677be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
6785ac14e1cSStefano Zampini   jac->dim                   = 0;
6793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6808695de01SBarry Smith }
6818695de01SBarry Smith 
682d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
683d71ae5a4SJacob Faibussowitsch {
68416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
68516d9e3a6SLisandro Dalcin 
68616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6879566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
688792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
6899566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
6909566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
6919566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
69216d9e3a6SLisandro Dalcin 
6939566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
6949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
6959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
6969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
6979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
6989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
6999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
7009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
7012e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
702be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
7039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
7049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
70542e5ec60SJeff-Hadley   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", NULL));
7069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
7079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
7082e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
7093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71016d9e3a6SLisandro Dalcin }
71116d9e3a6SLisandro Dalcin 
712ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems PetscOptionsObject)
713d71ae5a4SJacob Faibussowitsch {
71416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
715ace3abfcSBarry Smith   PetscBool flag;
71616d9e3a6SLisandro Dalcin 
71716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
718d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
7199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
720792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
7219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
722792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
7239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
724792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
725d0609cedSBarry Smith   PetscOptionsHeadEnd();
7263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72716d9e3a6SLisandro Dalcin }
72816d9e3a6SLisandro Dalcin 
729d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
730d71ae5a4SJacob Faibussowitsch {
73116d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
7329f196a02SMartin Diehl   PetscBool isascii;
73316d9e3a6SLisandro Dalcin 
73416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
7359f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
7369f196a02SMartin Diehl   if (isascii) {
7379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
73816d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
73963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
74016d9e3a6SLisandro Dalcin     } else {
7419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
74216d9e3a6SLisandro Dalcin     }
74316d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
7449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
74516d9e3a6SLisandro Dalcin     } else {
7469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
74716d9e3a6SLisandro Dalcin     }
74816d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
74963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
75016d9e3a6SLisandro Dalcin     } else {
7519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
75216d9e3a6SLisandro Dalcin     }
75316d9e3a6SLisandro Dalcin   }
7543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75516d9e3a6SLisandro Dalcin }
75616d9e3a6SLisandro Dalcin 
7573c61a47dSLukas static const char *HYPREILUType[] = {
7583c61a47dSLukas   "Block-Jacobi-ILUk", "Block-Jacobi-ILUT", "", "", "", "", "", "", "", "", /* 0-9 */
7593c61a47dSLukas   "GMRES-ILUk",        "GMRES-ILUT",        "", "", "", "", "", "", "", "", /* 10-19 */
7603c61a47dSLukas   "NSH-ILUk",          "NSH-ILUT",          "", "", "", "", "", "", "", "", /* 20-29 */
7613c61a47dSLukas   "RAS-ILUk",          "RAS-ILUT",          "", "", "", "", "", "", "", "", /* 30-39 */
7623c61a47dSLukas   "ddPQ-GMRES-ILUk",   "ddPQ-GMRES-ILUT",   "", "", "", "", "", "", "", "", /* 40-49 */
7633c61a47dSLukas   "GMRES-ILU0"                                                              /* 50 */
7643c61a47dSLukas };
7653c61a47dSLukas 
7663c61a47dSLukas static const char *HYPREILUIterSetup[] = {"default", "async-in-place", "async-explicit", "sync-explicit", "semisync-explicit"};
7673c61a47dSLukas 
768ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ILU(PC pc, PetscOptionItems PetscOptionsObject)
7693c61a47dSLukas {
7703c61a47dSLukas   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
7713c61a47dSLukas   PetscBool flg;
7723c61a47dSLukas   PetscInt  indx;
7733c61a47dSLukas   PetscReal tmpdbl;
7743c61a47dSLukas   PetscBool tmp_truth;
7753c61a47dSLukas 
7763c61a47dSLukas   PetscFunctionBegin;
7773c61a47dSLukas   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ILU Options");
7783c61a47dSLukas 
7793c61a47dSLukas   /* ILU: ILU Type */
7803c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
7813a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetType, jac->hsolver, indx);
7823c61a47dSLukas 
7833c61a47dSLukas   /* ILU: ILU iterative setup type*/
7843c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_iterative_setup_type", "Set ILU iterative setup type", "None", HYPREILUIterSetup, PETSC_STATIC_ARRAY_LENGTH(HYPREILUIterSetup), HYPREILUIterSetup[0], &indx, &flg));
7853a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetIterativeSetupType, jac->hsolver, indx);
7863c61a47dSLukas 
7873c61a47dSLukas   /* ILU: ILU iterative setup option*/
7883c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
7893a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetIterativeSetupOption, jac->hsolver, indx);
7903c61a47dSLukas 
7913c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
7923c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
7933a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetIterativeSetupMaxIter, jac->hsolver, indx);
7943c61a47dSLukas 
7953c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
7963c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
7973a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetIterativeSetupTolerance, jac->hsolver, tmpdbl);
7983c61a47dSLukas 
7993c61a47dSLukas   /* ILU: ILU Print Level */
8003c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
8013a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetPrintLevel, jac->hsolver, indx);
8023c61a47dSLukas 
8033c61a47dSLukas   /* ILU: Logging */
8043c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
8053a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetLogging, jac->hsolver, indx);
8063c61a47dSLukas 
8073c61a47dSLukas   /* ILU: ILU Level */
8083c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
8093a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetLevelOfFill, jac->hsolver, indx);
8103c61a47dSLukas 
8113c61a47dSLukas   /* ILU: ILU Max NNZ per row */
8123c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
8133a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetMaxNnzPerRow, jac->hsolver, indx);
8143c61a47dSLukas 
8153c61a47dSLukas   /* ILU: tolerance */
8163c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_tol", "Tolerance for ILU", "None", 0, &tmpdbl, &flg));
8173a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetTol, jac->hsolver, tmpdbl);
8183c61a47dSLukas 
8193c61a47dSLukas   /* ILU: maximum iteration count */
8203c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
8213a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetMaxIter, jac->hsolver, indx);
8223c61a47dSLukas 
8233c61a47dSLukas   /* ILU: drop threshold */
8243c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_drop_threshold", "Drop threshold for ILU", "None", 0, &tmpdbl, &flg));
8253a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetDropThreshold, jac->hsolver, tmpdbl);
8263c61a47dSLukas 
8273c61a47dSLukas   /* ILU: Triangular Solve */
8283c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
8293a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetTriSolve, jac->hsolver, tmp_truth);
8303c61a47dSLukas 
8313c61a47dSLukas   /* ILU: Lower Jacobi iteration */
8323c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
8333a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetLowerJacobiIters, jac->hsolver, indx);
8343c61a47dSLukas 
8353c61a47dSLukas   /* ILU: Upper Jacobi iteration */
8363c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
8373a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetUpperJacobiIters, jac->hsolver, indx);
8383c61a47dSLukas 
8393c61a47dSLukas   /* ILU: local reordering */
8403c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
8413a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_ILUSetLocalReordering, jac->hsolver, tmp_truth);
8423c61a47dSLukas 
8433c61a47dSLukas   PetscOptionsHeadEnd();
8443c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
8453c61a47dSLukas }
8463c61a47dSLukas 
8473c61a47dSLukas static PetscErrorCode PCView_HYPRE_ILU(PC pc, PetscViewer viewer)
8483c61a47dSLukas {
8493c61a47dSLukas   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
8503c61a47dSLukas   hypre_ParILUData *ilu_data = (hypre_ParILUData *)jac->hsolver;
8519f196a02SMartin Diehl   PetscBool         isascii;
8523c61a47dSLukas   PetscInt          indx;
8533c61a47dSLukas   PetscReal         tmpdbl;
8543c61a47dSLukas   PetscReal        *tmpdbl3;
8553c61a47dSLukas 
8563c61a47dSLukas   PetscFunctionBegin;
8579f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
8589f196a02SMartin Diehl   if (isascii) {
8593c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ILU preconditioning\n"));
8603c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIluType", indx = hypre_ParILUDataIluType(ilu_data));
8613c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
8623c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLfil", indx = hypre_ParILUDataLfil(ilu_data));
8633c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
8643c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxIter", indx = hypre_ParILUDataMaxIter(ilu_data));
8653c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
8663c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxRowNnz", indx = hypre_ParILUDataMaxRowNnz(ilu_data));
8673c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
8683c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTriSolve", indx = hypre_ParILUDataTriSolve(ilu_data));
8693c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
8703c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTol", tmpdbl = hypre_ParILUDataTol(ilu_data));
8713c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", tmpdbl));
8723c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataDroptol", tmpdbl3 = hypre_ParILUDataDroptol(ilu_data));
8733c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e / %e / %e\n", tmpdbl3[0], tmpdbl3[1], tmpdbl3[2]));
8743c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataReorderingType", indx = hypre_ParILUDataReorderingType(ilu_data));
8753c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
8763c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLowerJacobiIters", indx = hypre_ParILUDataLowerJacobiIters(ilu_data));
8773c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
8783c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataUpperJacobiIters", indx = hypre_ParILUDataUpperJacobiIters(ilu_data));
8793c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
8803c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataPrintLevel", indx = hypre_ParILUDataPrintLevel(ilu_data));
8813c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
8823c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLogging", indx = hypre_ParILUDataLogging(ilu_data));
8833c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
8843c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupType", indx = hypre_ParILUDataIterativeSetupType(ilu_data));
8853c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
8863c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupOption", indx = hypre_ParILUDataIterativeSetupOption(ilu_data));
8873c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
8883c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupMaxIter", indx = hypre_ParILUDataIterativeSetupMaxIter(ilu_data));
8893c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
8903c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupTolerance", tmpdbl = hypre_ParILUDataIterativeSetupTolerance(ilu_data));
8913c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", tmpdbl));
8923c61a47dSLukas   }
8933c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
8943c61a47dSLukas }
8953c61a47dSLukas 
896ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems PetscOptionsObject)
897d71ae5a4SJacob Faibussowitsch {
898db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
8998bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
900db966c6cSHong Zhang 
901db966c6cSHong Zhang   PetscFunctionBegin;
902d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
9039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
904792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
9058bf83915SBarry Smith 
9069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
9078bf83915SBarry Smith   if (flag) {
9088bf83915SBarry Smith     PetscMPIInt size;
9098bf83915SBarry Smith 
9109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
9117827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
912792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
9138bf83915SBarry Smith   }
9148bf83915SBarry Smith 
9159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
9168bf83915SBarry Smith   if (flag) {
9178bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
918792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
9198bf83915SBarry Smith   }
920d0609cedSBarry Smith   PetscOptionsHeadEnd();
9213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
922db966c6cSHong Zhang }
923db966c6cSHong Zhang 
924d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
925d71ae5a4SJacob Faibussowitsch {
926db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
9279f196a02SMartin Diehl   PetscBool isascii;
928db966c6cSHong Zhang 
929db966c6cSHong Zhang   PetscFunctionBegin;
9309f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
9319f196a02SMartin Diehl   if (isascii) {
9329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
933db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
93463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
935db966c6cSHong Zhang     } else {
9369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
937db966c6cSHong Zhang     }
9389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
93963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
940db966c6cSHong Zhang   }
9413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
942db966c6cSHong Zhang }
943db966c6cSHong Zhang 
944d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
945d71ae5a4SJacob Faibussowitsch {
94616d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
947f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
94816d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
94916d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
95016d9e3a6SLisandro Dalcin 
95116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9529566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
9539566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
954af221044SPierre Jolivet   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
955af221044SPierre Jolivet   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
95616d9e3a6SLisandro Dalcin 
957792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
958792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
959792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
96016d9e3a6SLisandro Dalcin 
9619371c9d4SSatish Balay   PetscStackCallExternalVoid(
9629371c9d4SSatish Balay     "Hypre Transpose solve", do {
9635f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
9645f80ce2aSJacob Faibussowitsch       if (hierr) {
96516d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
9665f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
96785245615SPierre Jolivet         HYPRE_ClearAllErrors();
9685f80ce2aSJacob Faibussowitsch       }
9695f80ce2aSJacob Faibussowitsch     } while (0));
97016d9e3a6SLisandro Dalcin 
9719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
9729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
9733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97416d9e3a6SLisandro Dalcin }
97516d9e3a6SLisandro Dalcin 
976d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
977d71ae5a4SJacob Faibussowitsch {
978db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
979db6f9c32SMark Adams 
980db6f9c32SMark Adams   PetscFunctionBegin;
981db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
982db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
983db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
984db6f9c32SMark Adams #endif
9853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
986db6f9c32SMark Adams }
987db6f9c32SMark Adams 
98816d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
9890f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
99016d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
99165de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
9923c61a47dSLukas static const char *HYPREBoomerAMGSmoothType[] = {"ILU", "Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
9939371c9d4SSatish 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"};
9949371c9d4SSatish 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"};
995d7185485SAlex Lindsay 
996ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems PetscOptionsObject)
997d71ae5a4SJacob Faibussowitsch {
99816d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
99922e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
1000ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
100173dcfd97SStefano Zampini   PetscReal   tmpdbl, twodbl[2];
1002589dcaf0SStefano Zampini   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
100316d9e3a6SLisandro Dalcin 
100416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1005d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
10069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
100716d9e3a6SLisandro Dalcin   if (flg) {
10084336a9eeSBarry Smith     jac->cycletype = indx + 1;
1009792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
101016d9e3a6SLisandro Dalcin   }
101152ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg, 2));
101252ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
101352ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg, 1));
101452ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
101552ce0ab5SPierre 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));
101652ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
101722e51d31SStefano Zampini   bs = 1;
101848a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
10199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
102048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
102116d9e3a6SLisandro Dalcin 
102252ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg, 0.0));
102352ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
102416d9e3a6SLisandro Dalcin 
102552ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg, 0));
102652ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
10270f1074feSSatish Balay 
10289566063dSJacob 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));
1029792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
10300f1074feSSatish Balay 
103152ce0ab5SPierre 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));
103252ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
10330f1074feSSatish Balay 
103452ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg, 0.0));
103552ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
103652ce0ab5SPierre Jolivet   PetscCall(PetscOptionsRangeReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg, 0.0, 1.0));
103752ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
103816d9e3a6SLisandro Dalcin 
103916d9e3a6SLisandro Dalcin   /* Grid sweeps */
10409566063dSJacob 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));
104116d9e3a6SLisandro Dalcin   if (flg) {
104216d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
104316d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
10440f1074feSSatish Balay     jac->gridsweeps[1] = indx;
10450f1074feSSatish Balay     /*defaults coarse to 1 */
10460f1074feSSatish Balay     jac->gridsweeps[2] = 1;
104716d9e3a6SLisandro Dalcin   }
10489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
104948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
10509566063dSJacob 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));
105148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
10529566063dSJacob 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));
105348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
10549566063dSJacob 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));
105548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
10569566063dSJacob 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));
105748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
10589566063dSJacob 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));
105948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
10609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
106116d9e3a6SLisandro Dalcin   if (flg) {
1062792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
10630f1074feSSatish Balay     jac->gridsweeps[0] = indx;
106416d9e3a6SLisandro Dalcin   }
10659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
106616d9e3a6SLisandro Dalcin   if (flg) {
1067792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
10680f1074feSSatish Balay     jac->gridsweeps[1] = indx;
106916d9e3a6SLisandro Dalcin   }
10709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
107116d9e3a6SLisandro Dalcin   if (flg) {
1072792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
10730f1074feSSatish Balay     jac->gridsweeps[2] = indx;
107416d9e3a6SLisandro Dalcin   }
107516d9e3a6SLisandro Dalcin 
10766a251517SEike Mueller   /* Smooth type */
1077dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
10786a251517SEike Mueller   if (flg) {
10796a251517SEike Mueller     jac->smoothtype = indx;
10803c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 5);
10818131ecf7SEike Mueller     jac->smoothnumlevels = 25;
1082792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
10838131ecf7SEike Mueller   }
10848131ecf7SEike Mueller 
10858131ecf7SEike Mueller   /* Number of smoothing levels */
10869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
10878131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
10888131ecf7SEike Mueller     jac->smoothnumlevels = indx;
1089792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
10906a251517SEike Mueller   }
10916a251517SEike Mueller 
10923c61a47dSLukas   /* Smooth num sweeps */
10933c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_sweeps", "Set number of smoother sweeps", "None", 1, &indx, &flg));
10943c61a47dSLukas   if (flg && indx > 0) {
10953c61a47dSLukas     jac->smoothsweeps = indx;
10963c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumSweeps, jac->hsolver, indx);
10973c61a47dSLukas   }
10983c61a47dSLukas 
10993c61a47dSLukas   /* ILU: ILU Type */
11003c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
11013a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUType, jac->hsolver, indx);
11023c61a47dSLukas 
11033c61a47dSLukas   /* ILU: ILU iterative setup type*/
11043c61a47dSLukas   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));
11053a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupType, jac->hsolver, indx);
11063c61a47dSLukas 
11073c61a47dSLukas   /* ILU: ILU iterative setup option*/
11083c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
11093a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupOption, jac->hsolver, indx);
11103c61a47dSLukas 
11113c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
11123c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
11133a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupMaxIter, jac->hsolver, indx);
11143c61a47dSLukas 
11153c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
11163c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
11173a7d0413SPierre Jolivet   if (flg) PetscCallExternal(hypre_BoomerAMGSetILUIterSetupTolerance, jac->hsolver, tmpdbl);
11183c61a47dSLukas 
11193c61a47dSLukas   /* ILU: ILU Print Level */
11203c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
11213a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, indx);
11223c61a47dSLukas 
11233c61a47dSLukas   /* ILU: Logging */
11243c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
11253a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetLogging, jac->hsolver, indx);
11263c61a47dSLukas 
11273c61a47dSLukas   /* ILU: ILU Level */
11283c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
11293a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILULevel, jac->hsolver, indx);
11303c61a47dSLukas 
11313c61a47dSLukas   /* ILU: ILU Max NNZ per row */
11323c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
11333a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUMaxRowNnz, jac->hsolver, indx);
11343c61a47dSLukas 
11353c61a47dSLukas   /* ILU: maximum iteration count */
11363c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
11373a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUMaxIter, jac->hsolver, indx);
11383c61a47dSLukas 
11393c61a47dSLukas   /* ILU: drop threshold */
11403c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_drop_tol", "Drop tolerance for ILU", "None", 0, &tmpdbl, &flg));
11413a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUDroptol, jac->hsolver, tmpdbl);
11423c61a47dSLukas 
11433c61a47dSLukas   /* ILU: Triangular Solve */
11443c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
11453a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUTriSolve, jac->hsolver, tmp_truth);
11463c61a47dSLukas 
11473c61a47dSLukas   /* ILU: Lower Jacobi iteration */
11483c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
11493a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILULowerJacobiIters, jac->hsolver, indx);
11503c61a47dSLukas 
11513c61a47dSLukas   /* ILU: Upper Jacobi iteration */
11523c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
11533a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILUUpperJacobiIters, jac->hsolver, indx);
11543c61a47dSLukas 
11553c61a47dSLukas   /* ILU: local reordering */
11563c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
11573a7d0413SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetILULocalReordering, jac->hsolver, tmp_truth);
11583c61a47dSLukas 
11591810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
11609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
11613c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11621810e44eSEike Mueller     jac->eu_level = indx;
1163792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
11641810e44eSEike Mueller   }
11651810e44eSEike Mueller 
11661810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
116773dcfd97SStefano Zampini   PetscReal droptolerance;
11689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
11693c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11701810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
1171792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
11721810e44eSEike Mueller   }
11731810e44eSEike Mueller 
11741810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
11759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
11763c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11771810e44eSEike Mueller     jac->eu_bj = tmp_truth;
1178792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
11791810e44eSEike Mueller   }
11801810e44eSEike Mueller 
118116d9e3a6SLisandro Dalcin   /* Relax type */
1182dd39110bSPierre 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));
118316d9e3a6SLisandro Dalcin   if (flg) {
11840f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
1185792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
11860f1074feSSatish Balay     /* by default, coarse type set to 9 */
11870f1074feSSatish Balay     jac->relaxtype[2] = 9;
1188792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
118916d9e3a6SLisandro Dalcin   }
1190dd39110bSPierre 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));
119116d9e3a6SLisandro Dalcin   if (flg) {
119216d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
1193792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
119416d9e3a6SLisandro Dalcin   }
1195dd39110bSPierre 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));
119616d9e3a6SLisandro Dalcin   if (flg) {
11970f1074feSSatish Balay     jac->relaxtype[1] = indx;
1198792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
119916d9e3a6SLisandro Dalcin   }
1200dd39110bSPierre 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));
120116d9e3a6SLisandro Dalcin   if (flg) {
12020f1074feSSatish Balay     jac->relaxtype[2] = indx;
1203792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
120416d9e3a6SLisandro Dalcin   }
120516d9e3a6SLisandro Dalcin 
120616d9e3a6SLisandro Dalcin   /* Relaxation Weight */
12079566063dSJacob 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));
120816d9e3a6SLisandro Dalcin   if (flg) {
1209792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
121016d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
121116d9e3a6SLisandro Dalcin   }
121216d9e3a6SLisandro Dalcin 
121316d9e3a6SLisandro Dalcin   n         = 2;
121416d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
12159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
121616d9e3a6SLisandro Dalcin   if (flg) {
12170fdf79fbSJacob 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);
121816d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1219792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
122016d9e3a6SLisandro Dalcin   }
122116d9e3a6SLisandro Dalcin 
122216d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
12239566063dSJacob 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));
122416d9e3a6SLisandro Dalcin   if (flg) {
1225792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
122616d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
122716d9e3a6SLisandro Dalcin   }
122816d9e3a6SLisandro Dalcin 
122916d9e3a6SLisandro Dalcin   n         = 2;
123016d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
12319566063dSJacob 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));
123216d9e3a6SLisandro Dalcin   if (flg) {
12330fdf79fbSJacob 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);
123416d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1235792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
123616d9e3a6SLisandro Dalcin   }
123716d9e3a6SLisandro Dalcin 
123816d9e3a6SLisandro Dalcin   /* the Relax Order */
12399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
124016d9e3a6SLisandro Dalcin 
12418afaa268SBarry Smith   if (flg && tmp_truth) {
124216d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
1243792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
124416d9e3a6SLisandro Dalcin   }
1245dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
124616d9e3a6SLisandro Dalcin   if (flg) {
124716d9e3a6SLisandro Dalcin     jac->measuretype = indx;
1248792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
124916d9e3a6SLisandro Dalcin   }
12500f1074feSSatish Balay   /* update list length 3/07 */
1251dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
125216d9e3a6SLisandro Dalcin   if (flg) {
125316d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
1254792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
125516d9e3a6SLisandro Dalcin   }
12560f1074feSSatish Balay 
12579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
125848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
12599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
126048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
1261db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
1262db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
1263d7185485SAlex Lindsay   PetscCall(PetscOptionsEList("-pc_mg_galerkin_mat_product_algorithm", "Type of SpGEMM to use in hypre (only for now)", "PCMGGalerkinSetMatProductAlgorithm", HYPRESpgemmTypes, PETSC_STATIC_ARRAY_LENGTH(HYPRESpgemmTypes), HYPRESpgemmTypes[0], &indx, &flg));
1264d7185485SAlex Lindsay   if (flg) PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, HYPRESpgemmTypes[indx]));
1265db6f9c32SMark Adams #endif
1266589dcaf0SStefano Zampini   /* AIR */
1267589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
12689566063dSJacob 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));
1269792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1270589dcaf0SStefano Zampini   if (jac->Rtype) {
127119be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
127219be502cSAlexander     char       *prerelax[256];
127319be502cSAlexander     char       *postrelax[256];
127419be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
127519be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
127619be502cSAlexander     PetscBool   matchF, matchC, matchA;
127719be502cSAlexander 
1278589dcaf0SStefano 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 */
1279589dcaf0SStefano Zampini 
12809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
1281792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1282589dcaf0SStefano Zampini 
12839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
1284792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1285589dcaf0SStefano Zampini 
12869566063dSJacob 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));
1287792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1288589dcaf0SStefano Zampini 
12899566063dSJacob 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));
1290792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
129119be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
129219be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
129319be502cSAlexander     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");
129419be502cSAlexander     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");
129519be502cSAlexander 
129619be502cSAlexander     grid_relax_points[0]    = NULL;
129719be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
129819be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
129919be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
130019be502cSAlexander     grid_relax_points[3][0] = 0;
130119be502cSAlexander 
130219be502cSAlexander     // set down relax scheme
130319be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
130419be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
130519be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
130619be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
130719be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
130819be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
130919be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
131019be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
131119be502cSAlexander     }
131219be502cSAlexander 
131319be502cSAlexander     // set up relax scheme
131419be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
131519be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
131619be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
131719be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
131819be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
131919be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
132019be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
132119be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
132219be502cSAlexander     }
132319be502cSAlexander 
132419be502cSAlexander     // set coarse relax scheme
132519be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
132619be502cSAlexander 
132719be502cSAlexander     // Pass relax schemes to hypre
132819be502cSAlexander     PetscCallExternal(HYPRE_BoomerAMGSetGridRelaxPoints, jac->hsolver, grid_relax_points);
132919be502cSAlexander 
133019be502cSAlexander     // cleanup memory
133119be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
133219be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1333589dcaf0SStefano Zampini   }
1334589dcaf0SStefano Zampini #endif
1335589dcaf0SStefano Zampini 
1336ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
133763a3b9bcSJacob 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);
1338ecae95adSPierre Jolivet #endif
1339ecae95adSPierre Jolivet 
13400f1074feSSatish Balay   /* new 3/07 */
1341dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1342589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1343589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1344792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
13450f1074feSSatish Balay   }
13460f1074feSSatish Balay 
13479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
134816d9e3a6SLisandro Dalcin   if (flg) {
1349b96a4a96SBarry Smith     level = 3;
13509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
13512fa5cd67SKarl Rupp 
1352b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1353792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
13542ae77aedSBarry Smith   }
13552ae77aedSBarry Smith 
13569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
13572ae77aedSBarry Smith   if (flg) {
1358b96a4a96SBarry Smith     level = 3;
13599566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
13602fa5cd67SKarl Rupp 
1361b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1362792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
136316d9e3a6SLisandro Dalcin   }
13648f87f92bSBarry Smith 
13659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
13668f87f92bSBarry Smith   if (flg && tmp_truth) {
13678f87f92bSBarry Smith     PetscInt tmp_int;
13689566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
13698f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1370792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1371792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1372792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1373792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
13748f87f92bSBarry Smith   }
13758f87f92bSBarry Smith 
13769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1377792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1378589dcaf0SStefano Zampini 
1379589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1380dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1381589dcaf0SStefano Zampini   if (flg) {
1382589dcaf0SStefano Zampini     jac->symt = indx;
1383792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1384589dcaf0SStefano Zampini   }
1385589dcaf0SStefano Zampini 
1386d0609cedSBarry Smith   PetscOptionsHeadEnd();
13873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
138816d9e3a6SLisandro Dalcin }
138916d9e3a6SLisandro Dalcin 
1390d71ae5a4SJacob 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)
1391d71ae5a4SJacob Faibussowitsch {
139216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13932cf14000SStefano Zampini   HYPRE_Int oits;
139416d9e3a6SLisandro Dalcin 
139516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
13969566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1397792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1398792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
139916d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
14009566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
140116d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1402792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
14034d0a8057SBarry Smith   *outits = oits;
14044d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
14054d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1406792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1407792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
14083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
140916d9e3a6SLisandro Dalcin }
141016d9e3a6SLisandro Dalcin 
1411d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1412d71ae5a4SJacob Faibussowitsch {
141316d9e3a6SLisandro Dalcin   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
14143c61a47dSLukas   hypre_ParAMGData *amg_data = (hypre_ParAMGData *)jac->hsolver;
14159f196a02SMartin Diehl   PetscBool         isascii;
14163c61a47dSLukas   PetscInt          indx;
14173c61a47dSLukas   PetscReal         val;
141816d9e3a6SLisandro Dalcin 
141916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
14209f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
14219f196a02SMartin Diehl   if (isascii) {
14229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
14239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
142463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
142563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
14269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
14279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
14289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
142963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
143048a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
143163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
143263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
14330f1074feSSatish Balay 
14349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
143516d9e3a6SLisandro Dalcin 
143663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
143763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
143863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
143916d9e3a6SLisandro Dalcin 
14409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
14419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
14429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
144316d9e3a6SLisandro Dalcin 
14449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
14459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
144616d9e3a6SLisandro Dalcin 
144719be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
144819be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
144919be502cSAlexander 
145016d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
14519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
145216d9e3a6SLisandro Dalcin     } else {
14539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
145416d9e3a6SLisandro Dalcin     }
14556a251517SEike Mueller     if (jac->smoothtype != -1) {
14569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
145763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
14583c61a47dSLukas       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num sweeps    %" PetscInt_FMT "\n", jac->smoothsweeps));
14593c61a47dSLukas       if (jac->smoothtype == 0) {
14603c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUType", indx = hypre_ParAMGDataILUType(amg_data));
14613c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
14623c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULevel", indx = hypre_ParAMGDataILULevel(amg_data));
14633c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
14643c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxIter", indx = hypre_ParAMGDataILUMaxIter(amg_data));
14653c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
14663c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxRowNnz", indx = hypre_ParAMGDataILUMaxRowNnz(amg_data));
14673c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
14683c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUTriSolve", indx = hypre_ParAMGDataILUTriSolve(amg_data));
14693c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
14703c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataTol", val = hypre_ParAMGDataTol(amg_data));
14713c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", val));
14723c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUDroptol", val = hypre_ParAMGDataILUDroptol(amg_data));
14733c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e\n", val));
14743c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULocalReordering", indx = hypre_ParAMGDataILULocalReordering(amg_data));
14753c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
14763c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULowerJacobiIters", indx = hypre_ParAMGDataILULowerJacobiIters(amg_data));
14773c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
14783c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUUpperJacobiIters", indx = hypre_ParAMGDataILUUpperJacobiIters(amg_data));
14793c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
14803c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataPrintLevel", indx = hypre_ParAMGDataPrintLevel(amg_data));
14813c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
14823c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataLogging", indx = hypre_ParAMGDataLogging(amg_data));
14833c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
14843c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupType", indx = hypre_ParAMGDataILUIterSetupType(amg_data));
14853c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
14863c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupOption", indx = hypre_ParAMGDataILUIterSetupOption(amg_data));
14873c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
14883c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupMaxIter", indx = hypre_ParAMGDataILUIterSetupMaxIter(amg_data));
14893c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
14903c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupTolerance", val = hypre_ParAMGDataILUIterSetupTolerance(amg_data));
14913c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", val));
14923c61a47dSLukas       }
14937e352d70SEike Mueller     } else {
14949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
14951810e44eSEike Mueller     }
14961810e44eSEike Mueller     if (jac->smoothtype == 3) {
149763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
14989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
149963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
15006a251517SEike Mueller     }
15019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
15029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
15039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
150448a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
15055272c319SBarry Smith     if (jac->vec_interp_variant) {
150663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
150763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
15089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
15098f87f92bSBarry Smith     }
151048a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1511db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
15129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
15132d6c3ceeSStefano Zampini #else
15142d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1515db6f9c32SMark Adams #endif
1516589dcaf0SStefano Zampini     /* AIR */
1517589dcaf0SStefano Zampini     if (jac->Rtype) {
151863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
15199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
15209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
15219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
152263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1523589dcaf0SStefano Zampini     }
152416d9e3a6SLisandro Dalcin   }
15253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
152616d9e3a6SLisandro Dalcin }
152716d9e3a6SLisandro Dalcin 
1528ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems PetscOptionsObject)
1529d71ae5a4SJacob Faibussowitsch {
153016d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
15314ddd07fcSJed Brown   PetscInt    indx;
1532ace3abfcSBarry Smith   PetscBool   flag;
153316d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
153416d9e3a6SLisandro Dalcin 
153516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1536d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
15379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
15389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1539792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
154016d9e3a6SLisandro Dalcin 
15419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1542792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
154316d9e3a6SLisandro Dalcin 
15449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1545792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
154616d9e3a6SLisandro Dalcin 
15479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1548792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
154916d9e3a6SLisandro Dalcin 
15509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1551792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
155216d9e3a6SLisandro Dalcin 
1553dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
155416d9e3a6SLisandro Dalcin   if (flag) {
155516d9e3a6SLisandro Dalcin     jac->symt = indx;
1556792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
155716d9e3a6SLisandro Dalcin   }
155816d9e3a6SLisandro Dalcin 
1559d0609cedSBarry Smith   PetscOptionsHeadEnd();
15603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
156116d9e3a6SLisandro Dalcin }
156216d9e3a6SLisandro Dalcin 
1563d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1564d71ae5a4SJacob Faibussowitsch {
156516d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
15669f196a02SMartin Diehl   PetscBool   isascii;
1567feb237baSPierre Jolivet   const char *symt = 0;
156816d9e3a6SLisandro Dalcin 
156916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
15709f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
15719f196a02SMartin Diehl   if (isascii) {
15729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
157363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
15749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
15759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
15769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
15779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
15789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
15792fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
15802fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
15812fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
158263a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
15839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
158416d9e3a6SLisandro Dalcin   }
15853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
158616d9e3a6SLisandro Dalcin }
1587f1580f4eSBarry Smith 
1588ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems PetscOptionsObject)
1589d71ae5a4SJacob Faibussowitsch {
15904cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15914cb006feSStefano Zampini   PetscInt  n;
15924cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
15934cb006feSStefano Zampini 
15944cb006feSStefano Zampini   PetscFunctionBegin;
1595d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
15969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1597792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
15989566063dSJacob 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));
1599792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
16009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1601792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
16029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1603792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
16049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
16059566063dSJacob 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));
16069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
16079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
160848a46eb9SPierre 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);
16099566063dSJacob 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));
16104cb006feSStefano Zampini   n = 5;
16119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
16124cb006feSStefano Zampini   if (flag || flag2) {
1613792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1614863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1615863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
16169371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1617a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
16184cb006feSStefano Zampini   }
16199566063dSJacob 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));
16204cb006feSStefano Zampini   n = 5;
16219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
16224cb006feSStefano Zampini   if (flag || flag2) {
1623792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1624863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1625863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
16269371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1627a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
16284cb006feSStefano Zampini   }
16299566063dSJacob 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));
163023df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1631792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
163223df4f25SStefano Zampini   }
1633d0609cedSBarry Smith   PetscOptionsHeadEnd();
16343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16354cb006feSStefano Zampini }
16364cb006feSStefano Zampini 
1637d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1638d71ae5a4SJacob Faibussowitsch {
16394cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16409f196a02SMartin Diehl   PetscBool isascii;
16414cb006feSStefano Zampini 
16424cb006feSStefano Zampini   PetscFunctionBegin;
16439f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
16449f196a02SMartin Diehl   if (isascii) {
16459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
164663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
164763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
164863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
164963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
165063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
165163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
165263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
16534cb006feSStefano Zampini     if (jac->alpha_Poisson) {
16549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
16554cb006feSStefano Zampini     } else {
16569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
16574cb006feSStefano Zampini     }
165863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
165963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
166063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
166163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
166263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
166363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
16644cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
16654cb006feSStefano Zampini       if (jac->beta_Poisson) {
16669566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
16674cb006feSStefano Zampini       } else {
16689566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
16694cb006feSStefano Zampini       }
167063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
167163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
167263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
167363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
167463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
167563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
167648a46eb9SPierre 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));
167723df4f25SStefano Zampini     } else {
16789566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
16794cb006feSStefano Zampini     }
16804cb006feSStefano Zampini   }
16813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16824cb006feSStefano Zampini }
16834cb006feSStefano Zampini 
1684ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems PetscOptionsObject)
1685d71ae5a4SJacob Faibussowitsch {
1686863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1687863406b8SStefano Zampini   PetscInt  n;
1688863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1689863406b8SStefano Zampini 
1690863406b8SStefano Zampini   PetscFunctionBegin;
1691d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
16929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1693792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
16949566063dSJacob 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));
1695792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
16969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1697792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
16989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1699792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
17009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
17019566063dSJacob 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));
17029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
17039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
170448a46eb9SPierre 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);
17059566063dSJacob 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));
1706863406b8SStefano Zampini   n = 5;
17079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
17089566063dSJacob 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));
1709863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1710792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1711863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1712863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1713863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
17149371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1715a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1716863406b8SStefano Zampini   }
17179566063dSJacob 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));
1718863406b8SStefano Zampini   n = 5;
17199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1720863406b8SStefano Zampini   if (flag || flag2) {
1721792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1722863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1723863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
17249371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1725a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1726863406b8SStefano Zampini   }
1727d0609cedSBarry Smith   PetscOptionsHeadEnd();
17283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1729863406b8SStefano Zampini }
1730863406b8SStefano Zampini 
1731d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1732d71ae5a4SJacob Faibussowitsch {
1733863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17349f196a02SMartin Diehl   PetscBool isascii;
1735863406b8SStefano Zampini 
1736863406b8SStefano Zampini   PetscFunctionBegin;
17379f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
17389f196a02SMartin Diehl   if (isascii) {
17399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
174063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
174163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
174263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
174363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
174463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
174563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
174663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
17479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
174863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
174963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
175063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
175163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
175263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
175363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
175463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
17559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
175663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
175763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
175863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
175963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
176063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
176163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1762863406b8SStefano Zampini   }
17633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1764863406b8SStefano Zampini }
1765863406b8SStefano Zampini 
1766d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1767d71ae5a4SJacob Faibussowitsch {
17684cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17695ac14e1cSStefano Zampini   PetscBool ishypre;
17704cb006feSStefano Zampini 
17714cb006feSStefano Zampini   PetscFunctionBegin;
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
17735ac14e1cSStefano Zampini   if (ishypre) {
17749566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
17759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17765ac14e1cSStefano Zampini     jac->G = G;
17775ac14e1cSStefano Zampini   } else {
17789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17799566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
17805ac14e1cSStefano Zampini   }
17813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17824cb006feSStefano Zampini }
17834cb006feSStefano Zampini 
17844cb006feSStefano Zampini /*@
1785*c3466c22SBarry Smith   PCHYPRESetDiscreteGradient - Set the discrete gradient matrix for `PCHYPRE` type of AMS or ADS
17864cb006feSStefano Zampini 
1787c3339decSBarry Smith   Collective
17884cb006feSStefano Zampini 
17894cb006feSStefano Zampini   Input Parameters:
17904cb006feSStefano Zampini + pc - the preconditioning context
17914cb006feSStefano Zampini - G  - the discrete gradient
17924cb006feSStefano Zampini 
17934cb006feSStefano Zampini   Level: intermediate
17944cb006feSStefano Zampini 
179595452b02SPatrick Sanan   Notes:
1796*c3466c22SBarry Smith   `G` should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1797147403d9SBarry Smith 
1798*c3466c22SBarry Smith   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
17994cb006feSStefano Zampini 
1800*c3466c22SBarry Smith   Developer Note:
1801f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1802f1580f4eSBarry Smith 
1803562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
18044cb006feSStefano Zampini @*/
1805d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1806d71ae5a4SJacob Faibussowitsch {
18074cb006feSStefano Zampini   PetscFunctionBegin;
18084cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
18094cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
18104cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1811cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
18123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18134cb006feSStefano Zampini }
18144cb006feSStefano Zampini 
1815d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1816d71ae5a4SJacob Faibussowitsch {
1817863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18185ac14e1cSStefano Zampini   PetscBool ishypre;
1819863406b8SStefano Zampini 
1820863406b8SStefano Zampini   PetscFunctionBegin;
18219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
18225ac14e1cSStefano Zampini   if (ishypre) {
18239566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
18249566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
18255ac14e1cSStefano Zampini     jac->C = C;
18265ac14e1cSStefano Zampini   } else {
18279566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
18289566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
18295ac14e1cSStefano Zampini   }
18303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1831863406b8SStefano Zampini }
1832863406b8SStefano Zampini 
1833863406b8SStefano Zampini /*@
1834*c3466c22SBarry Smith   PCHYPRESetDiscreteCurl - Set the discrete curl matrix for `PCHYPRE` type of ADS
1835863406b8SStefano Zampini 
1836c3339decSBarry Smith   Collective
1837863406b8SStefano Zampini 
1838863406b8SStefano Zampini   Input Parameters:
1839863406b8SStefano Zampini + pc - the preconditioning context
1840863406b8SStefano Zampini - C  - the discrete curl
1841863406b8SStefano Zampini 
1842863406b8SStefano Zampini   Level: intermediate
1843863406b8SStefano Zampini 
184495452b02SPatrick Sanan   Notes:
1845*c3466c22SBarry Smith   `C` should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1846147403d9SBarry Smith 
1847*c3466c22SBarry Smith   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.
1848*c3466c22SBarry Smith   Matrix entries are +1 and -1 depending on edge orientation with respect to the face orientation
1849863406b8SStefano Zampini 
1850feefa0e1SJacob Faibussowitsch   Developer Notes:
1851f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1852f1580f4eSBarry Smith 
1853*c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of ADS it should be called `PCHYPREADSSetDiscreteCurl()`
1854f1580f4eSBarry Smith 
1855562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1856863406b8SStefano Zampini @*/
1857d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1858d71ae5a4SJacob Faibussowitsch {
1859863406b8SStefano Zampini   PetscFunctionBegin;
1860863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1861863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1862863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1863cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
18643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1865863406b8SStefano Zampini }
1866863406b8SStefano Zampini 
1867d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1868d71ae5a4SJacob Faibussowitsch {
18696bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18706bf688a0SCe Qin   PetscBool ishypre;
18716bf688a0SCe Qin   PetscInt  i;
18726bf688a0SCe Qin 
18734d86920dSPierre Jolivet   PetscFunctionBegin;
18749566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
18759566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
18766bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
18779566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
18789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
18796bf688a0SCe Qin   }
18806bf688a0SCe Qin 
18816bf688a0SCe Qin   jac->dim = dim;
18826bf688a0SCe Qin   if (RT_PiFull) {
18839566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
18846bf688a0SCe Qin     if (ishypre) {
18859566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
18866bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
18876bf688a0SCe Qin     } else {
18889566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
18896bf688a0SCe Qin     }
18906bf688a0SCe Qin   }
18916bf688a0SCe Qin   if (RT_Pi) {
18926bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18936bf688a0SCe Qin       if (RT_Pi[i]) {
18949566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
18956bf688a0SCe Qin         if (ishypre) {
18969566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
18976bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
18986bf688a0SCe Qin         } else {
18999566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
19006bf688a0SCe Qin         }
19016bf688a0SCe Qin       }
19026bf688a0SCe Qin     }
19036bf688a0SCe Qin   }
19046bf688a0SCe Qin   if (ND_PiFull) {
19059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
19066bf688a0SCe Qin     if (ishypre) {
19079566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
19086bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
19096bf688a0SCe Qin     } else {
19109566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
19116bf688a0SCe Qin     }
19126bf688a0SCe Qin   }
19136bf688a0SCe Qin   if (ND_Pi) {
19146bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19156bf688a0SCe Qin       if (ND_Pi[i]) {
19169566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
19176bf688a0SCe Qin         if (ishypre) {
19189566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
19196bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
19206bf688a0SCe Qin         } else {
19219566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
19226bf688a0SCe Qin         }
19236bf688a0SCe Qin       }
19246bf688a0SCe Qin     }
19256bf688a0SCe Qin   }
19263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19276bf688a0SCe Qin }
19286bf688a0SCe Qin 
19296bf688a0SCe Qin /*@
1930*c3466c22SBarry Smith   PCHYPRESetInterpolations - Set the interpolation matrices for `PCHYPRE` type of AMS or ADS
19316bf688a0SCe Qin 
1932c3339decSBarry Smith   Collective
19336bf688a0SCe Qin 
19346bf688a0SCe Qin   Input Parameters:
19356bf688a0SCe Qin + pc        - the preconditioning context
19362fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
19372fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
19382fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
19392fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
19406bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
19416bf688a0SCe Qin 
1942f1580f4eSBarry Smith   Level: intermediate
1943f1580f4eSBarry Smith 
194495452b02SPatrick Sanan   Notes:
1945*c3466c22SBarry Smith   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to `NULL`.
1946147403d9SBarry Smith 
19476bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1948147403d9SBarry Smith 
1949*c3466c22SBarry Smith   Developer Note:
1950f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
19516bf688a0SCe Qin 
1952562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`
19536bf688a0SCe Qin @*/
1954d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1955d71ae5a4SJacob Faibussowitsch {
19566bf688a0SCe Qin   PetscInt i;
19576bf688a0SCe Qin 
19586bf688a0SCe Qin   PetscFunctionBegin;
19596bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
19606bf688a0SCe Qin   if (RT_PiFull) {
19616bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
19626bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
19636bf688a0SCe Qin   }
19646bf688a0SCe Qin   if (RT_Pi) {
19654f572ea9SToby Isaac     PetscAssertPointer(RT_Pi, 4);
19666bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19676bf688a0SCe Qin       if (RT_Pi[i]) {
19686bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
19696bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
19706bf688a0SCe Qin       }
19716bf688a0SCe Qin     }
19726bf688a0SCe Qin   }
19736bf688a0SCe Qin   if (ND_PiFull) {
19746bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
19756bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
19766bf688a0SCe Qin   }
19776bf688a0SCe Qin   if (ND_Pi) {
19784f572ea9SToby Isaac     PetscAssertPointer(ND_Pi, 6);
19796bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19806bf688a0SCe Qin       if (ND_Pi[i]) {
19816bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
19826bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
19836bf688a0SCe Qin       }
19846bf688a0SCe Qin     }
19856bf688a0SCe Qin   }
1986cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
19873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19886bf688a0SCe Qin }
19896bf688a0SCe Qin 
1990d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1991d71ae5a4SJacob Faibussowitsch {
19924cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
19935ac14e1cSStefano Zampini   PetscBool ishypre;
19944cb006feSStefano Zampini 
19954cb006feSStefano Zampini   PetscFunctionBegin;
19969566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
19975ac14e1cSStefano Zampini   if (ishypre) {
19985ac14e1cSStefano Zampini     if (isalpha) {
19999566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
20009566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
20015ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
20025ac14e1cSStefano Zampini     } else {
20035ac14e1cSStefano Zampini       if (A) {
20049566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
20055ac14e1cSStefano Zampini       } else {
20065ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
20075ac14e1cSStefano Zampini       }
20089566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
20095ac14e1cSStefano Zampini       jac->beta_Poisson = A;
20105ac14e1cSStefano Zampini     }
20115ac14e1cSStefano Zampini   } else {
20125ac14e1cSStefano Zampini     if (isalpha) {
20139566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
20149566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
20155ac14e1cSStefano Zampini     } else {
20165ac14e1cSStefano Zampini       if (A) {
20179566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
20189566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
20195ac14e1cSStefano Zampini       } else {
20209566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
20215ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
20225ac14e1cSStefano Zampini       }
20235ac14e1cSStefano Zampini     }
20245ac14e1cSStefano Zampini   }
20253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20264cb006feSStefano Zampini }
20274cb006feSStefano Zampini 
20284cb006feSStefano Zampini /*@
2029*c3466c22SBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set the vector Poisson matrix for `PCHYPRE` of type AMS
20304cb006feSStefano Zampini 
2031c3339decSBarry Smith   Collective
20324cb006feSStefano Zampini 
20334cb006feSStefano Zampini   Input Parameters:
20344cb006feSStefano Zampini + pc - the preconditioning context
20354cb006feSStefano Zampini - A  - the matrix
20364cb006feSStefano Zampini 
20374cb006feSStefano Zampini   Level: intermediate
20384cb006feSStefano Zampini 
2039f1580f4eSBarry Smith   Note:
2040*c3466c22SBarry Smith   `A` should be obtained by discretizing the vector valued Poisson problem with linear finite elements
20414cb006feSStefano Zampini 
2042feefa0e1SJacob Faibussowitsch   Developer Notes:
2043f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
2044f1580f4eSBarry Smith 
2045*c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of AMS it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
2046f1580f4eSBarry Smith 
2047562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
20484cb006feSStefano Zampini @*/
2049d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
2050d71ae5a4SJacob Faibussowitsch {
20514cb006feSStefano Zampini   PetscFunctionBegin;
20524cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20534cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
20544cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
2055cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
20563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20574cb006feSStefano Zampini }
20584cb006feSStefano Zampini 
20594cb006feSStefano Zampini /*@
2060*c3466c22SBarry Smith   PCHYPRESetBetaPoissonMatrix - Set the Poisson matrix for `PCHYPRE` of type AMS
20614cb006feSStefano Zampini 
2062c3339decSBarry Smith   Collective
20634cb006feSStefano Zampini 
20644cb006feSStefano Zampini   Input Parameters:
20654cb006feSStefano Zampini + pc - the preconditioning context
2066*c3466c22SBarry Smith - A  - the matrix, or `NULL` to turn it off
20674cb006feSStefano Zampini 
20684cb006feSStefano Zampini   Level: intermediate
20694cb006feSStefano Zampini 
2070f1580f4eSBarry Smith   Note:
2071*c3466c22SBarry Smith   `A` should be obtained by discretizing the Poisson problem with linear finite elements.
20724cb006feSStefano Zampini 
2073feefa0e1SJacob Faibussowitsch   Developer Notes:
2074f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
2075f1580f4eSBarry Smith 
2076*c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of AMS it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
2077f1580f4eSBarry Smith 
2078562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
20794cb006feSStefano Zampini @*/
2080d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
2081d71ae5a4SJacob Faibussowitsch {
20824cb006feSStefano Zampini   PetscFunctionBegin;
20834cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20844cb006feSStefano Zampini   if (A) {
20854cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
20864cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
20874cb006feSStefano Zampini   }
2088cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
20893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20904cb006feSStefano Zampini }
20914cb006feSStefano Zampini 
2092d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
2093d71ae5a4SJacob Faibussowitsch {
20944cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
20954cb006feSStefano Zampini 
20964cb006feSStefano Zampini   PetscFunctionBegin;
20974cb006feSStefano Zampini   /* throw away any vector if already set */
20989566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
20999566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
21009566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
21019566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
21029566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
21039566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
21049566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
21055ac14e1cSStefano Zampini   jac->dim = 2;
21064cb006feSStefano Zampini   if (zzo) {
21079566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
21089566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
21095ac14e1cSStefano Zampini     jac->dim++;
21104cb006feSStefano Zampini   }
21113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21124cb006feSStefano Zampini }
21134cb006feSStefano Zampini 
21144cb006feSStefano Zampini /*@
2115*c3466c22SBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type AMS
21164cb006feSStefano Zampini 
2117c3339decSBarry Smith   Collective
21184cb006feSStefano Zampini 
21194cb006feSStefano Zampini   Input Parameters:
21204cb006feSStefano Zampini + pc  - the preconditioning context
21212fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
21222fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
21234cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
21244cb006feSStefano Zampini 
21254cb006feSStefano Zampini   Level: intermediate
21264cb006feSStefano Zampini 
2127*c3466c22SBarry Smith   Developer Note:
2128*c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of AMS it should be called `PCHYPREAMSSetEdgeConstantVectors()`
2129f1580f4eSBarry Smith 
2130562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
21314cb006feSStefano Zampini @*/
2132d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
2133d71ae5a4SJacob Faibussowitsch {
21344cb006feSStefano Zampini   PetscFunctionBegin;
21354cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
21364cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
21374cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
21384cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
21394cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
21404cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
21414cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
2142cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
21433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21444cb006feSStefano Zampini }
21454cb006feSStefano Zampini 
2146d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
2147d71ae5a4SJacob Faibussowitsch {
2148be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2149be14dc20SKerry Key 
2150be14dc20SKerry Key   PetscFunctionBegin;
2151be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
2152be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
2153be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
2154be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
21553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2156be14dc20SKerry Key }
2157be14dc20SKerry Key 
2158be14dc20SKerry Key /*@
2159*c3466c22SBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type AMS
2160be14dc20SKerry Key 
2161c3339decSBarry Smith   Collective
2162be14dc20SKerry Key 
2163be14dc20SKerry Key   Input Parameters:
2164be14dc20SKerry Key + pc       - the preconditioning context
2165be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
2166be14dc20SKerry Key 
2167be14dc20SKerry Key   Level: intermediate
2168be14dc20SKerry Key 
2169be14dc20SKerry Key   Note:
2170f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
2171f1580f4eSBarry Smith 
2172562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
2173be14dc20SKerry Key @*/
2174d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
2175d71ae5a4SJacob Faibussowitsch {
2176be14dc20SKerry Key   PetscFunctionBegin;
2177be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2178be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
2179be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
2180be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
21813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2182be14dc20SKerry Key }
2183be14dc20SKerry Key 
2184d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2185d71ae5a4SJacob Faibussowitsch {
21864cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
21874cb006feSStefano Zampini   Vec       tv;
21884cb006feSStefano Zampini   PetscInt  i;
21894cb006feSStefano Zampini 
21904cb006feSStefano Zampini   PetscFunctionBegin;
21914cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
21929566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
21939566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
21949566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
21955ac14e1cSStefano Zampini   jac->dim = dim;
21965ac14e1cSStefano Zampini 
21974cb006feSStefano Zampini   /* compute IJ vector for coordinates */
21989566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
21999566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
22009566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
22014cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
22024cb006feSStefano Zampini     PetscScalar *array;
22034cb006feSStefano Zampini     PetscInt     j;
22044cb006feSStefano Zampini 
22059566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
22069566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
22076ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
22089566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
22099566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
22104cb006feSStefano Zampini   }
22119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
22123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22134cb006feSStefano Zampini }
22144cb006feSStefano Zampini 
2215d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
2216d71ae5a4SJacob Faibussowitsch {
221716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
221816d9e3a6SLisandro Dalcin 
221916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
222016d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
22213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
222216d9e3a6SLisandro Dalcin }
222316d9e3a6SLisandro Dalcin 
2224d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
2225d71ae5a4SJacob Faibussowitsch {
222616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2227ace3abfcSBarry Smith   PetscBool flag;
222816d9e3a6SLisandro Dalcin 
222916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
223016d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
22319566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
2232d7185485SAlex Lindsay     if (flag) PetscFunctionReturn(PETSC_SUCCESS);
223316d9e3a6SLisandro Dalcin   }
223416d9e3a6SLisandro Dalcin 
2235d7185485SAlex Lindsay   PetscCall(PCReset_HYPRE(pc));
2236d7185485SAlex Lindsay   PetscCall(PetscFree(jac->hypre_type));
2237d7185485SAlex Lindsay   PetscCall(PetscStrallocpy(name, &jac->hypre_type));
2238d7185485SAlex Lindsay 
223916d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
224016d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
224116d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
224216d9e3a6SLisandro Dalcin 
22433c61a47dSLukas   PetscCall(PetscStrcmp("ilu", jac->hypre_type, &flag));
22443c61a47dSLukas   if (flag) {
22453c61a47dSLukas     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
22463c61a47dSLukas     PetscCallExternal(HYPRE_ILUCreate, &jac->hsolver);
22473c61a47dSLukas     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ILU;
22483c61a47dSLukas     pc->ops->view           = PCView_HYPRE_ILU;
22493c61a47dSLukas     jac->destroy            = HYPRE_ILUDestroy;
22503c61a47dSLukas     jac->setup              = HYPRE_ILUSetup;
22513c61a47dSLukas     jac->solve              = HYPRE_ILUSolve;
22523c61a47dSLukas     jac->factorrowsize      = PETSC_DEFAULT;
22533c61a47dSLukas     PetscFunctionReturn(PETSC_SUCCESS);
22543c61a47dSLukas   }
22553c61a47dSLukas 
22569566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
225716d9e3a6SLisandro Dalcin   if (flag) {
22589566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2259792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
226016d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
226116d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
226216d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
226316d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
226416d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
226516d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
22663ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
226716d9e3a6SLisandro Dalcin   }
22689566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
2269db966c6cSHong Zhang   if (flag) {
22704e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
22717de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
22728bf83915SBarry Smith #endif
22739566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2274792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
2275db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
2276db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
2277db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
2278db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
2279db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
2280db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
2281db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
22823ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2283db966c6cSHong Zhang   }
22849566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
228516d9e3a6SLisandro Dalcin   if (flag) {
22869566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2287792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
228816d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
228916d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
229016d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
229116d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
229216d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
229316d9e3a6SLisandro Dalcin     /* initialize */
229416d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
22958966356dSPierre Jolivet     jac->threshold = .1;
229616d9e3a6SLisandro Dalcin     jac->filter    = .1;
229716d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
22982fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
22992fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
23002fa5cd67SKarl Rupp 
230116d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
230216d9e3a6SLisandro Dalcin     jac->symt = 0;
2303792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
2304792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
2305792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
2306792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
2307792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
2308792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
23093ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
231016d9e3a6SLisandro Dalcin   }
23119566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
231216d9e3a6SLisandro Dalcin   if (flag) {
2313792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
231416d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
231516d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
231616d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
231716d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
231885245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
23199566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
23209566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
232142e5ec60SJeff-Hadley     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", PCHYPREGetCFMarkers_BoomerAMG));
232216d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
232316d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
232416d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
232516d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
232616d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
232716d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
232816d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
232916d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
23308f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
233116d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
233216d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
233316d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
233416d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
23350f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
23366a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
2337b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
23381810e44eSEike Mueller     jac->eu_level                                                = 0;
23391810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
23401810e44eSEike Mueller     jac->eu_bj                                                   = 0;
234116d9e3a6SLisandro Dalcin     jac->relaxweight                                             = 1.0;
234216d9e3a6SLisandro Dalcin     jac->outerrelaxweight                                        = 1.0;
2343589dcaf0SStefano Zampini     jac->Rtype                                                   = 0;
2344589dcaf0SStefano Zampini     jac->Rstrongthreshold                                        = 0.25;
2345589dcaf0SStefano Zampini     jac->Rfilterthreshold                                        = 0.0;
2346589dcaf0SStefano Zampini     jac->Adroptype                                               = -1;
2347589dcaf0SStefano Zampini     jac->Adroptol                                                = 0.0;
23480f1074feSSatish Balay     jac->agg_nl                                                  = 0;
23490f1074feSSatish Balay     jac->pmax                                                    = 0;
23500f1074feSSatish Balay     jac->truncfactor                                             = 0.0;
23510f1074feSSatish Balay     jac->agg_num_paths                                           = 1;
2352589dcaf0SStefano Zampini     jac->maxc                                                    = 9;
2353589dcaf0SStefano Zampini     jac->minc                                                    = 1;
235422e51d31SStefano Zampini     jac->nodal_coarsening                                        = 0;
235522e51d31SStefano Zampini     jac->nodal_coarsening_diag                                   = 0;
235622e51d31SStefano Zampini     jac->vec_interp_variant                                      = 0;
235722e51d31SStefano Zampini     jac->vec_interp_qmax                                         = 0;
235822e51d31SStefano Zampini     jac->vec_interp_smooth                                       = PETSC_FALSE;
235922e51d31SStefano Zampini     jac->interp_refine                                           = 0;
23608f87f92bSBarry Smith     jac->nodal_relax                                             = PETSC_FALSE;
23618f87f92bSBarry Smith     jac->nodal_relax_levels                                      = 1;
23626ea7df73SStefano Zampini     jac->rap2                                                    = 0;
2363d7185485SAlex Lindsay     PetscObjectParameterSetDefault(jac, relaxorder, -1); /* Initialize with invalid value so we can recognize user input */
23643ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
236516d9e3a6SLisandro Dalcin   }
23669566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
23674cb006feSStefano Zampini   if (flag) {
23683ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
23694cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
23704cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
23714cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
23724cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
23734cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
23744cb006feSStefano Zampini     jac->coords[0]          = NULL;
23754cb006feSStefano Zampini     jac->coords[1]          = NULL;
23764cb006feSStefano Zampini     jac->coords[2]          = NULL;
2377be14dc20SKerry Key     jac->interior           = NULL;
23784cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2379863406b8SStefano Zampini     jac->as_print       = 0;
2380863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2381863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
23824cb006feSStefano Zampini     jac->ams_cycle_type = 13;
23834cb006feSStefano Zampini     /* Smoothing options */
2384863406b8SStefano Zampini     jac->as_relax_type   = 2;
2385863406b8SStefano Zampini     jac->as_relax_times  = 1;
2386863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2387863406b8SStefano Zampini     jac->as_omega        = 1.0;
23884cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2389863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2390863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
23910bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2392863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2393863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2394863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
23954cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2396863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2397863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
23980bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2399863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2400863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2401863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2402792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2403792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2404792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2405792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
24069371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2407792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2408863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2409863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
24109371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2411a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2412792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2413863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2414863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
24159371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2416a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
241723df4f25SStefano Zampini     /* Zero conductivity */
241823df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
241923df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
24203ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
24214cb006feSStefano Zampini   }
24229566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2423863406b8SStefano Zampini   if (flag) {
24243ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2425863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2426863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2427863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2428863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2429863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2430863406b8SStefano Zampini     jac->coords[0]          = NULL;
2431863406b8SStefano Zampini     jac->coords[1]          = NULL;
2432863406b8SStefano Zampini     jac->coords[2]          = NULL;
2433863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2434863406b8SStefano Zampini     jac->as_print       = 0;
2435863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2436863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2437863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2438863406b8SStefano Zampini     /* Smoothing options */
2439863406b8SStefano Zampini     jac->as_relax_type   = 2;
2440863406b8SStefano Zampini     jac->as_relax_times  = 1;
2441863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2442863406b8SStefano Zampini     jac->as_omega        = 1.0;
2443863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2444863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2445863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2446863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2447863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2448863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2449863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2450863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2451863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2452863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2453863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2454863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2455863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2456863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2457863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2458792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2459792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2460792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2461792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
24629371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2463792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2464863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2465863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2466863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
24679371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2468a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2469792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2470863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2471863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
24729371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2473a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
24743ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2475863406b8SStefano Zampini   }
24769566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
24772fa5cd67SKarl Rupp 
24780298fd71SBarry Smith   jac->hypre_type = NULL;
2479b06c524fSNuno Nobre   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, ilu, pilut, parasails, boomeramg, ams, ads", name);
248016d9e3a6SLisandro Dalcin }
248116d9e3a6SLisandro Dalcin 
248216d9e3a6SLisandro Dalcin /*
248316d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
248416d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
248516d9e3a6SLisandro Dalcin */
2486ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems PetscOptionsObject)
2487d71ae5a4SJacob Faibussowitsch {
24884ddd07fcSJed Brown   PetscInt    indx;
24893c61a47dSLukas   const char *type[] = {"ilu", "euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2490ace3abfcSBarry Smith   PetscBool   flg;
2491d7185485SAlex Lindsay   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
249216d9e3a6SLisandro Dalcin 
249316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2494d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2495dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
2496d7185485SAlex Lindsay   if (flg) PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
2497d7185485SAlex Lindsay   /*
2498d7185485SAlex Lindsay     Set the type if it was never set.
2499d7185485SAlex Lindsay   */
2500d7185485SAlex Lindsay   if (!jac->hypre_type) PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
2501dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2502d0609cedSBarry Smith   PetscOptionsHeadEnd();
25033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250416d9e3a6SLisandro Dalcin }
250516d9e3a6SLisandro Dalcin 
2506cc4c1da9SBarry Smith /*@
250716d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
250816d9e3a6SLisandro Dalcin 
250916d9e3a6SLisandro Dalcin   Input Parameters:
251016d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2511*c3466c22SBarry Smith - name - either euclid, ilu, pilut, parasails, boomeramg, ams, or ads
251216d9e3a6SLisandro Dalcin 
2513f1580f4eSBarry Smith   Options Database Key:
2514*c3466c22SBarry Smith . pc_hypre_type - One of euclid, ilu, pilut, parasails, boomeramg, ams, or ads
251516d9e3a6SLisandro Dalcin 
251616d9e3a6SLisandro Dalcin   Level: intermediate
251716d9e3a6SLisandro Dalcin 
2518562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
251916d9e3a6SLisandro Dalcin @*/
2520d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2521d71ae5a4SJacob Faibussowitsch {
252216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25230700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25244f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2525cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
25263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
252716d9e3a6SLisandro Dalcin }
252816d9e3a6SLisandro Dalcin 
252942e5ec60SJeff-Hadley /*@C
253042e5ec60SJeff-Hadley   PCHYPREGetCFMarkers - Gets CF marker arrays for all levels (except the finest level)
253142e5ec60SJeff-Hadley 
253242e5ec60SJeff-Hadley   Logically Collective
253342e5ec60SJeff-Hadley 
253442e5ec60SJeff-Hadley   Input Parameter:
253542e5ec60SJeff-Hadley . pc - the preconditioner context
253642e5ec60SJeff-Hadley 
253742e5ec60SJeff-Hadley   Output Parameters:
253842e5ec60SJeff-Hadley + n_per_level - the number of nodes per level (size of `num_levels`)
253942e5ec60SJeff-Hadley - CFMarkers   - the Coarse/Fine Boolean arrays (size of `num_levels` - 1)
254042e5ec60SJeff-Hadley 
2541*c3466c22SBarry Smith   Level: advanced
2542*c3466c22SBarry Smith 
254342e5ec60SJeff-Hadley   Note:
254442e5ec60SJeff-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.
254542e5ec60SJeff-Hadley 
254642e5ec60SJeff-Hadley .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
254742e5ec60SJeff-Hadley @*/
254842e5ec60SJeff-Hadley PetscErrorCode PCHYPREGetCFMarkers(PC pc, PetscInt *n_per_level[], PetscBT *CFMarkers[])
254942e5ec60SJeff-Hadley {
255042e5ec60SJeff-Hadley   PetscFunctionBegin;
255142e5ec60SJeff-Hadley   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
255242e5ec60SJeff-Hadley   PetscAssertPointer(n_per_level, 2);
255342e5ec60SJeff-Hadley   PetscAssertPointer(CFMarkers, 3);
255442e5ec60SJeff-Hadley   PetscUseMethod(pc, "PCHYPREGetCFMarkers_C", (PC, PetscInt *[], PetscBT *[]), (pc, n_per_level, CFMarkers));
255542e5ec60SJeff-Hadley   PetscFunctionReturn(PETSC_SUCCESS);
255642e5ec60SJeff-Hadley }
255742e5ec60SJeff-Hadley 
2558cc4c1da9SBarry Smith /*@
255916d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
256016d9e3a6SLisandro Dalcin 
256116d9e3a6SLisandro Dalcin   Input Parameter:
256216d9e3a6SLisandro Dalcin . pc - the preconditioner context
256316d9e3a6SLisandro Dalcin 
256416d9e3a6SLisandro Dalcin   Output Parameter:
2565*c3466c22SBarry Smith . name - either euclid, ilu, pilut, parasails, boomeramg, ams, or ads
256616d9e3a6SLisandro Dalcin 
256716d9e3a6SLisandro Dalcin   Level: intermediate
256816d9e3a6SLisandro Dalcin 
2569562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
257016d9e3a6SLisandro Dalcin @*/
2571d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2572d71ae5a4SJacob Faibussowitsch {
257316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25740700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25754f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2576cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
25773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
257816d9e3a6SLisandro Dalcin }
257916d9e3a6SLisandro Dalcin 
2580cc4c1da9SBarry Smith /*@
2581*c3466c22SBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of sparse matrix-matrix product for hypre's BoomerAMG to use on GPUs
2582db6f9c32SMark Adams 
2583c3339decSBarry Smith   Logically Collective
2584db6f9c32SMark Adams 
2585db6f9c32SMark Adams   Input Parameters:
2586db6f9c32SMark Adams + pc   - the hypre context
2587feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2588db6f9c32SMark Adams 
2589db6f9c32SMark Adams   Options Database Key:
2590*c3466c22SBarry Smith . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of sparse matrix-matrix product to use in hypre
2591db6f9c32SMark Adams 
2592db6f9c32SMark Adams   Level: intermediate
2593db6f9c32SMark Adams 
2594*c3466c22SBarry Smith   Developer Note:
2595f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2596db6f9c32SMark Adams 
2597562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2598db6f9c32SMark Adams @*/
2599d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2600d71ae5a4SJacob Faibussowitsch {
2601db6f9c32SMark Adams   PetscFunctionBegin;
2602db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2603cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
26043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2605db6f9c32SMark Adams }
2606db6f9c32SMark Adams 
2607cc4c1da9SBarry Smith /*@
2608*c3466c22SBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of sparse matrix-matrix product for hypre's BoomerAMG to use on GPUs
2609db6f9c32SMark Adams 
2610db6f9c32SMark Adams   Not Collective
2611db6f9c32SMark Adams 
2612db6f9c32SMark Adams   Input Parameter:
2613db6f9c32SMark Adams . pc - the multigrid context
2614db6f9c32SMark Adams 
2615db6f9c32SMark Adams   Output Parameter:
2616db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2617db6f9c32SMark Adams 
2618db6f9c32SMark Adams   Level: intermediate
2619db6f9c32SMark Adams 
2620a94f484eSPierre Jolivet .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinSetMatProductAlgorithm()`
2621db6f9c32SMark Adams @*/
2622d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2623d71ae5a4SJacob Faibussowitsch {
2624db6f9c32SMark Adams   PetscFunctionBegin;
2625db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2626cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
26273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2628db6f9c32SMark Adams }
2629db6f9c32SMark Adams 
263016d9e3a6SLisandro Dalcin /*MC
2631f1580f4eSBarry Smith   PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
263216d9e3a6SLisandro Dalcin 
263316d9e3a6SLisandro Dalcin   Options Database Keys:
2634b5a865d8SNuno Nobre +   -pc_hypre_type                           - One of `euclid`, `ilu`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2635*c3466c22SBarry Smith . -pc_hypre_boomeramg_nodal_coarsen <n>      - where `n` is from 1 to 6 (see `HYPRE_BoomerAMGSetNodal()`)
2636*c3466c22SBarry Smith . -pc_hypre_boomeramg_vec_interp_variant <v> - where `v` is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
26377cbeddf0SNuno Nobre - Many others - run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
263816d9e3a6SLisandro Dalcin 
263916d9e3a6SLisandro Dalcin   Level: intermediate
264016d9e3a6SLisandro Dalcin 
264195452b02SPatrick Sanan   Notes:
2642e1ded407SBarry Smith   Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
264316d9e3a6SLisandro Dalcin   the many hypre options can ONLY be set via the options database (e.g. the command line
264449567fc5SPierre Jolivet   or with `PetscOptionsSetValue()`, there are no functions to set them)
264516d9e3a6SLisandro Dalcin 
2646e1ded407SBarry Smith   The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2647e1ded407SBarry Smith   (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2648e1ded407SBarry Smith   `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2649e1ded407SBarry Smith   (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2650e1ded407SBarry Smith   iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2651e1ded407SBarry Smith   and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2652*c3466c22SBarry Smith   then AT MOST twenty V-cycles of BoomerAMG will be used.
265316d9e3a6SLisandro Dalcin 
2654e1ded407SBarry Smith   Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
26550f1074feSSatish Balay   (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2656e1ded407SBarry Smith   Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
265716d9e3a6SLisandro Dalcin 
2658*c3466c22SBarry Smith   If you provide a near null space to your matrix with `MatSetNearNullSpace()` it is ignored by hypre's BoomerAMG UNLESS you also use
2659e1ded407SBarry Smith   the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
26600b1a5bd9SEric Chamberland 
2661f1580f4eSBarry Smith   See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2662f1580f4eSBarry Smith 
2663e1ded407SBarry Smith   For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2664f1580f4eSBarry Smith   `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
266549567fc5SPierre Jolivet   `PCHYPREAMSSetInteriorNodes()`
2666f1580f4eSBarry Smith 
2667e1ded407SBarry 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
2668e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2669e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2670e1ded407SBarry Smith 
2671f1580f4eSBarry Smith   PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
26729e5bc791SBarry Smith 
2673ead8c081SBarry Smith   GPU Notes:
2674ead8c081SBarry Smith   To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2675f1580f4eSBarry Smith   Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2676ead8c081SBarry Smith 
2677ead8c081SBarry Smith   To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2678f1580f4eSBarry Smith   Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2679ead8c081SBarry Smith 
2680562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2681f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2682f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
268316d9e3a6SLisandro Dalcin M*/
268416d9e3a6SLisandro Dalcin 
2685d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2686d71ae5a4SJacob Faibussowitsch {
268716d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
268816d9e3a6SLisandro Dalcin 
268916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
26904dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
26912fa5cd67SKarl Rupp 
269216d9e3a6SLisandro Dalcin   pc->data                = jac;
26938695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
269416d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
269516d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
269616d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
269716d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
2698d7185485SAlex Lindsay   jac->hypre_type         = NULL;
269916d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
27009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
27019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
27029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
27039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
27049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
27059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
27069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2707be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
27089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
27099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
27109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
27116ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
27126ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
27139566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
27146ea7df73SStefano Zampini   #endif
27156ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
27169566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
27176ea7df73SStefano Zampini   #endif
27186ea7df73SStefano Zampini #endif
2719ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
27203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
272116d9e3a6SLisandro Dalcin }
2722ebc551c0SBarry Smith 
2723ebc551c0SBarry Smith typedef struct {
272468326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2725f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
27269e5bc791SBarry Smith 
27279e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
27284ddd07fcSJed Brown   PetscInt  its;
272973dcfd97SStefano Zampini   PetscReal tol;
27304ddd07fcSJed Brown   PetscInt  relax_type;
27314ddd07fcSJed Brown   PetscInt  rap_type;
27324ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
27334ddd07fcSJed Brown   PetscInt  max_levels;
27340be8cd64Sftrigaux   PetscInt  skip_relax;
27350be8cd64Sftrigaux   PetscBool print_statistics;
2736ebc551c0SBarry Smith } PC_PFMG;
2737ebc551c0SBarry Smith 
2738ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_PFMG(PC pc)
2739d71ae5a4SJacob Faibussowitsch {
2740f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2741ebc551c0SBarry Smith 
2742ebc551c0SBarry Smith   PetscFunctionBegin;
2743792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
27449566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
27459566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
27463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2747ebc551c0SBarry Smith }
2748ebc551c0SBarry Smith 
27499e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
27509e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
27519e5bc791SBarry Smith 
2752ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2753d71ae5a4SJacob Faibussowitsch {
27549f196a02SMartin Diehl   PetscBool isascii;
2755f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2756ebc551c0SBarry Smith 
2757ebc551c0SBarry Smith   PetscFunctionBegin;
27589f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
27599f196a02SMartin Diehl   if (isascii) {
27609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
276163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
27649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
276563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
276663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
27670be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
27689e5bc791SBarry Smith   }
27693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2770ebc551c0SBarry Smith }
2771ebc551c0SBarry Smith 
2772ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems PetscOptionsObject)
2773d71ae5a4SJacob Faibussowitsch {
2774f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2775ebc551c0SBarry Smith 
2776ebc551c0SBarry Smith   PetscFunctionBegin;
2777d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
27780be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
27799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2780792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
27819566063dSJacob 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));
2782792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
27839566063dSJacob 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));
2784792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
27859e5bc791SBarry Smith 
27869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2787792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
27883b46a515SGlenn Hammond 
27899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2790792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2791dd39110bSPierre 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));
2792792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2793dd39110bSPierre 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));
2794792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
27950be8cd64Sftrigaux   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));
27960be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2797d0609cedSBarry Smith   PetscOptionsHeadEnd();
27983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2799ebc551c0SBarry Smith }
2800ebc551c0SBarry Smith 
2801ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2802d71ae5a4SJacob Faibussowitsch {
2803f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2804d9ca1df4SBarry Smith   PetscScalar       *yy;
2805d9ca1df4SBarry Smith   const PetscScalar *xx;
28064ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
28072cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2808f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
2809f91d8e95SBarry Smith 
2810f91d8e95SBarry Smith   PetscFunctionBegin;
28119566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28129566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28132cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2814f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2815f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2816f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
28172cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
28182cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
28192cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
28202cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
28212cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
28222cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2823f91d8e95SBarry Smith 
2824f91d8e95SBarry Smith   /* copy x values over to hypre */
2825792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
28269566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2827792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
28289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2829792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2830792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2831f91d8e95SBarry Smith 
2832f91d8e95SBarry Smith   /* copy solution values back to PETSc */
28339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2834792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
28359566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
28363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2837f91d8e95SBarry Smith }
2838f91d8e95SBarry Smith 
2839d71ae5a4SJacob 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)
2840d71ae5a4SJacob Faibussowitsch {
28419e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
28422cf14000SStefano Zampini   HYPRE_Int oits;
28439e5bc791SBarry Smith 
28449e5bc791SBarry Smith   PetscFunctionBegin;
28459566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2846792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2847792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
28489e5bc791SBarry Smith 
28499566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2850792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
28519e5bc791SBarry Smith   *outits = oits;
28529e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
28539e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2854792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2855792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
28563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28579e5bc791SBarry Smith }
28589e5bc791SBarry Smith 
2859ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_PFMG(PC pc)
2860d71ae5a4SJacob Faibussowitsch {
28613a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
2862f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
2863ace3abfcSBarry Smith   PetscBool        flg;
28643a32d3dbSGlenn Hammond 
28653a32d3dbSGlenn Hammond   PetscFunctionBegin;
28669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
286728b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
28683a32d3dbSGlenn Hammond 
28693a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2870792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2871792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
28720be8cd64Sftrigaux 
28730be8cd64Sftrigaux   // Print Hypre statistics about the solve process
28740be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
28750be8cd64Sftrigaux 
28760be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
28770be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
28780be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28790be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28800be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
28810be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
28820be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
28830be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
28840be8cd64Sftrigaux 
2885792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2886792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
28873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28883a32d3dbSGlenn Hammond }
28893a32d3dbSGlenn Hammond 
2890ebc551c0SBarry Smith /*MC
2891ebc551c0SBarry Smith   PCPFMG - the hypre PFMG multigrid solver
2892ebc551c0SBarry Smith 
2893f1580f4eSBarry Smith   Options Database Keys:
289467b8a455SSatish Balay + -pc_pfmg_its <its>              - number of iterations of PFMG to use as preconditioner
289567b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps>  - number of smoothing steps before coarse grid solve
289667b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
289767b8a455SSatish Balay . -pc_pfmg_tol <tol>              - tolerance of PFMG
28989e5bc791SBarry 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
28990be8cd64Sftrigaux . -pc_pfmg_rap_type               - type of coarse matrix generation, one of Galerkin,non-Galerkin
2900f1580f4eSBarry Smith - -pc_pfmg_skip_relax             - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2901f1580f4eSBarry Smith                                     when the underlying problem is isotropic, one of 0,1
2902f1580f4eSBarry Smith 
2903f1580f4eSBarry Smith   Level: advanced
2904f91d8e95SBarry Smith 
290595452b02SPatrick Sanan   Notes:
290695452b02SPatrick Sanan   This is for CELL-centered descretizations
29079e5bc791SBarry Smith 
2908f1580f4eSBarry Smith   See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
29099e5bc791SBarry Smith 
2910f1580f4eSBarry Smith   See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2911f1580f4eSBarry Smith 
2912f1580f4eSBarry Smith   This must be used with the `MATHYPRESTRUCT` matrix type.
2913f1580f4eSBarry Smith 
2914f1580f4eSBarry Smith   This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2915f1580f4eSBarry Smith 
2916562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2917ebc551c0SBarry Smith M*/
2918ebc551c0SBarry Smith 
2919d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2920d71ae5a4SJacob Faibussowitsch {
2921ebc551c0SBarry Smith   PC_PFMG *ex;
2922ebc551c0SBarry Smith 
2923ebc551c0SBarry Smith   PetscFunctionBegin;
29249371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
292568326731SBarry Smith   pc->data = ex;
2926ebc551c0SBarry Smith 
29279e5bc791SBarry Smith   ex->its              = 1;
29289e5bc791SBarry Smith   ex->tol              = 1.e-8;
29299e5bc791SBarry Smith   ex->relax_type       = 1;
29309e5bc791SBarry Smith   ex->rap_type         = 0;
29319e5bc791SBarry Smith   ex->num_pre_relax    = 1;
29329e5bc791SBarry Smith   ex->num_post_relax   = 1;
29333b46a515SGlenn Hammond   ex->max_levels       = 0;
29340be8cd64Sftrigaux   ex->skip_relax       = 0;
29350be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
29369e5bc791SBarry Smith 
2937ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2938ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2939ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2940f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
29419e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
294268326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
29432fa5cd67SKarl Rupp 
29449566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2945ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2946792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
29473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2948ebc551c0SBarry Smith }
2949d851a50bSGlenn Hammond 
2950d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2951d851a50bSGlenn Hammond typedef struct {
2952d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2953d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2954d851a50bSGlenn Hammond 
2955d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
29564ddd07fcSJed Brown   PetscInt  its;
295773dcfd97SStefano Zampini   PetscReal tol;
29584ddd07fcSJed Brown   PetscInt  relax_type;
29594ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
2960d851a50bSGlenn Hammond } PC_SysPFMG;
2961d851a50bSGlenn Hammond 
2962ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SysPFMG(PC pc)
2963d71ae5a4SJacob Faibussowitsch {
2964d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2965d851a50bSGlenn Hammond 
2966d851a50bSGlenn Hammond   PetscFunctionBegin;
2967792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
29689566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
29699566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
29703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2971d851a50bSGlenn Hammond }
2972d851a50bSGlenn Hammond 
2973d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2974d851a50bSGlenn Hammond 
2975ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2976d71ae5a4SJacob Faibussowitsch {
29779f196a02SMartin Diehl   PetscBool   isascii;
2978d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2979d851a50bSGlenn Hammond 
2980d851a50bSGlenn Hammond   PetscFunctionBegin;
29819f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
29829f196a02SMartin Diehl   if (isascii) {
29839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
298463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
29859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
29869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
298763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2988d851a50bSGlenn Hammond   }
29893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2990d851a50bSGlenn Hammond }
2991d851a50bSGlenn Hammond 
2992ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems PetscOptionsObject)
2993d71ae5a4SJacob Faibussowitsch {
2994d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2995ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2996d851a50bSGlenn Hammond 
2997d851a50bSGlenn Hammond   PetscFunctionBegin;
2998d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
29999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
300048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
30019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
3002792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
30039566063dSJacob 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));
3004792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
30059566063dSJacob 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));
3006792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
3007d851a50bSGlenn Hammond 
30089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
3009792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
3010dd39110bSPierre 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));
3011792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
3012d0609cedSBarry Smith   PetscOptionsHeadEnd();
30133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3014d851a50bSGlenn Hammond }
3015d851a50bSGlenn Hammond 
3016ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
3017d71ae5a4SJacob Faibussowitsch {
3018d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
3019d9ca1df4SBarry Smith   PetscScalar       *yy;
3020d9ca1df4SBarry Smith   const PetscScalar *xx;
30214ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
30222cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
3023f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)pc->pmat->data;
30244ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
30254ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
30264ddd07fcSJed Brown   PetscInt           part     = 0;
30274ddd07fcSJed Brown   PetscInt           size;
30284ddd07fcSJed Brown   PetscInt           i;
3029d851a50bSGlenn Hammond 
3030d851a50bSGlenn Hammond   PetscFunctionBegin;
30319566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
30329566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
30332cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
3034d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
3035d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
3036d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
30372cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
30382cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
30392cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
30402cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
30412cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
30422cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
3043d851a50bSGlenn Hammond 
3044d851a50bSGlenn Hammond   size = 1;
30452fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
30462fa5cd67SKarl Rupp 
3047d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
3048d851a50bSGlenn Hammond   if (ordering) {
3049792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
30509566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3051792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
30529566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3053792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
3054792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
3055792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
3056d851a50bSGlenn Hammond 
3057d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30589566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3059792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
30609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
3061a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
3062d851a50bSGlenn Hammond     PetscScalar *z;
30634ddd07fcSJed Brown     PetscInt     j, k;
3064d851a50bSGlenn Hammond 
30659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
3066792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
30679566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3068d851a50bSGlenn Hammond 
3069d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
3070d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3071d851a50bSGlenn Hammond       k = i * nvars;
30722fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
3073d851a50bSGlenn Hammond     }
3074792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
30759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3076792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
3077792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
3078d851a50bSGlenn Hammond 
3079d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30809566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3081792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
3082d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
3083d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3084d851a50bSGlenn Hammond       k = i * nvars;
30852fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
3086d851a50bSGlenn Hammond     }
30879566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
30889566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
3089d851a50bSGlenn Hammond   }
30903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3091d851a50bSGlenn Hammond }
3092d851a50bSGlenn Hammond 
3093d71ae5a4SJacob 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)
3094d71ae5a4SJacob Faibussowitsch {
3095d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
30962cf14000SStefano Zampini   HYPRE_Int   oits;
3097d851a50bSGlenn Hammond 
3098d851a50bSGlenn Hammond   PetscFunctionBegin;
30999566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
3100792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
3101792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
31029566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
3103792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
3104d851a50bSGlenn Hammond   *outits = oits;
3105d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
3106d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
3107792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
3108792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
31093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3110d851a50bSGlenn Hammond }
3111d851a50bSGlenn Hammond 
3112ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SysPFMG(PC pc)
3113d71ae5a4SJacob Faibussowitsch {
3114d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
3115f4f49eeaSPierre Jolivet   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)pc->pmat->data;
3116ace3abfcSBarry Smith   PetscBool         flg;
3117d851a50bSGlenn Hammond 
3118d851a50bSGlenn Hammond   PetscFunctionBegin;
31199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
312028b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
3121d851a50bSGlenn Hammond 
3122d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
3123792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
3124792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
3125792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
3126792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
31273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3128d851a50bSGlenn Hammond }
3129d851a50bSGlenn Hammond 
3130d851a50bSGlenn Hammond /*MC
3131f1580f4eSBarry Smith    PCSYSPFMG - the hypre SysPFMG multigrid solver
3132d851a50bSGlenn Hammond 
3133d851a50bSGlenn Hammond    Level: advanced
3134d851a50bSGlenn Hammond 
3135f1580f4eSBarry Smith    Options Database Keys:
313667b8a455SSatish Balay + -pc_syspfmg_its <its>                                           - number of iterations of SysPFMG to use as preconditioner
313767b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps>                               - number of smoothing steps before coarse grid
313867b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps>                              - number of smoothing steps after coarse grid
313967b8a455SSatish Balay . -pc_syspfmg_tol <tol>                                           - tolerance of SysPFMG
314067b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
3141d851a50bSGlenn Hammond 
314295452b02SPatrick Sanan    Notes:
3143f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
3144f1580f4eSBarry Smith 
3145f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
3146f1580f4eSBarry Smith 
314795452b02SPatrick Sanan    This is for CELL-centered descretizations
3148d851a50bSGlenn Hammond 
3149f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
3150d851a50bSGlenn Hammond 
3151f1580f4eSBarry 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`.
3152f1580f4eSBarry Smith 
3153562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
3154d851a50bSGlenn Hammond M*/
3155d851a50bSGlenn Hammond 
3156d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
3157d71ae5a4SJacob Faibussowitsch {
3158d851a50bSGlenn Hammond   PC_SysPFMG *ex;
3159d851a50bSGlenn Hammond 
3160d851a50bSGlenn Hammond   PetscFunctionBegin;
31619371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
3162d851a50bSGlenn Hammond   pc->data = ex;
3163d851a50bSGlenn Hammond 
3164d851a50bSGlenn Hammond   ex->its            = 1;
3165d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
3166d851a50bSGlenn Hammond   ex->relax_type     = 1;
3167d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
3168d851a50bSGlenn Hammond   ex->num_post_relax = 1;
3169d851a50bSGlenn Hammond 
3170d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
3171d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
3172d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
3173d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
3174d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
3175d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
31762fa5cd67SKarl Rupp 
31779566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3178ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
3179792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
31803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3181d851a50bSGlenn Hammond }
31821c188c59Sftrigaux 
3183f1580f4eSBarry Smith /* PC SMG */
31841c188c59Sftrigaux typedef struct {
31851c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
31861c188c59Sftrigaux   HYPRE_StructSolver hsolver;
31871c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
318873dcfd97SStefano Zampini   PetscReal          tol;
31891c188c59Sftrigaux   PetscBool          print_statistics;
31901c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
31911c188c59Sftrigaux } PC_SMG;
31921c188c59Sftrigaux 
3193ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SMG(PC pc)
3194d71ae5a4SJacob Faibussowitsch {
31951c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
31961c188c59Sftrigaux 
31971c188c59Sftrigaux   PetscFunctionBegin;
31981c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
31991c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
32001c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
32013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32021c188c59Sftrigaux }
32031c188c59Sftrigaux 
3204ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
3205d71ae5a4SJacob Faibussowitsch {
32069f196a02SMartin Diehl   PetscBool isascii;
32071c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
32081c188c59Sftrigaux 
32091c188c59Sftrigaux   PetscFunctionBegin;
32109f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
32119f196a02SMartin Diehl   if (isascii) {
32121c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
32131c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
32141c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
32151c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
32161c188c59Sftrigaux   }
32173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32181c188c59Sftrigaux }
32191c188c59Sftrigaux 
3220ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems PetscOptionsObject)
3221d71ae5a4SJacob Faibussowitsch {
32221c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
32231c188c59Sftrigaux 
32241c188c59Sftrigaux   PetscFunctionBegin;
32251c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
32261c188c59Sftrigaux 
32271c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
32281c188c59Sftrigaux   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));
32291c188c59Sftrigaux   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));
32301c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
32311c188c59Sftrigaux 
32321c188c59Sftrigaux   PetscOptionsHeadEnd();
32333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32341c188c59Sftrigaux }
32351c188c59Sftrigaux 
3236ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
3237d71ae5a4SJacob Faibussowitsch {
32381c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
32391c188c59Sftrigaux   PetscScalar       *yy;
32401c188c59Sftrigaux   const PetscScalar *xx;
32411c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
32421c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
3243f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
32441c188c59Sftrigaux 
32451c188c59Sftrigaux   PetscFunctionBegin;
32461c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32471c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
32481c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
32491c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
32501c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
32511c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
32521c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
32531c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
32541c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
32551c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
32561c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
32571c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
32581c188c59Sftrigaux 
32591c188c59Sftrigaux   /* copy x values over to hypre */
32601c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
32611c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
32621c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
32631c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
32641c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
32651c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
32661c188c59Sftrigaux 
32671c188c59Sftrigaux   /* copy solution values back to PETSc */
32681c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
32691c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
32701c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
32713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32721c188c59Sftrigaux }
32731c188c59Sftrigaux 
3274d71ae5a4SJacob 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)
3275d71ae5a4SJacob Faibussowitsch {
32761c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
32771c188c59Sftrigaux   HYPRE_Int oits;
32781c188c59Sftrigaux 
32791c188c59Sftrigaux   PetscFunctionBegin;
32801c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32811c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
32821c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
32831c188c59Sftrigaux 
32841c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
32851c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
32861c188c59Sftrigaux   *outits = oits;
32871c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
32881c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
32891c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
32901c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
32913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32921c188c59Sftrigaux }
32931c188c59Sftrigaux 
3294ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SMG(PC pc)
3295d71ae5a4SJacob Faibussowitsch {
32961c188c59Sftrigaux   PetscInt         i, dim;
32971c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
3298f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
32991c188c59Sftrigaux   PetscBool        flg;
33001c188c59Sftrigaux   DMBoundaryType   p[3];
33011c188c59Sftrigaux   PetscInt         M[3];
33021c188c59Sftrigaux 
33031c188c59Sftrigaux   PetscFunctionBegin;
33041c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
33051c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
33061c188c59Sftrigaux 
33071c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
33081c188c59Sftrigaux   // Check if power of 2 in periodic directions
33091c188c59Sftrigaux   for (i = 0; i < dim; i++) {
3310966bd95aSPierre Jolivet     PetscCheck((M[i] & (M[i] - 1)) == 0 || p[i] != DM_BOUNDARY_PERIODIC, 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]);
33111c188c59Sftrigaux   }
33121c188c59Sftrigaux 
33131c188c59Sftrigaux   /* create the hypre solver object and set its information */
331457508eceSPierre Jolivet   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
33151c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
33161c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
33171c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
33181c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
33191c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
33201c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
33211c188c59Sftrigaux 
33221c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
33231c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
33243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33251c188c59Sftrigaux }
33261c188c59Sftrigaux 
33271c188c59Sftrigaux /*MC
33285cb80ecdSBarry Smith   PCSMG - the hypre (structured grid) SMG multigrid solver
33291c188c59Sftrigaux 
33301c188c59Sftrigaux   Level: advanced
33311c188c59Sftrigaux 
3332f1580f4eSBarry Smith   Options Database Keys:
33335cb80ecdSBarry Smith + -pc_smg_its <its>              - number of iterations of SMG to use as preconditioner
33345cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps>  - number of smoothing steps before coarse grid
33355cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
33365cb80ecdSBarry Smith - -pc_smg_tol <tol>              - tolerance of SMG
33371c188c59Sftrigaux 
33381c188c59Sftrigaux   Notes:
33391c188c59Sftrigaux   This is for CELL-centered descretizations
33401c188c59Sftrigaux 
33415cb80ecdSBarry Smith   This must be used with the `MATHYPRESTRUCT` `MatType`.
33421c188c59Sftrigaux 
3343f1580f4eSBarry 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`.
3344f1580f4eSBarry Smith 
3345f1580f4eSBarry Smith   See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3346f1580f4eSBarry Smith 
3347f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
33481c188c59Sftrigaux M*/
33491c188c59Sftrigaux 
3350d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3351d71ae5a4SJacob Faibussowitsch {
33521c188c59Sftrigaux   PC_SMG *ex;
33531c188c59Sftrigaux 
33541c188c59Sftrigaux   PetscFunctionBegin;
33559371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
33561c188c59Sftrigaux   pc->data = ex;
33571c188c59Sftrigaux 
33581c188c59Sftrigaux   ex->its            = 1;
33591c188c59Sftrigaux   ex->tol            = 1.e-8;
33601c188c59Sftrigaux   ex->num_pre_relax  = 1;
33611c188c59Sftrigaux   ex->num_post_relax = 1;
33621c188c59Sftrigaux 
33631c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
33641c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
33651c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
33661c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
33671c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
33681c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
33691c188c59Sftrigaux 
33701c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3371ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
33721c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
33733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33741c188c59Sftrigaux }
3375